The first draft to be able to parse rfc822 not cute. The little
from program was use as the first test case.
Showing
5 changed files
with
519 additions
and
13 deletions
... | @@ -34,17 +34,20 @@ | ... | @@ -34,17 +34,20 @@ |
34 | #include <unistd.h> | 34 | #include <unistd.h> |
35 | 35 | ||
36 | #include <mailutils/mailbox.h> | 36 | #include <mailutils/mailbox.h> |
37 | #include <mailutils/address.h> | ||
37 | #include <mailutils/registrar.h> | 38 | #include <mailutils/registrar.h> |
38 | 39 | ||
39 | int | 40 | int |
40 | main(int argc, char **argv) | 41 | main(int argc, char **argv) |
41 | { | 42 | { |
42 | mailbox_t mbox = NULL; | 43 | mailbox_t mbox; |
43 | size_t i; | 44 | size_t i; |
44 | size_t count = 0; | 45 | size_t count = 0; |
45 | char *mailbox_name = NULL; | 46 | char *mailbox_name = NULL; |
46 | char from[BUFSIZ]; | 47 | /* Arbitrary limits. A better approach would be to allocate |
47 | char subject[BUFSIZ]; | 48 | as we go along but it is not worth the trouble. */ |
49 | char buf[128]; | ||
50 | char personal[128]; | ||
48 | int status; | 51 | int status; |
49 | 52 | ||
50 | /* have an argument */ | 53 | /* have an argument */ |
... | @@ -60,8 +63,7 @@ main(int argc, char **argv) | ... | @@ -60,8 +63,7 @@ main(int argc, char **argv) |
60 | list_append (bookie, pop_record); | 63 | list_append (bookie, pop_record); |
61 | } | 64 | } |
62 | 65 | ||
63 | if ((status = mailbox_create_default (&mbox, mailbox_name)) != 0 | 66 | if ((status = mailbox_create_default (&mbox, mailbox_name)) != 0) |
64 | || (status = mailbox_open (mbox, MU_STREAM_READ)) != 0) | ||
65 | { | 67 | { |
66 | fprintf (stderr, "could not create/open: %s\n", strerror (status)); | 68 | fprintf (stderr, "could not create/open: %s\n", strerror (status)); |
67 | exit (1); | 69 | exit (1); |
... | @@ -74,21 +76,43 @@ main(int argc, char **argv) | ... | @@ -74,21 +76,43 @@ main(int argc, char **argv) |
74 | //debug_set_level (debug, MU_DEBUG_TRACE|MU_DEBUG_PROT); | 76 | //debug_set_level (debug, MU_DEBUG_TRACE|MU_DEBUG_PROT); |
75 | } | 77 | } |
76 | 78 | ||
79 | if ((status = mailbox_open (mbox, MU_STREAM_READ)) != 0) | ||
80 | { | ||
81 | fprintf (stderr, "could not create/open: %s\n", strerror (status)); | ||
82 | exit (1); | ||
83 | } | ||
84 | |||
77 | mailbox_messages_count (mbox, &count); | 85 | mailbox_messages_count (mbox, &count); |
78 | for (i = 1; i <= count; ++i) | 86 | for (i = 1; i <= count; ++i) |
79 | { | 87 | { |
80 | message_t msg; | 88 | message_t msg; |
81 | header_t hdr; | 89 | header_t hdr; |
90 | size_t len = 0; | ||
82 | if ((status = mailbox_get_message (mbox, i, &msg)) != 0 | 91 | if ((status = mailbox_get_message (mbox, i, &msg)) != 0 |
83 | || (status = message_get_header (msg, &hdr)) != 0) | 92 | || (status = message_get_header (msg, &hdr)) != 0) |
84 | { | 93 | { |
85 | fprintf (stderr, "msg %d : %s\n", i, strerror(status)); | 94 | fprintf (stderr, "msg %d : %s\n", i, strerror(status)); |
86 | exit(2); | 95 | exit(2); |
87 | } | 96 | } |
88 | header_get_value (hdr, MU_HEADER_FROM, from, 30, NULL); | ||
89 | header_get_value (hdr, MU_HEADER_SUBJECT, subject, 40, NULL); | ||
90 | 97 | ||
91 | fprintf (stdout, "%s\t%s\n", from, subject); | 98 | header_get_value (hdr, MU_HEADER_FROM, buf, sizeof (buf), &len); |
99 | if (len != 0) | ||
100 | { | ||
101 | address_t address = NULL; | ||
102 | address_create (&address, buf); | ||
103 | len = 0; | ||
104 | address_get_personal (address, personal, sizeof (personal), &len); | ||
105 | printf ("%s\t", (len != 0) ? personal : buf); | ||
106 | address_destroy (&address); | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | header_get_value (hdr, MU_HEADER_TO, buf, sizeof (buf), &len); | ||
111 | printf ("%s\t", buf); | ||
112 | } | ||
113 | |||
114 | header_get_value (hdr, MU_HEADER_SUBJECT, buf, sizeof (buf), NULL); | ||
115 | printf ("%s\n", buf); | ||
92 | } | 116 | } |
93 | mailbox_close (mbox); | 117 | mailbox_close (mbox); |
94 | return 0; | 118 | return 0; | ... | ... |
include/mailutils/address.h
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifndef _MAILUTILS_ADDRESS_H | ||
19 | #define _MAILUTILS_ADDRESS_H | ||
20 | |||
21 | #include <sys/types.h> | ||
22 | |||
23 | #ifndef __P | ||
24 | # ifdef __STDC__ | ||
25 | # define __P(args) args | ||
26 | # else | ||
27 | # define __P(args) () | ||
28 | # endif | ||
29 | #endif /*__P */ | ||
30 | |||
31 | #ifdef _cplusplus | ||
32 | extern "C" { | ||
33 | #endif | ||
34 | |||
35 | struct _address; | ||
36 | typedef struct _address *address_t; | ||
37 | |||
38 | extern int address_create __P ((address_t *, const char *)); | ||
39 | extern void address_destroy __P ((address_t *)); | ||
40 | |||
41 | extern int address_get_email __P ((address_t, char *, size_t, size_t *)); | ||
42 | extern int address_get_personal __P ((address_t, char *, size_t, size_t *)); | ||
43 | extern int address_get_comments __P ((address_t, char *, size_t, size_t *)); | ||
44 | extern int address_get_address __P ((address_t, char *, size_t, size_t *)); | ||
45 | |||
46 | #ifdef _cplusplus | ||
47 | } | ||
48 | #endif | ||
49 | |||
50 | #endif /* _MAILUTILS_ADDRESS_H */ |
mailbox/address.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | |||
22 | #include <string.h> | ||
23 | #include <stdio.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <string.h> | ||
26 | #include <ctype.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <errno.h> | ||
29 | |||
30 | #include <address0.h> | ||
31 | #include <misc.h> | ||
32 | |||
33 | /* | ||
34 | * parseaddr.c Read a valid RFC822 address with all the comments | ||
35 | * etc in it, and return _just_ the email address. | ||
36 | * | ||
37 | * Version: @(#)parseaddr.c 1.00 02-Apr-1999 miquels@cistron.nl | ||
38 | * | ||
39 | */ | ||
40 | |||
41 | struct token | ||
42 | { | ||
43 | struct token *next; | ||
44 | char word[1]; | ||
45 | }; | ||
46 | |||
47 | #define SKIPSPACE(p) do { while(*p && isspace(*p)) p++; } while(0) | ||
48 | |||
49 | /* Skip everything between quotes. */ | ||
50 | static void | ||
51 | quotes (const char **ptr) | ||
52 | { | ||
53 | const char *p = *ptr; | ||
54 | |||
55 | p++; | ||
56 | while (*p && *p != '"') | ||
57 | { | ||
58 | if (*p == '\\' && p[1]) | ||
59 | p++; | ||
60 | p++; | ||
61 | } | ||
62 | *ptr = p; | ||
63 | } | ||
64 | |||
65 | /* Return the next token. A token can be "<>()," or any "word". */ | ||
66 | static struct token * | ||
67 | gettoken (const char **ptr) | ||
68 | { | ||
69 | struct token *tok; | ||
70 | const char *p = *ptr; | ||
71 | const char *begin; | ||
72 | int l, quit = 0; | ||
73 | |||
74 | SKIPSPACE(p); | ||
75 | begin = p; | ||
76 | |||
77 | while (!quit) | ||
78 | { | ||
79 | switch (*p) | ||
80 | { | ||
81 | case 0: | ||
82 | case ' ': | ||
83 | case '\t': | ||
84 | case '\n': | ||
85 | quit = 1; | ||
86 | break; | ||
87 | case '(': | ||
88 | case ')': | ||
89 | case '<': | ||
90 | case '>': | ||
91 | case ',': | ||
92 | if (p == begin) | ||
93 | p++; | ||
94 | quit = 1; | ||
95 | break; | ||
96 | case '\\': | ||
97 | if (p[1]) | ||
98 | p++; | ||
99 | break; | ||
100 | case '"': | ||
101 | quotes (&p); | ||
102 | break; | ||
103 | } | ||
104 | if (!quit) | ||
105 | p++; | ||
106 | } | ||
107 | |||
108 | l = p - begin; | ||
109 | if (l == 0) | ||
110 | return NULL; | ||
111 | tok = malloc (sizeof (struct token) + l); | ||
112 | if (tok == NULL) | ||
113 | return NULL; | ||
114 | tok->next = NULL; | ||
115 | strncpy (tok->word, begin, l); | ||
116 | tok->word[l] = 0; | ||
117 | |||
118 | SKIPSPACE (p); | ||
119 | *ptr = p; | ||
120 | |||
121 | return tok; | ||
122 | } | ||
123 | |||
124 | /* Get email address from rfc822 address. */ | ||
125 | /* Note: This again as for header.c an awfull way of doing things. | ||
126 | Meaning I need a correct rfc822 Parser. This one does not | ||
127 | understand group. There is not doubt a better way to do this. */ | ||
128 | int | ||
129 | address_create (address_t *paddress, const char *addr) | ||
130 | { | ||
131 | const char *p; | ||
132 | struct token *t, *tok, *last; | ||
133 | struct token *brace = NULL; | ||
134 | struct token *comments = NULL; | ||
135 | struct token *start_comments = NULL; | ||
136 | address_t address; | ||
137 | address_t head; | ||
138 | int in_comment = 0; | ||
139 | int status = 0; | ||
140 | |||
141 | tok = last = NULL; | ||
142 | |||
143 | address = calloc (1, sizeof (*address)); | ||
144 | if (address == NULL) | ||
145 | return ENOMEM; | ||
146 | head = address; | ||
147 | /* Read address, remove comments right away. */ | ||
148 | p = addr; | ||
149 | while ((t = gettoken(&p)) != NULL && (t->word[0] != ',' || in_comment)) | ||
150 | { | ||
151 | if (t->word[0] == '(' || t->word[0] == ')' || in_comment) | ||
152 | { | ||
153 | if (t->word[0] == '(') | ||
154 | in_comment++; | ||
155 | if (t->word[0] == ')') | ||
156 | in_comment--; | ||
157 | if (!start_comments) | ||
158 | comments = start_comments = t; | ||
159 | else | ||
160 | { | ||
161 | comments->next = t; | ||
162 | comments = t; | ||
163 | } | ||
164 | continue; | ||
165 | } | ||
166 | |||
167 | if (t->word[0] == '<') | ||
168 | brace = t; | ||
169 | |||
170 | if (tok) | ||
171 | last->next = t; | ||
172 | else | ||
173 | tok = t; | ||
174 | last = t; | ||
175 | } | ||
176 | |||
177 | address->addr = strdup (addr); | ||
178 | if (address->addr == NULL) | ||
179 | { | ||
180 | address_destroy (&address); | ||
181 | status = ENOMEM; | ||
182 | goto freenodes; | ||
183 | } | ||
184 | |||
185 | /* Put extracted address into email */ | ||
186 | t = brace ? brace->next : tok; | ||
187 | for (; t && t->word[0] != ',' && t->word[0] != '>'; t = t->next) | ||
188 | { | ||
189 | char *tmp; | ||
190 | if (address->email | ||
191 | && (tmp = realloc (address->email, strlen (address->email) | ||
192 | + strlen (t->word) + 1)) != NULL) | ||
193 | { | ||
194 | address->email = tmp; | ||
195 | strcat (address->email, t->word); | ||
196 | } | ||
197 | else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL) | ||
198 | { | ||
199 | address->email = tmp; | ||
200 | strcat (address->email, t->word); | ||
201 | } | ||
202 | else | ||
203 | { | ||
204 | address_destroy (&address); | ||
205 | status = ENOMEM; | ||
206 | goto freenodes; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | /* Extract Comments. */ | ||
211 | for (t = start_comments; t ; t = t->next) | ||
212 | { | ||
213 | char *tmp; | ||
214 | if (t->word[0] == '(' || t->word[0] == ')') | ||
215 | continue; | ||
216 | if (address->comments | ||
217 | && (tmp = realloc (address->comments, strlen (address->comments) | ||
218 | + strlen (t->word) + 2)) != NULL) | ||
219 | { | ||
220 | address->comments = tmp; | ||
221 | strcat (address->comments, " "); | ||
222 | strcat (address->comments, t->word); | ||
223 | } | ||
224 | else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL) | ||
225 | { | ||
226 | address->comments = tmp; | ||
227 | strcat (address->comments, t->word); | ||
228 | } | ||
229 | else | ||
230 | { | ||
231 | address_destroy (&address); | ||
232 | status = ENOMEM; | ||
233 | goto freenodes; | ||
234 | } | ||
235 | } | ||
236 | |||
237 | /* Extract Personal. */ | ||
238 | if (brace == NULL) | ||
239 | { | ||
240 | address->personal = strdup (""); | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | int in_brace = 0; | ||
245 | for (t = tok; t ; t = t->next) | ||
246 | { | ||
247 | char *tmp; | ||
248 | if (t->word[0] == '<' || t->word[0] == '>' || in_brace) | ||
249 | { | ||
250 | if (t->word[0] == '<') | ||
251 | in_brace++; | ||
252 | else if (t->word[0] == '>') | ||
253 | in_brace--; | ||
254 | continue; | ||
255 | } | ||
256 | if (address->personal | ||
257 | && (tmp = realloc (address->personal, strlen (address->personal) | ||
258 | + strlen (t->word) + 2)) != NULL) | ||
259 | { | ||
260 | address->personal = tmp; | ||
261 | strcat (address->personal, " "); | ||
262 | strcat (address->personal, t->word); | ||
263 | } | ||
264 | else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL) | ||
265 | { | ||
266 | address->personal = tmp; | ||
267 | strcat (address->personal, t->word); | ||
268 | } | ||
269 | else | ||
270 | { | ||
271 | address_destroy (&address); | ||
272 | status = ENOMEM; | ||
273 | goto freenodes; | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
278 | *paddress = head; | ||
279 | |||
280 | /* Free list of tokens. */ | ||
281 | freenodes: | ||
282 | for (t = tok; t; t = last) | ||
283 | { | ||
284 | last = t->next; | ||
285 | free (t); | ||
286 | } | ||
287 | |||
288 | return status; | ||
289 | } | ||
290 | |||
291 | void | ||
292 | address_destroy (address_t *paddress) | ||
293 | { | ||
294 | if (paddress && *paddress) | ||
295 | { | ||
296 | address_t address = *paddress; | ||
297 | address_t current; | ||
298 | for (; address; address = current) | ||
299 | { | ||
300 | if (address->comments) | ||
301 | free (address->comments); | ||
302 | if (address->personal) | ||
303 | free (address->personal); | ||
304 | if (address->email) | ||
305 | free (address->email); | ||
306 | current = address->next; | ||
307 | free (address); | ||
308 | } | ||
309 | *paddress = NULL; | ||
310 | } | ||
311 | } | ||
312 | |||
313 | int | ||
314 | address_get_personal (address_t addr, char *buf, size_t len, size_t *n) | ||
315 | { | ||
316 | size_t i; | ||
317 | if (addr == NULL) | ||
318 | return EINVAL; | ||
319 | i = _cpystr (buf, addr->personal, len); | ||
320 | if (n) | ||
321 | *n = i; | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | int | ||
326 | address_get_comments (address_t addr, char *buf, size_t len, size_t *n) | ||
327 | { | ||
328 | size_t i; | ||
329 | if (addr == NULL) | ||
330 | return EINVAL; | ||
331 | i = _cpystr (buf, addr->comments, len); | ||
332 | if (n) | ||
333 | *n = i; | ||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | int | ||
338 | address_get_email (address_t addr, char *buf, size_t len, size_t *n) | ||
339 | { | ||
340 | size_t i; | ||
341 | if (addr == NULL) | ||
342 | return EINVAL; | ||
343 | i = _cpystr (buf, addr->email, len); | ||
344 | if (n) | ||
345 | *n = i; | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | int | ||
350 | address_get_address (address_t addr, char *buf, size_t len, size_t *n) | ||
351 | { | ||
352 | size_t i; | ||
353 | if (addr == NULL) | ||
354 | return EINVAL; | ||
355 | i = _cpystr (buf, addr->addr, len); | ||
356 | if (n) | ||
357 | *n = i; | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | #if 0 | ||
362 | int | ||
363 | main (int argc, char **argv) | ||
364 | { | ||
365 | address_t addr; | ||
366 | int i; | ||
367 | |||
368 | address_create (&addr, argv[1]); | ||
369 | for (i = 0; addr; addr = addr->next, i++) | ||
370 | { | ||
371 | printf ("%d\n", i); | ||
372 | if (addr->addr) | ||
373 | printf ("Address |%s|\n", addr->addr); | ||
374 | if (addr->comments) | ||
375 | printf ("Comments |%s|\n", addr->comments); | ||
376 | if (addr->personal) | ||
377 | printf ("Personal |%s|\n", addr->personal); | ||
378 | if (addr->email) | ||
379 | printf ("Email |%s|\n", addr->email); | ||
380 | } | ||
381 | return 0; | ||
382 | } | ||
383 | #endif |
mailbox/include/address0.h
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifndef _ADDRESS0_H | ||
19 | #define _ADDRESS_0H | ||
20 | |||
21 | #include <mailutils/address.h> | ||
22 | |||
23 | #ifndef __P | ||
24 | # ifdef __STDC__ | ||
25 | # define __P(args) args | ||
26 | # else | ||
27 | # define __P(args) () | ||
28 | # endif | ||
29 | #endif /*__P */ | ||
30 | |||
31 | #ifdef _cplusplus | ||
32 | extern "C" { | ||
33 | #endif | ||
34 | |||
35 | struct _address | ||
36 | { | ||
37 | char *comments; | ||
38 | char *personal; | ||
39 | char *email; | ||
40 | char *addr; | ||
41 | size_t num; | ||
42 | struct _address *next; | ||
43 | }; | ||
44 | |||
45 | #ifdef _cplusplus | ||
46 | } | ||
47 | #endif | ||
48 | |||
49 | #endif /* _ADDRESS0_H */ |
... | @@ -59,9 +59,9 @@ struct token | ... | @@ -59,9 +59,9 @@ struct token |
59 | 59 | ||
60 | /* Skip everything between quotes. */ | 60 | /* Skip everything between quotes. */ |
61 | static void | 61 | static void |
62 | quotes (char **ptr) | 62 | quotes (const char **ptr) |
63 | { | 63 | { |
64 | char *p = *ptr; | 64 | const char *p = *ptr; |
65 | 65 | ||
66 | p++; | 66 | p++; |
67 | while (*p && *p != '"') | 67 | while (*p && *p != '"') |
... | @@ -75,11 +75,11 @@ quotes (char **ptr) | ... | @@ -75,11 +75,11 @@ quotes (char **ptr) |
75 | 75 | ||
76 | /* Return the next token. A token can be "<>()," or any "word". */ | 76 | /* Return the next token. A token can be "<>()," or any "word". */ |
77 | static struct token * | 77 | static struct token * |
78 | gettoken (char **ptr) | 78 | gettoken (const char **ptr) |
79 | { | 79 | { |
80 | struct token *tok; | 80 | struct token *tok; |
81 | char *p = *ptr; | 81 | const char *p = *ptr; |
82 | char *begin; | 82 | const char *begin; |
83 | int l, quit = 0; | 83 | int l, quit = 0; |
84 | 84 | ||
85 | SKIPSPACE(p); | 85 | SKIPSPACE(p); | ... | ... |
-
Please register or sign in to post a comment