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

2.1       luotonen    1: 
2.2       luotonen    2: /* MODULE                                                      HTAAUtil.c
2.1       luotonen    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
2.3       duns       36: **     MD      Mark Donszelmann    duns@vxdeop.cern.ch
2.1       luotonen   37: **
                     38: ** HISTORY:
2.4     ! luotonen   39: **      8 Nov 93  MD   (VMS only) Added case insensitive comparison
        !            40: **                     in HTAA_templateCaseMatch
2.1       luotonen   41: **
                     42: **
                     43: ** BUGS:
                     44: **
                     45: **
                     46: */
                     47: 
                     48: #include <string.h>
                     49: #include "HTUtils.h"
                     50: #include "tcp.h"       /* NETREAD() etc.       */
                     51: #include "HTAAUtil.h"  /* Implemented here     */
                     52: #include "HTAssoc.h"   /* Assoc list           */
                     53: 
                     54: 
                     55: /* PUBLIC                                              HTAAScheme_enum()
                     56: **             TRANSLATE SCHEME NAME INTO
                     57: **             A SCHEME ENUMERATION
                     58: **
                     59: ** ON ENTRY:
                     60: **     name            is a string representing the scheme name.
                     61: **
                     62: ** ON EXIT:
                     63: **     returns         the enumerated constant for that scheme.
                     64: */
                     65: PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
                     66: {
                     67:     static char *upcased = NULL;
                     68:     char *cur;
                     69: 
                     70:     if (!name) return HTAA_UNKNOWN;
                     71: 
                     72:     StrAllocCopy(upcased, name);
                     73:     cur = upcased;
                     74:     while (*cur) {
                     75:        *cur = TOUPPER(*cur);
                     76:        cur++;
                     77:     }
                     78:     
2.4     ! luotonen   79:     if      (!strncmp(upcased, "NONE", 4))        return HTAA_NONE;
        !            80:     else if (!strncmp(upcased, "BASIC", 5))       return HTAA_BASIC;
        !            81:     else if (!strncmp(upcased, "PUBKEY", 6))      return HTAA_PUBKEY;
        !            82:     else if (!strncmp(upcased, "KERBEROSV4", 10))  return HTAA_KERBEROS_V4;
        !            83:     else if (!strncmp(upcased, "KERBEROSV5", 10))  return HTAA_KERBEROS_V5;
        !            84:     else                                          return HTAA_UNKNOWN;
2.1       luotonen   85: }
                     86: 
                     87: 
                     88: /* PUBLIC                                              HTAAScheme_name()
                     89: **                     GET THE NAME OF A GIVEN SCHEME
                     90: ** ON ENTRY:
                     91: **     scheme          is one of the scheme enum values:
                     92: **                     HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
                     93: **
                     94: ** ON EXIT:
                     95: **     returns         the name of the scheme, i.e.
                     96: **                     "None", "Basic", "Pubkey", ...
                     97: */
                     98: PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
                     99: {
                    100:     switch (scheme) {
                    101:       case HTAA_NONE:          return "None";          break;
                    102:       case HTAA_BASIC:         return "Basic";         break;
                    103:       case HTAA_PUBKEY:                return "Pubkey";        break;
                    104:       case HTAA_KERBEROS_V4:   return "KerberosV4";    break;
                    105:       case HTAA_KERBEROS_V5:   return "KerberosV5";    break;
                    106:       case HTAA_UNKNOWN:       return "UNKNOWN";       break;
                    107:       default:                 return "THIS-IS-A-BUG";
                    108:     }
                    109: }
                    110: 
                    111: 
                    112: 
2.4     ! luotonen  113: /* PUBLIC                                              HTMethod_inList()
2.1       luotonen  114: **             IS A METHOD IN A LIST OF METHOD NAMES
                    115: ** ON ENTRY:
                    116: **     method          is the method to look for.
                    117: **     list            is a list of method names.
                    118: **
                    119: ** ON EXIT:
                    120: **     returns         YES, if method was found.
                    121: **                     NO, if not found.
                    122: */
2.4     ! luotonen  123: PUBLIC BOOL HTMethod_inList ARGS2(HTAtom *,    method,
        !           124:                                  HTList *,     list)
2.1       luotonen  125: {
2.4     ! luotonen  126:     char *method_name;
2.1       luotonen  127:     HTList *cur = list;
                    128:     char *item;
                    129: 
2.4     ! luotonen  130:     if (!method || !(method_name = HTAtom_name(method))) {
        !           131:        fprintf(stderr, "HTMethod_inList: invalid param: %s is NULL!!\n",
        !           132:                (method ? "method's name (atom name)" : "method (atom)"));
        !           133:        return NO;
        !           134:     }
        !           135: 
2.1       luotonen  136:     while (NULL != (item = (char*)HTList_nextObject(cur))) {
                    137:        if (TRACE) fprintf(stderr, " %s", item);
2.4     ! luotonen  138:        if (0==strcasecomp(item, method_name))
2.1       luotonen  139:            return YES;
                    140:     }
                    141: 
                    142:     return NO; /* Not found */
                    143: }
                    144: 
                    145: 
                    146: 
                    147: /* PUBLIC                                              HTAA_templateMatch()
                    148: **             STRING COMPARISON FUNCTION FOR FILE NAMES
                    149: **                WITH ONE WILDCARD * IN THE TEMPLATE
                    150: ** NOTE:
                    151: **     This is essentially the same code as in HTRules.c, but it
                    152: **     cannot be used because it is embedded in between other code.
                    153: **     (In fact, HTRules.c should use this routine, but then this
                    154: **      routine would have to be more sophisticated... why is life
                    155: **      sometimes so hard...)
                    156: **
                    157: ** ON ENTRY:
                    158: **     template        is a template string to match the file name
                    159: **                     agaist, may contain a single wildcard
                    160: **                     character * which matches zero or more
                    161: **                     arbitrary characters.
                    162: **     filename        is the filename (or pathname) to be matched
                    163: **                     agaist the template.
                    164: **
                    165: ** ON EXIT:
                    166: **     returns         YES, if filename matches the template.
                    167: **                     NO, otherwise.
                    168: */
                    169: PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, template, 
                    170:                                     CONST char *, filename)
                    171: {
                    172:     CONST char *p = template;
                    173:     CONST char *q = filename;
                    174:     int m;
                    175: 
2.4     ! luotonen  176:     if (!template || !filename) {
        !           177:        if (TRACE) fprintf(stderr,
        !           178:                           "HTAA_templateMatch: invalid param: %s is NULL!!\n",
        !           179:                           (template ? "filename" : "template"));
        !           180:        return NO;
        !           181:     }
        !           182: 
2.1       luotonen  183:     for( ; *p  &&  *q  &&  *p == *q; p++, q++) /* Find first mismatch */
                    184:        ; /* do nothing else */
2.3       duns      185: 
2.1       luotonen  186:     if (!*p && !*q)    return YES;     /* Equally long equal strings */
                    187:     else if ('*' == *p) {              /* Wildcard */
                    188:        p++;                            /* Skip wildcard character */
                    189:        m = strlen(q) - strlen(p);      /* Amount to match to wildcard */
                    190:        if (m < 0) return NO;           /* No match, filename too short */
                    191:        else {                  /* Skip the matched characters and compare */
                    192:            if (strcmp(p, q+m)) return NO;      /* Tail mismatch */
                    193:            else                return YES;     /* Tail match */
                    194:        }
                    195:     }  /* if wildcard */
                    196:     else               return NO;      /* Length or character mismatch */
2.3       duns      197: }    
                    198: 
                    199: 
2.4     ! luotonen  200: /* PUBLIC                                      HTAA_templateCaseMatch()
2.3       duns      201: **             STRING COMPARISON FUNCTION FOR FILE NAMES
2.4     ! luotonen  202: **        WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
2.3       duns      203: ** NOTE:
                    204: **     This is essentially the same code as in HTAA_templateMatch, but
                    205: **     it compares case insensitive (for VMS). Reason for this routine
                    206: **     is that HTAA_templateMatch gets called from several places, also 
                    207: **     there where a case sensitive match is needed, so one cannot just
                    208: **     change the HTAA_templateMatch routine for VMS.
                    209: **
                    210: ** ON ENTRY:
                    211: **     template        is a template string to match the file name
                    212: **                     agaist, may contain a single wildcard
                    213: **                     character * which matches zero or more
                    214: **                     arbitrary characters.
                    215: **     filename        is the filename (or pathname) to be matched
                    216: **                     agaist the template.
                    217: **
                    218: ** ON EXIT:
                    219: **     returns         YES, if filename matches the template.
                    220: **                     NO, otherwise.
                    221: */
                    222: PUBLIC BOOL HTAA_templateCaseMatch ARGS2(CONST char *, template, 
                    223:                                         CONST char *, filename)
                    224: {
                    225:     CONST char *p = template;
                    226:     CONST char *q = filename;
                    227:     int m;
                    228: 
2.4     ! luotonen  229:     if (!template || !filename) {
        !           230:        if (TRACE) fprintf(stderr,
        !           231:                           "HTAA_templateCaseMatch: invalid param: %s is NULL!!\n",
        !           232:                           (template ? "filename" : "template"));
        !           233:        return NO;
        !           234:     }
        !           235: 
2.3       duns      236:     for( ; *p  &&  *q  &&  toupper(*p) == toupper(*q); p++, q++) /* Find first mismatch */
                    237:        ; /* do nothing else */
                    238: 
                    239:     if (!*p && !*q)    return YES;     /* Equally long equal strings */
                    240:     else if ('*' == *p) {              /* Wildcard */
                    241:        p++;                            /* Skip wildcard character */
                    242:        m = strlen(q) - strlen(p);      /* Amount to match to wildcard */
                    243:        if (m < 0) return NO;           /* No match, filename too short */
                    244:        else {                  /* Skip the matched characters and compare */
                    245:            if (strcasecomp(p, q+m))    return NO;      /* Tail mismatch */
                    246:            else                return YES;     /* Tail match */
                    247:        }
                    248:     }  /* if wildcard */
                    249:     else               return NO;      /* Length or character mismatch */
                    250: }    
2.1       luotonen  251: 
                    252: 
                    253: /* PUBLIC                                      HTAA_makeProtectionTemplate()
                    254: **             CREATE A PROTECTION TEMPLATE FOR THE FILES
                    255: **             IN THE SAME DIRECTORY AS THE GIVEN FILE
                    256: **             (Used by server if there is no fancier way for
                    257: **             it to tell the client, and by browser if server
                    258: **             didn't send WWW-ProtectionTemplate: field)
                    259: ** ON ENTRY:
                    260: **     docname is the document pathname (from URL).
                    261: **
                    262: ** ON EXIT:
                    263: **     returns a template matching docname, and other files
                    264: **             files in that directory.
                    265: **
                    266: **             E.g.  /foo/bar/x.html  =>  /foo/bar/ *
                    267: **                                                 ^
                    268: **                             Space only to prevent it from
                    269: **                             being a comment marker here,
                    270: **                             there really isn't any space.
                    271: */
                    272: PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
                    273: {
                    274:     char *template = NULL;
                    275:     char *slash = NULL;
                    276: 
                    277:     if (docname) {
                    278:        StrAllocCopy(template, docname);
                    279:        slash = strrchr(template, '/');
                    280:        if (slash) slash++;
                    281:        else slash = template;
2.2       luotonen  282:        *slash = (char)0;
2.1       luotonen  283:        StrAllocCat(template, "*");
                    284:     }
                    285:     else StrAllocCopy(template, "*");
                    286: 
                    287:     if (TRACE) fprintf(stderr,
                    288:                       "make_template: made template `%s' for file `%s'\n",
                    289:                       template, docname);
                    290: 
                    291:     return template;
                    292: }
                    293: 
                    294: 
                    295: 
                    296: 
                    297: /*
                    298: ** Skip leading whitespace from *s forward
                    299: */
                    300: #define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
                    301: 
                    302: /*
                    303: ** Kill trailing whitespace starting from *(s-1) backwords
                    304: */
2.2       luotonen  305: #define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)=(char)0;}
2.1       luotonen  306: 
                    307: 
                    308: /* PUBLIC                                              HTAA_parseArgList()
                    309: **             PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
                    310: ** ON ENTRY:
                    311: **     str     is a comma-separated list:
                    312: **
                    313: **                     item, item, item
                    314: **             where
                    315: **                     item ::= value
                    316: **                            | name=value
                    317: **                            | name="value"
                    318: **
                    319: **             Leading and trailing whitespace is ignored
                    320: **             everywhere except inside quotes, so the following
                    321: **             examples are equal:
                    322: **
                    323: **                     name=value,foo=bar
                    324: **                      name="value",foo="bar"
                    325: **                       name = value ,  foo = bar
                    326: **                        name = "value" ,  foo = "bar"
                    327: **
                    328: ** ON EXIT:
                    329: **     returns a list of name-value pairs (actually HTAssocList*).
                    330: **             For items with no name, just value, the name is
                    331: **             the number of order number of that item. E.g.
                    332: **             "1" for the first, etc.
                    333: */
                    334: PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
                    335: {
                    336:     HTAssocList *assoc_list = HTAssocList_new();
                    337:     char *cur = NULL;
                    338:     char *name = NULL;
                    339:     int index = 0;
                    340: 
                    341:     if (!str) return assoc_list;
                    342: 
                    343:     while (*str) {
                    344:        SKIPWS(str);                            /* Skip leading whitespace */
                    345:        cur = str;
                    346:        index++;
                    347: 
                    348:        while (*cur  &&  *cur != '='  &&  *cur != ',')
                    349:            cur++;      /* Find end of name (or lonely value without a name) */
                    350:        KILLWS(cur);    /* Kill trailing whitespace */
                    351: 
                    352:        if (*cur == '=') {                      /* Name followed by a value */
2.2       luotonen  353:            *(cur++) = (char)0;                 /* Terminate name */
2.1       luotonen  354:            StrAllocCopy(name, str);
                    355:            SKIPWS(cur);                        /* Skip WS leading the value */
                    356:            str = cur;
                    357:            if (*str == '"') {                  /* Quoted value */
                    358:                str++;
                    359:                cur = str;
                    360:                while (*cur  &&  *cur != '"') cur++;
                    361:                if (*cur == '"')
2.2       luotonen  362:                    *(cur++) = (char)0; /* Terminate value */
2.1       luotonen  363:                /* else it is lacking terminating quote */
                    364:                SKIPWS(cur);                    /* Skip WS leading comma */
                    365:                if (*cur == ',') cur++;         /* Skip separating colon */
                    366:            }
                    367:            else {                              /* Unquoted value */
                    368:                while (*cur  &&  *cur != ',') cur++;
                    369:                KILLWS(cur);                    /* Kill trailing whitespace */
                    370:                if (*cur == ',')
2.2       luotonen  371:                    *(cur++) = (char)0;
2.1       luotonen  372:                /* else *cur already NULL */
                    373:            }
                    374:        }
                    375:        else {  /* No name, just a value */
                    376:            if (*cur == ',') 
2.2       luotonen  377:                *(cur++) = (char)0;             /* Terminate value */
2.1       luotonen  378:            /* else last value on line (already terminated by NULL) */
                    379:            StrAllocCopy(name, "nnn");  /* Room for item order number */
                    380:            sprintf(name, "%d", index); /* Item order number for name */
                    381:        }
                    382:        HTAssocList_add(assoc_list, name, str);
                    383:        str = cur;
                    384:     } /* while *str */
                    385: 
                    386:     return assoc_list;
                    387: }
                    388: 

Webmaster