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