NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
handler.h File Reference

Decide how to display email content. More...

#include <stddef.h>
#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 *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...
 
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  int oflags = s->flags;
1609 
1610  if (recurse_level >= MUTT_MIME_MAX_DEPTH)
1611  {
1612  mutt_debug(LL_DEBUG1, "recurse level too deep. giving up.\n");
1613  return 1;
1614  }
1615  recurse_level++;
1616 
1617  /* first determine which handler to use to process this part */
1618 
1619  if (is_autoview(b))
1620  {
1621  handler = autoview_handler;
1622  s->flags &= ~MUTT_CHARCONV;
1623  }
1624  else if (b->type == TYPE_TEXT)
1625  {
1626  if (mutt_istr_equal("plain", b->subtype))
1627  {
1628  const bool c_reflow_text = cs_subset_bool(NeoMutt->sub, "reflow_text");
1629  /* avoid copying this part twice since removing the transfer-encoding is
1630  * the only operation needed. */
1631  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1632  {
1633  encrypted_handler = crypt_pgp_application_handler;
1634  handler = encrypted_handler;
1635  }
1636  else if (c_reflow_text && mutt_istr_equal("flowed", mutt_param_get(&b->parameter, "format")))
1637  {
1638  handler = rfc3676_handler;
1639  }
1640  else
1641  {
1642  handler = text_plain_handler;
1643  }
1644  }
1645  else if (mutt_istr_equal("enriched", b->subtype))
1646  handler = text_enriched_handler;
1647  else /* text body type without a handler */
1648  plaintext = false;
1649  }
1650  else if (b->type == TYPE_MESSAGE)
1651  {
1652  if (mutt_is_message_type(b->type, b->subtype))
1653  handler = message_handler;
1654  else if (mutt_istr_equal("delivery-status", b->subtype))
1655  plaintext = true;
1656  else if (mutt_istr_equal("external-body", b->subtype))
1657  handler = external_body_handler;
1658  }
1659  else if (b->type == TYPE_MULTIPART)
1660  {
1661  const char *const c_show_multipart_alternative =
1662  cs_subset_string(NeoMutt->sub, "show_multipart_alternative");
1663  if (!mutt_str_equal("inline", c_show_multipart_alternative) &&
1664  mutt_istr_equal("alternative", b->subtype))
1665  {
1666  handler = alternative_handler;
1667  }
1668  else if (!mutt_str_equal("inline", c_show_multipart_alternative) &&
1669  mutt_istr_equal("multilingual", b->subtype))
1670  {
1671  handler = multilingual_handler;
1672  }
1673  else if ((WithCrypto != 0) && mutt_istr_equal("signed", b->subtype))
1674  {
1675  if (!mutt_param_get(&b->parameter, "protocol"))
1676  mutt_error(_("Error: multipart/signed has no protocol"));
1677  else if (s->flags & MUTT_VERIFY)
1678  handler = mutt_signed_handler;
1679  }
1681  {
1682  encrypted_handler = valid_pgp_encrypted_handler;
1683  handler = encrypted_handler;
1684  }
1686  {
1687  encrypted_handler = malformed_pgp_encrypted_handler;
1688  handler = encrypted_handler;
1689  }
1690 
1691  if (!handler)
1692  handler = multipart_handler;
1693 
1694  if ((b->encoding != ENC_7BIT) && (b->encoding != ENC_8BIT) && (b->encoding != ENC_BINARY))
1695  {
1696  mutt_debug(LL_DEBUG1, "Bad encoding type %d for multipart entity, assuming 7 bit\n",
1697  b->encoding);
1698  b->encoding = ENC_7BIT;
1699  }
1700  }
1701  else if ((WithCrypto != 0) && (b->type == TYPE_APPLICATION))
1702  {
1703  if (OptDontHandlePgpKeys && mutt_istr_equal("pgp-keys", b->subtype))
1704  {
1705  /* pass raw part through for key extraction */
1706  plaintext = true;
1707  }
1708  else if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(b))
1709  {
1710  encrypted_handler = crypt_pgp_application_handler;
1711  handler = encrypted_handler;
1712  }
1713  else if (((WithCrypto & APPLICATION_SMIME) != 0) && mutt_is_application_smime(b))
1714  {
1715  encrypted_handler = crypt_smime_application_handler;
1716  handler = encrypted_handler;
1717  }
1718  }
1719 
1720  const bool c_honor_disposition =
1721  cs_subset_bool(NeoMutt->sub, "honor_disposition");
1722  /* only respect disposition == attachment if we're not
1723  * displaying from the attachment menu (i.e. pager) */
1724  if ((!c_honor_disposition || ((b->disposition != DISP_ATTACH) || OptViewAttach)) &&
1725  (plaintext || handler))
1726  {
1727  /* Prevent encrypted attachments from being included in replies
1728  * unless $include_encrypted is set. */
1729  const bool c_include_encrypted =
1730  cs_subset_bool(NeoMutt->sub, "include_encrypted");
1731  if ((s->flags & MUTT_REPLYING) && (s->flags & MUTT_FIRSTDONE) &&
1732  encrypted_handler && !c_include_encrypted)
1733  {
1734  goto cleanup;
1735  }
1736 
1737  rc = run_decode_and_handler(b, s, handler, plaintext);
1738  }
1739  /* print hint to use attachment menu for disposition == attachment
1740  * if we're not already being called from there */
1741  else if (s->flags & MUTT_DISPLAY)
1742  {
1743  struct Buffer msg = mutt_buffer_make(256);
1744 
1745  if (!OptViewAttach)
1746  {
1747  char keystroke[128] = { 0 };
1748  if (km_expand_key(keystroke, sizeof(keystroke),
1749  km_find_func(MENU_PAGER, OP_VIEW_ATTACHMENTS)))
1750  {
1751  if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1752  {
1753  /* L10N: %s expands to a keystroke/key binding, e.g. 'v'. */
1754  mutt_buffer_printf(&msg, _("[-- This is an attachment (use '%s' to view this part) --]\n"),
1755  keystroke);
1756  }
1757  else
1758  {
1759  /* L10N: %s/%s is a MIME type, e.g. "text/plain".
1760  The last %s expands to a keystroke/key binding, e.g. 'v'. */
1761  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (use '%s' to view this part) --]\n"),
1762  TYPE(b), b->subtype, keystroke);
1763  }
1764  }
1765  else
1766  {
1767  if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1768  {
1769  mutt_buffer_strcpy(&msg, _("[-- This is an attachment (need "
1770  "'view-attachments' bound to key) --]\n"));
1771  }
1772  else
1773  {
1774  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1775  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported (need 'view-attachments' bound to key) --]\n"),
1776  TYPE(b), b->subtype);
1777  }
1778  }
1779  }
1780  else
1781  {
1782  if (c_honor_disposition && (b->disposition == DISP_ATTACH))
1783  {
1784  mutt_buffer_strcpy(&msg, _("[-- This is an attachment --]\n"));
1785  }
1786  else
1787  {
1788  /* L10N: %s/%s is a MIME type, e.g. "text/plain". */
1789  mutt_buffer_printf(&msg, _("[-- %s/%s is unsupported --]\n"), TYPE(b), b->subtype);
1790  }
1791  }
1792  state_mark_attach(s);
1793  state_printf(s, "%s", mutt_buffer_string(&msg));
1794  mutt_buffer_dealloc(&msg);
1795  }
1796 
1797 cleanup:
1798  recurse_level--;
1799  s->flags = oflags | (s->flags & MUTT_FIRSTDONE);
1800  if (rc != 0)
1801  {
1802  mutt_debug(LL_DEBUG1, "Bailing on attachment of type %s/%s\n", TYPE(b),
1803  NONULL(b->subtype));
1804  }
1805 
1806  return rc;
1807 }
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:294
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:559
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:617
int mutt_is_valid_multipart_pgp_encrypted(struct Body *b)
Is this a valid multi-part encrypted message?
Definition: crypt.c:478
SecurityFlags mutt_is_malformed_multipart_pgp_encrypted(struct Body *b)
Check for malformed layout.
Definition: crypt.c:515
static int multipart_handler(struct Body *a, struct State *s)
Handler for multipart emails - Implements handler_t -.
Definition: handler.c:1213
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:320
int mutt_signed_handler(struct Body *b, struct State *s)
Verify a "multipart/signed" body - Implements handler_t -.
Definition: crypt.c:1152
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:1115
static int alternative_handler(struct Body *a, struct State *s)
Handler for multipart alternative emails - Implements handler_t -.
Definition: handler.c:928
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:445
int crypt_pgp_application_handler(struct Body *b, struct State *s)
Wrapper for CryptModuleSpecs::application_handler() - Implements handler_t -.
Definition: cryptglue.c:238
#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:477
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:1297
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
struct Keymap * km_find_func(enum MenuType mtype, int func)
Find a function's mapping in a Menu.
Definition: keymap.c:938
int km_expand_key(char *s, size_t len, struct Keymap *map)
Get the key string bound to a Keymap.
Definition: keymap.c:910
@ 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
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:904
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define WithCrypto
Definition: lib.h:113
bool OptDontHandlePgpKeys
(pseudo) used to extract PGP keys
Definition: options.h:41
bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:60
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:1428
int state_printf(struct State *s, const char *fmt,...)
Write a formatted string to the State.
Definition: state.c:185
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_CHARCONV
Do character set conversions.
Definition: state.h:36
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
#define MUTT_REPLYING
Are we replying?
Definition: state.h:38
#define NONULL(x)
Definition: string2.h:37
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:61
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:41
char * subtype
content-type subtype
Definition: body.h:59
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:40
unsigned int type
content-type primary type, ContentType
Definition: body.h:39
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:49
@ 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 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 1814 of file handler.c.

1815 {
1816  if (is_autoview(a))
1817  return true;
1818  if (a->type == TYPE_TEXT)
1819  return true;
1820  if (a->type == TYPE_MESSAGE)
1821  return true;
1822  if (a->type == TYPE_MULTIPART)
1823  {
1824  if (WithCrypto)
1825  {
1826  if (mutt_istr_equal(a->subtype, "signed") || mutt_istr_equal(a->subtype, "encrypted"))
1827  {
1828  return true;
1829  }
1830  }
1831 
1832  for (struct Body *b = a->parts; b; b = b->next)
1833  {
1834  if (mutt_can_decode(b))
1835  return true;
1836  }
1837  }
1838  else if ((WithCrypto != 0) && (a->type == TYPE_APPLICATION))
1839  {
1840  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(a))
1841  return true;
1843  return true;
1844  }
1845 
1846  return false;
1847 }
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1814
The body of an email.
Definition: body.h:35
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:71
struct Body * next
next attachment in the list
Definition: body.h:70
+ 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 1854 of file handler.c.

1855 {
1856  int istext = mutt_is_text_part(b) && (b->disposition == DISP_INLINE);
1857  iconv_t cd = (iconv_t) (-1);
1858 
1859  if (istext && (b->charset || (s->flags & MUTT_CHARCONV)))
1860  {
1861  const char *charset = b->charset;
1862  if (!charset)
1863  {
1864  const char *const c_assumed_charset =
1865  cs_subset_string(NeoMutt->sub, "assumed_charset");
1866  charset = mutt_param_get(&b->parameter, "charset");
1867  if (!charset && c_assumed_charset)
1868  charset = mutt_ch_get_default_charset();
1869  }
1870  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
1871  if (charset && c_charset)
1872  cd = mutt_ch_iconv_open(c_charset, charset, MUTT_ICONV_HOOK_FROM);
1873  }
1874 
1875  (void) fseeko(s->fp_in, b->offset, SEEK_SET);
1876  switch (b->encoding)
1877  {
1878  case ENC_QUOTED_PRINTABLE:
1879  decode_quoted(s, b->length,
1880  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1882  cd);
1883  break;
1884  case ENC_BASE64:
1885  mutt_decode_base64(s, b->length,
1886  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1888  cd);
1889  break;
1890  case ENC_UUENCODED:
1891  decode_uuencoded(s, b->length,
1892  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1894  cd);
1895  break;
1896  default:
1897  decode_xbit(s, b->length,
1898  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1900  cd);
1901  break;
1902  }
1903 
1904  if (cd != (iconv_t) (-1))
1905  iconv_close(cd);
1906 }
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:443
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
Definition: charset.c:576
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:434
LOFF_T offset
offset where the actual data begins
Definition: body.h:51
LOFF_T length
length (in bytes) of attachment
Definition: body.h:52
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:77
FILE * fp_in
File to read from.
Definition: state.h:46
+ 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];
1501  int ch, i;
1502  bool cr = false;
1503  char bufi[BUFI_SIZE];
1504  size_t l = 0;
1505 
1506  buf[4] = '\0';
1507 
1508  if (istext)
1509  state_set_prefix(s);
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 
1587  state_reset_prefix(s);
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:53
#define state_reset_prefix(state)
Definition: state.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function: