Commit a40eb4ad a40eb4ad3cc2783c38981e4446bac224dd456f0a by Alain Magloire

The first draft to be able to parse rfc822 not cute. The little

from program was use as the first test case.
1 parent a946ab0a
...@@ -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;
......
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 */
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
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);
......