annotate f-demime/header.c @ 2:1857d0d5a7bd

f-demime: fix parsing of Content-* headers
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 06 May 2023 06:33:26 +0000
parents 7e0d08176f32
children 612c4d0df768
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
1 /*
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
2 * This module implements initial processing (pass-through and collection)
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
3 * of message and body part headers.
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
4 */
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
5
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
6 #include <ctype.h>
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
7 #include <stdio.h>
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
8 #include <stdlib.h>
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
9 #include <string.h>
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
10 #include <strings.h>
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11 #include "defs.h"
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 extern enum msg_hdr_state hdr_state;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 extern char cont_type_buf[HDR_BUF_SIZE], cont_te_buf[HDR_BUF_SIZE];
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15 extern int got_cont_type, got_cont_te;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
16
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
17 static void
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 error(line, msg)
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19 char *line, *msg;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20 {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21 if (got_cont_type) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 fputs(cont_type_buf, stdout);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23 got_cont_type = 0;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
24 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
25 if (got_cont_te) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 fputs(cont_te_buf, stdout);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27 got_cont_te = 0;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29 printf("X-Fdemime-Error: %s\n", msg);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 puts(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
31 hdr_state = HDR_STATE_ERROR;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
32 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
33
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 static void
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35 error_ct_cont(hdr_name)
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 char *hdr_name;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
37 {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38 printf("X-Fdemime-Error: %s header is too long\n", hdr_name);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41 static void
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 cont_line(line)
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
43 char *line;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
44 {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45 unsigned prev_len;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47 switch (hdr_state) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 case HDR_STATE_BEGIN:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 error(line, "continuation line at the beginning of header");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
51 case HDR_STATE_GOTSOME:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
52 puts(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
53 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54 case HDR_STATE_CONT_TYPE:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 prev_len = strlen(cont_type_buf);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56 if (prev_len + strlen(line) + 2 > HDR_BUF_SIZE) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 error_ct_cont("Content-Type");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 fputs(cont_type_buf, stdout);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59 puts(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 hdr_state = HDR_STATE_ERROR;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 got_cont_type = 0;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64 sprintf(cont_type_buf + prev_len, "%s\n", line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
65 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66 case HDR_STATE_CONT_TE:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67 prev_len = strlen(cont_te_buf);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68 if (prev_len + strlen(line) + 2 > HDR_BUF_SIZE) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 error_ct_cont("Content-Transfer-Encoding");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 fputs(cont_te_buf, stdout);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
71 puts(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
72 hdr_state = HDR_STATE_ERROR;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
73 got_cont_te = 0;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
74 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
75 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
76 sprintf(cont_te_buf + prev_len, "%s\n", line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
77 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
78 default:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
79 fprintf(stderr,
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
80 "f-demime internal error: bad state in cont_line()\n");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
81 abort();
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
82 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
83 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
84
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
85 void
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
86 header_input_line(line)
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
87 char *line;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
88 {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
89 char *cp, savech;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
90 enum msg_hdr_state newhdr;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
91
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
92 if (!line[0]) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
93 process_header_end();
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
94 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
95 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
96 if (hdr_state == HDR_STATE_ERROR) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
97 puts(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
98 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
99 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
100 if (line[0] == ' ' || line[0] == '\t') {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
101 cont_line(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
102 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
103 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
104 cp = index(line, ':');
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
105 if (!cp) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
106 error(line, "header line has no colon");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
107 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
108 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
109 if (cp == line) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
110 error(line, "null header field name");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
111 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
112 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
113 while (cp[-1] == ' ' || cp[-1] == '\t')
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
114 cp--;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
115 savech = *cp;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
116 *cp = '\0';
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
117 if (!strcasecmp(line, "Content-Type"))
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
118 newhdr = HDR_STATE_CONT_TYPE;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
119 else if (!strcasecmp(line, "Content-Transfer-Encoding"))
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
120 newhdr = HDR_STATE_CONT_TE;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
121 else
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
122 newhdr = HDR_STATE_GOTSOME;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
123 *cp = savech;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
124 switch (newhdr) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
125 case HDR_STATE_CONT_TYPE:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
126 if (got_cont_type) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
127 error(line, "duplicate Content-Type");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
128 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
129 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
130 sprintf(cont_type_buf, "%s\n", line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
131 got_cont_type = 1;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
132 break;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
133 case HDR_STATE_CONT_TE:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
134 if (got_cont_te) {
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
135 error(line, "duplicate Content-Transfer-Encoding");
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
136 return;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
137 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
138 sprintf(cont_te_buf, "%s\n", line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
139 got_cont_te = 1;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
140 break;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
141 default:
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
142 puts(line);
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
143 }
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
144 hdr_state = newhdr;
7e0d08176f32 f-demime starting code
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
145 }