NeoMutt  2021-02-05-666-ge300cd
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 1604 of file handler.c.

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

◆ mutt_can_decode()

bool mutt_can_decode ( struct Body a)

Will decoding the attachment produce any output.

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

Definition at line 1821 of file handler.c.

1822 {
1823  if (is_autoview(a))
1824  return true;
1825  if (a->type == TYPE_TEXT)
1826  return true;
1827  if (a->type == TYPE_MESSAGE)
1828  return true;
1829  if (a->type == TYPE_MULTIPART)
1830  {
1831  if (WithCrypto)
1832  {
1833  if (mutt_istr_equal(a->subtype, "signed") || mutt_istr_equal(a->subtype, "encrypted"))
1834  {
1835  return true;
1836  }
1837  }
1838 
1839  for (struct Body *b = a->parts; b; b = b->next)
1840  {
1841  if (mutt_can_decode(b))
1842  return true;
1843  }
1844  }
1845  else if ((WithCrypto != 0) && (a->type == TYPE_APPLICATION))
1846  {
1847  if (((WithCrypto & APPLICATION_PGP) != 0) && mutt_is_application_pgp(a))
1848  return true;
1850  return true;
1851  }
1852 
1853  return false;
1854 }
#define WithCrypto
Definition: lib.h:113
static bool is_autoview(struct Body *b)
Should email body be filtered by mailcap.
Definition: handler.c:475
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
Definition: crypt.c:623
struct Body * next
next attachment in the list
Definition: body.h:53
The body of an email.
Definition: body.h:34
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:916
char * subtype
content-type subtype
Definition: body.h:37
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
Definition: lib.h:88
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
Type: &#39;text/*&#39;.
Definition: mime.h:38
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1821
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
Type: &#39;application/*&#39;.
Definition: mime.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_decode_attachment()

void mutt_decode_attachment ( struct Body b,
struct State s 
)

Decode an email's attachment.

Parameters
bBody of the email
sState of text being processed

Definition at line 1861 of file handler.c.

1862 {
1863  int istext = mutt_is_text_part(b) && (b->disposition == DISP_INLINE);
1864  iconv_t cd = (iconv_t) (-1);
1865 
1866  if (istext && (b->charset || (s->flags & MUTT_CHARCONV)))
1867  {
1868  const char *charset = b->charset;
1869  if (!charset)
1870  {
1871  const char *const c_assumed_charset =
1872  cs_subset_string(NeoMutt->sub, "assumed_charset");
1873  charset = mutt_param_get(&b->parameter, "charset");
1874  if (!charset && c_assumed_charset)
1875  charset = mutt_ch_get_default_charset();
1876  }
1877  const char *const c_charset = cs_subset_string(NeoMutt->sub, "charset");
1878  if (charset && c_charset)
1879  cd = mutt_ch_iconv_open(c_charset, charset, MUTT_ICONV_HOOK_FROM);
1880  }
1881 
1882  fseeko(s->fp_in, b->offset, SEEK_SET);
1883  switch (b->encoding)
1884  {
1885  case ENC_QUOTED_PRINTABLE:
1886  decode_quoted(s, b->length,
1887  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1889  cd);
1890  break;
1891  case ENC_BASE64:
1892  mutt_decode_base64(s, b->length,
1893  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1895  cd);
1896  break;
1897  case ENC_UUENCODED:
1898  decode_uuencoded(s, b->length,
1899  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1901  cd);
1902  break;
1903  default:
1904  decode_xbit(s, b->length,
1905  istext || (((WithCrypto & APPLICATION_PGP) != 0) &&
1907  cd);
1908  break;
1909  }
1910 
1911  if (cd != (iconv_t) (-1))
1912  iconv_close(cd);
1913 }
static void decode_xbit(struct State *s, long len, bool istext, iconv_t cd)
Decode xbit-encoded text.
Definition: handler.c:162
#define WithCrypto
Definition: lib.h:113
static void decode_uuencoded(struct State *s, long len, bool istext, iconv_t cd)
Decode uuencoded text.
Definition: handler.c:363
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
static void decode_quoted(struct State *s, long len, bool istext, iconv_t cd)
Decode an attachment encoded with quoted-printable.
Definition: handler.c:299
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
Container for Accounts, Notifications.
Definition: neomutt.h:36
FILE * fp_in
File to read from.
Definition: state.h:46
void mutt_decode_base64(struct State *s, size_t len, bool istext, iconv_t cd)
Decode base64-encoded text.
Definition: handler.c:1505
iconv_t mutt_ch_iconv_open(const char *tocode, const char *fromcode, uint8_t flags)
Set up iconv for conversions.
Definition: charset.c:569
unsigned int disposition
content-disposition, ContentDisposition
Definition: body.h:67
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
char * mutt_ch_get_default_charset(void)
Get the default character set.
Definition: charset.c:442
#define APPLICATION_PGP
Use PGP to encrypt/sign.
Definition: lib.h:87
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
#define MUTT_ICONV_HOOK_FROM
apply charset-hooks to fromcode
Definition: charset.h:72
char * charset
Send mode: charset of attached file as stored on disk.
Definition: body.h:49
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
Definition: muttlib.c:434
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
Definition: crypt.c:565
Quoted-printable text.
Definition: mime.h:51
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:84
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Content is inline.
Definition: mime.h:62
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
UUEncoded text.
Definition: mime.h:54
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

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

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