From Sam.
* examples/{Makefile,Addrs,addr.c,Addrs.good}: address test f/w. * include/mailutils/address.h,mailbox/{address.c,parse822.c}: now stuff a group name into an _address, and added a function to do a quick check if it is a group. * mailbox/parse822.c: fixed bug where ",sam@foo.bar" wasn't valid.
Showing
8 changed files
with
222 additions
and
37 deletions
1 | 2001-04-14 Sam Roberts | ||
2 | * examples/{Makefile,Addrs,addr.c,Addrs.good}: address test f/w. | ||
3 | * include/mailutils/address.h,mailbox/{address.c,parse822.c}: now | ||
4 | stuff a group name into an _address, and added a function to do | ||
5 | a quick check if it is a group. | ||
6 | * mailbox/parse822.c: fixed bug where ",sam@foo.bar" wasn't valid. | ||
7 | |||
1 | 2001-04-14 Alain Magloire | 8 | 2001-04-14 Alain Magloire |
2 | 9 | ||
3 | * mailbox/folder_imap.c: When calling imap_writeline () the | 10 | * mailbox/folder_imap.c: When calling imap_writeline () the | ... | ... |
... | @@ -11,14 +11,13 @@ RFC 822 for the details. "[]" pairs mean "optional", "/" means "one or | ... | @@ -11,14 +11,13 @@ RFC 822 for the details. "[]" pairs mean "optional", "/" means "one or |
11 | the other", and double-quoted characters are literals. | 11 | the other", and double-quoted characters are literals. |
12 | 12 | ||
13 | @example | 13 | @example |
14 | address-list = address ["," address-list] | ||
15 | address = mailbox / group | ||
16 | mailbox = addr-spec ["(" personal ")"] / | ||
17 | [personal] "<" [route] addr-spec ">" | ||
18 | addr-spec = local-part "@" domain | 14 | addr-spec = local-part "@" domain |
19 | group = phrase ":" mailbox-list ";" | 15 | mailbox = addr-spec ["(" display-name ")"] / |
20 | 16 | [display-name] "<" [route] addr-spec ">" | |
21 | mailbox-list = mailbox ["," mailbox-list] | 17 | mailbox-list = mailbox ["," mailbox-list] |
18 | group = display-name ":" [mailbox-list] ";" | ||
19 | address = mailbox / group | ||
20 | address-list = address ["," address-list] | ||
22 | @end example | 21 | @end example |
23 | 22 | ||
24 | Several address functions have a set of common arguments with consistent | 23 | Several address functions have a set of common arguments with consistent |
... | @@ -98,12 +97,18 @@ The return value is @code{0} on success and a code number on error conditions: | ... | @@ -98,12 +97,18 @@ The return value is @code{0} on success and a code number on error conditions: |
98 | 97 | ||
99 | @deftypefun int address_get_personal (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n}) | 98 | @deftypefun int address_get_personal (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n}) |
100 | 99 | ||
101 | Acesses the personal phrase describing the @var{no}th email address. This | 100 | Acesses the display-name describing the @var{no}th email address. This |
102 | personal is optional, so may not be present. If it is not present, but | 101 | display-name is optional, so may not be present. If it is not present, but |
103 | there is an RFC822 comment after the address, that comment will be | 102 | there is an RFC822 comment after the address, that comment will be |
104 | returned as the personal phrase, as this is a common usage of the comment | 103 | returned as the personal phrase, as this is a common usage of the comment |
105 | even though it is not defined in the internet mail standard. | 104 | even though it is not defined in the internet mail standard. |
106 | 105 | ||
106 | A group is a kind of a special case. It has a display-name, followed | ||
107 | by an optional mailbox-list. The display-name will be allocated an address | ||
108 | all it's own, but all the other elements (local-part, domain, etc.) will | ||
109 | be zero-length. So "a group: ;" is valid, will have a count of 1, but | ||
110 | address_get_email(), and all the rest, will return zero-length output. | ||
111 | |||
107 | The return value is @code{0} on success and a code number on error conditions: | 112 | The return value is @code{0} on success and a code number on error conditions: |
108 | @table @code | 113 | @table @code |
109 | @ADDRESSEINVAL | 114 | @ADDRESSEINVAL |
... | @@ -175,6 +180,24 @@ The return value is @code{0} on success and a code number on error conditions: | ... | @@ -175,6 +180,24 @@ The return value is @code{0} on success and a code number on error conditions: |
175 | @end table | 180 | @end table |
176 | @end deftypefun | 181 | @end deftypefun |
177 | 182 | ||
183 | @deftypefun int address_is_group (address_t *@var{addr}, size_t @var{no}, size_t @var{len}, int* @var{yes}) | ||
184 | |||
185 | Sets *@var{yes} to @code{1} if this address is just the name of a group, | ||
186 | @code{0} otherwise. This is faster than checking if the address has | ||
187 | a non-zero length personal, and a zero-length local_part and domain. | ||
188 | |||
189 | @var{yes} can be @code{nul}, though that doesn't serve much purpose other | ||
190 | than determining that @var{no} refers to an address. | ||
191 | |||
192 | Currently, there is no way to determine the end of the group. | ||
193 | |||
194 | The return value is @code{0} on success and a code number on error conditions: | ||
195 | @table @code | ||
196 | @ADDRESSEINVAL | ||
197 | @ADDRESSENOENT | ||
198 | @end table | ||
199 | @end deftypefun | ||
200 | |||
178 | @deftypefun int address_to_string (address_t *@var{addr}, char* @var{buf}, size_t @var{len}, size_t* @var{n}) | 201 | @deftypefun int address_to_string (address_t *@var{addr}, char* @var{buf}, size_t @var{len}, size_t* @var{n}) |
179 | 202 | ||
180 | Returns the entire address list as a single RFC822 formatted address | 203 | Returns the entire address list as a single RFC822 formatted address | ... | ... |
1 | Sam <@[matrix (smtp)], @[nexus: \[node 12\]]:sroberts@[10].[1]> | 1 | Sam <@[matrix (smtp)], @[nexus: \[node 12\]]:sroberts@[10].[1]> ; |
2 | a@b,z@y | ||
3 | ,a@b,z@y | ||
4 | a@b,z@y, | ||
5 | ,a@b,z@y, | ||
6 | a@b,,z@y | ||
7 | a@b,,,z@y | ||
8 | ,,,a@b,,, | ||
9 | ,a@b | ||
10 | a@b, | ||
11 | , | ||
12 | ,, | ||
13 | ,,, | ||
14 | a group: a@b,z@y ; | ||
15 | a group: ,a@b,z@y ; | ||
16 | a group: a@b,z@y, ; | ||
17 | a group: ,a@b,z@y, ; | ||
18 | a group: a@b,,z@y ; | ||
19 | a group: a@b,,,z@y ; | ||
20 | a group: ,,,a@b,,, ; | ||
21 | a group: ,a@b ; | ||
22 | a group: a@b, ; | ||
23 | a group: , ; | ||
24 | a group: ,, ; | ||
25 | a group: ,,, ; | ||
26 | Sam <@[matrix (smtp)], @[nexus: \[node 12\]]:sroberts@[10].[1]> ; | ||
2 | Aliens: Sam <@[matrix (smtp)]: sam@sam>, sroberts@[10].[1]; | 27 | Aliens: Sam <@[matrix (smtp)]: sam@sam>, sroberts@[10].[1]; |
3 | lo@hi, Aliens: Sam <@[matrix (smtp)]: sam@sam>, sroberts@[10].[1]; | 28 | lo@hi, Aliens: Sam <@[matrix (smtp)]: sam@sam>, sroberts@[10].[1]; |
4 | Aliens: Sam <@[matrix (smtp)]: sam@sam>, sroberts@[10].[1];, hi@lo | 29 | Aliens: Sam <@[matrix (smtp)]: sam@sam>, sroberts@[10].[1];, hi@lo |
... | @@ -15,7 +40,7 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=) | ... | @@ -15,7 +40,7 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=) |
15 | "'paul@pitbull-productions.com'" <paul@pitbull-productions.com>, | 40 | "'paul@pitbull-productions.com'" <paul@pitbull-productions.com>, |
16 | "'sam@cogent.ca'" <sam@cogent.ca>, "'sroberts@uniserve.com'" | 41 | "'sam@cogent.ca'" <sam@cogent.ca>, "'sroberts@uniserve.com'" |
17 | "'sroberts\@certicom\.ca'" <sroberts@certicom.ca> | 42 | "'sroberts\@certicom\.ca'" <sroberts@certicom.ca> |
18 | "=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=" <jcmarcos@datavoicees> | 43 | "=?iso-8859-1?Q?Juan_Carlos_Marcos_Rodr=EDguez?=" <jcmarcos@datavoice.es> |
19 | "Christian Edward Gruber" <christian.edward.gruber@gmx.net>, | 44 | "Christian Edward Gruber" <christian.edward.gruber@gmx.net>, |
20 | "D. J. Bernstein" <"djb- "@cr.yp.to> | 45 | "D. J. Bernstein" <"djb- "@cr.yp.to> |
21 | "D. J. Bernstein" <djb@cr.yp.to>, drums@cs.utk.edu | 46 | "D. J. Bernstein" <djb@cr.yp.to>, drums@cs.utk.edu |
... | @@ -58,9 +83,9 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=) | ... | @@ -58,9 +83,9 @@ list-ietf-wg-apps-drums@faerber.muc.de (=?ISO-8859-1?Q?Claus_F=E4rber?=) |
58 | =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@cisco.com> | 83 | =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@cisco.com> |
59 | =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@cisco.com>, | 84 | =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@cisco.com>, |
60 | =?US-ASCII?Q?gary=5Fc?= <gary_c@cunningham-lee.com> | 85 | =?US-ASCII?Q?gary=5Fc?= <gary_c@cunningham-lee.com> |
61 | =?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidusnet> | 86 | =?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidus.net> |
62 | =?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidusnet>, | 87 | =?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E?= Meunier <0@pervalidus.net>, |
63 | =?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?= <0@pervalidusnet> | 88 | =?iso-8859-1?Q?Fr=E9d=E9ric_L_=2E_W_=2E_Meunier?= <0@pervalidus.net> |
64 | =?iso-8859-1?Q?J=F8rgen_Thomsen?= <jth@postfix.jth.net> | 89 | =?iso-8859-1?Q?J=F8rgen_Thomsen?= <jth@postfix.jth.net> |
65 | =?iso-8859-1?Q?Jos=3F_C=2E_Garc=EDa_Sogo?= <jose@jaimedelamo.eu.org> | 90 | =?iso-8859-1?Q?Jos=3F_C=2E_Garc=EDa_Sogo?= <jose@jaimedelamo.eu.org> |
66 | =?iso-8859-1?Q?Mikko_H=E4nninen?= <Mikko.Hanninen@dna.fi> | 91 | =?iso-8859-1?Q?Mikko_H=E4nninen?= <Mikko.Hanninen@dna.fi> | ... | ... |
1 | CFLAGS = -Wall -pedantic -g | 1 | # Makefile |
2 | INCLUDES = -I../libmailbox | 2 | |
3 | LIBS = ../libmailbox/.libs/libmailbox.al | 3 | CFLAGS = -g -I../include |
4 | LDFLAGS = -g -static | ||
5 | LIBS = ../mailbox/.libs/libmailbox.a ../lib/libmailutils.a | ||
6 | |||
7 | default: addr | ||
8 | |||
9 | # showmail | ||
4 | 10 | ||
5 | showmail: showmail.c $(LIBS) | 11 | showmail: showmail.c $(LIBS) |
6 | $(CC) $(CFLAGS) $(INCLUDES) -o showmail showmail.c $(LIBS) | 12 | $(CC) $(CFLAGS) -o $@ $< $(LIBS) |
13 | |||
14 | # addr example and test | ||
15 | |||
16 | test: addr | ||
17 | ./addr < Addrs > Addrs.test | ||
18 | diff -u Addrs.good Addrs.test | ||
19 | @echo "---- There should be no differences! ----" | ||
7 | 20 | ||
8 | addr: addr.c $(LIBS) | 21 | addr: addr.c $(LIBS) |
9 | $(CC) $(CFLAGS) $(INCLUDES) -o addr addr.c $(LIBS) | 22 | $(CC) $(CFLAGS) -o $@ $< $(LIBS) |
23 | |||
24 | # clean and empty | ||
10 | 25 | ||
11 | clean: | 26 | clean: |
27 | rm -f *.o | ||
28 | |||
29 | empty: clean | ||
12 | rm -f addr showmail | 30 | rm -f addr showmail |
31 | ... | ... |
1 | #include <stdio.h> | 1 | #include <stdio.h> |
2 | #include <errno.h> | ||
2 | #include <mailutils/address.h> | 3 | #include <mailutils/address.h> |
3 | 4 | ||
5 | #define EPARSE ENOENT | ||
6 | |||
7 | static const char* err_name(int e) | ||
8 | { | ||
9 | struct { | ||
10 | int e; | ||
11 | const char* s; | ||
12 | } map[] = { | ||
13 | #define E(e) { e, #e }, | ||
14 | E(ENOENT) | ||
15 | E(EINVAL) | ||
16 | E(ENOMEM) | ||
17 | #undef E | ||
18 | { 0, NULL } | ||
19 | }; | ||
20 | static char s[sizeof(int) * 8 + 3]; | ||
21 | int i; | ||
22 | |||
23 | for(i = 0; map[i].s; i++) { | ||
24 | if(map[i].e == e) | ||
25 | return map[i].s; | ||
26 | } | ||
27 | sprintf(s, "[%d]", e); | ||
28 | |||
29 | return s; | ||
30 | } | ||
31 | |||
4 | static int parse(const char* str) | 32 | static int parse(const char* str) |
5 | { | 33 | { |
6 | size_t no = 0; | 34 | size_t no = 0; |
7 | size_t pcount; | 35 | size_t pcount = 0; |
36 | int status; | ||
8 | 37 | ||
9 | char buf[BUFSIZ]; | 38 | char buf[BUFSIZ]; |
10 | 39 | ||
11 | address_t address = NULL; | 40 | address_t address = NULL; |
12 | 41 | ||
13 | address_create(&address, str); | 42 | status = address_create(&address, str); |
14 | 43 | ||
15 | address_get_count(address, &pcount); | 44 | address_get_count(address, &pcount); |
16 | 45 | ||
46 | if(status) { | ||
47 | printf("%s=> error %s\n\n", str, err_name(status)); | ||
48 | return 0; | ||
49 | } else { | ||
17 | printf("%s=> pcount %d\n", str, pcount); | 50 | printf("%s=> pcount %d\n", str, pcount); |
51 | } | ||
18 | 52 | ||
19 | for(no = 1; no <= pcount; no++) { | 53 | for(no = 1; no <= pcount; no++) { |
20 | size_t got = 0; | 54 | size_t got = 0; |
55 | int isgroup; | ||
56 | |||
57 | address_is_group(address, no, &isgroup); | ||
58 | |||
21 | printf("%d ", no); | 59 | printf("%d ", no); |
22 | 60 | ||
61 | if(isgroup) { | ||
62 | address_get_personal(address, no, buf, sizeof(buf), &got); | ||
63 | |||
64 | printf("group <%s>\n", buf); | ||
65 | } else { | ||
23 | address_get_email(address, no, buf, sizeof(buf), 0); | 66 | address_get_email(address, no, buf, sizeof(buf), 0); |
24 | 67 | ||
25 | printf("email <%s>\n", buf); | 68 | printf("email <%s>\n", buf); |
69 | } | ||
26 | 70 | ||
27 | address_get_personal(address, no, buf, sizeof(buf), &got); | 71 | address_get_personal(address, no, buf, sizeof(buf), &got); |
28 | 72 | ||
29 | if(got) printf(" personal <%s>\n", buf); | 73 | if(got && !isgroup) printf(" personal <%s>\n", buf); |
30 | 74 | ||
31 | address_get_comments(address, no, buf, sizeof(buf), &got); | 75 | address_get_comments(address, no, buf, sizeof(buf), &got); |
32 | 76 | ... | ... |
... | @@ -52,6 +52,9 @@ extern int address_get_comments | ... | @@ -52,6 +52,9 @@ extern int address_get_comments |
52 | extern int address_get_route | 52 | extern int address_get_route |
53 | __P ((address_t, size_t, char *, size_t, size_t *)); | 53 | __P ((address_t, size_t, char *, size_t, size_t *)); |
54 | 54 | ||
55 | extern int address_is_group | ||
56 | __P ((address_t, size_t, int*)); | ||
57 | |||
55 | extern int address_to_string __P ((address_t, char *, size_t, size_t *)); | 58 | extern int address_to_string __P ((address_t, char *, size_t, size_t *)); |
56 | extern int address_get_count __P ((address_t, size_t *)); | 59 | extern int address_get_count __P ((address_t, size_t *)); |
57 | 60 | ... | ... |
... | @@ -46,8 +46,7 @@ address_create (address_t *a, const char *s) | ... | @@ -46,8 +46,7 @@ address_create (address_t *a, const char *s) |
46 | status = parse822_address_list (a, (char*) s); | 46 | status = parse822_address_list (a, (char*) s); |
47 | if (status == 0) | 47 | if (status == 0) |
48 | { | 48 | { |
49 | /* There was a group that got parsed correctly, but had | 49 | /* And address-list may contain 0 addresses but parse correctly. |
50 | * no addresses... | ||
51 | */ | 50 | */ |
52 | if (!*a) | 51 | if (!*a) |
53 | return ENOENT; | 52 | return ENOENT; |
... | @@ -220,6 +219,29 @@ address_get_route (address_t addr, size_t no, char *buf, size_t len, size_t *n) | ... | @@ -220,6 +219,29 @@ address_get_route (address_t addr, size_t no, char *buf, size_t len, size_t *n) |
220 | return status; | 219 | return status; |
221 | } | 220 | } |
222 | 221 | ||
222 | int | ||
223 | address_is_group (address_t addr, size_t no, int* yes) | ||
224 | { | ||
225 | size_t j; | ||
226 | int status = ENOENT; | ||
227 | if(addr == NULL) | ||
228 | return EINVAL; | ||
229 | for (j = 1; addr; addr = addr->next, j++) | ||
230 | { | ||
231 | if (j == no) | ||
232 | { | ||
233 | status = 0; | ||
234 | if(yes) | ||
235 | { | ||
236 | *yes = 0; | ||
237 | if(addr->personal && !addr->local_part && !addr->domain) | ||
238 | *yes = 1; | ||
239 | } | ||
240 | break; | ||
241 | } | ||
242 | } | ||
243 | return status; | ||
244 | } | ||
223 | 245 | ||
224 | int | 246 | int |
225 | address_to_string (address_t addr, char *buf, size_t len, size_t *n) | 247 | address_to_string (address_t addr, char *buf, size_t len, size_t *n) | ... | ... |
... | @@ -18,18 +18,41 @@ | ... | @@ -18,18 +18,41 @@ |
18 | /* | 18 | /* |
19 | Things to consider: | 19 | Things to consider: |
20 | 20 | ||
21 | - A group should create an address node with a group, accessable | 21 | - A group should create an address node for a group, accessable |
22 | with address_get_group(). | 22 | with address_get_personal(). Perhaps an is_group() would be |
23 | useful? Test that a zero-length phrase is rejected! So these | ||
24 | are invalid: | ||
25 | : a@b ; | ||
26 | "" : ; | ||
27 | |||
28 | - When parsing phrase, should I ignore non-ascii, or replace with a | ||
29 | '?' character? Right now parsing fails. | ||
23 | 30 | ||
24 | - Make domain optional in addr-spec, for parsing address lists | 31 | - Make domain optional in addr-spec, for parsing address lists |
25 | provided to local mail utilities. | 32 | provided to local mail utilities, but NOT in the addr-spec of a |
33 | route-addr. | ||
34 | |||
35 | - Are comments allowed in domain-literals? | ||
36 | |||
37 | - Need a way to mark the *end* of a group. Maybe add a field to _address, | ||
38 | int group_end;, so if you care, you can search for the end of | ||
39 | a group with address_is_group_end(); | ||
40 | |||
41 | - Need a way to parse "<>", it's a valid SMTP address... | ||
42 | |||
43 | - Need a way to parse ",,,", it's a valid address-list, it just doesn't | ||
44 | have any addresses. | ||
45 | |||
46 | - Functions for forming email addresses, quoting display-name, etc. | ||
47 | |||
48 | - The personal for ""Sam"" <sam@here> is "Sam", and for "'s@b'" <s@b> | ||
49 | is 's@b', should I strip those outside parentheses, or is that | ||
50 | too intrusive? Maybe an apps business if it wants to? | ||
26 | 51 | ||
27 | - Should we do best effort parsing, so parsing "sam@locahost, foo@" | 52 | - Should we do best effort parsing, so parsing "sam@locahost, foo@" |
28 | gets one address, or just say it is or it isn't in RFC format? | 53 | gets one address, or just say it is or it isn't in RFC format? |
29 | Right now we're strict, we'll see how it goes. | 54 | Right now we're strict, we'll see how it goes. |
30 | 55 | ||
31 | - quote local-part when generating email field of address_t. | ||
32 | |||
33 | - parse field names and bodies? | 56 | - parse field names and bodies? |
34 | - parse dates? | 57 | - parse dates? |
35 | - parse Received: field? | 58 | - parse Received: field? |
... | @@ -37,6 +60,7 @@ Things to consider: | ... | @@ -37,6 +60,7 @@ Things to consider: |
37 | - test for memory leaks on malloc failure | 60 | - test for memory leaks on malloc failure |
38 | - fix the realloc, try a struct _string { char* b, size_t sz }; | 61 | - fix the realloc, try a struct _string { char* b, size_t sz }; |
39 | 62 | ||
63 | - get example mail from drums, and from the perl code. | ||
40 | */ | 64 | */ |
41 | 65 | ||
42 | #ifdef HAVE_CONFIG_H | 66 | #ifdef HAVE_CONFIG_H |
... | @@ -499,9 +523,12 @@ static int fill_mb( | ... | @@ -499,9 +523,12 @@ static int fill_mb( |
499 | (*a)->comments = comments; | 523 | (*a)->comments = comments; |
500 | (*a)->personal = personal; | 524 | (*a)->personal = personal; |
501 | 525 | ||
502 | /* this is wrong, local must be quoted */ | ||
503 | do { | 526 | do { |
504 | /* loop exists only to break out of */ | 527 | /* loop exists only to break out of */ |
528 | if(!local || !domain) { | ||
529 | /* no email to construct */ | ||
530 | break; | ||
531 | } | ||
505 | if((rc = parse822_quote_local_part(&(*a)->email, local))) | 532 | if((rc = parse822_quote_local_part(&(*a)->email, local))) |
506 | break; | 533 | break; |
507 | if((rc = str_append(&(*a)->email, "@"))) | 534 | if((rc = str_append(&(*a)->email, "@"))) |
... | @@ -531,13 +558,20 @@ int parse822_address_list(address_t* a, const char* s) | ... | @@ -531,13 +558,20 @@ int parse822_address_list(address_t* a, const char* s) |
531 | int rc = EOK; | 558 | int rc = EOK; |
532 | address_t* n = a; /* the next address we'll be creating */ | 559 | address_t* n = a; /* the next address we'll be creating */ |
533 | 560 | ||
534 | if((rc = parse822_address(p, e, n))) | 561 | rc = parse822_address(p, e, n); |
535 | return rc; | ||
536 | |||
537 | parse822_skip_comments(p, e); | ||
538 | 562 | ||
563 | /* A list may start with a leading <,>, we'll find out if | ||
564 | * that's not the case at the top of the while, but give | ||
565 | * this a conditional OK unless there was some other kind | ||
566 | * of error. | ||
567 | */ | ||
568 | if(rc != EOK && rc != EPARSE) { | ||
569 | return rc; | ||
570 | } | ||
539 | while(*p < e) | 571 | while(*p < e) |
540 | { | 572 | { |
573 | parse822_skip_comments(p, e); | ||
574 | |||
541 | /* An address can contain a group, so an entire | 575 | /* An address can contain a group, so an entire |
542 | * list of addresses may have been appended, or no | 576 | * list of addresses may have been appended, or no |
543 | * addresses at all. Walk to the end. | 577 | * addresses at all. Walk to the end. |
... | @@ -565,8 +599,6 @@ int parse822_address_list(address_t* a, const char* s) | ... | @@ -565,8 +599,6 @@ int parse822_address_list(address_t* a, const char* s) |
565 | /* anything else is a fatal error, break out */ | 599 | /* anything else is a fatal error, break out */ |
566 | break; | 600 | break; |
567 | } | 601 | } |
568 | |||
569 | parse822_skip_comments(p, e); | ||
570 | } | 602 | } |
571 | 603 | ||
572 | if(rc) { | 604 | if(rc) { |
... | @@ -595,12 +627,13 @@ int parse822_group(const char** p, const char* e, address_t* a) | ... | @@ -595,12 +627,13 @@ int parse822_group(const char** p, const char* e, address_t* a) |
595 | const char* save = *p; | 627 | const char* save = *p; |
596 | address_t* asave = a; /* so we can destroy these if parsing fails */ | 628 | address_t* asave = a; /* so we can destroy these if parsing fails */ |
597 | int rc; | 629 | int rc; |
630 | char* phrase = 0; | ||
598 | 631 | ||
599 | parse822_skip_comments(p, e); | 632 | parse822_skip_comments(p, e); |
600 | 633 | ||
601 | *p = save; | 634 | *p = save; |
602 | 635 | ||
603 | if((rc = parse822_phrase(p, e, 0))) { | 636 | if((rc = parse822_phrase(p, e, &phrase))) { |
604 | return rc; | 637 | return rc; |
605 | } | 638 | } |
606 | 639 | ||
... | @@ -611,11 +644,20 @@ int parse822_group(const char** p, const char* e, address_t* a) | ... | @@ -611,11 +644,20 @@ int parse822_group(const char** p, const char* e, address_t* a) |
611 | return rc; | 644 | return rc; |
612 | } | 645 | } |
613 | 646 | ||
647 | /* fake up an address node for the group's descriptive phrase, if | ||
648 | * it fails, clean-up will happen after the loop | ||
649 | */ | ||
650 | if((rc = fill_mb(a, 0, phrase, 0, 0)) == EOK) { | ||
651 | a = &(*a)->next; | ||
652 | } else { | ||
653 | str_free(&phrase); | ||
654 | } | ||
655 | |||
614 | /* Basically, on each loop, we may find a mailbox, but we must find | 656 | /* Basically, on each loop, we may find a mailbox, but we must find |
615 | * a comma after the mailbox, otherwise we've popped off the end | 657 | * a comma after the mailbox, otherwise we've popped off the end |
616 | * of the list. | 658 | * of the list. |
617 | */ | 659 | */ |
618 | for(;;) { | 660 | while(!rc) { |
619 | parse822_skip_comments(p, e); | 661 | parse822_skip_comments(p, e); |
620 | 662 | ||
621 | /* it's ok not be a mailbox, but other errors are fatal */ | 663 | /* it's ok not be a mailbox, but other errors are fatal */ | ... | ... |
-
Please register or sign in to post a comment