|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include "mail.h"
4: #include "string.h"
5: #include "header.h"
6: #include "aux.h"
7: #include <regexp.h>
8:
9: /* imported */
10: extern char *malloc();
11: extern char *strcpy();
12: extern char *strchr();
13: extern int strncmp();
14: extern void exit();
15:
16: /* predeclared */
17: extern void addheader();
18: extern void addbody();
19:
20: /* global to this file */
21: static regexp *rfprog;
22: static regexp *fprog;
23:
24: /* imported */
25: extern int extrafrom;
26:
27: /*
28: * Input header from standard input. Actually two extra lines are also
29: * read, but this is a problem. Save some header lines in the header
30: * array.
31: */
32: extern
33: getheader(fgetsp, fp)
34: char *(*fgetsp)();
35: FILE *fp;
36: {
37: char buf[4096];
38: string *line;
39: string *from=NULL;
40: string *date=NULL;
41: char *cp;
42: header *hp;
43: int n;
44:
45: /*
46: * forget any old headers
47: */
48: for (hp = hdrs; *(hp->name) != '\0'; hp++)
49: hp->line = (string *)0;
50:
51: /*
52: * preload the first line for the parsing below
53: */
54: if((*fgetsp)(buf, sizeof buf, fp) == NULL)
55: return ferror(fp) ? -1 : 0;
56:
57: /* If the first line of an rfc822 message
58: * is a unix from line, use that to `seed' the From: and
59: * Date: fields.
60: */
61: if(strncmp(buf, "From ", 5)==0) {
62: if (getunixfrom(buf, &from, &date)==0) {
63: for (hp = hdrs; *(hp->name) != '\0'; hp++) {
64: if (STRCMP("UnixFrom:", hp) == 0) {
65: hp->line = from;
66: from = (string *)0;
67: continue;
68: };
69: if (STRCMP("UnixDate:", hp) == 0) {
70: hp->line = date;
71: date = (string *)0;
72: continue;
73: };
74: }
75: return 0;
76: }
77: }
78:
79: /* Now get real 822 headers */
80: while (buf[0] != '\n' && buf[0] != '\0') {
81: /* gather a multiple line header field */
82: line = s_new();
83: do {
84: s_append(line, buf);
85: if((*fgetsp)(buf, sizeof buf, fp) == NULL) {
86: if(ferror(fp))
87: return -1;
88: *buf = 0;
89: break;
90: }
91: } while (*buf==' ' || *buf=='\t');
92:
93: /* header lines must contain `:' with no preceding white */
94: for(cp=s_to_c(line); *cp; cp++)
95: if(isspace(*cp) || *cp==':')
96: break;
97: if (*cp != ':') {
98: addbody(line);
99: break;
100: }
101:
102: /* look for `important' headers */
103: for (hp = hdrs; *(hp->name) != '\0'; hp++) {
104: if (cistrncmp(s_to_c(line), hp->name, hp->size) == 0) {
105: hp->line = line;
106: break;
107: };
108: }
109: addheader(line);
110: }
111: /* at this point, buf contains a line of the body */
112: if(buf[0])
113: addbody(s_copy(buf));
114: return 0;
115: }
116:
117: /*
118: * Keep a (circular) list of header lines to output.
119: */
120: typedef struct quux{
121: struct quux *next;
122: string *line;
123: } hlist;
124: static hlist dummy = { &dummy, '\0' };
125: static hlist *list = &dummy;
126:
127: /*
128: * Add to list of header lines.
129: */
130: extern void
131: addheader(line)
132: string *line;
133: {
134: hlist *thing;
135:
136: thing = (hlist *)malloc(sizeof(hlist));
137: if (thing == NULL) {
138: perror("reading header");
139: exit(1);
140: }
141: thing->line = line;
142: thing->next = list->next;
143: list->next = thing;
144: list = thing;
145: }
146:
147: /*
148: * Print list of headers.
149: */
150: extern int
151: printheaders(fputsp, fp, originalfrom)
152: FILE *fp;
153: int (*fputsp)();
154: {
155: hlist *thing, *othing;
156: int printed = 0;
157:
158: for(thing = list->next->next; thing != &dummy; ){
159: printed++;
160: if(originalfrom && strncmp(s_to_c(thing->line), "From:", 5)==0)
161: (*fputsp)("Original-", fp);
162: (*fputsp)(s_to_c(thing->line), fp);
163: s_free(thing->line);
164: othing = thing;
165: thing = thing->next;
166: free(othing);
167: }
168: list = dummy.next = &dummy; /* reinitialize for future calls */
169: return(printed);
170: }
171:
172: /*
173: * Keep a (circular) list of body lines to output.
174: */
175: static hlist bdummy = { &bdummy, '\0' };
176: static hlist *blist = &bdummy;
177:
178: /*
179: * Add to list of body lines.
180: */
181: extern void
182: addbody(line)
183: string *line;
184: {
185: hlist *thing;
186:
187: thing = (hlist *)malloc(sizeof(hlist));
188: if (thing == NULL) {
189: perror("reading header");
190: exit(1);
191: }
192: thing->line = line;
193: thing->next = blist->next;
194: blist->next = thing;
195: blist = thing;
196: }
197:
198: /*
199: * Print list of body lines
200: */
201: extern void
202: printbodies(fputsp, fp)
203: FILE *fp;
204: int (*fputsp)();
205: {
206: hlist *thing, *othing;
207: int line = 0;
208:
209: for(thing = blist->next->next; thing != &bdummy; ){
210: /* dump extraneous new line */
211: if(line++!=0 || *s_to_c(thing->line)!='\n')
212: (*fputsp)(s_to_c(thing->line), fp);
213: s_free(thing->line);
214: othing = thing;
215: thing = thing->next;
216: free(othing);
217: }
218: blist = bdummy.next = &bdummy;
219: }
220:
221: /*
222: * extract sender and date from a unix remote from line. return -1
223: * if its the wrong format, 0 otherwise.
224: */
225: getunixfrom(line, fpp, dpp)
226: char *line;
227: string **fpp;
228: string **dpp;
229: {
230: regsubexp subexp[10];
231:
232: if (rfprog == NULL)
233: rfprog = regcomp(REMFROMRE);
234: if (regexec(rfprog, line, subexp, 10)) {
235: *fpp = s_new();
236: append_match(subexp, *fpp, REMSYSMATCH);
237: s_append(*fpp, "!");
238: append_match(subexp, *fpp, REMSENDERMATCH);
239: *dpp = s_new();
240: append_match(subexp, *dpp, REMDATEMATCH);
241: return 0;
242: }
243: if (fprog == NULL)
244: fprog = regcomp(FROMRE);
245: if (regexec(fprog, line, subexp, 10)) {
246: *fpp = s_new();
247: append_match(subexp, *fpp, SENDERMATCH);
248: *dpp = s_new();
249: append_match(subexp, *dpp, DATEMATCH);
250: return 0;
251: }
252: return -1;
253: }
254:
255: /*
256: * The addr is either the first whitespace delimited token or
257: * the first thing enclosed in "<" ">".
258: * Sets extrafrom > 0 if a from line with other cruft in it.
259: */
260: extern string *
261: getaddr(line)
262: char *line;
263: {
264: register char *lp;
265: register int comment = 0;
266: register int anticomment = 0;
267: register int inquote = 0;
268: static string *sender=0;
269:
270: if (!sender)
271: sender = s_new();
272: s_restart(sender);
273: lp = line;
274: for (; *lp; lp++) {
275: if (comment) {
276: if (*lp=='(')
277: comment++;
278: if (*lp==')')
279: comment--;
280: continue;
281: }
282: if (anticomment) {
283: if (*lp=='>') {
284: if (*(lp+1)!='\n')
285: extrafrom++;
286: break;
287: }
288: }
289: if (inquote) {
290: if (*lp=='"')
291: inquote = 0;
292: s_putc(sender, *lp);
293: continue;
294: }
295: switch (*lp) {
296: case '\t':
297: case '\n':
298: break;
299: case ' ':
300: if (cistrncmp(lp, " at ", sizeof(" at ")-1)==0) {
301: s_putc(sender, '@');
302: lp += sizeof(" at ")-2;
303: }
304: break;
305: case '<':
306: anticomment = 1;
307: if(*s_to_c(sender)!='\0')
308: extrafrom++;
309: s_restart(sender);
310: break;
311: case '(':
312: extrafrom++;
313: comment++;
314: break;
315: case '"':
316: inquote = 1;
317: /* fall through */
318: default:
319: s_putc(sender, *lp);
320: break;
321: }
322: }
323: s_terminate(sender);
324: s_restart(sender);
325: return(sender);
326: }
327:
328: /*
329: * case independent string compare
330: */
331: extern int
332: cistrncmp(s1, s2, n)
333: char *s1;
334: char *s2;
335: {
336: int c1, c2;
337:
338: for(; *s1 && n>0; n--, s1++, s2++){
339: c1 = isupper(*s1) ? tolower(*s1) : *s1;
340: c2 = isupper(*s2) ? tolower(*s2) : *s2;
341: if (c1 != c2)
342: return -1;
343: }
344: return(0);
345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.