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