Re: libwww, HTAAUtil.h changes

kordex - wrote:
> I have read this change history: http://www.w3.org/Library/User/History.html
> .
>   
Do you have at least read access to the CVS repository ?
> I have a piece of code which uses HTAAUtil.h and specifically needs this
> section of HTAAUtil.h
>
> typedef enum {
>     HTAA_UNKNOWN,
>     HTAA_NONE,
>     HTAA_BASIC,
>     HTAA_PUBKEY,
>     HTAA_KERBEROS_V4,
>     HTAA_KERBEROS_V5,
>     HTAA_MAX_SCHEMES                            /* THIS MUST ALWAYS BE LAST!
> */
> } HTAAScheme;
>   
Yes, that was still in
    revision 2.4
    date: 1995/11/20 00:13:25;  author: frystyk;  state: Exp;  lines: +7 -9
    Merged Error and Dialog system
> There is no mention of removing it or anything on that url. I searched the
> source and it should be mentioned in change log of "Release 4.1b1 May 20
> 1996" as it exists in "Release 4.0D February 12 1996".
>   
The very next commit associated with that file has a simple entry,
    revision 2.25
    date: 1996/02/20 19:25:00;  author: frystyk;  state: Exp;  lines: 
+187 -163
    new AA

However, as you can see from the appended diff, [1] there were radical 
changes . . .

> The software is an old www-browser (Mosaic) which i am trying to make little
> more closer to modern standards.
>   
Yes, I recall this project from one of your earlier postings.
> I need to know what were these used for inside libwww and how are they
> replaced.
>   
This is an interesting question of cybernetic archeology, though I think 
we could drive such an investigation from the commit date and comment.  
The most obvious next step would be to examine the HTAAUtil.c, which was 
modified along with the header file definitions, e.g.,

    revision 2.19
    date: 1996/02/20 19:24:59;  author: frystyk;  state: Exp;  lines: 
+503 -308
 
As before, you can see from the appended diff, [2] there were extensive 
changes . . .

Perhaps we can formulate a command that will, for every file, check the 
log for an appropriate revision and pull an appropriate diff.  For the 
moment, with a command and some editing, we have

    RCS file: /sources/public/libwww/Library/src/HTAABrow.c,v
    date: 1996/02/20 19:24:56;  author: frystyk;  state: Exp;  lines: 
+247 -736
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAABrow.html,v
    date: 1996/02/20 19:24:58;  author: frystyk;  state: Exp;  lines: 
+23 -166
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAAUtil.c,v
    date: 1996/02/20 19:24:59;  author: frystyk;  state: Exp;  lines: 
+503 -308
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAAUtil.html,v
    date: 1996/02/20 19:25:00;  author: frystyk;  state: Exp;  lines: 
+187 -163
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAccess.c,v
    date: 1996/02/20 19:25:01;  author: frystyk;  state: Exp;  lines: +5 -2
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAccess.html,v
    date: 1996/02/20 19:25:03;  author: frystyk;  state: Exp;  lines: +2 -2
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAssoc.c,v
    date: 1996/02/20 19:25:04;  author: frystyk;  state: Exp;  lines: +2 -2
    new AA
    RCS file: /sources/public/libwww/Library/src/HTAssoc.html,v
    date: 1996/02/20 19:25:04;  author: frystyk;  state: Exp;  lines: +23 -1
    new AA
    RCS file: /sources/public/libwww/Library/src/HTBind.c,v
    date: 1996/02/20 19:25:05;  author: frystyk;  state: Exp;  lines: +2 -1
    new AA
    RCS file: /sources/public/libwww/Library/src/HTMIME.c,v
    date: 1996/02/20 19:25:08;  author: frystyk;  state: Exp;  lines: +17 -5
    new AA
    RCS file: /sources/public/libwww/Library/src/HTReq.html,v
    date: 1996/02/20 19:25:09;  author: frystyk;  state: Exp;  lines: +32 -1
    new AA
    RCS file: /sources/public/libwww/Library/src/HTReqMan.c,v
    date: 1996/02/20 19:25:10;  author: frystyk;  state: Exp;  lines: 
+47 -25
    new AA
    RCS file: /sources/public/libwww/Library/src/HTReqMan.html,v
    date: 1996/02/20 19:25:11;  author: frystyk;  state: Exp;  lines: +8 -2
    new AA
    RCS file: /sources/public/libwww/Library/src/HTTP.c,v
    date: 1996/02/20 19:25:12;  author: frystyk;  state: Exp;  lines: +7 -9
    new AA
    RCS file: /sources/public/libwww/Library/src/HTTPReq.c,v
    date: 1996/02/20 19:25:13;  author: frystyk;  state: Exp;  lines: +10 -7
    new AA
    RCS file: /sources/public/libwww/Library/src/HTTPServ.c,v
    date: 1996/02/20 19:25:14;  author: frystyk;  state: Exp;  lines: +1 -1
    new AA
    RCS file: /sources/public/libwww/Library/src/HTUtils.html,v
    date: 1996/02/20 19:25:15;  author: frystyk;  state: Exp;  lines: +3 -1
    new AA
   
more,
l8r,
v

[1]  $ cvs diff -r 2.24 -r 2.25 HTAAUtil.html | tee ~/tmp/HTAAUtil.html.diff
Index: HTAAUtil.html
===================================================================
RCS file: /sources/public/libwww/Library/src/HTAAUtil.html,v
retrieving revision 2.24
retrieving revision 2.25
diff -r2.24 -r2.25
3,4c3,4
< <TITLE>Utilities for the Authorization</TITLE>
< <!-- Changed by: Henrik Frystyk Nielsen, 19-Nov-1995 -->
---
 > <TITLE>Authentication Manager</TITLE>
 > <!-- Changed by: Henrik Frystyk Nielsen, 20-Feb-1996 -->
8,9c8
< <H1>Common Parts of Authorization Module to Both Server And
< Browser</H1>
---
 > <H1>Authentication Manager</H1>
18,39c17,30
< This module is the interface to the common parts of Access
< Authorization (AA) package for both server and browser. Important to
< know about memory allocation:<P>
<
< Routines in this module use dynamic allocation, but free automatically
< all the memory reserved by them. Therefore the caller never has to
< (and never should) free() any object returned by these functions.<P>
<
< Therefore also all the strings returned by this package are only valid
< until the next call to the same function is made. This approach is
< selected, because of the nature of access authorization: no string
< returned by the package needs to be valid longer than until the next
< call.  This also makes it easy to plug the AA package in: you don't
< have to ponder whether to free() something here or is it done
< somewhere else (because it is always done somewhere else).<P>
<
< The strings that the package needs to store are copied so the original
< strings given as parameters to AA functions may be freed or modified
< with no side effects.<P>
<
< Also note: The AA package does not free() anything else than what it
< has itself allocated. <P>
---
 > This module handles the registration of multiple Access authentication
 > schemes with support for both clients and servers. The module allows
 > multiple authentication schemes to be registered at run time so that
 > the client and server easily can extend the set of authentication
 > schemes. The Library does already support two welknown schemes from
 > the HTTP specification: <B>basic</B> and <B>digest</B> but othes can
 > be added. <P>
 >
 > Authentication information is kept separate from the various
 > autehntication schemes so that the management of authentication
 > information such as challenges and credentials can be handed
 > independent of the scheme used. All information about authentication
 > information is stored in a <A HREF="#authbase">Authentication
 > Information base</A>.<P>
42,44c33,34
< it is a part of the <A
< HREF="http://www.w3.org/pub/WWW/Library/">
< W3C Reference Library</A>.
---
 > it is a part of the <A HREF="http://www.w3.org/pub/WWW/Library/"> W3C
 > Reference Library</A>.
49c39
< #include "HTList.h"
---
 > #include "HTAssoc.h"
57c47
< #define PASSWD_FILE   "/home2/luotonen/passwd"
---
 > #define PASSWD_FILE   "/tmp/passwd"
61c51
< #define GROUP_FILE    "/home2/luotonen/group"
---
 > #define GROUP_FILE    "/tmp/group"
80,83c70
< HTRequest structure. The AA module is declared in <A
< HREF="HTAAUtil.html">HTAAUtil</A> and <A HREF="HTAABrow.html">
< HTAABrow</A>. The enumeration <CODE>HTAAScheme </CODE>represents the
< possible authentication schemes used by the WWW Access Authorization.
---
 > HTRequest object.
86,96d72
< typedef enum {
<     HTAA_UNKNOWN,
<     HTAA_NONE,
<     HTAA_BASIC,
<     HTAA_PUBKEY,
<     HTAA_KERBEROS_V4,
<     HTAA_KERBEROS_V5,
<     HTAA_MAX_SCHEMES                          /* THIS MUST ALWAYS BE 
LAST! */
< } HTAAScheme;
<
<
124c100,160
< <H2>Authentication Schemes</H2>
---
 > <H2>Authentication Scheme Registration</H2>
 >
 > Registering an autentication scheme involes the following parts:
 >
 > <DL>
 > <DT><B>scheme</B>
 > <DD>The name of the scheme which is used to identify the scheme, for
 > example as the <CODE>&lt;scheme&gt;</CODE> part of the
 > <CODE>WWW-authenticate</CODE> HTTP header.
 >
 > <DT><B>parser</B>
 > <DD>Each scheme must have a <EM>parser</EM> callback function that can
 > parse and interpret either the challenge sent by a server application
 > or the credentials sent by the client to see whether they can be
 > fulfilled or not. In the case of a client, the parser is called each
 > time a request did not optain authorization to access the
 > resource. The parser should then parse the challenge and store it so
 > that we know what we must fulfill if a new request is issued. If the
 > app is a server then the parser should validate that the credentails
 > are sufficent for accessing the resource.
 >
 > <DT><B>generator</B>
 > <DD>A scheme must also have a <EM>generator</EM> callback function
 > that can be called to generate a valid challenge or credentials to be
 > sent to the other part. If a new request is issued and we have a
 > challenge for this request then the generator should make sure that we
 > get the right credentials. This can for example be by asking the user
 > for a user name a and password. In the case of a server, the generator
 > should generate a challenge that must be answered in order to access
 > the resource.
 >
 > <DT><B>garbage collection</B>
 > <DD>The authentication information base has to be able to delete
 > authentication information but as it doesn't know the format of the
 > scheme specific parts, you must register a garbage collector which
 > also is a callback function. The info base manager then calls this
 > function each time authentication information is either being deleted
 > or updated.
 >
 > </DL>
 >
 > The request object has two hooks for the access authentication
 > handler: <CODE>challenge</CODE> and <CODE>credentials.</CODE>. Both
 > are association lists but the format is completely for the
 > <CODE>parser</CODE> and the <CODE>generator</CODE> callback functions
 > to manage. By using callback functions for parsing and generating
 > valid authentication/authorization information, this module is
 > independent of each scheme and hence allows for highly different
 > schemes.
 >
 > <H3>Callback Functions</H3>
 >
 > The types for the parser and generator callback functions are
 > symmetric in that the parser expects an association list of unparsed
 > data and returns a scheme dependent data object to be added to the
 > authentication information base. The callback functions are made so
 > that they can be used both on client side and on server side. The
 > <CODE>scheme</CODE> parameter is to tell the current authentication
 > scheme. That way, the same callback functions can be for multiple
 > schemes if needed.
 >
126,134c162,163
< /* PUBLIC                                             HTAAScheme_enum()
< **            TRANSLATE SCHEME NAME TO A SCHEME ENUMERATION
< ** ON ENTRY:
< **    name            is a string representing the scheme name.
< **
< ** ON EXIT:
< **    returns         the enumerated constant for that scheme.
< */
< extern HTAAScheme HTAAScheme_enum (CONST char* name);
---
 > typedef BOOL HTAuthParCallback        (HTRequest *    request,
 >                                CONST char *   scheme);
135a165,168
 > typedef BOOL HTAuthGenCallback        (HTRequest *    request,
 >                                CONST char *   scheme,
 >                                char *         realm,
 >                                void *         data);
137,147c170,172
< /* PUBLIC                                             HTAAScheme_name()
< **                    GET THE NAME OF A GIVEN SCHEME
< ** ON ENTRY:
< **    scheme          is one of the scheme enum values:
< **                    HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
< **
< ** ON EXIT:
< **    returns         the name of the scheme, i.e.
< **                    "none", "basic", "pubkey", ...
< */
< extern char *HTAAScheme_name (HTAAScheme scheme);
---
 > typedef BOOL HTAuthGcCallback (CONST char *   scheme,
 >                                void *         data);
 > </PRE>
150,172c175
< /* extern                                             HTAA_templateMatch()
< **            STRING COMPARISON FUNCTION FOR FILE NAMES
< **               WITH ONE WILDCARD * IN THE TEMPLATE
< ** NOTE:
< **    This is essentially the same code as in HTRules.c, but it
< **    cannot be used because it is embedded in between other code.
< **    (In fact, HTRules.c should use this routine, but then this
< **     routine would have to be more sophisticated... why is life
< **     sometimes so hard...)
< **
< ** ON ENTRY:
< **    tmplate         is a template string to match the file name
< **                    agaist, may contain a single wildcard
< **                    character * which matches zero or more
< **                    arbitrary characters.
< **    filename        is the filename (or pathname) to be matched
< **                    agaist the template.
< **
< ** ON EXIT:
< **    returns         YES, if filename matches the template.
< **                    NO, otherwise.
< */
< extern BOOL HTAA_templateMatch (CONST char * tmplate, CONST char * 
filename);
---
 > <H3>Add an Authentication Scheme</H3>
173a177,179
 > You can add an authentication scheme by using the following
 > method. Each of the callback function must have the type as defined
 > below.
175,197c181,186
< /* PUBLIC                                         HTAA_templateCaseMatch()
< **            STRING COMPARISON FUNCTION FOR FILE NAMES
< **               WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
< ** NOTE:
< **    This is essentially the same code as in HTAA_templateMatch, but
< **    it compares case insensitive (for VMS). Reason for this routine
< **    is that HTAA_templateMatch gets called from several places, also
< **    there where a case sensitive match is needed, so one cannot just
< **    change the HTAA_templateMatch routine for VMS.
< **
< ** ON ENTRY:
< **    template        is a template string to match the file name
< **                    agaist, may contain a single wildcard
< **                    character * which matches zero or more
< **                    arbitrary characters.
< **    filename        is the filename (or pathname) to be matched
< **                    agaist the template.
< **
< ** ON EXIT:
< **    returns         YES, if filename matches the template.
< **                    NO, otherwise.
< */
< extern BOOL HTAA_templateCaseMatch (CONST char * tmpl, CONST char * 
filename);
---
 > <PRE>
 > extern BOOL HTAuthCall_add    (CONST char *           scheme,
 >                                HTAuthParCallback *    parser,
 >                                HTAuthGenCallback *    generator,
 >                                HTAuthGcCallback *     gc);
 > </PRE>
198a188
 > <H3>Delete an Authentication Scheme</H3>
200,219c190,194
< /* PUBLIC                                     
HTAA_makeProtectionTemplate()
< **            CREATE A PROTECTION TEMPLATE FOR THE FILES
< **            IN THE SAME DIRECTORY AS THE GIVEN FILE
< **            (Used by server if there is no fancier way for
< **            it to tell the client, and by browser if server
< **            didn't send WWW-ProtectionTemplate: field)
< ** ON ENTRY:
< **    docname is the document pathname (from URL).
< **
< ** ON EXIT:
< **    returns a template matching docname, and other files
< **            files in that directory.
< **
< **            E.g.  /foo/bar/x.html  =>  /foo/bar/ *
< **                                                ^
< **                            Space only to prevent it from
< **                            being a comment marker here,
< **                            there really isn't any space.
< */
< extern char *HTAA_makeProtectionTemplate (CONST char * docname);
---
 > Likewise, you can delete an authentication scheme:
 >
 > <PRE>
 > extern BOOL HTAuthCall_delete (CONST char * scheme);
 > extern BOOL HTAuthCall_deleteAll (void);
221c196,204
< <H2>MIME Argument List Parser</H2>
---
 >
 > <H2>Generating Calls to callback functions</H2>
 >
 > <H3>Call An authentication Scheme Parser</H3>
 >
 > This function looks for a authentication scheme that matches what we
 > have in the request object and calls the parser callback function.
 > Case is not significant. Return YES or whatever callback returns
 >
222a206,207
 > extern BOOL HTAuth_parse (HTRequest * request);
 > </PRE>
224,250c209,213
< /* PUBLIC                                             HTAA_parseArgList()
< **            PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
< ** ON ENTRY:
< **    str     is a comma-separated list:
< **
< **                    item, item, item
< **            where
< **                    item ::= value
< **                           | name=value
< **                           | name="value"
< **
< **            Leading and trailing whitespace is ignored
< **            everywhere except inside quotes, so the following
< **            examples are equal:
< **
< **                    name=value,foo=bar
< **                     name="value",foo="bar"
< **                      name = value ,  foo = bar
< **                       name = "value" ,  foo = "bar"
< **
< ** ON EXIT:
< **    returns a list of name-value pairs (actually HTAssocList*).
< **            For items with no name, just value, the name is
< **            the number of order number of that item. E.g.
< **            "1" for the first, etc.
< */
< extern HTList *HTAA_parseArgList (char * str);
---
 > <H3>Call An authentication Scheme Generator</H3>
 >
 > This function looks for a any authentication scheme that protects this
 > resource and calls the generator callback in order to make a challenge
 > or credentials. Return YES or whatever callback returns
251a215,272
 > <PRE>
 > extern BOOL HTAuth_generate (HTRequest * request);
 > </PRE>
 >
 > <H3>Call An authentication Scheme Garbage Collector</H3>
 >
 > This function looks for a authentication scheme that matches what we
 > have in the request object and calls the cleanup callback function.
 > Case is not significant. Return YES if callback found else NO
 >
 > <PRE>
 > extern BOOL HTAuth_cleanup (CONST char * scheme, void * data);
 > </PRE>
 >
 > <A NAME="authbase"><H2>Authentication Information Databases</H2></A>
 >
 > The authentication information is stored in a database managed by this
 > module. In the current implementation, a database is a list of
 > sub-authentication databases, each uniquely identified by a hostname
 > and a port number.  Each database contains a set of templates which
 > can be used to predict what information to use in a hierarchical
 > tree. All authentication dependent information is stored as opaque
 > data in a <CODE>node</CODE> referenced by a <EM>realm</EM> and a
 > <EM>URL template</EM>. <P>
 >
 > Normally applications would only keep one auth base but if it wants
 > different protection setup as a function of different interfaces then
 > it can have one auth base representing each interface. <P>
 >
 > Server applications can have different authentication setups for each
 > hostname and port number they control. For example, a server with
 > interfaces "www.foo.com" and "internal.foo.com" can have different
 > protection setups for each interface.
 >
 > <H3>Initialize the Authentication database</H3>
 >
 > <PRE>
 > extern BOOL HTAuthInfo_init (void);
 > </PRE>
 >
 > <H3>Terminate the Database</H3>
 >
 > <PRE>
 > extern BOOL HTAuthInfo_terminate (void);
 > </PRE>
 >
 > <H3>Add information to the Database</H3>
 >
 > Add an access authentication information node to the database. If
 > the entry is already found then it is replaced with the new one.
 > The template must follow normal URI syntax but can include a wildcard
 > Return YES if added (or replaced), else NO
 >
 > <PRE>
 > extern BOOL HTAuthInfo_add    (CONST char *   scheme,
 >                                char *         url,
 >                                char *         realm,
 >                                void *         data);
256c277,280
< </PRE>End of file HTAAUtil.h.</BODY>
---
 > </PRE>
 >
 > End of file declaration
 > </BODY>

[2]  $ cvs diff -r 2.18 -r 2.19 HTAAUtil.c | tee ~/tmp/HTAAUtil.c.diff
Index: HTAAUtil.c
===================================================================
RCS file: /sources/public/libwww/Library/src/HTAAUtil.c,v
retrieving revision 2.18
retrieving revision 2.19
diff -r2.18 -r2.19
8,34c8,17
< ** IMPORTANT:
< **    Routines in this module use dynamic allocation, but free
< **    automatically all the memory reserved by them.
< **
< **    Therefore the caller never has to (and never should)
< **    free() any object returned by these functions.
< **
< **    Therefore also all the strings returned by this package
< **    are only valid until the next call to the same function
< **    is made. This approach is selected, because of the nature
< **    of access authorization: no string returned by the package
< **    needs to be valid longer than until the next call.
< **
< **    This also makes it easy to plug the AA package in:
< **    you don't have to ponder whether to free() something
< **    here or is it done somewhere else (because it is always
< **    done somewhere else).
< **
< **    The strings that the package needs to store are copied
< **    so the original strings given as parameters to AA
< **    functions may be freed or modified with no side effects.
< **
< **    The AA package does not free() anything else than what
< **    it has itself allocated.
< **
< **    AA (Access Authorization) package means modules which
< **    names start with HTAA.
---
 > **    The authentication information is stored in a list of 
authentication
 > **    data bases, each uniquely identified by a hostname and a port 
number.
 > **    Each data base contains a set of templates which can be used to 
predict
 > **    what information to use in a hierarchical tree. All authentication
 > **    dependent information is stored as opaque data in a anode. Normally
 > **    a server application would only keep one auth base but if it wants
 > **    different protection setup as a function of different 
interfaces then
 > **    it can have one auth base representing each interface. For 
example a
 > **    server with interfaces "www.foo.com" and "internal.foo.com" can 
have
 > **    different protection setups for each interface.
38a22
 > **    HFN     Henrik Frystyk
43,47d26
< **
< **
< ** BUGS:
< **
< **
54,66c33,76
< #include "HTAAUtil.h" /* Implemented here     */
< #include "HTAssoc.h"  /* Assoc list           */
<
<
< /* PUBLIC                                             HTAAScheme_enum()
< **            TRANSLATE SCHEME NAME INTO
< **            A SCHEME ENUMERATION
< **
< ** ON ENTRY:
< **    name            is a string representing the scheme name.
< **
< ** ON EXIT:
< **    returns         the enumerated constant for that scheme.
---
 > #include "HTParse.h"
 > #include "HTReqMan.h"
 > #include "HTAssoc.h"
 > #include "HTAAUtil.h"                                  /* Implemented 
here */
 >
 > typedef struct _HTAuthScheme {
 >     char *            scheme;
 >     HTAuthParCallback *       parser;
 >     HTAuthGenCallback *       generator;
 >     HTAuthGcCallback *        gc;
 > } HTAuthScheme;
 >
 > PRIVATE HTList * HTSchemes;   /* List of registered authentication 
schemes */
 >
 > typedef struct _HTABase {               /* Server Authentication info 
base */
 >     char *    host;
 >     int               port;
 >     HTList *  templates;                /* List of templates for this 
base */
 >     HTList *  nodes;                        /* List of nodes for this 
base */
 > } HTABase;
 >
 > typedef struct _HTANode {               /* Authentication scheme 
specifics */
 >     char *    realm;
 >     char *    scheme;
 >     void *    data;
 > } HTANode;
 >
 > typedef struct _HTATemplate {                  /* Hierarchical 
information */
 >     char *    tmplate;
 >     HTANode * node;
 > } HTATemplate;
 >
 > PRIVATE HTList * AuthBases = NULL;          /* Current authentication 
base */
 >
 > /* 
------------------------------------------------------------------------- */
 > /*                         AUTHENTICATION 
SCHEMES                          */
 > /* 
------------------------------------------------------------------------- */
 >
 > /*    HTAuthCall_add
 > **    --------------
 > **    Register a callback functions that is to be called when we want to
 > **    parse challenges and to generate credentials - or the other way 
round.
 > **    If you are a server then you want to do the latter and if you 
are a
 > **    client then you want to do the former.
68c78,81
< PUBLIC HTAAScheme HTAAScheme_enum (CONST char* name)
---
 > PUBLIC BOOL HTAuthCall_add (CONST char *      scheme,
 >                           HTAuthParCallback * parser,
 >                           HTAuthGenCallback * generator,
 >                           HTAuthGcCallback *  gc)
70,71c83,98
<     static char *upcased = NULL;
<     char *cur;
---
 >     if (scheme && parser && generator && gc) {
 >       HTAuthScheme * me;
 >       if (AUTH_TRACE)
 >           HTTrace("Auth add.... %s with parser %p and generator %p\n",
 >                   scheme, (void *) parser, (void *) generator);
 >       if ((me = (HTAuthScheme *) HT_CALLOC(1, sizeof(HTAuthScheme))) 
== NULL)
 >           HT_OUTOFMEM("HTAuthCall_add");
 >       StrAllocCopy(me->scheme, scheme);
 >       me->parser = parser;
 >       me->generator = generator;
 >       me->gc = gc;
 >       if (!HTSchemes) HTSchemes = HTList_new();
 >       return HTList_addObject(HTSchemes, (void *) me);
 >     }
 >     return NO;
 > }
73c100,120
<     if (!name) return HTAA_UNKNOWN;
---
 > /*    HTAuthCall_delete
 > **    -------------------
 > **    Unregister a authentication scheme from the list
 > **    Return YES if OK, else NO
 > */
 > PUBLIC BOOL HTAuthCall_delete (CONST char * scheme)
 > {
 >     HTList * cur = HTSchemes;
 >     if (scheme && cur) {
 >       HTAuthScheme * pres;
 >       while ((pres = (HTAuthScheme *) HTList_nextObject(cur))) {
 >           if (!strcmp(scheme, pres->scheme)) {
 >               HTList_removeObject(HTSchemes, (void *) pres);
 >               HT_FREE(pres->scheme);
 >               HT_FREE(pres);
 >               return YES;
 >           }
 >       }
 >     }
 >     return NO;
 > }
75,79c122,139
<     StrAllocCopy(upcased, name);
<     cur = upcased;
<     while (*cur) {
<       *cur = TOUPPER(*cur);
<       cur++;
---
 > /*    HTAuthCall_deleteAll
 > **    ----------------------
 > **    Unregisters all call back functions
 > **    Returns YES if OK, else NO
 > */
 > PUBLIC BOOL HTAuthCall_deleteAll (void)
 > {
 >     HTList * cur = HTSchemes;
 >     if (AUTH_TRACE) HTTrace("Auth delete. all schemes\n");
 >     if (cur) {
 >       HTAuthScheme * pres;
 >       while ((pres = (HTAuthScheme *) HTList_nextObject(cur))) {
 >           HT_FREE(pres->scheme);
 >           HT_FREE(pres);
 >       }
 >       HTList_delete(HTSchemes);
 >       HTSchemes = NULL;
 >       return YES;
81,87c141
<    
<     if      (!strncmp(upcased, "NONE", 4))       return HTAA_NONE;
<     else if (!strncmp(upcased, "BASIC", 5))      return HTAA_BASIC;
<     else if (!strncmp(upcased, "PUBKEY", 6))     return HTAA_PUBKEY;
<     else if (!strncmp(upcased, "KERBEROSV4", 10))  return 
HTAA_KERBEROS_V4;
<     else if (!strncmp(upcased, "KERBEROSV5", 10))  return 
HTAA_KERBEROS_V5;
<     else                                         return HTAA_UNKNOWN;
---
 >     return NO;
89a144,154
 > /* 
------------------------------------------------------------------------- */
 > /*                   AUTHENTICATION INFORMATION DATA 
BASE                  */
 > /* 
------------------------------------------------------------------------- */
 >
 > /*    This module maintains an authentication information database
 > **    which contains informations for generate either credentials or
 > **    challenges. The database is symmetric for both server and client
 > **    applications and the implementation can be changed independent 
of the
 > **    API so if you fell like using a fancy database toolkit then 
feel free
 > **    to go right ahead :-)
 > */
91,110c156,171
< /* PUBLIC                                             HTAAScheme_name()
< **                    GET THE NAME OF A GIVEN SCHEME
< ** ON ENTRY:
< **    scheme          is one of the scheme enum values:
< **                    HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
< **
< ** ON EXIT:
< **    returns         the name of the scheme, i.e.
< **                    "None", "Basic", "Pubkey", ...
< */
< PUBLIC char *HTAAScheme_name (HTAAScheme scheme)
< {
<     switch (scheme) {
<       case HTAA_NONE:         return "None";          break;
<       case HTAA_BASIC:                return "Basic";         break;
<       case HTAA_PUBKEY:               return "Pubkey";        break;
<       case HTAA_KERBEROS_V4:  return "KerberosV4";    break;
<       case HTAA_KERBEROS_V5:  return "KerberosV5";    break;
<       case HTAA_UNKNOWN:      return "UNKNOWN";       break;
<       default:                        return "THIS-IS-A-BUG";
---
 > /*
 > **    Create a new anode
 > **    Returns new object or NULL if error
 > */
 > PRIVATE HTANode * HTANode_new (HTABase * base, CONST char * realm,
 >                              CONST char * scheme, void * data)
 > {
 >     if (base && realm && scheme) {
 >       HTANode * me;
 >       if ((me = (HTANode *) HT_CALLOC(1, sizeof(HTANode))) == NULL)
 >           HT_OUTOFMEM("HTANode_new");
 >       StrAllocCopy(me->realm, realm);
 >       StrAllocCopy(me->scheme, scheme);
 >       me->data = data;
 >       HTList_addObject(base->nodes, (void *) me);
 >       return me;
111a173
 >     return NULL;
113a176,191
 > /*
 > **    Delete a node. We call the scheme gc callback to handle the opaque
 > **    data object.
 > */
 > PRIVATE BOOL HTANode_delete (HTABase * base, HTANode * me)
 > {
 >     if (base && me) {
 >       HTAuth_cleanup(me->scheme, me->data);
 >       HT_FREE(me->realm);
 >       HT_FREE(me->scheme);
 >       HTList_removeObject(base->nodes, (void *) me);
 >       HT_FREE(me);
 >       return YES;
 >     }
 >     return NO;
 > }
114a193,207
 > /*
 > **    Search an authentication base for a matching anode.
 > **    Return the anode object found or NULL if none
 > */
 > PRIVATE HTANode * HTANode_find (HTABase * base, CONST char * realm)
 > {   
 >     if (base && base->nodes && realm) {
 >       HTList * cur = base->nodes;
 >       HTANode * pres;
 >       while ((pres = (HTANode *) HTList_nextObject(cur))) {
 >           if (!strcmp(pres->realm, realm)) return pres;
 >       }
 >     }
 >     return NULL;
 > }
116,259c209,226
< /* PUBLIC                                             HTAA_templateMatch()
< **            STRING COMPARISON FUNCTION FOR FILE NAMES
< **               WITH ONE WILDCARD * IN THE TEMPLATE
< ** NOTE:
< **    This is essentially the same code as in HTRules.c, but it
< **    cannot be used because it is embedded in between other code.
< **    (In fact, HTRules.c should use this routine, but then this
< **     routine would have to be more sophisticated... why is life
< **     sometimes so hard...)
< **
< ** ON ENTRY:
< **    template        is a template string to match the file name
< **                    agaist, may contain a single wildcard
< **                    character * which matches zero or more
< **                    arbitrary characters.
< **    filename        is the filename (or pathname) to be matched
< **                    agaist the template.
< **
< ** ON EXIT:
< **    returns         YES, if filename matches the template.
< **                    NO, otherwise.
< */
< PUBLIC BOOL HTAA_templateMatch (CONST char * tmplate,
<                                    CONST char * filename)
< {
<     CONST char *p = tmplate;
<     CONST char *q = filename;
<     int m;
<
<     if (!tmplate || !filename) {
<       if (PROT_TRACE)
<           HTTrace("HTAA_templateMatch: invalid param: %s is NULL!!\n",
<                   (tmplate ? "filename" : "template"));
<       return NO;
<     }
<
<     for( ; *p  &&  *q  &&  *p == *q; p++, q++)        /* Find first 
mismatch */
<       ; /* do nothing else */
<
<     if (!*p && !*q)   return YES;     /* Equally long equal strings */
<     else if ('*' == *p) {             /* Wildcard */
<       p++;                            /* Skip wildcard character */
<       m = strlen(q) - strlen(p);      /* Amount to match to wildcard */
<       if (m < 0) return NO;           /* No match, filename too short */
<       else {                  /* Skip the matched characters and 
compare */
<           if (strcmp(p, q+m)) return NO;      /* Tail mismatch */
<           else                return YES;     /* Tail match */
<       }
<     } /* if wildcard */
<     else              return NO;      /* Length or character mismatch */
< }   
<
<
< /* PUBLIC                                     HTAA_templateCaseMatch()
< **            STRING COMPARISON FUNCTION FOR FILE NAMES
< **       WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
< ** NOTE:
< **    This is essentially the same code as in HTAA_templateMatch, but
< **    it compares case insensitive (for VMS). Reason for this routine
< **    is that HTAA_templateMatch gets called from several places, also
< **    there where a case sensitive match is needed, so one cannot just
< **    change the HTAA_templateMatch routine for VMS.
< **
< ** ON ENTRY:
< **    tmplate         is a template string to match the file name
< **                    agaist, may contain a single wildcard
< **                    character * which matches zero or more
< **                    arbitrary characters.
< **    filename        is the filename (or pathname) to be matched
< **                    agaist the template.
< **
< ** ON EXIT:
< **    returns         YES, if filename matches the template.
< **                    NO, otherwise.
< */
< PUBLIC BOOL HTAA_templateCaseMatch (CONST char * tmplate,
<                                        CONST char * filename)
< {
<     CONST char *p = tmplate;
<     CONST char *q = filename;
<     int m;
<
<     if (!tmplate || !filename) {
<       if (PROT_TRACE)
<           HTTrace(
<                   "HTAA_templateCaseMatch: invalid param: %s is NULL!!\n",
<                   (tmplate ? "filename" : "template"));
<       return NO;
<     }
<
<     for( ; *p  &&  *q  &&  TOUPPER(*p) == TOUPPER(*q); p++, q++) /* 
Find first mismatch */
<       ; /* do nothing else */
<
<     if (!*p && !*q)   return YES;     /* Equally long equal strings */
<     else if ('*' == *p) {             /* Wildcard */
<       p++;                            /* Skip wildcard character */
<       m = strlen(q) - strlen(p);      /* Amount to match to wildcard */
<       if (m < 0) return NO;           /* No match, filename too short */
<       else {                  /* Skip the matched characters and 
compare */
<           if (strcasecomp(p, q+m))    return NO;      /* Tail mismatch */
<           else                return YES;     /* Tail match */
<       }
<     } /* if wildcard */
<     else              return NO;      /* Length or character mismatch */
< }   
<
<
< /* PUBLIC                                     
HTAA_makeProtectionTemplate()
< **            CREATE A PROTECTION TEMPLATE FOR THE FILES
< **            IN THE SAME DIRECTORY AS THE GIVEN FILE
< **            (Used by server if there is no fancier way for
< **            it to tell the client, and by browser if server
< **            didn't send WWW-ProtectionTemplate: field)
< ** ON ENTRY:
< **    docname is the document pathname (from URL).
< **
< ** ON EXIT:
< **    returns a template matching docname, and other files
< **            files in that directory.
< **
< **            E.g.  /foo/bar/x.html  =>  /foo/bar/ *
< **                                                ^
< **                            Space only to prevent it from
< **                            being a comment marker here,
< **                            there really isn't any space.
< */
< PUBLIC char *HTAA_makeProtectionTemplate (CONST char * docname)
< {
<     char *tmplate = NULL;
<     char *slash = NULL;
<
<     if (docname) {
<       StrAllocCopy(tmplate, docname);
<       slash = strrchr(tmplate, '/');
<       if (slash) slash++;
<       else slash = tmplate;
<       *slash = (char)0;
<       StrAllocCat(tmplate, "*");
<     }
<     else StrAllocCopy(tmplate, "*");
<
<     if (PROT_TRACE)
<       HTTrace("make_template: made template `%s' for file `%s'\n",
<               tmplate, docname);
---
 > /*
 > **    Create a new template and add to authentication base
 > **    Returns new object or NULL if error
 > */
 > PRIVATE HTATemplate * HTATemplate_new (HTABase * base, char * tmplate,
 >                                      HTANode * node)
 > {
 >     if (base && tmplate && node) {
 >       HTATemplate * me;
 >       if ((me = (HTATemplate *) HT_CALLOC(1, sizeof(HTATemplate))) == 
NULL)
 >           HT_OUTOFMEM("HTATemplate_new");
 >       me->node = node;
 >       me->tmplate = tmplate;
 >       HTList_addObject(base->templates, (void *) me);
 >       return me;
 >     }
 >     return NULL;
 > }
261c228,239
<     return tmplate;
---
 > /*
 > **    Delete a template
 > */
 > PRIVATE BOOL HTATemplate_delete (HTABase * base, HTATemplate * me)
 > {
 >     if (base && me) {
 >       HT_FREE(me->tmplate);
 >       HTList_removeObject(base->templates, (void *) me);
 >       HT_FREE(me);
 >       return YES;
 >     }
 >     return NO;
263a242,261
 > /*
 > **    Search an authentication base for a matching template.
 > **    Return the template object found or NULL if none
 > */
 > PRIVATE HTATemplate * HTATemplate_find (HTABase * base, CONST char 
*docname)
 > {
 >     if (base && base->templates && docname) {
 >       HTList * cur = base->templates;
 >       HTATemplate * pres;
 >       while ((pres = (HTATemplate *) HTList_nextObject(cur))) {
 >           if (HTStrMatch(pres->tmplate, docname)) {
 >               if (AUTH_TRACE)
 >                   HTTrace("Template.... `%s' matched `%s'\n",
 >                           docname, pres->tmplate);
 >               return pres;
 >           }
 >       }
 >     }
 >     return NULL;
 > }
264a263,282
 > /*
 > **    Search an authentication base for a HTATemplate object in order to
 > **    update it with a new HTANode. We do this whenever we replace a 
anode
 > **    Return YES if OK, else NO
 > */
 > PRIVATE BOOL HTATemplate_update (HTABase * base, HTANode * old, 
HTANode *me)
 > {
 >     if (base && old && me) {
 >       HTList * cur = base->templates;
 >       HTATemplate * pres;
 >       while ((pres = (HTATemplate *) HTList_nextObject(cur))) {
 >           if (pres->node == old) {
 >               pres->node = me;
 >               if (AUTH_TRACE) HTTrace("Template.... updating %p\n", 
pres);
 >               return YES;
 >           }
 >       }
 >     }
 >     return NO;
 > }
265a284,303
 > /*
 > **    Create a new authentication base
 > **    Returns new object or NULL if error
 > */
 > PRIVATE HTABase * HTABase_new (CONST char * host, int port)
 > {
 >     if (host) {
 >       HTABase * me;
 >       if ((me = (HTABase *) HT_CALLOC(1, sizeof(HTABase))) == NULL)
 >           HT_OUTOFMEM("HTABase_new");
 >       StrAllocCopy(me->host, host);
 >       me->port = (port > 0 ? port : 80);
 >       me->templates = HTList_new();
 >       me->nodes = HTList_new();
 >       HTList_addObject(AuthBases, (void *) me);
 >       if (AUTH_TRACE) HTTrace("Auth Base... %p created\n", me);
 >       return me;
 >     }
 >     return NULL;
 > }
268c306
< ** Skip leading whitespace from *s forward
---
 > **    Delete a complete server tree and everything within it.
270c308,334
< #define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
---
 > PRIVATE BOOL HTABase_delete (HTABase * base)
 > {
 >     if (base) {
 >       HTList * cur;
 >
 >       /* Free all templates */
 >       if ((cur = base->templates)) {
 >           HTATemplate * pres;
 >           while ((pres = (HTATemplate *) HTList_lastObject(cur)))
 >               HTATemplate_delete(base, pres);
 >           HTList_delete(base->templates);
 >       }
 >
 >       /* Free all nodes */
 >       if ((cur = base->nodes)) {
 >           HTANode * pres;
 >           while ((pres = (HTANode *) HTList_lastObject(cur)))
 >               HTANode_delete(base, pres);
 >           HTList_delete(base->nodes);    
 >       }
 >
 >       HT_FREE(base->host);
 >       HT_FREE(base);
 >       return YES;
 >     }
 >     return NO;
 > }
273c337
< ** Kill trailing whitespace starting from *(s-1) backwords
---
 > **    Find a authentication base. Return NULL if not found
275c339,350
< #define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') 
*(c--)=(char)0;}
---
 > PRIVATE HTABase * HTABase_find (CONST char * host, int port)
 > {
 >     HTList * cur = AuthBases;
 >     if (port <= 0) port = 80;
 >     if (host && cur) {
 >       HTABase * pres;
 >       while ((pres = (HTABase *) HTList_nextObject(cur))) {
 >           if (pres->port==port && !strcmp(pres->host, host)) return pres;
 >       }
 >     }
 >     return NULL;
 > }
276a352,385
 > /* 
------------------------------------------------------------------------- */
 > /*               HANDLING THE AUTHENTICATION INFORMATION 
BASE              */
 > /* 
------------------------------------------------------------------------- */
 >
 > /*    HTAuthInfo_add
 > **    --------------
 > **    Add an access authentication information node to the database. If
 > **    the entry is already found then it is replaced with the new one.
 > **    The template must follow normal URI syntax but can include a 
wildcard
 > **    Return YES if added (or replaced), else NO
 > */
 > PUBLIC BOOL HTAuthInfo_add (CONST char * scheme, char * url,
 >                           char * realm, void * data)
 > {
 >     HTABase * base;
 >     HTANode * anode;
 >     if (!scheme || !url || !realm || !data) return NO;
 >     if (AUTH_TRACE) HTTrace("Auth base... adding info for `%s'\n", url);
 >     if (!AuthBases) AuthBases = HTList_new();
 >
 >     /* Find an existing authentication base or create new */
 >     {
 >       char * host = HTParse(url, "", PARSE_HOST);
 >       char * colon = strchr(host, ':');
 >       int port = 80;
 >       if (colon ) {
 >           *(colon++) = '\0';                       /* Chop off port 
number */
 >           port = atoi(colon);
 >       }
 >       if ((base = HTABase_find(host, port)) == NULL)
 >           base = HTABase_new(host, port);
 >       HT_FREE(host);
 >       if (!base) return NO;                  /* Couldn't create a new 
base */
 >     }
278,343c387,400
< /* PUBLIC                                             HTAA_parseArgList()
< **            PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
< ** ON ENTRY:
< **    str     is a comma-separated list:
< **
< **                    item, item, item
< **            where
< **                    item ::= value
< **                           | name=value
< **                           | name="value"
< **
< **            Leading and trailing whitespace is ignored
< **            everywhere except inside quotes, so the following
< **            examples are equal:
< **
< **                    name=value,foo=bar
< **                     name="value",foo="bar"
< **                      name = value ,  foo = bar
< **                       name = "value" ,  foo = "bar"
< **
< ** ON EXIT:
< **    returns a list of name-value pairs (actually HTAssocList*).
< **            For items with no name, just value, the name is
< **            the number of order number of that item. E.g.
< **            "1" for the first, etc.
< */
< PUBLIC HTAssocList *HTAA_parseArgList (char * str)
< {
<     HTAssocList *assoc_list = HTAssocList_new();
<     char *cur = NULL;
<     char *name = NULL;
<     int index = 0;
<
<     if (!str) return assoc_list;
<
<     while (*str) {
<       SKIPWS(str);                            /* Skip leading 
whitespace */
<       cur = str;
<       index++;
<
<       while (*cur  &&  *cur != '='  &&  *cur != ',')
<           cur++;      /* Find end of name (or lonely value without a 
name) */
<       KILLWS(cur);    /* Kill trailing whitespace */
<
<       if (*cur == '=') {                      /* Name followed by a 
value */
<           *(cur++) = (char)0;                 /* Terminate name */
<           StrAllocCopy(name, str);
<           SKIPWS(cur);                        /* Skip WS leading the 
value */
<           str = cur;
<           if (*str == '"') {                  /* Quoted value */
<               str++;
<               cur = str;
<               while (*cur  &&  *cur != '"') cur++;
<               if (*cur == '"')
<                   *(cur++) = (char)0; /* Terminate value */
<               /* else it is lacking terminating quote */
<               SKIPWS(cur);                    /* Skip WS leading comma */
<               if (*cur == ',') cur++;         /* Skip separating colon */
<           }
<           else {                              /* Unquoted value */
<               while (*cur  &&  *cur != ',') cur++;
<               KILLWS(cur);                    /* Kill trailing 
whitespace */
<               if (*cur == ',')
<                   *(cur++) = (char)0;
<               /* else *cur already NULL */
<           }
---
 >     /*
 >     ** Find a matching anode or create a new one. If we find an 
existing one
 >     ** we also update the template pointing to the anode. Otherwise 
we create
 >     ** a new template as well.
 >     */
 >     {
 >       HTANode * old = HTANode_find(base, realm);
 >       anode = HTANode_new(base, realm, scheme, data);
 >       if (old) {
 >           HTATemplate_update(base, old, anode);
 >           HTANode_delete(base, old);
 >       } else {
 >           char * docname = HTParse(url, "", PARSE_PATH);
 >           HTATemplate_new(base, docname, anode);
345,356c402,403
<       else {  /* No name, just a value */
<           if (*cur == ',')
<               *(cur++) = (char)0;             /* Terminate value */
<           /* else last value on line (already terminated by NULL) */
<           StrAllocCopy(name, "nnn");  /* Room for item order number */
<           sprintf(name, "%d", index); /* Item order number for name */
<       }
<       HTAssocList_add(assoc_list, name, str);
<       str = cur;
<     } /* while *str */
<     HT_FREE(name);                                         /* Henrik 
14/03-94 */
<     return assoc_list;
---
 >     }
 >     return anode ? YES : NO;
358a406,465
 > /*    HTAuthInfo_deleteAll
 > **    --------------------
 > **    Remove the Database
 > */
 > PUBLIC BOOL HTAuthInfo_deleteAll (void)
 > {
 >     if (AuthBases) {
 >       HTList * cur = AuthBases;
 >       HTABase * pres;
 >       while ((pres = (HTABase *) HTList_nextObject(cur)))
 >           HTABase_delete(pres);
 >       HTList_delete(AuthBases);
 >       AuthBases = NULL;
 >       return YES;
 >     }
 >     return NO;
 > }
 >
 > /*    AuthInfo_find
 > **    -------------
 > **    Seaches the set of authentication information bases for a match
 > **    In order to find an anode we do the following:
 > **
 > **            1) Find the right auth base
 > **            2) See if there is a realm match
 > **            3) See if there is a template match for URL
 > **
 > **    Return the node found else NULL which means that we don't have any
 > **    authentication information to hook on to this request or response
 > */
 > PRIVATE HTANode * HTAuthInfo_find (char * url, char * realm)
 > {
 >     HTABase * base;
 >     HTATemplate * tmplate;
 >     HTANode * anode;
 >     if (AUTH_TRACE)
 >       HTTrace("Auth base... looking for info on `%s'\n", url);
 >
 >     /* Find an existing authentication base */
 >     {
 >       char * host = HTParse(url, "", PARSE_HOST);
 >       char * colon = strchr(host, ':');
 >       int port = 80;
 >       if (colon ) {
 >           *(colon++) = '\0';                       /* Chop off port 
number */
 >           port = atoi(colon);
 >       }
 >       base = HTABase_find(host, port);
 >       HT_FREE(host);
 >       if (base == NULL) return NULL;                     /* Base not 
found */
 >     }
 >
 >     /* Do we have a realm to look for? */
 >     if (realm) {
 >       if ((anode = HTANode_find(base, realm)) != NULL) {
 >           if (AUTH_TRACE)
 >               HTTrace("Auth info... found matching realm `%s\'\n", 
realm);
 >           return anode;
 >       }
 >     }
359a467,476
 >     /* If no realm or realm not found then look for template */
 >     {
 >       char * docname = HTParse(url, "", PARSE_PATH);
 >       if ((tmplate = HTATemplate_find(base, docname)) != NULL)
 >           anode = tmplate->node;
 >       HT_FREE(docname);
 >       return anode;
 >     }
 >     return NULL;                                               /* No 
match */
 > }
360a478,504
 > /* 
------------------------------------------------------------------------- */
 > /*               PARSE AND GENERATE CHELLENGES AND 
CREDENTIALS             */
 > /* 
------------------------------------------------------------------------- */
 >
 > /*    HTAuth_parse
 > **    ------------
 > **    This function looks for a authentication scheme that matches 
what we
 > **    have in the request object and calls the parser callback function.
 > **    Case is not significant.
 > **    Return YES or whatever callback returns
 > */
 > PUBLIC BOOL HTAuth_parse (HTRequest * request)
 > {
 >     HTList * cur = HTSchemes;
 >     if (request && request->scheme && request->challenge && cur) {
 >       HTAuthScheme * pres;
 >       while ((pres = (HTAuthScheme *) HTList_nextObject(cur))) {
 >           if (!strcasecomp(request->scheme, pres->scheme)) {
 >               if (AUTH_TRACE)
 >                   HTTrace("Auth Calling Parser %p\n", pres->parser);
 >               return (*(pres->parser))(request, pres->scheme);
 >           }
 >       }
 >     }
 >     if (AUTH_TRACE)HTTrace("Auth Parse.. No challenge or credentials 
found\n");
 >     return YES;
 > }
361a506,534
 > /*    HTAuth_generate
 > **    ---------------
 > **    This function looks for a any authentication scheme that protects
 > **    this resource and calls the generator callback in order to make a
 > **    challenge or setup credentials depending on whether we are a server
 > **    or a client.
 > **    Return YES or whatever callback returns
 > */
 > PUBLIC BOOL HTAuth_generate (HTRequest * request)
 > {
 >     HTList * cur = HTSchemes;
 >     if (request && cur) {
 >       char * url = HTAnchor_physical(request->anchor);
 >       HTANode * node = HTAuthInfo_find(url, request->realm);
 >       if (node && node->data) {
 >           HTAuthScheme * pres;
 >           while ((pres = (HTAuthScheme *) HTList_nextObject(cur))) {
 >               if (!strcasecomp(node->scheme, pres->scheme)) {
 >                   if (AUTH_TRACE)
 >                       HTTrace("Auth Calling Generator 
%p\n",pres->generator);
 >                   return (*(pres->generator))(request, node->scheme,
 >                                               node->realm, node->data);
 >               }
 >           }
 >       }
 >     }
 >     if (AUTH_TRACE)HTTrace("Auth Gen.... No challenge or credentials 
found\n");
 >     return YES;
 > }
362a536,557
 > /*    HTAuth_cleanup
 > **    --------------
 > **    This function looks for a authentication scheme that matches 
what we
 > **    have in the request object and calls the cleanup callback function.
 > **    Case is not significant. If the scheme is not registered then
 > **    Return YES if callback found else NO
 > */
 > PUBLIC BOOL HTAuth_cleanup (CONST char * scheme, void * data)
 > {
 >     HTList * cur = HTSchemes;
 >     if (scheme && cur && data) {
 >       HTAuthScheme * pres;
 >       while ((pres = (HTAuthScheme *) HTList_nextObject(cur))) {
 >           if (!strcasecomp(scheme, pres->scheme)) {
 >               if (AUTH_TRACE) HTTrace("Auth Calling gc %p\n", pres->gc);
 >               (*(pres->gc))(scheme, data);
 >               return YES;
 >           }
 >       }
 >     }
 >     return NO;
 > }

-- 
"The future is here. It's just not evenly distributed yet."
 -- William Gibson, quoted by Whitfield Diffie

Received on Friday, 28 March 2008 00:08:47 UTC