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