Imported upstream version 0.59.3
[hcoop/debian/courier-authlib.git] / rfc822 / imapsubj.c
1 /*
2 ** Copyright 2000 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 /*
7 ** $Id: imapsubj.c,v 1.10 2006/04/11 02:24:59 mrsam Exp $
8 */
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include "rfc822.h"
14 #include "config.h"
15
16 #if HAVE_STRCASECMP
17
18 #else
19 #define strcasecmp stricmp
20 #endif
21
22 #if HAVE_STRNCASECMP
23
24 #else
25 #define strncasecmp strnicmp
26 #endif
27
28 /* Skip over blobs */
29
30 static char *skipblob(char *p, char **save_blob_ptr)
31 {
32 char *q;
33 char *orig_p=p;
34 int isalldigits=1;
35
36 if (*p == '[')
37 {
38 for (q= p+1; *q; q++)
39 if (*q == '[' || *q == ']')
40 break;
41 else if (strchr("0123456789", *q) == NULL)
42 isalldigits=0;
43
44 if (*q == ']')
45 {
46 p=q+1;
47
48 while (isspace((int)(unsigned char)*p))
49 {
50 ++p;
51 }
52
53 if (save_blob_ptr && *save_blob_ptr && !isalldigits)
54 {
55 while (orig_p != p)
56 *(*save_blob_ptr)++=*orig_p++;
57 }
58
59 return (p);
60 }
61 }
62 return (p);
63 }
64
65 static char *skipblobs(char *p, char **save_blob_ptr)
66 {
67 char *q=p;
68
69 do
70 {
71 p=q;
72 q=skipblob(p, save_blob_ptr);
73 } while (q != p);
74 return (q);
75 }
76
77 /* Remove artifacts from the subject header */
78
79 static void stripsubj(char *s, int *hasrefwd, char *save_blob_buf)
80 {
81 char *p;
82 char *q;
83 int doit;
84
85 for (p=q=s; *p; p++)
86 {
87 if (!isspace((int)(unsigned char)*p))
88 {
89 *q++=*p;
90 continue;
91 }
92 while (p[1] && isspace((int)(unsigned char)p[1]))
93 {
94 ++p;
95 }
96 *q++=' ';
97 }
98 *q=0;
99
100 do
101 {
102 doit=0;
103 /*
104 **
105 ** (2) Remove all trailing text of the subject that matches
106 ** the subj-trailer ABNF, repeat until no more matches are
107 ** possible.
108 **
109 ** subj-trailer = "(fwd)" / WSP
110 */
111
112 for (p=s; *p; p++)
113 ;
114 while (p > s)
115 {
116 if ( isspace((int)(unsigned char)p[-1]))
117 {
118 --p;
119 continue;
120 }
121 if (p-s >= 5 && strncasecmp(p-5, "(FWD)", 5) == 0)
122 {
123 p -= 5;
124 *hasrefwd |= CORESUBJ_FWD;
125 continue;
126 }
127 break;
128 }
129 *p=0;
130
131 for (p=s; *p; )
132 {
133 for (;;)
134 {
135 char *orig_blob_ptr;
136 int flag=CORESUBJ_FWD;
137
138 /*
139 **
140 ** (3) Remove all prefix text of the subject
141 ** that matches the subj-leader ABNF.
142 **
143 ** subj-leader = (*subj-blob subj-refwd) / WSP
144 **
145 ** subj-blob = "[" *BLOBCHAR "]" *WSP
146 **
147 ** subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":"
148 **
149 ** BLOBCHAR = %x01-5a / %x5c / %x5e-7f
150 ** ; any CHAR except '[' and ']'
151 */
152
153 if (isspace((int)(unsigned char)*p))
154 {
155 ++p;
156 continue;
157 }
158
159 q=skipblobs(p, NULL);
160
161 if (strncasecmp(q, "RE", 2) == 0)
162 {
163 flag=CORESUBJ_RE;
164 q += 2;
165 }
166 else if (strncasecmp(q, "FWD", 3) == 0)
167 {
168 q += 3;
169 }
170 else if (strncasecmp(q, "FW", 2) == 0)
171 {
172 q += 2;
173 }
174 else q=0;
175
176 if (q)
177 {
178 orig_blob_ptr=save_blob_buf;
179
180 q=skipblob(q, &save_blob_buf);
181 if (*q == ':')
182 {
183 p=q+1;
184 *hasrefwd |= flag;
185 continue;
186 }
187
188 save_blob_buf=orig_blob_ptr;
189 }
190
191
192 /*
193 ** (4) If there is prefix text of the subject
194 ** that matches the subj-blob ABNF, and
195 ** removing that prefix leaves a non-empty
196 ** subj-base, then remove the prefix text.
197 **
198 ** subj-base = NONWSP *([*WSP] NONWSP)
199 ** ; can be a subj-blob
200 */
201
202 orig_blob_ptr=save_blob_buf;
203
204 q=skipblob(p, &save_blob_buf);
205
206 if (q != p && *q)
207 {
208 p=q;
209 continue;
210 }
211 save_blob_buf=orig_blob_ptr;
212 break;
213 }
214
215 /*
216 **
217 ** (6) If the resulting text begins with the
218 ** subj-fwd-hdr ABNF and ends with the subj-fwd-trl
219 ** ABNF, remove the subj-fwd-hdr and subj-fwd-trl and
220 ** repeat from step (2).
221 **
222 ** subj-fwd-hdr = "[fwd:"
223 **
224 ** subj-fwd-trl = "]"
225 */
226
227 if (strncasecmp(p, "[FWD:", 5) == 0)
228 {
229 q=strrchr(p, ']');
230 if (q && q[1] == 0)
231 {
232 *q=0;
233 p += 5;
234 *hasrefwd |= CORESUBJ_FWD;
235
236 for (q=s; (*q++=*p++) != 0; )
237 ;
238 doit=1;
239 }
240 }
241 break;
242 }
243 } while (doit);
244
245 q=s;
246 while ( (*q++ = *p++) != 0)
247 ;
248 if (save_blob_buf)
249 *save_blob_buf=0;
250 }
251
252 char *rfc822_coresubj(const char *s, int *hasrefwd)
253 {
254 char *q=strdup(s), *r;
255 int dummy;
256
257 if (!hasrefwd)
258 hasrefwd= &dummy;
259
260 *hasrefwd=0;
261 if (!q) return (0);
262
263 for (r=q; *r; r++)
264 if ((*r & 0x80) == 0) /* Just US-ASCII casing, thanks */
265 *r=toupper((int)(unsigned char)*r);
266 stripsubj(q, hasrefwd, 0);
267 return (q);
268 }
269
270 char *rfc822_coresubj_nouc(const char *s, int *hasrefwd)
271 {
272 char *q=strdup(s);
273 int dummy;
274
275 if (!hasrefwd)
276 hasrefwd= &dummy;
277
278 *hasrefwd=0;
279 if (!q) return (0);
280
281 stripsubj(q, hasrefwd, 0);
282 return (q);
283 }
284
285 char *rfc822_coresubj_keepblobs(const char *s)
286 {
287 char *q=strdup(s), *r;
288 int dummy;
289
290 if (!q) return (0);
291
292 r=strdup(s);
293 if (!r)
294 {
295 free(q);
296 return (0);
297 }
298
299 stripsubj(q, &dummy, r);
300 strcat(r, q);
301 free(q);
302 return (r);
303 }