Tasmota/lib/libesp32/ESP32-Mail-Client/src/RFC2047.cpp
2020-10-26 12:51:06 +00:00

240 lines
3.5 KiB
C++
Executable File

#ifndef RFC2047_CPP
#define RFC2047_CPP
#ifdef ESP32
#include "RFC2047.h"
RFC2047::RFC2047(){}
void RFC2047::rfc2047Decode(char *d, const char *s, size_t dlen){
const char *p, *q;
size_t n;
int found_encoded = 0;
dlen--; /* save room for the terminal nul */
while (*s && dlen > 0)
{
if ((p = strstr (s, "=?")) == NULL ||
(q = strchr (p + 2, '?')) == NULL ||
(q = strchr (q + 1, '?')) == NULL ||
(q = strstr (q + 1, "?=")) == NULL)
{
/* no encoded words */
if (d != s)
strfcpy (d, s, dlen + 1);
return;
}
if (p != s)
{
n = (size_t) (p - s);
/* ignore spaces between encoded words */
if (!found_encoded || strspn (s, " \t\r\n") != n)
{
if (n > dlen)
n = dlen;
if (d != s)
memcpy (d, s, n);
d += n;
dlen -= n;
}
}
rfc2047DecodeWord (d, p, dlen);
found_encoded = 1;
s = q + 2;
n = strlen (d);
dlen -= n;
d += n;
}
*d = 0;
}
void RFC2047::rfc2047DecodeWord(char *d, const char *s, size_t dlen){
char *p = safe_strdup (s);
char *pp = p;
char *pd = d;
size_t len = dlen;
int enc = 0, filter = 0, count = 0, c1, c2, c3, c4;
while ((pp = strtok (pp, "?")) != NULL)
{
count++;
switch (count)
{
case 2:
if (strcasecmp (pp, Charset) != 0)
{
filter = 1;
}
break;
case 3:
if (toupper (*pp) == 'Q')
enc = ENCQUOTEDPRINTABLE;
else if (toupper (*pp) == 'B')
enc = ENCBASE64;
else
return;
break;
case 4:
if (enc == ENCQUOTEDPRINTABLE)
{
while (*pp && len > 0)
{
if (*pp == '_')
{
*pd++ = ' ';
len--;
}
else if (*pp == '=')
{
*pd++ = (hexval(pp[1]) << 4) | hexval(pp[2]);
len--;
pp += 2;
}
else
{
*pd++ = *pp;
len--;
}
pp++;
}
*pd = 0;
}
else if (enc == ENCBASE64)
{
while (*pp && len > 0)
{
c1 = base64val(pp[0]);
c2 = base64val(pp[1]);
*pd++ = (c1 << 2) | ((c2 >> 4) & 0x3);
if (--len == 0) break;
if (pp[2] == '=') break;
c3 = base64val(pp[2]);
*pd++ = ((c2 & 0xf) << 4) | ((c3 >> 2) & 0xf);
if (--len == 0)
break;
if (pp[3] == '=')
break;
c4 = base64val(pp[3]);
*pd++ = ((c3 & 0x3) << 6) | c4;
if (--len == 0)
break;
pp += 4;
}
*pd = 0;
}
break;
}
pp = 0;
}
safe_free (&p);
if (filter)
{
pd = d;
while (*pd)
{
if (!IsPrint (*pd))
*pd = '?';
pd++;
}
}
return;
}
void *RFC2047::safe_calloc (size_t nmemb, size_t size)
{
void *p;
if (!nmemb || !size)
return NULL;
if (!(p = calloc (nmemb, size)))
{
//out of memory
return NULL;
}
return p;
}
void *RFC2047::safe_malloc (unsigned int siz)
{
void *p;
if (siz == 0)
return 0;
if ((p = (void *) malloc (siz)) == 0)
{
//out of memory
return NULL;
}
return (p);
}
void RFC2047::safe_realloc (void **p, size_t siz)
{
void *r;
if (siz == 0)
{
if (*p)
{
free (*p);
*p = NULL;
}
return;
}
if (*p)
r = (void *) realloc (*p, siz);
else
{
r = (void *) malloc (siz);
}
if (!r)
{
//out of memory
return;
}
*p = r;
}
void RFC2047::safe_free (void *ptr)
{
void **p = (void **)ptr;
if (*p)
{
free (*p);
*p = 0;
}
}
char *RFC2047::safe_strdup (const char *s)
{
char *p;
size_t l;
if (!s || !*s) return 0;
l = strlen (s) + 1;
p = (char *)safe_malloc (l);
memcpy (p, s, l);
return (p);
}
#endif //ESP32
#endif //RFC2047_CPP