1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
7 #include <ccan/str/str.h>
8 #include <ccan/list/list.h>
11 #include <ccan/rfc822/rfc822.h>
14 #include <ccan/tal/talloc/talloc.h>
16 #include <ccan/tal/tal.h>
20 void *memmem(const void *haystack, size_t haystacklen,
21 const void *needle, size_t needlelen)
26 last = p + haystacklen - needlelen;
29 if (memcmp(p, needle, needlelen) == 0)
31 } while (p++ <= last);
37 static void (*allocation_failure_hook)(const char *);
39 static void NORETURN default_allocation_failure(const char *s)
41 fprintf(stderr, "ccan/rfc822: Allocation failure: %s", s);
45 static void allocation_failure(const char *s)
47 if (allocation_failure_hook)
48 (*allocation_failure_hook)(s);
50 default_allocation_failure(s);
53 void rfc822_set_allocation_failure_handler(void (*h)(const char *))
55 allocation_failure_hook = h;
58 #define ALLOC_CHECK(p, r) \
61 allocation_failure(__FILE__ ":" stringify(__LINE__)); \
67 * No real point doing fancy resizing hashes, when any given mail
68 * message is unlikely to have more than a fairly small number of
69 * distinct header types. This should be ample.
71 #define INDEX_HASH_SIZE 63
74 const char *data, *end;
75 const char *remainder;
76 struct list_head headers;
77 struct list_head header_index[INDEX_HASH_SIZE];
81 struct rfc822_header {
82 struct bytestring all, rawname, rawvalue;
83 struct bytestring unfolded;
84 struct list_node list;
85 struct rfc822_header *name_next;
88 struct rfc822_headers_of_name {
89 struct bytestring name;
90 struct rfc822_header *first;
91 struct rfc822_header **lastptr;
92 struct list_node bucket;
95 struct rfc822_msg *rfc822_check(const struct rfc822_msg *msg,
99 if (!list_check(&msg->headers, abortstr))
101 if (!tal_check(msg, abortstr))
103 return (struct rfc822_msg *)msg;
106 #ifdef CCAN_RFC822_DEBUG
107 #define CHECK(msg, str) do { rfc822_check((msg), (str)); } while (0)
109 #define CHECK(msg, str) do { } while (0)
112 struct rfc822_msg *rfc822_start(const void *ctx, const char *p, size_t len)
114 struct rfc822_msg *msg;
117 msg = tal(ctx, struct rfc822_msg);
118 ALLOC_CHECK(msg, NULL);
123 msg->remainder = msg->data;
126 list_head_init(&msg->headers);
128 for (i = 0; i < INDEX_HASH_SIZE; i++)
129 list_head_init(&msg->header_index[i]);
131 CHECK(msg, "<rfc22_start");
136 void rfc822_free(struct rfc822_msg *msg)
138 CHECK(msg, ">rfc822_free");
142 static struct rfc822_header *next_header_cached(struct rfc822_msg *msg,
143 struct rfc822_header *hdr)
145 struct list_node *h = &msg->headers.n;
146 const struct list_node *n = h;
148 CHECK(msg, ">next_header_cached");
156 CHECK(msg, "<next_header_cached");
158 return list_entry(n->next, struct rfc822_header, list);
161 static const char *next_line(const char *start, const char *end)
163 const char *p = memchr(start, '\n', end - start);
165 return p ? (p + 1) : end;
168 static struct rfc822_header *index_header(struct rfc822_msg *msg,
169 struct rfc822_header *hdr);
171 static struct rfc822_header *next_header_parse(struct rfc822_msg *msg)
173 const char *h, *eh, *ev, *colon;
174 struct rfc822_header *hi;
176 CHECK(msg, ">next_header_parse");
181 if (msg->body && (msg->remainder >= msg->body))
185 eh = next_line(h, msg->end);
188 if ((ev > h) && (ev[-1] == '\n'))
190 if ((ev > h) && (ev[-1] == '\r'))
193 /* Found the end of the headers */
195 assert(!msg->body || (msg->body == eh));
202 while ((eh < msg->end) && rfc822_iswsp(*eh))
203 eh = next_line(eh, msg->end);
206 msg->remainder = NULL;
211 hi = talz(msg, struct rfc822_header);
212 ALLOC_CHECK(hi, NULL);
214 hi->all = bytestring(h, eh - h);
215 list_add_tail(&msg->headers, &hi->list);
217 colon = memchr(h, ':', hi->all.len);
219 hi->rawname = bytestring(h, colon - h);
220 hi->rawvalue = bytestring(colon + 1, eh - colon - 1);
222 hi->rawname = bytestring_NULL;
223 hi->rawvalue = bytestring_NULL;
226 CHECK(msg, "<next_header_parse");
228 return index_header(msg, hi);
231 struct rfc822_header *rfc822_next_header(struct rfc822_msg *msg,
232 struct rfc822_header *hdr)
234 struct rfc822_header *h;
236 CHECK(msg, ">rfc822_next_header");
238 h = next_header_cached(msg, hdr);
242 return next_header_parse(msg);
245 struct bytestring rfc822_body(struct rfc822_msg *msg)
247 CHECK(msg, ">rfc822_body");
249 if (!msg->body && msg->remainder) {
252 p = memmem(msg->remainder, msg->end - msg->remainder,
254 q = memmem(msg->remainder, msg->end - msg->remainder,
257 if (p && (!q || (p < q)))
259 else if (q && (!p || (q < p)))
262 if (msg->body >= msg->end) {
263 assert(msg->body == msg->end);
268 CHECK(msg, "<rfc822_body");
271 return bytestring(msg->body, msg->end - msg->body);
273 return bytestring_NULL;
276 enum rfc822_header_errors rfc822_header_errors(struct rfc822_msg *msg,
277 struct rfc822_header *hdr)
279 enum rfc822_header_errors err = 0;
282 if (!hdr->rawname.ptr) {
283 err |= RFC822_HDR_NO_COLON;
285 for (i = 0; i < hdr->rawname.len; i++) {
286 char c = hdr->rawname.ptr[i];
290 if ((c < 33) || (c > 126)) {
291 err |= RFC822_HDR_BAD_NAME_CHARS;
299 struct bytestring rfc822_header_raw_content(struct rfc822_msg *msg,
300 struct rfc822_header *hdr)
305 struct bytestring rfc822_header_raw_name(struct rfc822_msg *msg,
306 struct rfc822_header *hdr)
311 struct bytestring rfc822_header_raw_value(struct rfc822_msg *msg,
312 struct rfc822_header *hdr)
314 return hdr->rawvalue;
317 static void get_line(struct bytestring in, struct bytestring *first,
318 struct bytestring *rest)
320 size_t rawlen, trimlen;
321 const char *inp = in.ptr;
324 nl = memchr(inp, '\n', in.len);
328 rawlen = nl - inp + 1;
331 if ((trimlen > 0) && (inp[trimlen-1] == '\n')) {
333 if ((trimlen > 0) && (inp[trimlen-1] == '\r'))
337 *first = bytestring(in.ptr, trimlen);
340 *rest = bytestring(in.ptr + rawlen, in.len - rawlen);
342 *rest = bytestring_NULL;
346 struct bytestring rfc822_header_unfolded_value(struct rfc822_msg *msg,
347 struct rfc822_header *hdr)
349 struct bytestring raw = rfc822_header_raw_value(msg, hdr);
350 struct bytestring next, rest;
354 if (!hdr->unfolded.ptr) {
357 get_line(rest, &next, &rest);
363 hdr->unfolded = bytestring(raw.ptr, len);
365 char *unfold = tal_arr(msg, char, len);
368 ALLOC_CHECK(unfold, bytestring_NULL);
372 get_line(rest, &next, &rest);
373 memcpy(p, next.ptr, next.len);
377 assert(p == (unfold + len));
378 hdr->unfolded = bytestring(unfold, len);
382 return hdr->unfolded;
385 /* Specifically locale *un*aware tolower() - headers should be ascii
386 * only, and if they're not best to leave them as is */
387 static char xtolower(char c)
389 if ((c >= 'A') && (c <= 'Z'))
390 return 'a' + (c - 'A');
395 static bool hdr_name_eq(struct bytestring a, struct bytestring b)
402 for (i = 0; i < a.len; i++)
403 if (xtolower(a.ptr[i]) != xtolower(b.ptr[i]))
409 bool rfc822_header_is(struct rfc822_msg *msg, struct rfc822_header *hdr,
412 struct bytestring hname = rfc822_header_raw_name(msg, hdr);
414 if (!hname.ptr || !name)
417 return hdr_name_eq(hname, bytestring_from_string(name));
420 static unsigned headerhash(struct bytestring name)
423 * This is stolen from hash_string() in ccan/hash, but adapted
424 * to add the xtolower() call and use a bytestring
429 for (i = 0; i < name.len; i++)
430 ret = (ret << 5) - ret + xtolower(name.ptr[i]);
432 return ret % INDEX_HASH_SIZE;
435 static struct rfc822_headers_of_name *headers_of_name(struct rfc822_msg *msg,
436 struct bytestring name)
438 unsigned hash = headerhash(name);
439 struct rfc822_headers_of_name *hn;
441 list_for_each(&msg->header_index[hash], hn, bucket) {
442 if (hdr_name_eq(hn->name, name))
449 static struct rfc822_header *index_header(struct rfc822_msg *msg,
450 struct rfc822_header *hdr)
452 struct bytestring hname = rfc822_header_raw_name(msg, hdr);
453 struct rfc822_headers_of_name *hn = headers_of_name(msg, hname);
456 unsigned hash = headerhash(hname);
458 hn = talz(msg, struct rfc822_headers_of_name);
459 ALLOC_CHECK(hn, NULL);
463 hn->lastptr = &hn->first;
464 list_add_tail(&msg->header_index[hash], &hn->bucket);
467 hdr->name_next = NULL;
468 *(hn->lastptr) = hdr;
469 hn->lastptr = &hdr->name_next;
473 struct rfc822_header *rfc822_first_header_of_name(struct rfc822_msg *msg,
476 struct bytestring namebs = bytestring_from_string(name);
477 struct rfc822_headers_of_name *hn = headers_of_name(msg, namebs);
478 struct rfc822_header *hdr;
484 hdr = next_header_parse(msg);
485 if (hdr && rfc822_header_is(msg, hdr, name))
492 struct rfc822_header *rfc822_next_header_of_name(struct rfc822_msg *msg,
493 struct rfc822_header *hdr,
497 return rfc822_first_header_of_name(msg, name);
499 if (hdr->name_next) {
500 assert(rfc822_header_is(msg, hdr->name_next, name));
501 return hdr->name_next;
505 hdr = next_header_parse(msg);
506 if (hdr && rfc822_header_is(msg, hdr, name))