*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*DRAFT*

			   IMSP client API
			   ---------------

			   by Chris Newman
			    draft 6/20/94

1.0 Status of this document
---------------------------
This is a draft of this document, and is subject to change.

1.1 Introduction
----------------
Interactive Mail Support Protocol (IMSP) provides support services for
a set of IMAP servers.  Some of these services such as options and
address books are disjoint from IMAP services.  Other services such
as the FIND and SUBSCRIBE services are designed to replace similar,
but more limited services in IMAP.  Because of the latter type of
service, it is desirable to have the IMSP client API well integrated
with the current c-client IMAP library, preferably in such a way that
a new combined c-client/IMSP library can be linked against an existing
c-client Mail User Agent (MUA) and automatically take advantage of
IMSP's expanded service.

When possible, this API will use c-client functionality.  For example,
IMSP error messages will be displayed using the mm_log callback, and
login credentials will be obtained via the mm_login callback.

2.0 Datatypes
-------------
1) A "support stream" structure.  It needs to specify address book
   drivers, option drivers, a list of open address books, a cached
   mailbox list and a list of c-client MAILSTREAMs.  A replacement for
   the c-client mail_open() will be needed which takes a support
   stream instead of a MAILSTREAM to recycle.  This type will be
   referred to as "SUPPORTSTREAM".

2) A key-value pair array which is useful for specifying a list of
   field-data pairs for an address book entry.  This structure is made
   up of two string pointers as follows:

   typedef struct keyvalue {
       char *key, *value;
   } keyvalue;

3) An "address book" access descriptor.  This type may refer to either
   a local file or an IMSP server and IMSP address book name pair.
   This will be referred to as type "abook".

4) An "address book driver" that contains calls to manage all the
   address book functions listed below.  This will be referred to as
   type "abookdriver".

5) An "options driver" that contains calls to manage all the option
   functions listed below.  This will be referred to as type
   "optiondriver".

3.0 IMSP/SUPPORTSTREAM connection control
-----------------------------------------
SUPPORTSTREAM *support_new(void)

This returns a pointer to a new support stream.

void support_done(SUPPORTSTREAM *s);

This closes the support stream and releases all memory or other
resources associated with it.  This will close any associated address
book pointers or and possibly MAILSTREAMS.

void support_add_adriver(SUPPORTSTREAM *s, abookdriver *d);

This adds the specified address book driver to the SUPPORTSTREAM.
Returns error status.

void support_add_odriver(SUPPORTSTREAM *s, optiondriver *d);

This adds the specified option driver to the SUPPORTSTREAM. Returns
error status.

long imsp_open(SUPPORTSTREAM *s, char *hostname);

This attempts to open an IMSP connection to the specified hostname.
If a connection is successfully opened, then the IMSP address book and
option drivers will automatically be added as the first SUPPORTSTREAM
drivers.  This will use c-client's mm_login() callback to get the
username and password as needed.  Returns error status.

4.0 MAILSTREAM support
----------------------
MAILSTREAM *mailbox_open(SUPPORTSTREAM *s, char *name, char *options);

This should be used instead of mail_open() in c-client.  It will open
the specified mailbox using the SUPPORTSTREAM/IMSP as appropriate.
This will also set the driver for the MAILSTREAM such that
find/create/rename/delete and other routines superceeded by IMSP are
handled properly.

void mailbox_close(MAILSTREAM *m);

This will close and "free" the MAILSTREAM m.  The library may keep m
open and recycle it on future mailbox_open() calls.

5.0 Options
-----------
void mm_option(SUPPORTSTREAM *s, char *option, char *value, int
	read_write_flag);

This is the callback used whenever a "* OPTION" from the server is
processed, or an option is read from a local option file.  The option
and value parameters will point to strings representing the option
name and its value respectively.  The read_write_flag will be non-zero
if the option may be modified by the client.

long option_get(SUPPORTSTREAM *s, char *pattern);

This will call mm_option for all the options matching the specified
pattern (using wildcards as in the IMSP specification).  Returns error
status.

long option_lock(SUPPORTSTREAM *s, char *option);

This will lock the specified option, and may call mm_option to update
its value.  Returns error status.

void option_unlock(SUPPORTSTREAM *s, char *option);

This will unlock the specified option.

long option_set(SUPPORTSTREAM *s, char *option, char *value);

This will set the value for the specified option.  This may also call
mm_option with the new value.  If the value is NULL, the option is
unset.  Returns error status.

5.1 Discussion of Options
-------------------------
The user interface is expected to call option_lock() on read-write
options before displaying them in a context where the user may modify
them.  If a lock fails on an option with "already locked" status the
user should be asked if they want to "break the lock" before a call to
option_set().  option_lock() is an advisory lock and will not be
enforced by the API.  Since options are per-user, an "already locked"
error indicates the user has another active client showing options in
a modifiable context.

6.0 Address books
-----------------
void mm_addressbook(SUPPORTSTREAM *s, char *abook_name, char sep_char);

This callback is passed the name of a valid address book.  The
sep_char is the hierarchy separator character or the NIL character.

void mm_address(abook ab, char *name, keyvalue *fdata, int count);

This callback is passed the name of an entry in the specified address
book, and a list of field/data pairs.  The fdata & count arguments are
0 except in response to an explicit fetch command.  If fdata is
non-zero, it is only guarenteed to stay around until return from
mm_address.

long abook_create(SUPPORTSTREAM *s, char *name);

This creates an address book with the given name.  Returns error status.

long abook_delete(SUPPORTSTREAM *s, char *name);

This deletes an address book with the given name.  Returns error status.

long abook_rename(SUPPORTSTREAM *s, char *oldname, char *newname);

This renames an address book with name "oldname" to "newname".  Returns
error status.

long abook_find(SUPPORTSTREAM *s, char *pattern);

This calls mm_addressbook for each address book on the specified
connection that matches the pattern and is readable by the current
user.  Returns error status.

abook *abook_open(SUPPORTSTREAM *s, char *abook_name, void *private);

This "opens" the specified address book, returning an abook structure
to access its contents.  For IMSP, this will not generate any protocol
requests.  If abook_name is NULL, the default address book (specified
by the IMSP login name of the current user for the IMSP driver) will
be used.  Returns NULL on failure.

void abook_close(abook *ab);

This "closes" the specified address book and releases any resources it
uses.

long abook_getlist(abook *ab);

This calls mm_address() for each address in the specified address
book.  Returns error status.

long abook_search(abook *ab, char *pattern, keyvalue *criteria,
	long number_of_criteria);

This calls mm_address() for each address in the specified address book
that matches the pattern and criteria.  The criteria is specified as
defined in the IMSP specification, and may be NULL if
number_of_criteria is 0.  Returns error status.

long abook_fetch(abook *ab, char *name);

This calls mm_address() for with the field data pairs for the
specified address book entry.  Returns error status.

long abook_lock(abook *ab, char *name);

This places an advisory lock on the specified address book entry.
Returns error status.

void abook_unlock(abook *ab, char *name);

This removes an advisory lock from the specified entry.

long abook_store(abook *ab, char *name, keyvalue *field_data,
	long number_of_field_data_pairs);

This stores the field_data in the specified address book entry.
number_of_field_data_pairs must be at least 1.  Returns error status.

long abook_deleteent(abook *ab, char *name);

This deletes the specified address book entry.  Returns error status.

char *abook_expand(abook *ab, char *name);

This will return a CRLF separated list of email addresses for the
specified address book entry.  It will return NULL on failure.  Note
that an address book entry need not have any email field.  Clients
must not use the email field returned by abook_fetch() -- they must
call this function.  This function may "open" other address books to
expand address references via the "members" field of the address book.
The returned data may be destroyed by future calls to abook_expand().

6.1 Address book access control
-------------------------------

void mm_abookacl(abook *ab, char *identifier, char *rights);

Callback used to specify access rights.  The "identifier" parameter
will be NULL if this is the result of a "MYRIGHTS".

long abook_getacl(abook *ab, int myrights);

If myrights is 1, this will call mm_abookacl with the rights for the
current user, otherwise it will call mm_abookacl for each entry in the
access control list.  Returns error status.

long abook_setacl(abook *ab, char *identifier, char *rights);

This sets the access control rights for "identifier" to "rights".  May
call mm_abookacl() with the actual rights set.  Returns error status.

6.2 Discussion of Address books
-------------------------------
A utility function to convert ACL rights strings to/from bit-vectors
will be provided.

The user interface is expected to call abook_lock() before displaying
the contents of an address book entry is a context where the user may
modify it.
