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