Annotation of libwww/Library/src/HTAAUtil.c, revision 2.10
2.9 frystyk 1: /* HTAAUtil.c
2: ** COMMON PARTS OF ACCESS AUTHORIZATION MODULE
3: ** FOR BOTH SERVER AND BROWSER
4: **
5: ** (c) COPYRIGHT CERN 1994.
6: ** Please first read the full copyright statement in the file COPYRIGH.
2.1 luotonen 7: **
8: ** IMPORTANT:
9: ** Routines in this module use dynamic allocation, but free
10: ** automatically all the memory reserved by them.
11: **
12: ** Therefore the caller never has to (and never should)
13: ** free() any object returned by these functions.
14: **
15: ** Therefore also all the strings returned by this package
16: ** are only valid until the next call to the same function
17: ** is made. This approach is selected, because of the nature
18: ** of access authorization: no string returned by the package
19: ** needs to be valid longer than until the next call.
20: **
21: ** This also makes it easy to plug the AA package in:
22: ** you don't have to ponder whether to free() something
23: ** here or is it done somewhere else (because it is always
24: ** done somewhere else).
25: **
26: ** The strings that the package needs to store are copied
27: ** so the original strings given as parameters to AA
28: ** functions may be freed or modified with no side effects.
29: **
30: ** The AA package does not free() anything else than what
31: ** it has itself allocated.
32: **
33: ** AA (Access Authorization) package means modules which
34: ** names start with HTAA.
35: **
36: ** AUTHORS:
37: ** AL Ari Luotonen luotonen@dxcern.cern.ch
2.3 duns 38: ** MD Mark Donszelmann duns@vxdeop.cern.ch
2.1 luotonen 39: **
40: ** HISTORY:
2.4 luotonen 41: ** 8 Nov 93 MD (VMS only) Added case insensitive comparison
42: ** in HTAA_templateCaseMatch
2.1 luotonen 43: **
44: **
45: ** BUGS:
46: **
47: **
48: */
49:
2.10 ! roeber 50: #include "sysdep.h"
! 51:
2.1 luotonen 52: #include "HTUtils.h"
53: #include "HTAAUtil.h" /* Implemented here */
54: #include "HTAssoc.h" /* Assoc list */
55:
56:
57: /* PUBLIC HTAAScheme_enum()
58: ** TRANSLATE SCHEME NAME INTO
59: ** A SCHEME ENUMERATION
60: **
61: ** ON ENTRY:
62: ** name is a string representing the scheme name.
63: **
64: ** ON EXIT:
65: ** returns the enumerated constant for that scheme.
66: */
67: PUBLIC HTAAScheme HTAAScheme_enum ARGS1(CONST char*, name)
68: {
69: static char *upcased = NULL;
70: char *cur;
71:
72: if (!name) return HTAA_UNKNOWN;
73:
74: StrAllocCopy(upcased, name);
75: cur = upcased;
76: while (*cur) {
77: *cur = TOUPPER(*cur);
78: cur++;
79: }
80:
2.4 luotonen 81: if (!strncmp(upcased, "NONE", 4)) return HTAA_NONE;
82: else if (!strncmp(upcased, "BASIC", 5)) return HTAA_BASIC;
83: else if (!strncmp(upcased, "PUBKEY", 6)) return HTAA_PUBKEY;
84: else if (!strncmp(upcased, "KERBEROSV4", 10)) return HTAA_KERBEROS_V4;
85: else if (!strncmp(upcased, "KERBEROSV5", 10)) return HTAA_KERBEROS_V5;
86: else return HTAA_UNKNOWN;
2.1 luotonen 87: }
88:
89:
90: /* PUBLIC HTAAScheme_name()
91: ** GET THE NAME OF A GIVEN SCHEME
92: ** ON ENTRY:
93: ** scheme is one of the scheme enum values:
94: ** HTAA_NONE, HTAA_BASIC, HTAA_PUBKEY, ...
95: **
96: ** ON EXIT:
97: ** returns the name of the scheme, i.e.
98: ** "None", "Basic", "Pubkey", ...
99: */
100: PUBLIC char *HTAAScheme_name ARGS1(HTAAScheme, scheme)
101: {
102: switch (scheme) {
103: case HTAA_NONE: return "None"; break;
104: case HTAA_BASIC: return "Basic"; break;
105: case HTAA_PUBKEY: return "Pubkey"; break;
106: case HTAA_KERBEROS_V4: return "KerberosV4"; break;
107: case HTAA_KERBEROS_V5: return "KerberosV5"; break;
108: case HTAA_UNKNOWN: return "UNKNOWN"; break;
109: default: return "THIS-IS-A-BUG";
110: }
111: }
112:
113:
114:
115: /* PUBLIC HTAA_templateMatch()
116: ** STRING COMPARISON FUNCTION FOR FILE NAMES
117: ** WITH ONE WILDCARD * IN THE TEMPLATE
118: ** NOTE:
119: ** This is essentially the same code as in HTRules.c, but it
120: ** cannot be used because it is embedded in between other code.
121: ** (In fact, HTRules.c should use this routine, but then this
122: ** routine would have to be more sophisticated... why is life
123: ** sometimes so hard...)
124: **
125: ** ON ENTRY:
126: ** template is a template string to match the file name
127: ** agaist, may contain a single wildcard
128: ** character * which matches zero or more
129: ** arbitrary characters.
130: ** filename is the filename (or pathname) to be matched
131: ** agaist the template.
132: **
133: ** ON EXIT:
134: ** returns YES, if filename matches the template.
135: ** NO, otherwise.
136: */
2.8 frystyk 137: PUBLIC BOOL HTAA_templateMatch ARGS2(CONST char *, tmplate,
2.1 luotonen 138: CONST char *, filename)
139: {
2.8 frystyk 140: CONST char *p = tmplate;
2.1 luotonen 141: CONST char *q = filename;
142: int m;
143:
2.8 frystyk 144: if (!tmplate || !filename) {
2.4 luotonen 145: if (TRACE) fprintf(stderr,
146: "HTAA_templateMatch: invalid param: %s is NULL!!\n",
2.8 frystyk 147: (tmplate ? "filename" : "template"));
2.4 luotonen 148: return NO;
149: }
150:
2.1 luotonen 151: for( ; *p && *q && *p == *q; p++, q++) /* Find first mismatch */
152: ; /* do nothing else */
2.3 duns 153:
2.1 luotonen 154: if (!*p && !*q) return YES; /* Equally long equal strings */
155: else if ('*' == *p) { /* Wildcard */
156: p++; /* Skip wildcard character */
157: m = strlen(q) - strlen(p); /* Amount to match to wildcard */
158: if (m < 0) return NO; /* No match, filename too short */
159: else { /* Skip the matched characters and compare */
160: if (strcmp(p, q+m)) return NO; /* Tail mismatch */
161: else return YES; /* Tail match */
162: }
163: } /* if wildcard */
164: else return NO; /* Length or character mismatch */
2.3 duns 165: }
166:
167:
2.4 luotonen 168: /* PUBLIC HTAA_templateCaseMatch()
2.3 duns 169: ** STRING COMPARISON FUNCTION FOR FILE NAMES
2.4 luotonen 170: ** WITH ONE WILDCARD * IN THE TEMPLATE (Case Insensitive)
2.3 duns 171: ** NOTE:
172: ** This is essentially the same code as in HTAA_templateMatch, but
173: ** it compares case insensitive (for VMS). Reason for this routine
174: ** is that HTAA_templateMatch gets called from several places, also
175: ** there where a case sensitive match is needed, so one cannot just
176: ** change the HTAA_templateMatch routine for VMS.
177: **
178: ** ON ENTRY:
2.8 frystyk 179: ** tmplate is a template string to match the file name
2.3 duns 180: ** agaist, may contain a single wildcard
181: ** character * which matches zero or more
182: ** arbitrary characters.
183: ** filename is the filename (or pathname) to be matched
184: ** agaist the template.
185: **
186: ** ON EXIT:
187: ** returns YES, if filename matches the template.
188: ** NO, otherwise.
189: */
2.8 frystyk 190: PUBLIC BOOL HTAA_templateCaseMatch ARGS2(CONST char *, tmplate,
2.3 duns 191: CONST char *, filename)
192: {
2.8 frystyk 193: CONST char *p = tmplate;
2.3 duns 194: CONST char *q = filename;
195: int m;
196:
2.8 frystyk 197: if (!tmplate || !filename) {
2.4 luotonen 198: if (TRACE) fprintf(stderr,
199: "HTAA_templateCaseMatch: invalid param: %s is NULL!!\n",
2.8 frystyk 200: (tmplate ? "filename" : "template"));
2.4 luotonen 201: return NO;
202: }
203:
2.3 duns 204: for( ; *p && *q && toupper(*p) == toupper(*q); p++, q++) /* Find first mismatch */
205: ; /* do nothing else */
206:
207: if (!*p && !*q) return YES; /* Equally long equal strings */
208: else if ('*' == *p) { /* Wildcard */
209: p++; /* Skip wildcard character */
210: m = strlen(q) - strlen(p); /* Amount to match to wildcard */
211: if (m < 0) return NO; /* No match, filename too short */
212: else { /* Skip the matched characters and compare */
213: if (strcasecomp(p, q+m)) return NO; /* Tail mismatch */
214: else return YES; /* Tail match */
215: }
216: } /* if wildcard */
217: else return NO; /* Length or character mismatch */
218: }
2.1 luotonen 219:
220:
221: /* PUBLIC HTAA_makeProtectionTemplate()
222: ** CREATE A PROTECTION TEMPLATE FOR THE FILES
223: ** IN THE SAME DIRECTORY AS THE GIVEN FILE
224: ** (Used by server if there is no fancier way for
225: ** it to tell the client, and by browser if server
226: ** didn't send WWW-ProtectionTemplate: field)
227: ** ON ENTRY:
228: ** docname is the document pathname (from URL).
229: **
230: ** ON EXIT:
231: ** returns a template matching docname, and other files
232: ** files in that directory.
233: **
234: ** E.g. /foo/bar/x.html => /foo/bar/ *
235: ** ^
236: ** Space only to prevent it from
237: ** being a comment marker here,
238: ** there really isn't any space.
239: */
240: PUBLIC char *HTAA_makeProtectionTemplate ARGS1(CONST char *, docname)
241: {
2.8 frystyk 242: char *tmplate = NULL;
2.1 luotonen 243: char *slash = NULL;
244:
245: if (docname) {
2.8 frystyk 246: StrAllocCopy(tmplate, docname);
247: slash = strrchr(tmplate, '/');
2.1 luotonen 248: if (slash) slash++;
2.8 frystyk 249: else slash = tmplate;
2.2 luotonen 250: *slash = (char)0;
2.8 frystyk 251: StrAllocCat(tmplate, "*");
2.1 luotonen 252: }
2.8 frystyk 253: else StrAllocCopy(tmplate, "*");
2.1 luotonen 254:
255: if (TRACE) fprintf(stderr,
256: "make_template: made template `%s' for file `%s'\n",
2.8 frystyk 257: tmplate, docname);
2.1 luotonen 258:
2.8 frystyk 259: return tmplate;
2.1 luotonen 260: }
261:
262:
263:
264:
265: /*
266: ** Skip leading whitespace from *s forward
267: */
268: #define SKIPWS(s) while (*s==' ' || *s=='\t') s++;
269:
270: /*
271: ** Kill trailing whitespace starting from *(s-1) backwords
272: */
2.2 luotonen 273: #define KILLWS(s) {char *c=s-1; while (*c==' ' || *c=='\t') *(c--)=(char)0;}
2.1 luotonen 274:
275:
276: /* PUBLIC HTAA_parseArgList()
277: ** PARSE AN ARGUMENT LIST GIVEN IN A HEADER FIELD
278: ** ON ENTRY:
279: ** str is a comma-separated list:
280: **
281: ** item, item, item
282: ** where
283: ** item ::= value
284: ** | name=value
285: ** | name="value"
286: **
287: ** Leading and trailing whitespace is ignored
288: ** everywhere except inside quotes, so the following
289: ** examples are equal:
290: **
291: ** name=value,foo=bar
292: ** name="value",foo="bar"
293: ** name = value , foo = bar
294: ** name = "value" , foo = "bar"
295: **
296: ** ON EXIT:
297: ** returns a list of name-value pairs (actually HTAssocList*).
298: ** For items with no name, just value, the name is
299: ** the number of order number of that item. E.g.
300: ** "1" for the first, etc.
301: */
302: PUBLIC HTAssocList *HTAA_parseArgList ARGS1(char *, str)
303: {
304: HTAssocList *assoc_list = HTAssocList_new();
305: char *cur = NULL;
306: char *name = NULL;
307: int index = 0;
308:
309: if (!str) return assoc_list;
310:
311: while (*str) {
312: SKIPWS(str); /* Skip leading whitespace */
313: cur = str;
314: index++;
315:
316: while (*cur && *cur != '=' && *cur != ',')
317: cur++; /* Find end of name (or lonely value without a name) */
318: KILLWS(cur); /* Kill trailing whitespace */
319:
320: if (*cur == '=') { /* Name followed by a value */
2.2 luotonen 321: *(cur++) = (char)0; /* Terminate name */
2.1 luotonen 322: StrAllocCopy(name, str);
323: SKIPWS(cur); /* Skip WS leading the value */
324: str = cur;
325: if (*str == '"') { /* Quoted value */
326: str++;
327: cur = str;
328: while (*cur && *cur != '"') cur++;
329: if (*cur == '"')
2.2 luotonen 330: *(cur++) = (char)0; /* Terminate value */
2.1 luotonen 331: /* else it is lacking terminating quote */
332: SKIPWS(cur); /* Skip WS leading comma */
333: if (*cur == ',') cur++; /* Skip separating colon */
334: }
335: else { /* Unquoted value */
336: while (*cur && *cur != ',') cur++;
337: KILLWS(cur); /* Kill trailing whitespace */
338: if (*cur == ',')
2.2 luotonen 339: *(cur++) = (char)0;
2.1 luotonen 340: /* else *cur already NULL */
341: }
342: }
343: else { /* No name, just a value */
344: if (*cur == ',')
2.2 luotonen 345: *(cur++) = (char)0; /* Terminate value */
2.1 luotonen 346: /* else last value on line (already terminated by NULL) */
347: StrAllocCopy(name, "nnn"); /* Room for item order number */
348: sprintf(name, "%d", index); /* Item order number for name */
349: }
350: HTAssocList_add(assoc_list, name, str);
351: str = cur;
352: } /* while *str */
2.6 frystyk 353: FREE(name); /* Henrik 14/03-94 */
2.1 luotonen 354: return assoc_list;
355: }
2.6 frystyk 356:
357:
358:
359:
360:
2.1 luotonen 361:
Webmaster