rohrpost

A commandline mail client to change the world as we see it.
git clone git://r-36.net/rohrpost
Log | Files | Refs | LICENSE

commit 1d75e5542ed2feff99e7ef2aa2108a679fa7460c
parent e7a3f1cfb83fe1477038016bb6a574f49d62239c
Author: Christoph Lohmann <20h@r-36.net>
Date:   Sun, 16 Feb 2014 22:50:09 +0100

Many changes at once, sorry.

1.) mime.c is now able to parse boundaries surrounded just by LF.
2.) Add some more descriptive comments to ind.c
3.) Fix quote.c to convert CRLF to LF.
4.) Add a plain conversion from CRLF to LF in »text/« mime types.
5.) Remove the print.c from the tests. This must have been gone. I will
    somewhen redo it.

Diffstat:
Makefile | 2+-
dos.c | 39+++++++++++++++++++++++++++++++++++++++
dos.h | 13+++++++++++++
ind.c | 7+++++++
mime.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
quote.c | 13++++++++-----
test/Makefile | 4++--
test/mimetest.c | 4++--
test/printtest.c | 3---
9 files changed, 153 insertions(+), 24 deletions(-)

diff --git a/Makefile b/Makefile @@ -7,7 +7,7 @@ SRC = ${NAME}.c ind.c llist.c cfg.c txtdb.c mark.c cur.c \ select.c sieve.c net.c base64.c strio.c parser.c pager.c \ mime.c folder.c imap.c inc.c stats.c capability.c pick.c \ flag.c copy.c remove.c scan.c quote.c view.c \ - param.c part.c add.c ids.c util.c path.c + param.c part.c add.c ids.c util.c path.c dos.c OBJ = ${SRC:.c=.o} diff --git a/dos.c b/dos.c @@ -0,0 +1,39 @@ +/* + * Copy me if you can. + * by 20h + */ + +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +#include "ind.h" + +char * +dosenc(char *str, int l) +{ + /* To be implemented. */ + return str; +} + +char * +dosdec(char *str, int *len) +{ + char *ret; + int i, rlen; + + ret = NULL; + for (i = 0, rlen = 0; i < *len; i++) { + if (str[i] == '\r' && i < (*len)-1 && str[i+1] == '\n') + continue; + + ret = reallocz(ret, (++rlen)+1, 0); + ret[rlen-1] = str[i]; + ret[rlen] = '\0'; + } + *len = rlen; + + return ret; +} + diff --git a/dos.h b/dos.h @@ -0,0 +1,13 @@ +/* + * Copy me if you can. + * by 20h + */ + +#ifndef __DOS_H__ +#define __DOS_H__ + +char *dosenc(char *str, int l); +char *dosdec(char *str, int *len); + +#endif + diff --git a/ind.c b/ind.c @@ -393,6 +393,9 @@ readstdin(int *len) return readtoeof(stdin, len); } +/* + * Get line from string buffer. + */ char * sgets(char *s, int size, char **p) { @@ -479,6 +482,10 @@ strisascii(char *str) return 1; } +/* + * Find a whitespace character in a certain limit. This is used for formatting + * mail to a certain width. + */ char * findlimitws(char *str, int limit) { diff --git a/mime.c b/mime.c @@ -20,6 +20,7 @@ #include "base64.h" #include "quote.h" #include "param.h" +#include "dos.h" char *argv0; @@ -496,6 +497,9 @@ mime_paramsort(llistelem_t *elem1, llistelem_t *elem2) return a - b; } +/* + * Order and concatenate ordered params. + */ llist_t * mime_sanitizeparams(llist_t *params) { @@ -535,6 +539,9 @@ mime_sanitizeparams(llist_t *params) nvalue[0] = '*'; } + /* + * Sort and concatenate the return list. + */ forllist(reorder, param) { hits = llist_new(); forllist(params, nparam) { @@ -572,6 +579,7 @@ mime_parseheader(char *field) { char *tok, *buf, *key, *value, *sep, *eq, quot; llist_t *ret; + int tlen; buf = memdup(field, strlen(field)+1); @@ -581,8 +589,16 @@ mime_parseheader(char *field) key = NULL; value = NULL; + /* + * 0.) Sanitize the beginning and the end. + */ while (isspace(tok[0])) tok++; + tlen = strlen(tok); + while (isspace(tok[tlen-1])) { + tok[tlen-1] = '\0'; + tlen--; + } /* * 1.) ([\t\r\v\f ]*)key @@ -718,13 +734,18 @@ char * mime_sgetbound(char *bound, char **p, char *max, int *len, int *choice) { char *ret, *op; - int slen, foundit; + int slen, foundit, isnl, isend, beginning; ret = NULL; + //printf("bound = '%s'\n", bound); + //printf("p = '%s'\n", *p); slen = strlen(bound); *choice = 0; foundit = 0; + isnl = 0; + beginning = 0; + isend = 0; for (op = *p; op < max; op++) { /* * Handling invalid nested boundaries. @@ -734,12 +755,25 @@ mime_sgetbound(char *bound, char **p, char *max, int *len, int *choice) */ if (op == *p && op+slen < max && !strncmp(op, bound, slen)) { + //printf("boundary: non-standard.\n"); if (!strncmp(op+slen, "--\r\n", 4)) { - foundit = 4; + foundit = 1; + isend = 1; + break; + } + if (!strncmp(op+slen, "--\n", 3)) { + isend = 1; + foundit = 1; + isnl = 1; break; } if (!strncmp(op+slen, "\r\n", 2)) { - foundit = 3; + foundit = 1; + break; + } + if (!strncmp(op+slen, "\n", 1)) { + foundit = 1; + isnl = 1; break; } } @@ -749,24 +783,52 @@ mime_sgetbound(char *bound, char **p, char *max, int *len, int *choice) */ if (!strncmp(op, "\r\n", 2) && op+2+slen < max && !strncmp(op+2, bound, slen)) { + //printf("boundary: standard '\\r\\n'.\n"); if (!strncmp(op+2+slen, "--\r\n", 4)) { - foundit = 2; + isend = 1; + foundit = 1; + beginning = 1; break; } if (!strncmp(op+2+slen, "\r\n", 2)) { foundit = 1; + beginning = 1; + break; + } + } + + if (!strncmp(op, "\n", 1) && op+1+slen < max + && !strncmp(op+1, bound, slen)) { + //printf("boundary: standard '\\n'.\n"); + if (!strncmp(op+1+slen, "--\n", 3)) { + isend = 1; + foundit = 1; + isnl = 1; + beginning = 1; + break; + } + if (!strncmp(op+1+slen, "\n", 1)) { + foundit = 1; + isnl = 1; + beginning = 1; break; } } } if (foundit) { - if (!(foundit % 2)) { + //printf("foundit = %d, shortending = %d, beginning = %d\n", + // foundit, shortending, beginning); + if (isend) { *choice = 1; slen += 2; } + *len = op - *p; ret = memdupz(*p, *len); - *p = op + ((foundit > 2)? 2 : 4) + slen; + + *p = op + (1 + beginning) * (2 - isnl) + slen; + + //printf("p = '%s'\n", *p); } return ret; @@ -835,14 +897,14 @@ mime_parsebufintern(mime_t *mime, char *str, int len) switch (mime->state) { case HEADERVALUE: - //printf("hdrvalue: %s (%d)\n", buf, (int)strlen(buf)); - switch (buf[0]) { case ' ': case '\t': case '\r': case '\f': case '\v': + //printf("hdrvalue: %s (%d)\n", buf, + // (int)strlen(buf)); /* * " value" */ @@ -897,7 +959,9 @@ mime_parsebufintern(mime_t *mime, char *str, int len) tvalue = NULL; sscanf(buf, "%1024m[^: \t\r\v\f]:" "%1024m[^\n]", &key, &value); - //printf("%s = %s\n", key, tvalue); + if (value == NULL) + value = memdupz(" ", 2); + //printf("%s = %s\n", key, value); if (key != NULL && value != NULL) { tvalue = value + strspn(value, " \t\r\v\f"); @@ -931,7 +995,7 @@ mimeparsebufbodyparse: partlen = str - p + len; mime->body = memdupz(p, partlen); mime->bodylen = partlen; - //printf("strlen = %d; partlen = %d;\n", strlen(mime->body), + //printf("strlen = %ld; partlen = %d;\n", strlen(mime->body), // partlen); //printf("mime->body = \"%s\"\n", mime->body); @@ -1177,14 +1241,20 @@ mime_decodepartencoding(mime_t *mime, int *len) { char *ret; + printf("ct = %s\n", mime->ct); + printf("cte = %s\n", mime->cte); ret = NULL; - if (!strcasecmp(mime->cte, "base64")) { *len = mime->bodylen; ret = b64dec(mime->body, len); } else if (!strcasecmp(mime->cte, "quoted-printable")) { *len = mime->bodylen; ret = qpdec(mime->body, len, 0); + } else if (!strncasecmp(mime->ct, "text/", 5)) { + /* Convert CRLF to LF. */ + printf("Text encoding.\n"); + *len = mime->bodylen; + ret = dosdec(mime->body, len); } if (ret == NULL && mime->body != NULL && mime->bodylen > 0) { diff --git a/quote.c b/quote.c @@ -85,10 +85,7 @@ qpdec(char *str, int *len, int ishdr) add = '\0'; switch (str[i]) { case '_': - if (ishdr) - add = ' '; - else - add = '_'; + add = (ishdr)? ' ' : '_'; break; case '=': pbreak = 0; @@ -119,7 +116,13 @@ qpdec(char *str, int *len, int ishdr) i += 2; break; default: - add = str[i]; + /* + * Convert CRLF to LF. + */ + if (str[i] == '\r' && i < (*len)-1 && str[i+1] == '\n') + add = '\0'; + else + add = str[i]; break; } if (add == '\0') diff --git a/test/Makefile b/test/Makefile @@ -42,7 +42,7 @@ imaptest: gcc -g -std=gnu99 -I.. -o imaptest imaptest.c ../ind.c ../llist.c \ ../mime.c ../parser.c ../net.c ../strio.c ../base64.c \ ../imap.c ../mark.c ../txtdb.c ../cfg.c ../inc.c ../flag.c \ - ../print.c ../quote.c ../param.c -lssl -lcrypto -D_XOPEN_SOURCE + ../quote.c ../param.c -lssl -lcrypto -D_XOPEN_SOURCE @echo Now run ./imaptest user pass 'tpcs!host!imaps' b64test: @@ -54,7 +54,7 @@ pqtest: @echo Now run ./pqtest printtest: - gcc -g -std=gnu99 -I.. -o printtest printtest.c ../print.c ../ind.c + gcc -g -std=gnu99 -I.. -o printtest printtest.c ../ind.c @echo Now run ./printtest encodetest: diff --git a/test/mimetest.c b/test/mimetest.c @@ -73,7 +73,7 @@ main(int argc, char *argv[]) if (argc < 2 || !strcmp(argv[1], "-d")) { str = readstdin(&len); - mime = mime_parsestr(str, len); + mime = mime_parsebuf(str, len); free(str); printf("\nmessage:\n"); @@ -99,7 +99,7 @@ main(int argc, char *argv[]) for (i = 0; i < nelem(hdrs); i++) { printf("\nhdrs%d: %s\n", i, hdrs[i]); - mime = mime_parsestr(hdrs[i], strlen(hdrs[i])); + mime = mime_parsebuf(hdrs[i], strlen(hdrs[i])); if (mime == NULL) { printf("Test failed!\n"); continue; diff --git a/test/printtest.c b/test/printtest.c @@ -10,9 +10,6 @@ #include <stdlib.h> #include <stdio.h> -#include "print.h" - - int main(int argc, char *argv[]) {