Initial support for saving attachments to file

This commit is contained in:
Bobbi Webber-Manners 2020-07-01 19:48:22 -04:00
parent d2da9ddaec
commit 6a4889bf63

View File

@ -452,9 +452,14 @@ uint8_t hexdigit(char c) {
/* /*
* Decode linebuf[] from quoted-printable format and print on screen * Decode linebuf[] from quoted-printable format and print on screen
*/ */
void print_quoted_printable(void) { void decode_quoted_printable(FILE *fp, uint8_t binary) {
uint16_t i = 0; uint16_t i = 0;
char c; char c;
if (!fp) {
if (binary)
return;
fp = stdout;
}
while (c = linebuf[i]) { while (c = linebuf[i]) {
if (c == '=') { if (c == '=') {
if (linebuf[i + 1] == '\r') // Trailing '=' is a soft EOL if (linebuf[i + 1] == '\r') // Trailing '=' is a soft EOL
@ -462,29 +467,83 @@ void print_quoted_printable(void) {
// Otherwise '=xx' where x is a hex digit // Otherwise '=xx' where x is a hex digit
c = 16 * hexdigit(linebuf[i + 1]) + hexdigit(linebuf[i + 2]); c = 16 * hexdigit(linebuf[i + 1]) + hexdigit(linebuf[i + 2]);
if ((c >= 0x20) && (c <= 0x7e)) if ((c >= 0x20) && (c <= 0x7e))
putchar(c); fputc(c, fp);
i += 3; i += 3;
} else { } else {
putchar(c); fputc(c, fp);
++i; ++i;
} }
} }
} }
/* /*
* Decode linebuf[] from Base64 format and print on screen * Return value of character in Base64 encoding.
* Maybe a table is smaller/better?
*/ */
void print_base64(void) { uint32_t base64_char(char c) {
// TODO if ((c >= 'A') && (c <= 'Z'))
return c - 'A';
if ((c >= 'a') && (c <= 'z'))
return c - 'a' + 26;
if ((c >= '0') && (c <= '9'))
return c - '0' + 52;
if (c == '+')
return 62;
if (c == '/')
return 63;
if (c == '=') // Padding
return 0;
return 0; // Should never happen
}
/*
* Decode linebuf[] from Base64 format and print on screen
* Each line of base64 has up to 76 chars
*/
void decode_base64(FILE *fp, uint8_t binary) {
uint16_t i = 0, j = 0;
union {
uint32_t val;
char c[4];
} u;
if (!fp) {
if (binary)
return;
fp = stdout;
}
while (linebuf[i] != '\r') {
u.val = base64_char(linebuf[i]) << 18;
u.val |= base64_char(linebuf[i + 1]) << 12;
u.val |= base64_char(linebuf[i + 2]) << 6;
u.val |= base64_char(linebuf[i + 3]);
if (linebuf[i + 2] == '=') {
// Two padding chars 'xx=='
fputc(u.c[1], fp);
fputc(u.c[2], fp);
return;
}
if (linebuf[i + 1] == '=') {
// One padding char 'x==='
fputc(u.c[1], fp);
return;
}
fputc(u.c[2], fp);
fputc(u.c[1], fp);
fputc(u.c[0], fp);
i += 4;
}
} }
/* /*
* Display email with simple pager functionality * Display email with simple pager functionality
* Includes support for decoding MIME headers
*/ */
void email_pager(void) { void email_pager(void) {
uint32_t pos = 0; uint32_t pos = 0;
uint8_t *p = (uint8_t*)CURSORROW, mime = 0, mime_type = 0; uint8_t *p = (uint8_t*)CURSORROW, mime = 0;
struct emailhdrs *h = get_headers(selection); struct emailhdrs *h = get_headers(selection);
uint8_t mime_enc, mime_binary;
FILE *attachfp;
uint8_t eof; uint8_t eof;
char c; char c;
clrscr(); clrscr();
@ -497,6 +556,8 @@ void email_pager(void) {
pos = h->skipbytes; pos = h->skipbytes;
fseek(fp, pos, SEEK_SET); // Skip over headers fseek(fp, pos, SEEK_SET); // Skip over headers
restart: restart:
eof = 0;
attachfp = NULL;
clrscr(); clrscr();
fputs("Date: ", stdout); fputs("Date: ", stdout);
printfield(h->date, 0, 39); printfield(h->date, 0, 39);
@ -513,40 +574,50 @@ restart:
fputs("\n\n", stdout); fputs("\n\n", stdout);
get_line(fp, 1); // Reset buffer get_line(fp, 1); // Reset buffer
while (1) { while (1) {
if (get_line(fp, 0) == -1) if (get_line(fp, 0) == -1) {
eof = 1; eof = 1;
else { } else {
if ((mime >= 1) && (!strncmp(linebuf, "--", 2))) { if ((mime >= 1) && (!strncmp(linebuf, "--", 2))) {
mime = 2; mime = 2;
mime_type = 0; mime_enc = 0;
} else if ((mime >= 2) && (!strncmp(linebuf, "Content-Type: ", 14))) { mime_binary = 0;
if ((!strncmp(linebuf + 14, "text/plain", 10)) || } else if ((mime >= 2) && (!strncasecmp(linebuf, "Content-Type: ", 14))) {
(!strncmp(linebuf + 14, "text/html", 9))) { if (!strncmp(linebuf + 14, "text/plain", 10))
mime = 3; mime = 3;
} else { else if (!strncmp(linebuf + 14, "text/html", 9)) {
printf("Unsupp content %s\n", linebuf + 14); printf("\n<Not showing HTML>\n");
mime = 1; mime = 1;
} else {
mime_binary = 1;
mime = 3;
} }
} else if ((mime >= 2) && (!strncmp(linebuf, "Content-Transfer-Encoding: ", 27))) { } else if ((mime >= 2) && (!strncasecmp(linebuf, "Content-Transfer-Encoding: ", 27))) {
mime = 3; mime = 3;
if (!strncmp(linebuf + 27, "7bit", 4)) if (!strncmp(linebuf + 27, "7bit", 4))
mime_type = 0; mime_enc = 0;
else if (!strncmp(linebuf + 27, "quoted-printable", 16)) else if (!strncmp(linebuf + 27, "quoted-printable", 16))
mime_type = 1; mime_enc = 1;
else if (!strncmp(linebuf + 27, "base64", 6)) else if (!strncmp(linebuf + 27, "base64", 6))
mime_type = 2; mime_enc = 2;
else { else {
printf("Unsupp encoding %s\n", linebuf + 27); printf("** Unsupp encoding %s\n", linebuf + 27);
mime = 1; mime = 1;
} }
} else if ((mime >= 2) && (strstr(linebuf, "filename="))) {
sprintf(filename, "%s/ATTACHMENTS/%s", cfg_emaildir, strstr(linebuf, "filename=") + 9);
filename[strlen(filename) - 1] = '\0'; // Remove '\r'
printf("** Attachment -> %s\n", filename);
attachfp = fopen(filename, "wb"); // TODO MUST CLOSE THIS TOO !!
if (!attachfp)
printf("** Can't open %s\n", filename);
} else if ((mime == 3) && (!strncmp(linebuf, "\r", 1))) } else if ((mime == 3) && (!strncmp(linebuf, "\r", 1)))
mime = 4; mime = 4;
if ((mime == 0) || ((mime == 4) && (mime_type == 0))) if ((mime == 0) || ((mime == 4) && (mime_enc == 0)))
fputs(linebuf, stdout); fputs(linebuf, stdout);
else if ((mime == 4) && (mime_type == 1)) else if ((mime == 4) && (mime_enc == 1))
print_quoted_printable(); decode_quoted_printable(attachfp, mime_binary);
else if ((mime == 4) && (mime_type == 2)) else if ((mime == 4) && (mime_enc == 2))
print_base64(); decode_base64(attachfp, mime_binary);
} }
if ((*p) == 22) { // Use the CURSOR ROW location if ((*p) == 22) { // Use the CURSOR ROW location
putchar(INVERSE); putchar(INVERSE);