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);