mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-11-17 15:07:30 +00:00
Updates to email_pager() / wrap_line_mime() are *mostly* working now
This commit is contained in:
parent
c4c80165c2
commit
4231d627b9
316
apps/email.c
316
apps/email.c
@ -620,45 +620,29 @@ void putline(FILE *fp, char *s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform word wrapping, for a line of text, which may contain embedded '\r'
|
* Perform word wrapping for a line of plain text. For each call, this function
|
||||||
* carriage returns, perform word-wrapping. For each call, this function will
|
* will output one line of text (or a partial line if there is not enough input).
|
||||||
* output one line of text (or a partial line if there is not enough input).
|
|
||||||
* fp - File handle to use for output.
|
* fp - File handle to use for output.
|
||||||
* s - Pointer to pointer to input buffer. If all text is consumed, this is
|
* s - Pointer to pointer to input buffer. If all text is consumed, this is
|
||||||
* set to NULL. If there is text left in the buffer to be consumed then
|
* set to NULL. If there is text left in the buffer to be consumed then
|
||||||
* the pointer will be advanced to point to the next text to process.
|
* the pointer will be advanced to point to the next text to process.
|
||||||
* mime - Set to 1 if we are wrapping content which was decoded from
|
|
||||||
* Quoted-Printable or Base64. In this case line does not necessarily
|
|
||||||
* end in EOL.
|
|
||||||
*/
|
*/
|
||||||
void word_wrap_line(FILE *fp, char **s, uint8_t mime) {
|
void word_wrap_line_plaintext(FILE *fp, char **s) {
|
||||||
static uint8_t col = 0; // Keeps track of screen column
|
static uint8_t col = 0; // Keeps track of screen column
|
||||||
char *ss = *s;
|
char *ss = *s;
|
||||||
char *ret = strchr(ss, '\r');
|
|
||||||
uint16_t l = strlen(ss);
|
uint16_t l = strlen(ss);
|
||||||
char *nextline = NULL;
|
char *nextline = NULL;
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
if (ret) {
|
if (col + l <= 80) { // Fits on this line
|
||||||
if (l >= (ret - ss) + 1) // If '\r' is not at the end ...
|
|
||||||
nextline = ss + (ret - ss) + 1; // Keep track of next line(s)
|
|
||||||
l = ret - ss;
|
|
||||||
}
|
|
||||||
if ((!mime && (col + l <= 80)) ||
|
|
||||||
(mime && ret && (col + l) <= 80)) { // Fits on this line
|
|
||||||
// if (col + l <= 80) { // Fits on this line
|
|
||||||
col += l;
|
col += l;
|
||||||
putline(fp, ss);
|
putline(fp, ss);
|
||||||
if (ret) {
|
col = 0;
|
||||||
col = 0;
|
if (col + l != 80)
|
||||||
if (col + l != 80)
|
fputc('\r', fp);
|
||||||
fputc('\r', fp);
|
*s = NULL;
|
||||||
}
|
|
||||||
*s = nextline;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i = 80 - col; // Doesn't fit, need to break
|
i = 80 - col; // Doesn't fit, need to break
|
||||||
if (i > l)
|
|
||||||
i = l;
|
|
||||||
while ((ss[--i] != ' ') && (i > 0));
|
while ((ss[--i] != ' ') && (i > 0));
|
||||||
if (i == 0) { // No space character found
|
if (i == 0) { // No space character found
|
||||||
if (col == 0) // Doesn't fit on full line
|
if (col == 0) // Doesn't fit on full line
|
||||||
@ -677,6 +661,85 @@ void word_wrap_line(FILE *fp, char **s, uint8_t mime) {
|
|||||||
*s = ss + i + 1;
|
*s = ss + i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform word wrapping, for a line of MIME decoded text, which may contain
|
||||||
|
* multiple embedded '\r' carriage returns, or no carriage return at all.
|
||||||
|
* fp - File handle to use for output.
|
||||||
|
* s - Pointer to pointer to input buffer. If all text is consumed, this is
|
||||||
|
* set to NULL. If there is text left in the buffer to be consumed then
|
||||||
|
* the pointer will be advanced to point to the next text to process.
|
||||||
|
* Returns 1 if the caller should invoke the routine again before obtaining
|
||||||
|
* more input, or 0 if there is nothing more to do or caller needs to get more
|
||||||
|
* input before next call.
|
||||||
|
*/
|
||||||
|
uint8_t word_wrap_line_mime(FILE *fp, char **s) {
|
||||||
|
static uint8_t col = 0; // Keeps track of screen column
|
||||||
|
char *ss = *s;
|
||||||
|
char *ret = strchr(ss, '\r');
|
||||||
|
uint16_t l = strlen(ss);
|
||||||
|
char *nextline = NULL;
|
||||||
|
uint16_t i;
|
||||||
|
if (l == 0)
|
||||||
|
return 0; // Need more input to proceed
|
||||||
|
//printf("word_wrap_line_mine l=%d\n", l);
|
||||||
|
if (ret) {
|
||||||
|
//printf("RET l=%d rhs=%d\n", l, (ret - ss) + 1);
|
||||||
|
if (l > (ret - ss) + 1) // If '\r' is not at the end ...
|
||||||
|
nextline = ss + (ret - ss) + 1; // Keep track of next line(s)
|
||||||
|
l = ret - ss;
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
//printf("RET");
|
||||||
|
if ((col + l) <= 80) { // Fits on this line
|
||||||
|
//printf("FITS\n");
|
||||||
|
col += l;
|
||||||
|
putline(fp, ss);
|
||||||
|
if (ret) {
|
||||||
|
col = 0;
|
||||||
|
if (col + l != 80)
|
||||||
|
fputc('\r', fp);
|
||||||
|
}
|
||||||
|
//printf("\nnextline=%p\n", nextline);
|
||||||
|
*s = nextline;
|
||||||
|
return (*s ? 1 : 0); // Caller should invoke again
|
||||||
|
}
|
||||||
|
//printf("NOFIT");
|
||||||
|
i = 80 - col; // Doesn't fit, need to break
|
||||||
|
if (i > l)
|
||||||
|
i = l;
|
||||||
|
while ((ss[--i] != ' ') && (i > 0));
|
||||||
|
if (i == 0) { // No space character found
|
||||||
|
//printf("NOSPC\n");
|
||||||
|
if (col == 0) // Doesn't fit on full line
|
||||||
|
for (i = 0; i < 80; ++i) { // Truncate @80 chars
|
||||||
|
fputc(ss[i], fp);
|
||||||
|
*s = ss + l + 1;
|
||||||
|
} else // There is stuff on this line already
|
||||||
|
fputc('\r', fp); // Try a blank line
|
||||||
|
col = 0;
|
||||||
|
return (ret ? (*s ? 0 : 1) : 0); // If EOL, caller should invoke again
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//printf("NORET");
|
||||||
|
// No EOL
|
||||||
|
i = 80 - col; // Doesn't fit, need to break
|
||||||
|
if (i > l)
|
||||||
|
i = l;
|
||||||
|
while ((ss[--i] != ' ') && (i > 0));
|
||||||
|
if (i == 0) { // No space character found
|
||||||
|
//printf("NOSPC\n");
|
||||||
|
return 0; // Need more input to proceed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("SPC %d\n", i);
|
||||||
|
ss[i] = '\0'; // Space was found, split line
|
||||||
|
putline(fp, ss);
|
||||||
|
fputc('\r', fp);
|
||||||
|
col = 0;
|
||||||
|
*s = ss + i + 1;
|
||||||
|
return (*s ? 1 : 0); // Caller should invoke again
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OK to d/l attachment?
|
* OK to d/l attachment?
|
||||||
*/
|
*/
|
||||||
@ -792,7 +855,7 @@ void email_pager(struct emailhdrs *h) {
|
|||||||
FILE *attachfp;
|
FILE *attachfp;
|
||||||
uint16_t linecount, chars;
|
uint16_t linecount, chars;
|
||||||
uint8_t mime_enc, mime_binary, eof, screennum, maxscreennum;
|
uint8_t mime_enc, mime_binary, eof, screennum, maxscreennum;
|
||||||
char c, *readp;
|
char c, *readp, *writep;
|
||||||
clrscr2();
|
clrscr2();
|
||||||
sprintf(filename, "%s/%s/EMAIL.%u", cfg_emaildir, curr_mbox, h->emailnum);
|
sprintf(filename, "%s/%s/EMAIL.%u", cfg_emaildir, curr_mbox, h->emailnum);
|
||||||
fp = fopen(filename, "rb");
|
fp = fopen(filename, "rb");
|
||||||
@ -808,6 +871,7 @@ restart:
|
|||||||
eof = 0;
|
eof = 0;
|
||||||
linecount = 0;
|
linecount = 0;
|
||||||
readp = linebuf;
|
readp = linebuf;
|
||||||
|
writep = linebuf;
|
||||||
attachfp = NULL;
|
attachfp = NULL;
|
||||||
if (sbackfp)
|
if (sbackfp)
|
||||||
fclose(sbackfp);
|
fclose(sbackfp);
|
||||||
@ -836,11 +900,15 @@ restart:
|
|||||||
fputs("\n\n", stdout);
|
fputs("\n\n", stdout);
|
||||||
get_line(fp, 1, linebuf, &pos); // Reset buffer
|
get_line(fp, 1, linebuf, &pos); // Reset buffer
|
||||||
while (1) {
|
while (1) {
|
||||||
readp = linebuf;
|
if (!readp)
|
||||||
if (get_line(fp, 0, readp, &pos) == -1)
|
readp = linebuf;
|
||||||
|
if (!writep)
|
||||||
|
writep = linebuf;
|
||||||
|
//printf("READ W=%p R=%p\n", writep, readp);
|
||||||
|
if (get_line(fp, 0, writep, &pos) == -1)
|
||||||
eof = 1;
|
eof = 1;
|
||||||
++linecount;
|
++linecount;
|
||||||
if ((mime >= 1) && (!strncmp(readp, "--", 2))) {
|
if ((mime >= 1) && (!strncmp(writep, "--", 2))) {
|
||||||
if (attachfp)
|
if (attachfp)
|
||||||
fclose(attachfp);
|
fclose(attachfp);
|
||||||
if ((mime == 4) && mime_binary) {
|
if ((mime == 4) && mime_binary) {
|
||||||
@ -851,33 +919,33 @@ restart:
|
|||||||
mime = 2;
|
mime = 2;
|
||||||
mime_enc = ENC_7BIT;
|
mime_enc = ENC_7BIT;
|
||||||
mime_binary = 0;
|
mime_binary = 0;
|
||||||
readp = NULL; // Read next line from disk
|
readp = writep = NULL;
|
||||||
} else if ((mime < 4) && (mime >= 2)) {
|
} else if ((mime < 4) && (mime >= 2)) {
|
||||||
if (!strncasecmp(readp, "Content-Type: ", 14)) {
|
if (!strncasecmp(writep, "Content-Type: ", 14)) {
|
||||||
if (!strncmp(readp + 14, "text/plain", 10)) {
|
if (!strncmp(writep + 14, "text/plain", 10)) {
|
||||||
mime = 3;
|
mime = 3;
|
||||||
} else if (!strncmp(readp + 14, "text/html", 9)) {
|
} else if (!strncmp(writep + 14, "text/html", 9)) {
|
||||||
printf("\n<Not showing HTML>\n");
|
printf("\n<Not showing HTML>\n");
|
||||||
mime = 1;
|
mime = 1;
|
||||||
} else {
|
} else {
|
||||||
mime_binary = 1;
|
mime_binary = 1;
|
||||||
mime = 3;
|
mime = 3;
|
||||||
}
|
}
|
||||||
} else if (!strncasecmp(readp, "Content-Transfer-Encoding: ", 27)) {
|
} else if (!strncasecmp(writep, "Content-Transfer-Encoding: ", 27)) {
|
||||||
mime = 3;
|
mime = 3;
|
||||||
if (!strncmp(readp + 27, "7bit", 4))
|
if (!strncmp(writep + 27, "7bit", 4))
|
||||||
mime_enc = ENC_7BIT;
|
mime_enc = ENC_7BIT;
|
||||||
else if (!strncmp(readp + 27, "quoted-printable", 16))
|
else if (!strncmp(writep + 27, "quoted-printable", 16))
|
||||||
mime_enc = ENC_QP;
|
mime_enc = ENC_QP;
|
||||||
else if (!strncmp(readp + 27, "base64", 6))
|
else if (!strncmp(writep + 27, "base64", 6))
|
||||||
mime_enc = ENC_B64;
|
mime_enc = ENC_B64;
|
||||||
else {
|
else {
|
||||||
printf("** Unsupp encoding %s\n", readp + 27);
|
printf("** Unsupp encoding %s\n", writep + 27);
|
||||||
mime = 1;
|
mime = 1;
|
||||||
}
|
}
|
||||||
} else if (strstr(readp, "filename=")) {
|
} else if (strstr(writep, "filename=")) {
|
||||||
sprintf(filename, "%s/ATTACHMENTS/%s",
|
sprintf(filename, "%s/ATTACHMENTS/%s",
|
||||||
cfg_emaildir, strstr(readp, "filename=") + 9);
|
cfg_emaildir, strstr(writep, "filename=") + 9);
|
||||||
sanitize_filename(filename);
|
sanitize_filename(filename);
|
||||||
if (prompt_okay_attachment(filename)) {
|
if (prompt_okay_attachment(filename)) {
|
||||||
printf("** Attachment -> %s ", filename);
|
printf("** Attachment -> %s ", filename);
|
||||||
@ -886,115 +954,125 @@ restart:
|
|||||||
printf("\n** Can't open %s ", filename);
|
printf("\n** Can't open %s ", filename);
|
||||||
} else
|
} else
|
||||||
attachfp = NULL;
|
attachfp = NULL;
|
||||||
} else if ((mime == 3) && (!strncmp(readp, "\r", 1))) {
|
} else if ((mime == 3) && (!strncmp(writep, "\r", 1))) {
|
||||||
mime = 4;
|
mime = 4;
|
||||||
if (!attachfp && mime_binary) {
|
if (!attachfp && mime_binary) {
|
||||||
mime_enc = ENC_SKIP; // Skip over binary MIME parts with no filename
|
mime_enc = ENC_SKIP; // Skip over binary MIME parts with no filename
|
||||||
fputs("Skipping ", stdout);
|
fputs("Skipping ", stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
readp = NULL; // Read next line from disk
|
readp = writep = NULL;
|
||||||
} else if (mime == 4) {
|
} else if (mime == 4) {
|
||||||
switch (mime_enc) {
|
switch (mime_enc) {
|
||||||
case ENC_QP:
|
case ENC_QP:
|
||||||
chars = decode_quoted_printable(readp);
|
chars = decode_quoted_printable(writep);
|
||||||
break;
|
break;
|
||||||
case ENC_B64:
|
case ENC_B64:
|
||||||
chars = decode_base64(readp);
|
chars = decode_base64(writep);
|
||||||
break;
|
break;
|
||||||
case ENC_SKIP:
|
case ENC_SKIP:
|
||||||
readp = NULL; // Read next line from disk
|
readp = writep = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (mime_binary && !(linecount % 10))
|
if (mime_binary && !(linecount % 10))
|
||||||
spinner();
|
spinner();
|
||||||
}
|
}
|
||||||
do {
|
if (readp) {
|
||||||
if (readp) {
|
if (mime == 0) {
|
||||||
if (mime == 0)
|
while (readp)
|
||||||
word_wrap_line(stdout, &readp, 0);
|
word_wrap_line_plaintext(stdout, &readp);
|
||||||
if (mime == 1)
|
writep = NULL;
|
||||||
readp = NULL;
|
}
|
||||||
if (mime == 4) {
|
if (mime == 1) {
|
||||||
if (mime_binary) {
|
readp = writep = NULL;
|
||||||
if (attachfp)
|
}
|
||||||
fwrite(readp, 1, chars, attachfp);
|
if (mime == 4) {
|
||||||
readp = 0;
|
if (mime_binary) {
|
||||||
} else {
|
if (attachfp)
|
||||||
word_wrap_line(stdout, &readp, 0 /* 1 */);
|
fwrite(readp, 1, chars, attachfp);
|
||||||
}
|
readp = writep = NULL;
|
||||||
|
} else {
|
||||||
|
//while (word_wrap_line_mime(stdout, &readp));
|
||||||
|
do {
|
||||||
|
c = word_wrap_line_mime(stdout, &readp);
|
||||||
|
cgetc(); //DEBUG
|
||||||
|
} while (c == 1);
|
||||||
|
if (readp)
|
||||||
|
writep += chars;
|
||||||
|
else
|
||||||
|
writep = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((*cursorrow == 22) || eof) {
|
}
|
||||||
printf("\n%c[%05lu] %s | B)ack | T)op | H)drs | M)IME | Q)uit%c",
|
if ((*cursorrow == 22) || eof) {
|
||||||
INVERSE,
|
printf("\n%c[%05lu] %s | B)ack | T)op | H)drs | M)IME | Q)uit%c",
|
||||||
pos,
|
INVERSE,
|
||||||
(eof ? " ** END ** " : "SPACE continue reading"),
|
pos,
|
||||||
NORMAL);
|
(eof ? " ** END ** " : "SPACE continue reading"),
|
||||||
if (sbackfp) {
|
NORMAL);
|
||||||
save_screen_to_scrollback(sbackfp);
|
if (sbackfp) {
|
||||||
++screennum;
|
save_screen_to_scrollback(sbackfp);
|
||||||
++maxscreennum;
|
++screennum;
|
||||||
}
|
++maxscreennum;
|
||||||
|
}
|
||||||
retry:
|
retry:
|
||||||
c = cgetc();
|
c = cgetc();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ' ':
|
case ' ':
|
||||||
if (sbackfp && (screennum < maxscreennum)) {
|
if (sbackfp && (screennum < maxscreennum)) {
|
||||||
load_screen_from_scrollback(sbackfp, ++screennum);
|
load_screen_from_scrollback(sbackfp, ++screennum);
|
||||||
goto retry;
|
goto retry;
|
||||||
} else {
|
} else {
|
||||||
if (eof) {
|
if (eof) {
|
||||||
putchar(BELL);
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'B':
|
|
||||||
case 'b':
|
|
||||||
if (sbackfp && (screennum > 1)) {
|
|
||||||
load_screen_from_scrollback(sbackfp, --screennum);
|
|
||||||
goto retry;
|
|
||||||
} else {
|
|
||||||
putchar(BELL);
|
putchar(BELL);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 'T':
|
|
||||||
case 't':
|
|
||||||
mime = 0;
|
|
||||||
pos = h->skipbytes;
|
|
||||||
fseek(fp, pos, SEEK_SET);
|
|
||||||
goto restart;
|
|
||||||
break;
|
|
||||||
case 'H':
|
|
||||||
case 'h':
|
|
||||||
mime = 0;
|
|
||||||
pos = 0;
|
|
||||||
fseek(fp, pos, SEEK_SET);
|
|
||||||
goto restart;
|
|
||||||
break;
|
break;
|
||||||
case 'M':
|
case 'B':
|
||||||
case 'm':
|
case 'b':
|
||||||
mime = 1;
|
if (sbackfp && (screennum > 1)) {
|
||||||
pos = h->skipbytes;
|
load_screen_from_scrollback(sbackfp, --screennum);
|
||||||
fseek(fp, pos, SEEK_SET);
|
goto retry;
|
||||||
goto restart;
|
} else {
|
||||||
case 'Q':
|
|
||||||
case 'q':
|
|
||||||
if (attachfp)
|
|
||||||
fclose(attachfp);
|
|
||||||
if (sbackfp)
|
|
||||||
fclose(sbackfp);
|
|
||||||
fclose(fp);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
putchar(BELL);
|
putchar(BELL);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
clrscr2();
|
break;
|
||||||
|
case 'T':
|
||||||
|
case 't':
|
||||||
|
mime = 0;
|
||||||
|
pos = h->skipbytes;
|
||||||
|
fseek(fp, pos, SEEK_SET);
|
||||||
|
goto restart;
|
||||||
|
break;
|
||||||
|
case 'H':
|
||||||
|
case 'h':
|
||||||
|
mime = 0;
|
||||||
|
pos = 0;
|
||||||
|
fseek(fp, pos, SEEK_SET);
|
||||||
|
goto restart;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
case 'm':
|
||||||
|
mime = 1;
|
||||||
|
pos = h->skipbytes;
|
||||||
|
fseek(fp, pos, SEEK_SET);
|
||||||
|
goto restart;
|
||||||
|
case 'Q':
|
||||||
|
case 'q':
|
||||||
|
if (attachfp)
|
||||||
|
fclose(attachfp);
|
||||||
|
if (sbackfp)
|
||||||
|
fclose(sbackfp);
|
||||||
|
fclose(fp);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
putchar(BELL);
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
} while (readp);
|
clrscr2();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user