tMany changes at once, sorry. - rohrpost - A commandline mail client to change the world as we see it.
 (HTM) git clone git://r-36.net/rohrpost
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) LICENSE
       ---
 (DIR) commit 1d75e5542ed2feff99e7ef2aa2108a679fa7460c
 (DIR) parent e7a3f1cfb83fe1477038016bb6a574f49d62239c
 (HTM) 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(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       t@@ -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}
        
 (DIR) diff --git a/dos.c b/dos.c
       t@@ -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;
       +}
       +
 (DIR) diff --git a/dos.h b/dos.h
       t@@ -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
       +
 (DIR) diff --git a/ind.c b/ind.c
       t@@ -393,6 +393,9 @@ readstdin(int *len)
                return readtoeof(stdin, len);
        }
        
       +/*
       + * Get line from string buffer.
       + */
        char *
        sgets(char *s, int size, char **p)
        {
       t@@ -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)
        {
 (DIR) diff --git a/mime.c b/mime.c
       t@@ -20,6 +20,7 @@
        #include "base64.h"
        #include "quote.h"
        #include "param.h"
       +#include "dos.h"
        
        char *argv0;
        
       t@@ -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)
        {
       t@@ -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) {
       t@@ -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);
        
       t@@ -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
       t@@ -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.
       t@@ -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;
                                }
                        }
       t@@ -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;
       t@@ -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"
                                         */
       t@@ -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");
       t@@ -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);
        
       t@@ -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) {
 (DIR) diff --git a/quote.c b/quote.c
       t@@ -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;
       t@@ -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')
 (DIR) diff --git a/test/Makefile b/test/Makefile
       t@@ -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:
       t@@ -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:
 (DIR) diff --git a/test/mimetest.c b/test/mimetest.c
       t@@ -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");
       t@@ -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;
 (DIR) diff --git a/test/printtest.c b/test/printtest.c
       t@@ -10,9 +10,6 @@
        #include <stdlib.h>
        #include <stdio.h>
        
       -#include "print.h"
       -
       -
        int
        main(int argc, char *argv[])
        {