1 /*
2 ** Copyright 2001-2011 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5 
6 #include	"config.h"
7 #include	<stdio.h>
8 #include	<ctype.h>
9 #include	<stdlib.h>
10 #include	<string.h>
11 #include	"rfc822hdr.h"
12 
13 
14 /*
15 ** Read the next mail header.
16 */
17 
rfc822hdr_read(struct rfc822hdr * h,FILE * f,off_t * pos,off_t epos)18 int rfc822hdr_read(struct rfc822hdr *h, FILE *f, off_t *pos, off_t epos)
19 {
20 	size_t n=0;
21 	int c;
22 
23 	for (;;)
24 	{
25 		if ( n >= h->hdrsize)
26 		{
27 			size_t hn=h->hdrsize + 1024;
28 			char *p= h->header ? realloc(h->header, hn):
29 				malloc(hn);
30 
31 			if (!p)
32 				return (-1);
33 
34 			h->header=p;
35 			h->hdrsize=hn;
36 		}
37 
38 		if (pos && *pos >= epos)
39 		{
40 			h->header[n]=0;
41 			break;
42 		}
43 
44 		c=getc(f);
45 		if (c == EOF)
46 		{
47 			if (pos)
48 				*pos=epos;
49 			h->header[n]=0;
50 			break;
51 		}
52 		if (pos)
53 			++*pos;
54 
55 		h->header[n]=c;
56 		if (c == '\n')
57 		{
58 			if (n == 0)
59 			{
60 				if (pos)
61 					*pos=epos;
62 				h->header[n]=0;
63 				break;
64 			}
65 
66 			c=getc(f);
67 			if (c != EOF)
68 				ungetc(c, f);
69 			if (c == '\n' || c == '\r' ||
70 			    !isspace((int)(unsigned char)c))
71 			{
72 				h->header[n]=0;
73 				break;
74 			}
75 		}
76 		n++;
77 		if (h->maxsize && n + 2 > h->maxsize)
78 			--n;
79 	}
80 
81 	if (n == 0)
82 	{
83 		if (pos)
84 			*pos=epos;
85 		h->value=h->header;
86 		return (1);
87 	}
88 
89 	for (h->value=h->header; *h->value; ++h->value)
90 	{
91 		if (*h->value == ':')
92 		{
93 			*h->value++=0;
94 			while (*h->value &&
95 			       isspace((int)(unsigned char)*h->value))
96 				++h->value;
97 			break;
98 		}
99 	}
100 	return (0);
101 }
102 
rfc822hdr_fixname(struct rfc822hdr * h)103 void rfc822hdr_fixname(struct rfc822hdr *h)
104 {
105 	char *p;
106 
107 	for (p=h->header; *p; p++)
108 	{
109 		*p=tolower((int)(unsigned char)*p);
110 	}
111 }
112 
rfc822hdr_collapse(struct rfc822hdr * h)113 void rfc822hdr_collapse(struct rfc822hdr *h)
114 {
115 	char *p, *q;
116 
117 	for (p=q=h->value; *p; )
118 	{
119 		if (*p == '\n')
120 		{
121 			while (*p && isspace((int)(unsigned char)*p))
122 				++p;
123 			*q++=' ';
124 			continue;
125 		}
126 		*q++ = *p++;
127 	}
128 	*q=0;
129 }
130 
131 /* This is, basically, a case-insensitive US-ASCII comparison function */
132 
133 #define lc(x) ((x) >= 'A' && (x) <= 'Z' ? (x) + ('a'-'A'):(x))
134 
rfc822hdr_namecmp(const char * a,const char * b)135 int rfc822hdr_namecmp(const char *a, const char *b)
136 {
137 	int rc;
138 
139 	while ((rc=(int)(unsigned char)lc(*a) - (int)(unsigned char)lc(*b))==0)
140 	{
141 		if (!*a)
142 			return 0;
143 		++a;
144 		++b;
145 	}
146 
147 	return rc;
148 }
149 
rfc822hdr_is_addr(const char * hdr)150 int rfc822hdr_is_addr(const char *hdr)
151 {
152 	return rfc822hdr_namecmp(hdr, "from") == 0 ||
153 		rfc822hdr_namecmp(hdr, "to") == 0 ||
154 		rfc822hdr_namecmp(hdr, "cc") == 0 ||
155 		rfc822hdr_namecmp(hdr, "bcc") == 0 ||
156 		rfc822hdr_namecmp(hdr, "resent-from") == 0 ||
157 		rfc822hdr_namecmp(hdr, "resent-to") == 0 ||
158 		rfc822hdr_namecmp(hdr, "resent-cc") == 0 ||
159 		rfc822hdr_namecmp(hdr, "resent-bcc") == 0;
160 }
161