Annotation of libwww/Library/src/HTRules.c, revision 2.19
2.19 ! luotonen 1: /* Configuration manager for Clients HTRules.c
! 2: ** =================================
2.1 timbl 3: **
2.19 ! luotonen 4: ** This module is replaced by HTConfig.c in httpd.
2.1 timbl 5: **
6: ** History:
7: ** 3 Jun 91 Written TBL
8: ** 10 Aug 91 Authorisation added after Daniel Martin (pass, fail)
9: ** Rule order in file changed
10: ** Comments allowed with # on 1st char of rule line
11: ** 17 Jun 92 Bug fix: pass and fail failed if didn't contain '*' TBL
2.9 secret 12: ** 1 Sep 93 Bug fix: no memory check - Nathan Torkington
13: ** BYTE_ADDRESSING removed - Arthur Secret
2.12 luotonen 14: ** 11 Sep 93 MD Changed %i into %d in debug printf.
2.10 duns 15: ** VMS does not recognize %i.
16: ** Bug Fix: in case of PASS, only one parameter to printf.
2.12 luotonen 17: ** 19 Sep 93 AL Added Access Authorization stuff.
18: ** 1 Nov 93 AL Added htbin.
2.15 luotonen 19: ** 30 Nov 93 AL Added HTTranslateReq().
2.19 ! luotonen 20: ** 4 Feb 94 AL Took away all the daemon-specific stuff.
2.11 luotonen 21: **
2.1 timbl 22: */
23:
24: /* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
25: #include "HTRules.h"
26:
27: #include <stdio.h>
28: #include "tcp.h"
29: #include "HTFile.h"
2.17 luotonen 30: #include "HTParse.h" /* HTParse() */
2.18 luotonen 31: #include "HTAAUtil.h"
32:
33: #ifndef VMS
34: #include <pwd.h> /* Unix password file routine: getpwnam() */
35: #endif /* not VMS */
36:
2.1 timbl 37:
38: #define LINE_LENGTH 256
39:
40:
41: typedef struct _rule {
42: struct _rule * next;
43: HTRuleOp op;
44: char * pattern;
45: char * equiv;
46: } rule;
47:
2.13 luotonen 48:
2.1 timbl 49: /* Module-wide variables
50: ** ---------------------
51: */
52:
53: PRIVATE rule * rules = 0; /* Pointer to first on list */
54: #ifndef PUT_ON_HEAD
55: PRIVATE rule * rule_tail = 0; /* Pointer to last on list */
56: #endif
57:
2.11 luotonen 58:
2.1 timbl 59: /* Add rule to the list HTAddRule()
60: ** --------------------
61: **
62: ** On entry,
63: ** pattern points to 0-terminated string containing a single "*"
64: ** equiv points to the equivalent string with * for the
65: ** place where the text matched by * goes.
66: ** On exit,
67: ** returns 0 if success, -1 if error.
68: */
2.9 secret 69:
2.15 luotonen 70: PUBLIC int HTAddRule ARGS3(HTRuleOp, op,
71: CONST char *, pattern,
72: CONST char *, equiv)
2.9 secret 73: { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */
74: rule * temp;
75: char * pPattern;
76:
77: temp = (rule *)malloc(sizeof(*temp));
78: if (temp==NULL)
79: outofmem(__FILE__, "HTAddRule");
80: pPattern = (char *)malloc(strlen(pattern)+1);
81: if (pPattern==NULL)
82: outofmem(__FILE__, "HTAddRule");
2.1 timbl 83: if (equiv) { /* Two operands */
84: char * pEquiv = (char *)malloc(strlen(equiv)+1);
2.9 secret 85: if (pEquiv==NULL)
86: outofmem(__FILE__, "HTAddRule");
2.1 timbl 87: temp->equiv = pEquiv;
88: strcpy(pEquiv, equiv);
89: } else {
90: temp->equiv = 0;
91: }
92: temp->pattern = pPattern;
93: temp->op = op;
94:
95: strcpy(pPattern, pattern);
2.10 duns 96: if (TRACE) {
97: if (equiv)
2.17 luotonen 98: fprintf(stderr, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv);
2.10 duns 99: else
2.17 luotonen 100: fprintf(stderr, "Rule: For `%s' op %d\n", pattern, op);
2.10 duns 101: }
2.1 timbl 102:
103: #ifdef PUT_ON_HEAD
104: temp->next = rules;
105: rules = temp;
106: #else
107: temp->next = 0;
108: if (rule_tail) rule_tail->next = temp;
109: else rules = temp;
110: rule_tail = temp;
111: #endif
112:
113:
114: return 0;
115: }
116:
117:
118: /* Clear all rules HTClearRules()
119: ** ---------------
120: **
121: ** On exit,
122: ** There are no rules
123: ** returns 0 if success, -1 if error.
124: **
125: ** See also
126: ** HTAddRule()
127: */
2.15 luotonen 128: PUBLIC int HTClearRules NOARGS
2.1 timbl 129: {
130: while (rules) {
131: rule * temp = rules;
132: rules = temp->next;
133: free(temp->pattern);
134: free(temp->equiv);
135: free(temp);
136: }
137: #ifndef PUT_ON_HEAD
138: rule_tail = 0;
139: #endif
140:
141: return 0;
142: }
143:
144:
2.18 luotonen 145: PRIVATE char * wrap ARGS1(char *, s)
146: {
147: if (s && *s=='/') {
148: char * n = (char*)malloc(strlen(s) + 6);
149: if (!n) outofmem(__FILE__, "HTRules:wrap");
150: sprintf(n, "file:%s", s);
151: free(s);
152: return n;
153: }
154: return s;
155: }
156:
157:
158:
2.1 timbl 159: /* Translate by rules HTTranslate()
160: ** ------------------
161: **
2.15 luotonen 162: ** ATTENTION:
163: ** THIS FUNCTION HAS BEEN OBSOLITED BY HTTranslateReq()
164: ** ON SERVER SIDE -- ON BROWSER SIDE THIS IS STILL USED!
165: ** Don't add new server features to this, this already has
166: ** more than it can handle cleanly.
167: **
168: ** The most recently defined rules are applied last.
2.1 timbl 169: **
170: ** On entry,
171: ** required points to a string whose equivalent value is neeed
172: ** On exit,
173: ** returns the address of the equivalent string allocated from
174: ** the heap which the CALLER MUST FREE. If no translation
175: ** occured, then it is a copy of te original.
2.11 luotonen 176: ** NEW FEATURES:
177: ** When a "protect" or "defprot" rule is mathed,
178: ** a call to HTAA_setCurrentProtection() or
179: ** HTAA_setDefaultProtection() is made to notify
180: ** the Access Authorization module that the file is
181: ** protected, and so it knows how to handle it.
182: ** -- AL
2.1 timbl 183: */
2.15 luotonen 184: PUBLIC char * HTTranslate ARGS1(CONST char *, required)
2.1 timbl 185: {
186: rule * r;
2.11 luotonen 187: char *current = NULL;
188: StrAllocCopy(current, required);
189:
2.15 luotonen 190: #ifdef OLD_CODE
2.11 luotonen 191: HTAA_clearProtections(); /* Reset from previous call -- AL */
2.15 luotonen 192: #endif
2.11 luotonen 193:
2.1 timbl 194: for(r = rules; r; r = r->next) {
195: char * p = r->pattern;
2.11 luotonen 196: int m=0; /* Number of characters matched against wildcard */
2.1 timbl 197: CONST char * q = current;
198: for(;*p && *q; p++, q++) { /* Find first mismatch */
199: if (*p!=*q) break;
200: }
201:
202: if (*p == '*') { /* Match up to wildcard */
203: m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
204: if(m<0) continue; /* tail is too short to match */
205: if (0!=strcmp(q+m, p+1)) continue; /* Tail mismatch */
206: } else /* Not wildcard */
207: if (*p != *q) continue; /* plain mismatch: go to next rule */
208:
209: switch (r->op) { /* Perform operation */
2.11 luotonen 210:
2.1 timbl 211: case HT_Pass: /* Authorised */
212: if (!r->equiv) {
2.17 luotonen 213: CTRACE(stderr, "HTRule: Pass `%s'\n", current);
2.18 luotonen 214: return wrap(current);
2.1 timbl 215: }
2.11 luotonen 216: /* Else fall through ...to map and pass */
2.1 timbl 217:
218: case HT_Map:
219: if (*p == *q) { /* End of both strings, no wildcard */
2.17 luotonen 220: CTRACE(stderr, "For `%s' using `%s'\n", current, r->equiv);
221: StrAllocCopy(current, r->equiv); /* use entire translation */
2.1 timbl 222: } else {
223: char * ins = strchr(r->equiv, '*'); /* Insertion point */
224: if (ins) { /* Consistent rule!!! */
225: char * temp = (char *)malloc(
226: strlen(r->equiv)-1 + m + 1);
2.9 secret 227: if (temp==NULL)
228: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1 timbl 229: strncpy(temp, r->equiv, ins-r->equiv);
230: /* Note: temp may be unterminated now! */
231: strncpy(temp+(ins-r->equiv), q, m); /* Matched bit */
232: strcpy (temp+(ins-r->equiv)+m, ins+1); /* Last bit */
2.17 luotonen 233: CTRACE(stderr, "For `%s' using `%s'\n",
2.1 timbl 234: current, temp);
235: free(current);
236: current = temp; /* Use this */
237:
238: } else { /* No insertion point */
239: char * temp = (char *)malloc(strlen(r->equiv)+1);
2.9 secret 240: if (temp==NULL)
241: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1 timbl 242: strcpy(temp, r->equiv);
2.17 luotonen 243: CTRACE(stderr, "For `%s' using `%s'\n", current, temp);
2.1 timbl 244: free(current);
245: current = temp; /* Use this */
246: } /* If no insertion point exists */
247: }
248: if (r->op == HT_Pass) {
2.17 luotonen 249: CTRACE(stderr, "HTRule: ...and pass `%s'\n", current);
2.18 luotonen 250: return wrap(current);
2.1 timbl 251: }
252: break;
253:
2.11 luotonen 254: case HT_Fail: /* Unauthorised */
2.15 luotonen 255: default:
2.17 luotonen 256: CTRACE(stderr,"HTRule: *** FAIL `%s'\n", current);
257: return (char *)0;
2.1 timbl 258:
2.11 luotonen 259: } /* if tail matches ... switch operation */
2.1 timbl 260:
261: } /* loop over rules */
262:
2.19 ! luotonen 263: if (current) free(current);
! 264: return NULL;
2.15 luotonen 265: }
266:
267:
268:
2.7 timbl 269: /* Load one line of configuration
270: ** ------------------------------
271: **
272: ** Call this, for example, to load a X resource with config info.
273: **
274: ** returns 0 OK, < 0 syntax error.
275: */
2.15 luotonen 276: PUBLIC int HTSetConfiguration ARGS1(CONST char *, config)
2.7 timbl 277: {
278: HTRuleOp op;
279: char * line = NULL;
280: char * pointer = line;
281: char *word1, *word2, *word3;
282: float quality, secs, secs_per_byte;
283: int status;
284:
285: StrAllocCopy(line, config);
286: {
287: char * p = strchr(line, '#'); /* Chop off comments */
288: if (p) *p = 0;
289: }
290: pointer = line;
291: word1 = HTNextField(&pointer);
292: if (!word1) {
293: free(line);
294: return 0;
295: } ; /* Comment only or blank */
2.11 luotonen 296:
2.7 timbl 297: word2 = HTNextField(&pointer);
2.19 ! luotonen 298: word3 = HTNextField(&pointer);
2.11 luotonen 299:
2.7 timbl 300: if (!word2) {
301: fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
302: free(line);
303: return -2; /*syntax error */
304: }
305:
2.17 luotonen 306: if (0==strcasecomp(word1, "suffix") ||
307: 0==strcasecomp(word1, "addtype")) {
2.8 timbl 308: char * encoding = HTNextField(&pointer);
309: if (pointer) status = sscanf(pointer, "%f", &quality);
310: else status = 0;
2.17 luotonen 311: HTAddType(word2, word3,
2.8 timbl 312: encoding ? encoding : "binary",
313: status >= 1? quality : 1.0);
2.7 timbl 314:
2.17 luotonen 315: } else if (0==strcasecomp(word1, "addencoding") ||
316: 0==strcasecomp(word1, "encoding")) {
317: if (pointer)
318: status = sscanf(pointer, "%f", &quality);
319: else status = 0;
320: HTAddEncoding(word2, word3,
321: status >= 1 ? quality : 1.0);
322:
323: } else if (0==strcasecomp(word1, "addlanguage") ||
324: 0==strcasecomp(word1, "language")) {
325: if (pointer)
326: status = sscanf(pointer, "%f", &quality);
327: else status = 0;
328: HTAddLanguage(word2, word3,
329: status >= 1 ? quality : 1.0);
330:
2.7 timbl 331: } else if (0==strcasecomp(word1, "presentation")) {
2.8 timbl 332: if (pointer) status = sscanf(pointer, "%f%f%f",
333: &quality, &secs, &secs_per_byte);
334: else status = 0;
2.14 timbl 335: if (!HTConversions) HTConversions = HTList_new();
336: HTSetPresentation(HTConversions, word2, word3,
2.7 timbl 337: status >= 1? quality : 1.0,
2.11 luotonen 338: status >= 2 ? secs : 0.0,
2.7 timbl 339: status >= 3 ? secs_per_byte : 0.0 );
2.12 luotonen 340:
2.7 timbl 341: } else {
342: op = 0==strcasecomp(word1, "map") ? HT_Map
343: : 0==strcasecomp(word1, "pass") ? HT_Pass
344: : 0==strcasecomp(word1, "fail") ? HT_Fail
2.19 ! luotonen 345: : HT_Invalid;
2.7 timbl 346: if (op==HT_Invalid) {
2.17 luotonen 347: CTRACE(stderr, "HTRule: Bad rule `%s'\n", config);
2.7 timbl 348: } else {
349: HTAddRule(op, word2, word3);
350: }
351: }
352: free(line);
353: return 0;
354: }
355:
2.1 timbl 356:
2.11 luotonen 357: /* Load the rules from a file HTLoadRules()
2.1 timbl 358: ** --------------------------
359: **
360: ** On entry,
361: ** Rules can be in any state
362: ** On exit,
363: ** Any existing rules will have been kept.
2.7 timbl 364: ** Any new rules will have been loaded.
365: ** Returns 0 if no error, 0 if error!
2.1 timbl 366: **
367: ** Bugs:
368: ** The strings may not contain spaces.
369: */
370:
371: int HTLoadRules ARGS1(CONST char *, filename)
372: {
373: FILE * fp = fopen(filename, "r");
374: char line[LINE_LENGTH+1];
375:
376: if (!fp) {
2.17 luotonen 377: CTRACE(stderr, "HTRules: Can't open rules file %s\n", filename);
2.1 timbl 378: return -1; /* File open error */
379: }
380: for(;;) {
381: if (!fgets(line, LINE_LENGTH+1, fp)) break; /* EOF or error */
2.7 timbl 382: (void) HTSetConfiguration(line);
2.1 timbl 383: }
384: fclose(fp);
2.7 timbl 385: return 0; /* No error or syntax errors ignored */
2.1 timbl 386: }
2.11 luotonen 387:
Webmaster