Annotation of libwww/Library/src/HTAAUtil.c, revision 2.1

2.1     ! luotonen    1: 
        !             2: /* MODULE                                                      HTAABoth.c
        !             3: **             COMMON PARTS OF ACCESS AUTHORIZATION MODULE
        !             4: **                     FOR BOTH SERVER AND BROWSER
        !             5: **
        !             6: ** IMPORTANT:
        !             7: **     Routines in this module use dynamic allocation, but free
        !             8: **     automatically all the memory reserved by them.
        !             9: **
        !            10: **     Therefore the caller never has to (and never should)
        !            11: **     free() any object returned by these functions.
        !            12: **
        !            13: **     Therefore also all the strings returned by this package
        !            14: **     are only valid until the next call to the same function
        !            15: **     is made. This approach is selected, because of the nature
        !            16: **     of access authorization: no string returned by the package
        !            17: **     needs to be valid longer than until the next call.
        !            18: **
        !            19: **     This also makes it easy to plug the AA package in:
        !            20: **     you don't have to ponder whether to free() something
        !            21: **     here or is it done somewhere else (because it is always
        !            22: **     done somewhere else).
        !            23: **
        !            24: **     The strings that the package needs to store are copied
        !            25: **     so the original strings given as parameters to AA
        !            26: **     functions may be freed or modified with no side effects.
        !            27: **
        !            28: **     The AA package does not free() anything else than what
        !            29: **     it has itself allocated.
        !            30: **
        !            31: **     AA (Access Authorization) package means modules which
        !            32: **     names start with HTAA.
        !            33: **
        !            34: ** AUTHORS:
        !            35: **     AL      Ari Luotonen    luotonen@dxcern.cern.ch
        !            36: **
        !            37: ** HISTORY:
        !            38: **
        !            39: **
        !            40: ** BUGS:
        !            41: **
        !            42: **
        !            43: */
        !            44: 
        !            45: #include <string.h>
        !            46: #include "HTUtils.h"
        !            47: #include "tcp.h"       /* NETREAD() etc.       */
        !            48: #include "HTAAUtil.h"  /* Implemented here     */
        !            49: #include "HTAssoc.h"   /* Assoc list           */
        !            50: 
        !            51: 
        !            52: /* PUBLIC                                              HTAAScheme_enum()
        !            53: **             TRANSLATE SCHEME NAME INTO
        !            54: **             A SCHEME ENUMERATION
        !            55: **
        !            56: ** ON ENTRY:
        !            57: **     name            is a string representing the scheme name.
        !            58: **
        !            59: ** ON EXIT:
        !            60: **     returns         the enumerated constant for that scheme.
        !            61: */
        !            62: PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
        !            63: {
        !            64:     static char *upcased = NULL;
        !            65:     char *cur;
        !            66: 
        !            67:     if (!name) return HTAA_UNKNOWN;
        !            68: 
        !            69:     StrAllocCopy(upcased, name);
        !            70:     cur = upcased;
        !            71:     while (*cur) {
        !            72:        *cur = TOUPPER(*cur);
        !            73:        cur++;
        !            74:     }
        !            75:     
        !            76:     if (!strncmp(upcased, "NONE", 4))
        !            77:        return HTAA_NONE;
        !            78:     else if (!strncmp(upcased, "BASIC", 5))
        !            79:        return HTAA_BASIC;
        !            80:     else if (!strncmp(upcased, "PUBKEY", 6))
        !            81:        return HTAA_PUBKEY;
        !            82:     else if (!strncmp(upcased, "KERBEROSV4", 10))
        !            83:        return HTAA_KERBEROS_V4;
        !            84:     else if (!strncmp(upcased, "KERBEROSV5", 10))
        !            85:        return HTAA_KERBEROS_V5;
        !            86:     else
        !            87:        return HTAA_UNKNOWN;
        !            88: }
        !            89: 
        !            90: 
        !            91: /* PUBLIC                                              HTAAScheme_name()
        !            92: **                     GET THE NAME OF A GIVEN SCHEME
        !            93: ** ON ENTRY:
        !            94: **     scheme          is one of the scheme enum values:
        !            95: **                     HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
        !            96: **
        !            97: ** ON EXIT:
        !            98: **     returns         the name of the scheme, i.e.
        !            99: **                     "None", "Basic", "Pubkey", ...
        !           100: */
        !           101: PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
        !           102: {
        !           103:     switch (scheme) {
        !           104:       case HTAA_NONE:          return "None";          break;
        !           105:       case HTAA_BASIC:         return "Basic";         break;
        !           106:       case HTAA_PUBKEY:                return "Pubkey";        break;
        !           107:       case HTAA_KERBEROS_V4:   return "KerberosV4";    break;
        !           108:       case HTAA_KERBEROS_V5:   return "KerberosV5";    break;
        !           109:       case HTAA_UNKNOWN:       return "UNKNOWN";       break;
        !           110:       default:                 return "THIS-IS-A-BUG";
        !           111:     }
        !           112: }
        !           113: 
        !           114: 
        !           115: /* PUBLIC                                                  HTAAMethod_enum()
        !           116: **             TRANSLATE METHOD NAME INTO AN ENUMERATED VALUE
        !           117: ** ON ENTRY:
        !           118: **     name            is the method name to translate.
        !           119: **
        !           120: ** ON EXIT:
        !           121: **     returns         HTAAMethod enumerated value corresponding
        !           122: **                     to the given name.
        !           123: */
        !           124: PUBLIC HTAAMethod HTAAMethod_enum ARGS1(CONST char *, name)
        !           125: {
        !           126:     char tmp[MAX_METHODNAME_LEN+1];
        !           127:     CONST char *src = name;
        !           128:     char *dest = tmp;
        !           129: 
        !           130:     if (!name) return METHOD_UNKNOWN;
        !           131: 
        !           132:     while (*src) {
        !           133:        *dest = TOUPPER(*src);
        !           134:        dest++;
        !           135:        src++;
        !           136:     }
        !           137:     *dest = 0;
        !           138: 
        !           139:     if (0==strcmp(tmp, "GET"))
        !           140:        return METHOD_GET;
        !           141:     else if (0==strcmp(tmp, "PUT"))
        !           142:        return METHOD_PUT;
        !           143:     else
        !           144:        return METHOD_UNKNOWN;
        !           145: }
        !           146: 
        !           147: 
        !           148: /* PUBLIC                                              HTAAMethod_name()
        !           149: **                     GET THE NAME OF A GIVEN METHOD
        !           150: ** ON ENTRY:
        !           151: **     method          is one of the method enum values:
        !           152: **                     METHOD_GET, METHOD_PUT, ...
        !           153: **
        !           154: ** ON EXIT:
        !           155: **     returns         the name of the scheme, i.e.
        !           156: **                     "GET", "PUT", ...
        !           157: */
        !           158: PUBLIC char *HTAAMethod_name ARGS1(HTAAMethod, method)
        !           159: {
        !           160:     switch (method) {
        !           161:       case METHOD_GET:         return "GET";           break;
        !           162:       case METHOD_PUT:         return "PUT";           break;
        !           163:       case METHOD_UNKNOWN:     return "UNKNOWN";       break;
        !           164:       default:                 return "THIS-IS-A-BUG";
        !           165:     }
        !           166: }
        !           167: 
        !           168: 
        !           169: /* PUBLIC                                              HTAAMethod_inList()
        !           170: **             IS A METHOD IN A LIST OF METHOD NAMES
        !           171: ** ON ENTRY:
        !           172: **     method          is the method to look for.
        !           173: **     list            is a list of method names.
        !           174: **
        !           175: ** ON EXIT:
        !           176: **     returns         YES, if method was found.
        !           177: **                     NO, if not found.
        !           178: */
        !           179: PUBLIC BOOL HTAAMethod_inList ARGS2(HTAAMethod,        method,
        !           180:                                    HTList *,   list)
        !           181: {
        !           182:     HTList *cur = list;
        !           183:     char *item;
        !           184: 
        !           185:     while (NULL != (item = (char*)HTList_nextObject(cur))) {
        !           186:        if (TRACE) fprintf(stderr, " %s", item);
        !           187:        if (method == HTAAMethod_enum(item))
        !           188:            return YES;
        !           189:     }
        !           190: 
        !           191:     return NO; /* Not found */
        !           192: }
        !           193: 
        !           194: 
        !           195: 
        !           196: /* PUBLIC                                              HTAA_templateMatch()
        !           197: **             STRING COMPARISON FUNCTION FOR FILE NAMES
        !           198: **                WITH ONE WILDCARD * IN THE TEMPLATE
        !           199: ** NOTE:
        !           200: **     This is essentially the same code as in HTRules.c, but it
        !           201: **     cannot be used because it is embedded in between other code.
        !           202: **     (In fact, HTRules.c should use this routine, but then this
        !           203: **      routine would have to be more sophisticated... why is life
        !           204: **      sometimes so hard...)
        !           205: **
        !           206: ** ON ENTRY:
        !           207: **     template        is a template string to match the file name
        !           208: **                     agaist, may contain a single wildcard
        !           209: **                     character * which matches zero or more
        !           210: **                     arbitrary characters.
        !           211: **     filename        is the filename (or pathname) to be matched
        !           212: **                     agaist the template.
        !           213: **
        !           214: ** ON EXIT:
        !           215: **     returns         YES, if filename matches the template.
        !           216: **                     NO, otherwise.
        !           217: */
        !           218: PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template, 
        !           219:                                     CONST char *, filename)
        !           220: {
        !           221:     CONST char *p = template;
        !           222:     CONST char *q = filename;
        !           223:     int m;
        !           224: 
        !           225:     for( ; *p  &&  *q  &&  *p == *q; p++, q++) /* Find first mismatch */
        !           226:        ; /* do nothing else */
        !           227:     
        !           228:     if (!*p && !*q)    return YES;     /* Equally long equal strings */
        !           229:     else if ('*' == *p) {              /* Wildcard */
        !           230:        p++;                            /* Skip wildcard character */
        !           231:        m = strlen(q) - strlen(p);      /* Amount to match to wildcard */
        !           232:        if (m < 0) return NO;           /* No match, filename too short */
        !           233:        else {                  /* Skip the matched characters and compare */
        !           234:            if (strcmp(p, q+m)) return NO;      /* Tail mismatch */
        !           235:            else                return YES;     /* Tail match */
        !           236:        }
        !           237:     }  /* if wildcard */
        !           238:     else               return NO;      /* Length or character mismatch */
        !           239: }
        !           240: 
        !           241: 
        !           242: /* PUBLIC                                      HTAA_makeProtectionTemplate()
        !           243: **             CREATE A PROTECTION TEMPLATE FOR THE FILES
        !           244: **             IN THE SAME DIRECTORY AS THE GIVEN FILE
        !           245: **             (Used by server if there is no fancier way for
        !           246: **             it to tell the client, and by browser if server
        !           247: **             didn't send WWW-ProtectionTemplate: field)
        !           248: ** ON ENTRY:
        !           249: **     docname is the document pathname (from URL).
        !           250: **
        !           251: ** ON EXIT:
        !           252: **     returns a template matching docname, and other files
        !           253: **             files in that directory.
        !           254: **
        !           255: **             E.g.  /foo/bar/x.html  =>  /foo/bar/ *
        !           256: **                                                 ^
        !           257: **                             Space only to prevent it from
        !           258: **                             being a comment marker here,
        !           259: **                             there really isn't any space.
        !           260: */
        !           261: PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
        !           262: {
        !           263:     char *template = NULL;
        !           264:     char *slash = NULL;
        !           265: 
        !           266:     if (docname) {
        !           267:        StrAllocCopy(template, docname);
        !           268:        slash = strrchr(template, '/');
        !           269:        if (slash) slash++;
        !           270:        else slash = template;
        !           271:        *slash = NULL;
        !           272:        StrAllocCat(template, "*");
        !           273:     }
        !           274:     else StrAllocCopy(template, "*");
        !           275: 
        !           276:     if (TRACE) fprintf(stderr,
        !           277:                       "make_template: made template `%s' for file `%s'\n",
        !           278:                       template, docname);
        !           279: 
        !           280:     return template;
        !           281: }
        !           282: 
        !           283: 
        !           284: 
        !           285: 
        !           286: /*
        !           287: ** Skip leading whitespace from *s forward
        !           288: */
        !           289: #define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
        !           290: 
        !           291: /*
        !           292: ** Kill trailing whitespace starting from *(s-1) backwords
        !           293: */
        !           294: #define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)=NULL;}
        !           295: 
        !           296: 
        !           297: /* PUBLIC                                              HTAA_parseArgList()
        !           298: **             PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
        !           299: ** ON ENTRY:
        !           300: **     str     is a comma-separated list:
        !           301: **
        !           302: **                     item, item, item
        !           303: **             where
        !           304: **                     item ::= value
        !           305: **                            | name=value
        !           306: **                            | name="value"
        !           307: **
        !           308: **             Leading and trailing whitespace is ignored
        !           309: **             everywhere except inside quotes, so the following
        !           310: **             examples are equal:
        !           311: **
        !           312: **                     name=value,foo=bar
        !           313: **                      name="value",foo="bar"
        !           314: **                       name = value ,  foo = bar
        !           315: **                        name = "value" ,  foo = "bar"
        !           316: **
        !           317: ** ON EXIT:
        !           318: **     returns a list of name-value pairs (actually HTAssocList*).
        !           319: **             For items with no name, just value, the name is
        !           320: **             the number of order number of that item. E.g.
        !           321: **             "1" for the first, etc.
        !           322: */
        !           323: PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
        !           324: {
        !           325:     HTAssocList *assoc_list = HTAssocList_new();
        !           326:     char *cur = NULL;
        !           327:     char *name = NULL;
        !           328:     int index = 0;
        !           329: 
        !           330:     if (!str) return assoc_list;
        !           331: 
        !           332:     while (*str) {
        !           333:        SKIPWS(str);                            /* Skip leading whitespace */
        !           334:        cur = str;
        !           335:        index++;
        !           336: 
        !           337:        while (*cur  &&  *cur != '='  &&  *cur != ',')
        !           338:            cur++;      /* Find end of name (or lonely value without a name) */
        !           339:        KILLWS(cur);    /* Kill trailing whitespace */
        !           340: 
        !           341:        if (*cur == '=') {                      /* Name followed by a value */
        !           342:            *(cur++) = NULL;                    /* Terminate name */
        !           343:            StrAllocCopy(name, str);
        !           344:            SKIPWS(cur);                        /* Skip WS leading the value */
        !           345:            str = cur;
        !           346:            if (*str == '"') {                  /* Quoted value */
        !           347:                str++;
        !           348:                cur = str;
        !           349:                while (*cur  &&  *cur != '"') cur++;
        !           350:                if (*cur == '"')
        !           351:                    *(cur++) = NULL;            /* Terminate value */
        !           352:                /* else it is lacking terminating quote */
        !           353:                SKIPWS(cur);                    /* Skip WS leading comma */
        !           354:                if (*cur == ',') cur++;         /* Skip separating colon */
        !           355:            }
        !           356:            else {                              /* Unquoted value */
        !           357:                while (*cur  &&  *cur != ',') cur++;
        !           358:                KILLWS(cur);                    /* Kill trailing whitespace */
        !           359:                if (*cur == ',')
        !           360:                    *(cur++) = NULL;
        !           361:                /* else *cur already NULL */
        !           362:            }
        !           363:        }
        !           364:        else {  /* No name, just a value */
        !           365:            if (*cur == ',') 
        !           366:                *(cur++) = NULL;                /* Terminate value */
        !           367:            /* else last value on line (already terminated by NULL) */
        !           368:            StrAllocCopy(name, "nnn");  /* Room for item order number */
        !           369:            sprintf(name, "%d", index); /* Item order number for name */
        !           370:        }
        !           371:        HTAssocList_add(assoc_list, name, str);
        !           372:        str = cur;
        !           373:     } /* while *str */
        !           374: 
        !           375:     return assoc_list;
        !           376: }
        !           377: 
        !           378: 
        !           379: 
        !           380: /************** HEADER LINE READER -- DOES UNFOLDING *************************/
        !           381: 
        !           382: #define BUFFER_SIZE    1024
        !           383: 
        !           384: PRIVATE char buffer[BUFFER_SIZE + 1];
        !           385: PRIVATE char *start_pointer = buffer;
        !           386: PRIVATE char *end_pointer = buffer;
        !           387: PRIVATE int in_soc = -1;
        !           388: 
        !           389: /* PUBLIC                                              HTAA_setupReader()
        !           390: **             SET UP HEADER LINE READER, i.e. give
        !           391: **             the already-read-but-not-yet-processed
        !           392: **             buffer of text to be read before more
        !           393: **             is read from the socket.
        !           394: ** ON ENTRY:
        !           395: **     start_of_headers is a pointer to a buffer containing
        !           396: **                     the beginning of the header lines
        !           397: **                     (rest will be read from a socket).
        !           398: **     length          is the number of valid characters in
        !           399: **                     'start_of_headers' buffer.
        !           400: **     soc             is the socket to use when start_of_headers
        !           401: **                     buffer is used up.
        !           402: ** ON EXIT:
        !           403: **     returns         nothing.
        !           404: **                     Subsequent calls to HTAA_getUnfoldedLine()
        !           405: **                     will use this buffer first and then
        !           406: **                     proceed to read from socket.
        !           407: */
        !           408: PUBLIC void HTAA_setupReader ARGS3(char *,     start_of_headers,
        !           409:                                   int,         length,
        !           410:                                   int,         soc)
        !           411: {
        !           412:     start_pointer = buffer;
        !           413:     if (start_of_headers) {
        !           414:        strncpy(buffer, start_of_headers, length);
        !           415:        buffer[length] = NULL;
        !           416:        end_pointer = buffer + length;
        !           417:     }
        !           418:     else {
        !           419:        *start_pointer = NULL;
        !           420:        end_pointer = start_pointer;
        !           421:     }
        !           422:     in_soc = soc;
        !           423: }
        !           424: 
        !           425: 
        !           426: /* PUBLIC                                              HTAA_getUnfoldedLine()
        !           427: **             READ AN UNFOLDED HEADER LINE FROM SOCKET
        !           428: ** ON ENTRY:
        !           429: **     HTAA_setupReader must absolutely be called before
        !           430: **     this function to set up internal buffer.
        !           431: **
        !           432: ** ON EXIT:
        !           433: **     returns a newly-allocated character string representing
        !           434: **             the read line.  The line is unfolded, i.e.
        !           435: **             lines that begin with whitespace are appended
        !           436: **             to current line.  E.g.
        !           437: **
        !           438: **                     Field-Name: Blaa-Blaa
        !           439: **                      This-Is-A-Continuation-Line
        !           440: **                      Here-Is_Another
        !           441: **
        !           442: **             is seen by the caller as:
        !           443: **
        !           444: **     Field-Name: Blaa-Blaa This-Is-A-Continuation-Line Here-Is_Another
        !           445: **
        !           446: */
        !           447: PUBLIC char *HTAA_getUnfoldedLine NOARGS
        !           448: {
        !           449:     char *line = NULL;
        !           450:     char *cur;
        !           451:     int count;
        !           452:     BOOL peek_for_folding = NO;
        !           453: 
        !           454:     if (in_soc < 0) {
        !           455:        fprintf(stderr, "%s %s\n",
        !           456:                "HTAA_getUnfoldedLine: buffer not initialized",
        !           457:                "with function HTAA_setupReader()");
        !           458:        return NULL;
        !           459:     }
        !           460: 
        !           461:     for(;;) {
        !           462: 
        !           463:        /* Reading from socket */
        !           464: 
        !           465:        if (start_pointer >= end_pointer) {/*Read the next block and continue*/
        !           466:            count = NETREAD(in_soc, buffer, BUFFER_SIZE);
        !           467:            if (count <= 0) {
        !           468:                in_soc = -1;
        !           469:                return line;
        !           470:            }
        !           471:            start_pointer = buffer;
        !           472:            end_pointer = buffer + count;
        !           473:            *end_pointer = NULL;
        !           474: #ifdef NOT_ASCII
        !           475:            cur = start_pointer;
        !           476:            while (cur < end_pointer) {
        !           477:                *cur = TOASCII(*cur);
        !           478:                cur++;
        !           479:            }
        !           480: #endif /*NOT_ASCII*/
        !           481:        }
        !           482:        cur = start_pointer;
        !           483: 
        !           484: 
        !           485:        /* Unfolding */
        !           486:        
        !           487:        if (peek_for_folding) {
        !           488:            if (*cur != ' '  &&  *cur != '\t')
        !           489:                return line;    /* Ok, no continuation line */
        !           490:            else                /* So this is a continuation line, continue */
        !           491:                peek_for_folding = NO;
        !           492:        }
        !           493: 
        !           494: 
        !           495:        /* Finding end-of-line */
        !           496: 
        !           497:        while (cur < end_pointer && *cur != '\n') /* Find the end-of-line */
        !           498:            cur++;                                /* (or end-of-buffer).  */
        !           499: 
        !           500:        
        !           501:        /* Terminating line */
        !           502: 
        !           503:        if (cur < end_pointer) {        /* So *cur==LF, terminate line */
        !           504:            *cur = NULL;                /* Overwrite LF */
        !           505:            if (*(cur-1) == '\r')
        !           506:                *(cur-1) = NULL;        /* Overwrite CR */
        !           507:            peek_for_folding = YES;     /* Check for a continuation line */
        !           508:        }
        !           509: 
        !           510: 
        !           511:        /* Copying the result */
        !           512: 
        !           513:        if (line)
        !           514:            StrAllocCat(line, start_pointer);   /* Append */
        !           515:        else
        !           516:            StrAllocCopy(line, start_pointer);  /* A new line */
        !           517: 
        !           518:        start_pointer = cur+1;  /* Skip the read line */
        !           519: 
        !           520:     } /* forever */
        !           521: }
        !           522: 
        !           523: 
        !           524: 
        !           525: 

Webmaster