tRewrite RFC5322 helpers to be independent from headers structure - scribo - Email-based phlog generator
 (HTM) git clone git://git.z3bra.org/scribo.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 8c8ef05376c10ddbd4afaff7376a62fbce82e673
 (DIR) parent 2b0a9a4d1f589eb8ec7b814eeda2ae88b28266ba
 (HTM) Author: Willy Goiffon <dev@z3bra.org>
       Date:   Mon,  7 Sep 2020 17:29:44 +0200
       
       Rewrite RFC5322 helpers to be independent from headers structure
       
       Diffstat:
         M rfc5322.c                           |     102 ++++++++++++-------------------
         M rfc5322.h                           |      17 +++--------------
         M scribo.c                            |      64 +++++++++++++++++++++++++++----
       
       3 files changed, 98 insertions(+), 85 deletions(-)
       ---
 (DIR) diff --git a/rfc5322.c b/rfc5322.c
       t@@ -6,29 +6,53 @@
        
        #include "rfc5322.h"
        
       -struct header *
       -rfc5322_header(char *s)
       +#define HDRSIZ 997
       +
       +#ifndef strlcpy
       +size_t strlcpy(char *dst, const char *src, size_t siz);
       +#endif
       +#ifndef strlcat
       +size_t strlcat(char *dst, const char *src, size_t siz);
       +#endif
       +
       +char *
       +rfc5322_headername(const char *s)
       +{
       +        static char n[HDRSIZ];
       +        char *p;
       +
       +        strlcpy(n, s, sizeof(n));
       +
       +        p = n;
       +        return strsep(&p, ":");
       +}
       +
       +char *
       +rfc5322_headerbody(const char *s)
        {
       -        char *f, *b;
       -        struct header *h;
       +        static char n[BUFSIZ + HDRSIZ + 1];
       +        char *p;
        
       -        if (!(f = strsep(&s, ":")))
       -                return NULL;
       +        strlcpy(n, s, sizeof(n));
        
       -        while (isblank(*s)) s++;
       +        p = n + strlen(rfc5322_headername(s)) + 1;
       +        while (isblank(*p)) p++;
        
       -        if (!(b = strsep(&s, "\r\n")))
       -                return NULL;
       +        return strsep(&p, "\r\n");
       +}
        
       -        if (!(h = calloc(sizeof(*h), 1)))
       -                return NULL;
        
       -        h->field = strdup(f);
       -        h->body = strdup(b);
       +size_t
       +rfc5322_unfold(char *body, char *line, size_t n)
       +{
       +        /* trim leading whitespace when current body is empty */
       +        if (strnlen(body, n) == 0)
       +                while (isblank(*line)) line++;
        
       -        return h;
       +        return strlcat(body, strsep(&line, "\r\n"), n);
        }
        
       +
        time_t
        rfc5322_date(const char *s)
        {
       t@@ -41,53 +65,3 @@ rfc5322_date(const char *s)
        
                return mktime(&tm);
        }
       -
       -int
       -rfc5322_unfold(struct header *h, char *buf)
       -{
       -        char *l, *p;
       -        size_t len;
       -
       -        l = strsep(&buf, "\r\n");
       -        if (!l)
       -                return -1;
       -
       -        len = strlen(h->body) + strlen(l);
       -
       -        p = realloc(h->body, len);
       -        if (!p)
       -                return -1;
       -
       -        strcat(p, l);
       -
       -        h->body = p;
       -
       -        return 0;
       -}
       -
       -int
       -rfc5322_parse(FILE *fp, struct headers *head)
       -{
       -        size_t bufsiz;
       -        ssize_t len;
       -        char *buf = NULL;
       -        struct header *p = NULL;
       -
       -        while ((len = getline(&buf, &bufsiz, fp)) > 0) {
       -                /* done parsin headers */
       -                if (!strcmp(buf, "\n"))
       -                        break;
       -
       -                if (isblank(*buf)) {
       -                        rfc5322_unfold(p, buf);
       -                } else {
       -                        p = rfc5322_header(buf);
       -                        if (p)
       -                                SLIST_INSERT_HEAD(head, p, entries);
       -                }
       -        }
       -
       -        free(buf);
       -
       -        return 0;
       -}
 (DIR) diff --git a/rfc5322.h b/rfc5322.h
       t@@ -1,14 +1,3 @@
       -#include <sys/queue.h>
       -
       -struct header {
       -        char *field;
       -        char *body;
       -        SLIST_ENTRY(header) entries;
       -};
       -
       -SLIST_HEAD(headers, header);
       -
       -time_t rfc5322_date(const char *);
       -struct header *rfc5322_header(char *);
       -int rfc5322_unfold(struct header *, char *);
       -int rfc5322_parse(FILE *, struct headers *);
       +char *rfc5322_headername(const char *);
       +char *rfc5322_headerbody(const char *);
       +size_t rfc5322_unfold(char *, char *, size_t);
 (DIR) diff --git a/scribo.c b/scribo.c
       t@@ -11,6 +11,20 @@
        #include "config.h"
        #include "rfc5322.h"
        
       +/* header field */
       +struct hdr {
       +        char name[BUFSIZ];
       +        char body[BUFSIZ];
       +        SLIST_ENTRY(hdr) entries;
       +};
       +
       +/* header section */
       +SLIST_HEAD(headers, hdr);
       +
       +#ifndef strlcpy
       +size_t strlcpy(char *dst, const char *src, size_t siz);
       +#endif
       +
        void
        usage(char *pgm)
        {
       t@@ -18,13 +32,48 @@ usage(char *pgm)
        }
        
        int
       +parseheaders(FILE *fp, struct headers *head)
       +{
       +        char *buf = NULL;
       +        size_t bufsiz = 0;
       +        ssize_t len;
       +        struct hdr *h;
       +
       +        SLIST_INIT(head);
       +
       +        while ((len = getline(&buf, &bufsiz, fp)) > 0) {
       +                /* a single newline mark the end of header section */
       +                if (!strncmp(buf, "\r\n", 2))
       +                        break;
       +
       +                if (isblank(*buf)) {
       +                        rfc5322_unfold(h->body, buf, sizeof(h->body));
       +                        continue;
       +                }
       +
       +                if (!(h = malloc(sizeof(*h))))
       +                return -1;
       +
       +                strlcpy(h->name, rfc5322_headername(buf), sizeof(h->name));
       +                strlcpy(h->body, rfc5322_headerbody(buf), sizeof(h->body));
       +                SLIST_INSERT_HEAD(head, h, entries);
       +        }
       +
       +        free(buf);
       +
       +        if (len < 0)
       +                return -1;
       +
       +        return 0;
       +}
       +
       +int
        main(int argc, char *argv[])
        {
                FILE *in = stdin, *out = stdout;
       -        struct header *p = NULL;
       -        struct headers head = SLIST_HEAD_INITIALIZER(headers);
                char *argv0, *infile, *outfile, buf[BUFSIZ];
                size_t len;
       +        struct headers headers;
        
                infile = NULL;
                outfile = NULL;
       t@@ -53,13 +102,14 @@ main(int argc, char *argv[])
                if (outfile)
                        out = fopen(outfile, "w");
        
       -        if (rfc5322_parse(in, &head) < 0)
       +        if (parseheaders(in, &headers) < 0)
                        return -1;
        
       -        SLIST_FOREACH(p, &head, entries) {
       -                if (!strcmp(p->field, "Subject"))
       -                        fprintf(out, "# %s\n\n", p->body);
       -        }
       +        struct hdr *p;
       +        SLIST_FOREACH(p, &headers, entries)
       +                printf("%s: %s\n", p->name, p->body);
       +
       +        return 0;
        
                while ((len = fread(buf, 1, BUFSIZ, in)))
                        fwrite(buf, 1, len, out);