Imported Upstream version 0.66.1
[hcoop/debian/courier-authlib.git] / libs / rfc822 / rfc822hdr.c
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
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
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
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
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
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 }