Commit cbae2d18 cbae2d18a1dbe0be8fd2e78288ea5b27200e39c3 by Alain Magloire

New changes to document the address_t object and code added.

1 parent 4a49feb8
2001-03-09 Sam Roberts
* doc/address.texi: documented all the functions in address.h
* doc/url.texi: corrected location or url.h header
2001-03-08 Sam Roberts
* README-alpha: Be clearer on how to configure.
......
......@@ -3,91 +3,31 @@
The @code{address_t} object is used to hold information about a parsed
RFC822 address list, and is an opaque
data structure to the user. Functions are provided to retrieve information
about the address list. An address list is a sequence of addresses, each
of which has four components: an optional phrase describing the address, the
local-part of the address, the domain of the address, and an optional
comment field.
about a address in the address list.
If the phrase is present it is probably the personal name
associated with the the address, if not, the comment may contain some
identifying information.
Several address functions have a set of common arguments, which are described
here to avoid repetition.
Since the address-list may contain multiple addresses, they are accessed
by a @strong{one-based index number}, @var{no}.
Since an address-list may contain multiple addresses, they are accessed
by a @strong{one-based} index number, @var{no}. The index is one-based
because pop, imap, and other message stores commonly use one-based
counts to access messages and attributes of messages.
Comment: Why is this one-based? nobody
familiar with C would ever expect that!
If @var{len} is greater than @code{0} it is the length of the buffer
@var{buf}, and as much of the component as possible will be copied
into the buffer. The buffer will be nul terminated.
The size of a particular component
may be queried by providing @code{0} for the @var{len} of the buffer,
in which case the buffer is optional and if @var{n} is provided
*@var{n} is assigned the length of the component string.
If @var{len}
is greater than @code{0} it is the length of the buffer @var{buf}, and
as much of the component as possible will be copied into the buffer.
The size of a particular component may be queried by providing @code{0}
for the @var{len} of the buffer, in which case the buffer is optional.
In this case, if @var{n} is provided *@var{n} is assigned the length of
the component string.
Comments:
The API isn't complete, there are useful things you can't do.
There needs to be a way of accessing the local-part and the
domain of an email address seperately, the syntax of local-part is too complex
to expect somebody to parse it, in particular strchring for '@@'
will fail if there is an '@@' in the local-part, which is valid if
its quoted or escaped.
You can't create an address or an address list.
Creating one should apropriately quote unsafe characters in the local
part and phrase/personal name, not allow a comment (its deprecated), etc.
What about groups? They are easy to parse, but a pain from an api point
of view. _address, instead of being a pure linked list, could
be more tree-like, so each _address also contained and _address* group
member. If there was a group, then email would be the name of the group,
something like "my special group: ;", and group would be the (possibly
empty) list of addresses in the group, and each of those addresses
could in turn be a group, etc.
This data structure reflects the structure of an address ok, but doesn't
address (;-)) what happens if you had a program that just wanted to print
out all the recipients email addresses. The @var{no} could still be
a linear index into the tree, so those not wanting to know could not
know, and the group nodes could silently dissappear.
But what if you wanted to iterate the whole tree?
address_is_group(addr, no)? address_get_group_name(addr, no)?
address_get_group(addr, &addr)?
For creating, maybe the easy way is to splice an address list.
address_create(&addr, NULL)
address_insert(addr, -1, "Big John", "bluesman", "yahoo.com");
What happens if @var{no} is past the end of the list? I think you
just get zero-length output, but it should be an error, maybe EINVAL.
// -1 is the end, anything else is position to be inserted at, for ex.
address_create(&group, NULL)
address_insert(group, -1, "Sam", "sroberts", "uniserve.com");
address_insert(group, -1, "Joe @ \"home\"", "joe", "uniserve.com");
address_insert_group(addr, group, "the uniserve boys");
This would be:
@example
Big John <bluesman@@yahoo.com>, the uniserve boys: Sam
<sroberts@@uniserve.com>, "Joe @@ \"home\"" <joe@@uniserve.com> ;
@end example
This is just a sketch of what I think should be conceptually possible
in a complete address parser class. Basically the goals are to be
able to see the structure of an RFC822 address exactly (except for
comments... they get munged together if present, but what the hell,
they're comments!) and to build as complex an address as is
possible. Simple things should still be simple.
Musings:
Two problems are domain literals, and non-ascii characters. I
think domain literals should be parsed from [127.0.0.1] into
......@@ -105,7 +45,9 @@ belong here, it's a layer on top of rfc822.
@deftypefun int address_create (address_t *@var{addr}, const char *@var{string})
This function allocates and initializes @var{addr} by parsing the
RFC822 address-list @var{string}.
RFC822 address-list @var{string}. Parsing is best effort, if the
@var{string} isn't a valid RFC822 syntax list of addresses, then
the results are undefined.
The return value is @code{0} on success and a code number on error conditions:
@table @code
......@@ -118,9 +60,12 @@ Not enough memory to allocate resources.
The @var{addr} is destroyed.
@end deftypefun
@deftypefun int address_get_email (address_t *@var{addr},
size_t no, char* buf, size_t len, size_t* n)
Acesses the @var{no}th email address component.
@deftypefun int address_get_email (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n})
Acesses the @var{no}th email address component of the address list. This
address is the plain email address, correctly quoted, suitable for
using in an smtp dialog, for example, or as the address part of
a contact book entry.
The return value is @code{0} on success and a code number on error conditions:
@table @code
......@@ -129,3 +74,108 @@ The return value is @code{0} on success and a code number on error conditions:
@end table
@end deftypefun
@deftypefun int address_get_personal (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n})
Acesses the personal phrase describing the @var{no}th email address. This
phrase is optional, so may not be present.
The return value is @code{0} on success and a code number on error conditions:
@table @code
@item EINVAL
@var{addr} is NULL.
@end table
@end deftypefun
@deftypefun int address_get_comments (address_t *@var{addr}, size_t @var{no}, char* @var{buf}, size_t @var{len}, size_t* @var{n})
Acesses the comments extracted while parsing the @var{no}th email address.
These comments have no defined meaning, but in the absence of the personal
descriptive phrase, may describe the email address.
The return value is @code{0} on success and a code number on error conditions:
@table @code
@item EINVAL
@var{addr} is NULL.
@end table
@end deftypefun
@deftypefun int address_to_string (address_t *@var{addr}, char* @var{buf}, size_t @var{len}, size_t* @var{n})
Returns the entire address list as a single RFC822 formatted address
list.
The return value is @code{0} on success and a code number on error conditions:
@table @code
@item EINVAL
@var{addr} is NULL.
@end table
@end deftypefun
@deftypefun int address_get_count (address_t *@var{addr}, size_t* @var{no})
Returns the number of addresses in the address list.
The return value is @code{0} on success and a code number on error conditions:
@table @code
@item EINVAL
@var{addr} is NULL.
@end table
@end deftypefun
@section Example
@example
#include <stdio.h>
#include <mailutils/address.h>
int
main(int argc, const char *argv[])
@{
for(argc = 1; argv[argc]; argc++)
@{
const char* str = argv[argc];
address_t address = NULL;
address_create(&address, str);
printf("'%s' ->\n", str);
@{
size_t no = 0;
size_t pcount;
address_get_count(address, &pcount);
printf(" pcount %d\n", pcount);
for(no = 1; no <= pcount; no++)
@{
char buf[BUFSIZ];
address_get_personal(address, no, buf, sizeof(buf), 0);
printf(" personal '%s'\n", buf);
address_get_comments(address, no, buf, sizeof(buf), 0);
printf(" comments '%s'\n", buf);
address_get_email(address, no, buf, sizeof(buf), 0);
printf(" email '%s'\n", buf);
address_to_string(address, buf, sizeof(buf), 0);
printf(" to_string '%s'\n", buf);
@}
@}
address_destroy(&address);
@}
return 0;
@}
@end example
......
......@@ -108,7 +108,7 @@ Initialize and parse the @var{url}
@section Helper functions
@example
#include <url.h>
#include <mailutils/url.h>
#include <stdio.h>
#include <string.h>
......