1 /*
2 * Routines to read headers of the style found in HTTP and mail
3 *
4 * Part of HTML-XML-utils, see:
5 * http://www.w3.org/Tools/HTML-XML-utils/
6 *
7 * Copyright © 2008 World Wide Web Consortium
8 * See http://www.w3.org/Consortium/Legal/copyright-software
9 *
10 * Author: Bert Bos <bert@w3.org>
11 * Created: 6 August 2008
12 */
13 #include "config.h"
14 #include <assert.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 #include <string.h>
19 #include <stdbool.h>
20 #include "export.h"
21 #include "heap.e"
22 #include "types.e"
23 #include "dict.e"
24
25 #define BUFLEN 4096 /* Max len of header lines */
26
27
28 /* read_mail_headers -- read mail-style headers into headers, false on error */
read_mail_headers(FILE * f,Dictionary headers)29 EXPORT bool read_mail_headers(FILE *f, Dictionary headers)
30 {
31 int i;
32 string p, line = NULL;
33 char buf[BUFLEN];
34
35 /* Read first line */
36 if (!fgets(buf, sizeof(buf), f)) return (ferror(f) == 0);
37 if (!(line = strdup(buf))) return false;
38
39 /* While not read an empty line, read and process more lines */
40 while (line[0] != '\r' && line[0] != '\n' && fgets(buf, sizeof(buf), f)) {
41 i = strlen(line);
42 assert(i != 0);
43 if (line[i-1] != '\n') {
44 strapp(&line, buf, NULL); /* Previous fgets() didn't reach eol */
45 } else if (buf[0] == ' ' || buf[0] == '\t') { /* Continuation line */
46 if (line[i-1] == '\n') line[i-1] = '\0';
47 if (i > 1 && line[i-2] == '\r') line[i-2] = '\0';
48 strapp(&line, buf + 1, NULL);
49 } else {
50 if (!(p = strchr(line, ':'))) {free(line); return 0;} /* Syntax error */
51 *p = '\0';
52 for (p++; isspace(*p); p++) ;
53 for (i = strlen(p) - 1; i >= 0 && isspace(p[i]); i--) p[i] = '\0';
54 down(line); /* Header name to lowercase */
55 if (!dict_add(headers, line, p)) {free(line); return 0;}
56 free(line);
57 line = newstring(buf);
58 }
59 }
60 free(line);
61
62 return ferror(f) == 0;
63 }
64