NeoMutt  2022-04-29-178-g3b62e6
Teaching an old dog new tricks
DOXYGEN
handler.h File Reference

Decide how to display email content. More...

#include <iconv.h>
#include <stdbool.h>
+ Include dependency graph for handler.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int mutt_body_handler (struct Body *b, struct State *s)
 Handler for the Body of an email. More...
 
bool mutt_can_decode (struct Body *b)
 Will decoding the attachment produce any output. More...
 
bool mutt_prefer_as_attachment (struct Body *b)
 Do we want this part as an attachment? More...
 
void mutt_decode_attachment (struct Body *b, struct State *s)
 Decode an email's attachment. More...
 
void mutt_decode_base64 (struct State *s, size_t len, bool istext, iconv_t cd)
 Decode base64-encoded text. 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.h.

Function Documentation

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

1598{
1599 if (!b || !s)
1600 return -1;
1601
1602 bool plaintext = false;
1603 handler_t handler = NULL;
1604 handler_t encrypted_handler = NULL;
1605 int rc = 0;
1606 static unsigned short recurse_level = 0;
1607
1608 const int oflags = s->flags;
1609 const bool is_attachment_display = (oflags & MUTT_DISPLAY_ATTACH);
1610
1611 if (recurse_level >= MUTT_MIME_MAX_DEPTH)
1612 {
1613 mutt_debug(LL_DEBUG1, "recurse level too deep. giving up.\n");
1614 return 1;
1615 }
1616 recurse_level++;
1617
1618 /* first determine which handler to use to process this part */
1619
1620 if (is_autoview(b))
1621 {
1622 handler = autoview_handler;
1623 s->flags &= ~MUTT_CHARCONV;
1624 }
1625 else if (b->type == TYPE_TEXT)
1626 {
1627 if (mutt_istr_equal("plain", b->subtype))
1628 {
1629 const bool c_reflow_text = cs_subset_bool(NeoMutt->sub, "reflow_text");
1630 /* avoid copying this part twice since removing the transfer-encoding is
1631 * the only operation needed. */
1633 {
1634 encrypted_handler = crypt_pgp_application_handler;
1635 handler = encrypted_handler;
1636 }
1637 else if (c_reflow_text &&
1638 mutt_istr_equal("flowed", mutt_param_get(&b->parameter, "format")))
1639 {
1640 handler = rfc3676_handler;
1641 }
1642 else
1643 {
1644 handler = text_plain_handler;
1645 }
1646 }
1647 else if (mutt_istr_equal("enriched", b->subtype))
1648 handler = text_enriched_handler;
1649 else /* text body type without a handler */
1650 plaintext = false;
1651 }
1652 else if (b->type == TYPE_MESSAGE)
1653 {
1654 if (mutt_is_message_type(b->type, b->subtype))
1655 handler = message_handler;
1656 else if (mutt_istr_equal("delivery-status", b->subtype))
1657 plaintext = true;
1658 else if (mutt_istr_equal("external-body", b->subtype))
1659 handler = external_body_handler;
1660 }
1661 else if (b->type == TYPE_MULTIPART)
1662 {
1663 const char *const c_show_multipart_alternative = cs_subset_string(NeoMutt->sub, "show_multipart_alternative");
1664 if (!mutt_str_equal("inline", c_show_multipart_alternative) &&
1665 mutt_istr_equal("alternative", b->subtype))
1666 {
1667 handler = alternative_handler;
1668 }
1669 else if (!mutt_str_equal("inline", c_show_multipart_alternative) &&
1670 mutt_istr_equal("multilingual", b->subtype))
1671 {
1672 handler = multilingual_handler;
1673 }
1674 else if ((WithCrypto != 0) && mutt_istr_equal("signed", b->subtype))
1675 {
1676 if (!mutt_param_get(&b->parameter, "protocol"))
1677 mutt_error(_("Error: multipart/signed has no protocol"));
1678 else if (s->flags & MUTT_VERIFY)
1679 handler = mutt_signed_handler;
1680 }
1682 {
1683 encrypted_handler = valid_pgp_encrypted_handler;
1684 handler = encrypted_handler;
1685 }
1687 {
1688 encrypted_handler = malformed_pgp_encrypted_handler;
1689 handler = encrypted_handler;
1690 }
1691
1692 if (!handler)
1693 handler = multipart_handler;
1694
1695 if ((b->encoding != ENC_7BIT) && (b->encoding != ENC_8BIT) && (b->encoding != ENC_BINARY))
1696 {
1697 mutt_debug(LL_DEBUG1, "Bad encoding type %d for multipart entity, assuming 7 bit\n",
1698 b->encoding);
1699 b->encoding = ENC_7BIT;
1700 }
1701 }
1702 else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1703 {
1704 if (OptDontHandlePgpKeys && mutt_istr_equal("pgp-keys", b->subtype))
1705 {
1706 /* pass raw part through for key extraction */
1707 plaintext = true;
1708 }
1709 else if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1710 {
1711 encrypted_handler = crypt_pgp_application_handler;
1712 handler = encrypted_handler;
1713 }
1714 else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(b))
1715 {
1716 encrypted_handler = crypt_smime_application_handler;
1717 handler = encrypted_handler;
1718 }
1719 }
1720
1721 /* only respect disposition == attachment if we're not
1722 * displaying from the attachment menu (i.e. pager) */
1723 if ((plaintext || handler) && (is_attachment_display || !mutt_prefer_as_attachment(b)))
1724 {
1725 /* Prevent encrypted attachments from being included in replies
1726 * unless $include_encrypted is set. */
1727 const bool c_include_encrypted = cs_subset_bool(NeoMutt->sub, "include_encrypted");
1728 if ((s->flags & MUTT_REPLYING) && (s->flags & MUTT_FIRSTDONE) &&
1729 encrypted_handler && !c_include_encrypted)
1730 {
1731 goto cleanup;
1732 }
1733
1734 rc = run_decode_and_handler(b, s, handler, plaintext);
1735 }
1736 /* print hint to use attachment menu for disposition == attachment
1737 * if we're not already being called from there */
1738 else if (s->flags & MUTT_DISPLAY)
1739 {
1740 const bool c_honor_disposition = cs_subset_bool(NeoMutt->sub, "honor_disposition");
1741 struct Buffer msg = mutt_buffer_make(256);
1742
1743 if (!is_attachment_display)
1744 {
1745 char keystroke[128] = { 0 };
1746 if (km_expand_key(keystroke, sizeof(keystroke),
1747 km_find_func(MENU_PAGER, OP_VIEW_ATTACHMENTS)))
1748 {
1749 if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1750 {
1751 /* L10N: %s expands to a keystroke/key binding, e.g. 'v'. */
1752 mutt_buffer_printf(&msg, _("[-- This is an attachment (use '%s' to view this part) --]\n"),
1753 keystroke);
1754 }
1755 else
1756 {
1757 /* L10N: %s/%s is a MIME type, e.g. "text/plain".
1758 The last %s expands to a keystroke/key binding, e.g. 'v'. */
1759 mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (use '%s' to view this part) --]\n"),
1760 TYPE(b), b->subtype, keystroke);
1761 }
1762 }
1763 else
1764 {
1765 if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1766 {
1767 mutt_buffer_strcpy(&msg, _("[-- This is an attachment (need 'view-attachments' bound to key) --]\n"));
1768 }
1769 else
1770 {
1771 /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1772 mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (need 'view-attachments' bound to key) --]\n"),
1773 TYPE(b), b->subtype);
1774 }
1775 }
1776 }
1777 else
1778 {
1779 if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1780 {
1781 mutt_buffer_strcpy(&msg, _("[-- This is an attachment --]\n"));
1782 }
1783 else
1784 {
1785 /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1786 mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported --]\n"), TYPE(b), b->subtype);
1787 }
1788 }
1790 state_printf(s, "%s", mutt_buffer_string(&msg));
1791 mutt_buffer_dealloc(&msg);
1792 }
1793
1794cleanup:
1795 recurse_level--;
1796 s->flags = oflags | (s->flags & MUTT_FIRSTDONE);
1797 if (rc != 0)
1798 {
1799 mutt_debug(LL_DEBUG1, "Bailing on attachment of type %s/%s\n", TYPE(b),
1800 NONULL(b->subtype));
1801 }
1802
1803 return rc;
1804}
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:63
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:310
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:292
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:158
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:544
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:601
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:463
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:500
static int multipart_handler(struct Body *a, struct State *s)
Handler for multipart emails - Implements handler_t -.
Definition: handler.c:1212
static int message_handler(struct Body *a, struct State *s)
Handler for message/rfc822 body parts - Implements handler_t -.
Definition: handler.c:704
static int malformed_pgp_encrypted_handler(struct Body *b, struct State *s)
Handler for invalid pgp-encrypted emails - Implements handler_t -.
Definition: handler.c:1466
int rfc3676_handler(struct Body *a, struct State *s)
Body handler implementing RFC3676 for format=flowed - Implements handler_t -.
Definition: rfc3676.c:318
int mutt_signed_handler(struct Body *b, struct State *s)
Verify a "multipart/signed" body - Implements handler_t -.
Definition: crypt.c:1124
static int autoview_handler(struct Body *a, struct State *s)
Handler for autoviewable attachments - Implements handler_t -.
Definition: handler.c:524
static int text_plain_handler(struct Body *b, struct State *s)
Handler for plain text - Implements handler_t -.
Definition: handler.c:677
int text_enriched_handler(struct Body *a, struct State *s)
Handler for enriched text - Implements handler_t -.
Definition: enriched.c:459
static int multilingual_handler(struct Body *a, struct State *s)
Handler for multi-lingual emails - Implements handler_t -.
Definition: handler.c:1110
static int alternative_handler(struct Body *a, struct State *s)
Handler for multipart alternative emails - Implements handler_t -.
Definition: handler.c:926
static int valid_pgp_encrypted_handler(struct Body *b, struct State *s)
Handler for valid pgp-encrypted emails - Implements handler_t -.
Definition: handler.c:1437
static int external_body_handler(struct Body *b, struct State *s)
Handler for external-body emails - Implements handler_t -.
Definition: handler.c:756
int crypt_smime_application_handler(struct Body *b, struct State *s)
Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.
Definition: cryptglue.c:444
int crypt_pgp_application_handler(struct Body *b, struct State *s)
Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.
Definition: cryptglue.c:237
#define mutt_error(...)
Definition: logging.h:87
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
int(* handler_t)(struct Body *b, struct State *s)
Definition: handler.c:80
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:478
bool mutt_prefer_as_attachment(struct Body *b)
Do we want this part as an attachment?
Definition: handler.c:1811
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:1294
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition: keymap.c:956
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:928
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
@ 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
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
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
@ DISP_ATTACH
Content is attached.
Definition: mime.h:63
#define TYPE(body)
Definition: mime.h:89
#define _(a)
Definition: message.h:28
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:183
void state_mark_attach(struct State *s)
Write a unique marker around content.
Definition: state.c:71
#define MUTT_FIRSTDONE
The first attachment has been done.
Definition: state.h:39
#define MUTT_VERIFY
Perform signature verification.
Definition: state.h:33
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define MUTT_DISPLAY_ATTACH
We are displaying an attachment.
Definition: state.h:40
#define MUTT_REPLYING
Are we replying?
Definition: state.h:38
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:796
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:784
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:90
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:91
#define WithCrypto
Definition: lib.h:116
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:41
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1442
#define NONULL(x)
Definition: string2.h:37
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:42
char * subtype
content-type subtype
Definition: body.h:60
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:41
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
String manipulation buffer.
Definition: buffer.h:34
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:50
@ MENU_PAGER
Pager pager (email viewer)
Definition: type.h:54
+ 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 1827 of file handler.c.

1828{
1829 if (is_autoview(b))
1830 return true;
1831 if (b->type == TYPE_TEXT)
1832 return true;
1833 if (b->type == TYPE_MESSAGE)
1834 return true;
1835 if (b->type == TYPE_MULTIPART)
1836 {
1837 if (WithCrypto)
1838 {
1839 if (mutt_istr_equal(b->subtype, "signed") || mutt_istr_equal(b->subtype, "encrypted"))
1840 {
1841 return true;
1842 }
1843 }
1844
1845 for (struct Body *part = b->parts; part; part = part->next)
1846 {
1847 if (mutt_can_decode(part))
1848 return true;
1849 }
1850 }
1851 else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1852 {
1854 return true;
1856 return true;
1857 }
1858
1859 return false;
1860}
bool mutt_can_decode(struct Body *b)
Will decoding the attachment produce any output.
Definition: handler.c:1827
The body of an email.
Definition: body.h:36
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
struct Body * next
next attachment in the list
Definition: body.h:71
+ 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 1811 of file handler.c.

1812{
1813 if (!mutt_can_decode(b))
1814 return true;
1815
1816 if (b->disposition != DISP_ATTACH)
1817 return false;
1818
1819 return cs_subset_bool(NeoMutt->sub, "honor_disposition");
1820}
+ 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 1867 of file handler.c.

1868{
1869 int istext = mutt_is_text_part(b) && (b->disposition == DISP_INLINE);
1870 iconv_t cd = (iconv_t) (-1);
1871
1872 if (!mutt_file_seek(s->fp_in, b->offset, SEEK_SET))
1873 {
1874 return;
1875 }
1876
1877 if (istext && (b->charset || (s->flags & MUTT_CHARCONV)))
1878 {
1879 const char *charset = b->charset;
1880 if (!charset)
1881 {
1882 const struct Slist *const c_assumed_charset = cs_subset_slist(NeoMutt->sub, "assumed_charset");
1883 charset = mutt_param_get(&b->parameter, "charset");
1884 if (!charset && c_assumed_charset)
1885 charset = mutt_ch_get_default_charset();
1886 }
1887 const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
1888 if (charset && c_charset)
1889 cd = mutt_ch_iconv_open(c_charset, charset, MUTT_ICONV_HOOK_FROM);
1890 }
1891
1892 switch (b->encoding)
1893 {
1895 decode_quoted(s, b->length,
1896 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1898 cd);
1899 break;
1900 case ENC_BASE64:
1902 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1904 cd);
1905 break;
1906 case ENC_UUENCODED:
1908 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1910 cd);
1911 break;
1912 default:
1913 decode_xbit(s, b->length,
1914 istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1916 cd);
1917 break;
1918 }
1919
1920 if (cd != (iconv_t) (-1))
1921 iconv_close(cd);
1922}
const struct Slist * cs_subset_slist(const struct ConfigSubset *sub, const char *name)
Get a string-list config item by name.
Definition: helpers.c:268
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:690
static void decode_uuencoded(struct State *s, long len, bool istext, iconv_t cd)
Decode uuencoded text.
Definition: handler.c:365
static void decode_quoted(struct State *s, long len, bool istext, iconv_t cd)
Decode an attachment encoded with quoted-printable.
Definition: handler.c:301
static void decode_xbit(struct State *s, long len, bool istext, iconv_t cd)
Decode xbit-encoded text.
Definition: handler.c:164
void mutt_decode_base64(struct State *s, size_t len, bool istext, iconv_t cd)
Decode base64-encoded text.
Definition: handler.c:1498
@ 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
@ DISP_INLINE
Content is inline.
Definition: mime.h:62
char * mutt_ch_get_default_charset(void)
Get the default character set.
Definition: charset.c:439
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
Definition: charset.c:564
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:433
LOFF_T offset
offset where the actual data begins
Definition: body.h:52
LOFF_T length
length (in bytes) of attachment
Definition: body.h:53
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:78
String list.
Definition: slist.h:47
FILE * fp_in
File to read from.
Definition: state.h:47
+ 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 1498 of file handler.c.

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