Annotation of libwww/Library/src/HTRules.c, revision 2.17
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.15 luotonen 18: ** 30 Nov 93 AL Added HTTranslateReq().
2.11 luotonen 19: **
2.1 timbl 20: */
21:
22: /* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
23: #include "HTRules.h"
24:
25: #include <stdio.h>
26: #include "tcp.h"
27: #include "HTFile.h"
2.17 ! luotonen 28: #include "HTParse.h" /* HTParse() */
2.1 timbl 29:
30: #define LINE_LENGTH 256
31:
32:
33: typedef struct _rule {
34: struct _rule * next;
35: HTRuleOp op;
36: char * pattern;
37: char * equiv;
38: } rule;
39:
2.17 ! luotonen 40: /* Global variables
2.12 luotonen 41: ** ----------------
42: */
2.17 ! luotonen 43: PUBLIC char * HTBinDir = NULL; /* Physical /htbin directory */
! 44: /* path (this is obsolite, and */
! 45: /* only used if HTSearchScript */
! 46: /* is given as non-absolute -- */
! 47: /* and this is only for rule */
! 48: /* file backward-compatibility. */
! 49: PUBLIC char * HTSearchScript = NULL; /* Search script name. */
! 50: PUBLIC char * HTPutScript = NULL; /* Script to handle PUT */
! 51: PUBLIC char * HTPostScript = NULL; /* Script to handle POST */
2.12 luotonen 52:
2.13 luotonen 53:
2.1 timbl 54: /* Module-wide variables
55: ** ---------------------
56: */
57:
58: PRIVATE rule * rules = 0; /* Pointer to first on list */
59: #ifndef PUT_ON_HEAD
60: PRIVATE rule * rule_tail = 0; /* Pointer to last on list */
61: #endif
62:
2.11 luotonen 63:
2.1 timbl 64: /* Add rule to the list HTAddRule()
65: ** --------------------
66: **
67: ** On entry,
68: ** pattern points to 0-terminated string containing a single "*"
69: ** equiv points to the equivalent string with * for the
70: ** place where the text matched by * goes.
71: ** On exit,
72: ** returns 0 if success, -1 if error.
73: */
2.9 secret 74:
2.15 luotonen 75: PUBLIC int HTAddRule ARGS3(HTRuleOp, op,
76: CONST char *, pattern,
77: CONST char *, equiv)
2.9 secret 78: { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */
79: rule * temp;
80: char * pPattern;
81:
82: temp = (rule *)malloc(sizeof(*temp));
83: if (temp==NULL)
84: outofmem(__FILE__, "HTAddRule");
85: pPattern = (char *)malloc(strlen(pattern)+1);
86: if (pPattern==NULL)
87: outofmem(__FILE__, "HTAddRule");
2.1 timbl 88: if (equiv) { /* Two operands */
89: char * pEquiv = (char *)malloc(strlen(equiv)+1);
2.9 secret 90: if (pEquiv==NULL)
91: outofmem(__FILE__, "HTAddRule");
2.1 timbl 92: temp->equiv = pEquiv;
93: strcpy(pEquiv, equiv);
94: } else {
95: temp->equiv = 0;
96: }
97: temp->pattern = pPattern;
98: temp->op = op;
99:
100: strcpy(pPattern, pattern);
2.10 duns 101: if (TRACE) {
102: if (equiv)
2.17 ! luotonen 103: fprintf(stderr, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv);
2.10 duns 104: else
2.17 ! luotonen 105: fprintf(stderr, "Rule: For `%s' op %d\n", pattern, op);
2.10 duns 106: }
2.1 timbl 107:
108: #ifdef PUT_ON_HEAD
109: temp->next = rules;
110: rules = temp;
111: #else
112: temp->next = 0;
113: if (rule_tail) rule_tail->next = temp;
114: else rules = temp;
115: rule_tail = temp;
116: #endif
117:
118:
119: return 0;
120: }
121:
122:
123: /* Clear all rules HTClearRules()
124: ** ---------------
125: **
126: ** On exit,
127: ** There are no rules
128: ** returns 0 if success, -1 if error.
129: **
130: ** See also
131: ** HTAddRule()
132: */
2.15 luotonen 133: PUBLIC int HTClearRules NOARGS
2.1 timbl 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: **
2.15 luotonen 153: ** ATTENTION:
154: ** THIS FUNCTION HAS BEEN OBSOLITED BY HTTranslateReq()
155: ** ON SERVER SIDE -- ON BROWSER SIDE THIS IS STILL USED!
156: ** Don't add new server features to this, this already has
157: ** more than it can handle cleanly.
158: **
159: ** The most recently defined rules are applied last.
2.1 timbl 160: **
161: ** On entry,
162: ** required points to a string whose equivalent value is neeed
163: ** On exit,
164: ** returns the address of the equivalent string allocated from
165: ** the heap which the CALLER MUST FREE. If no translation
166: ** occured, then it is a copy of te original.
2.11 luotonen 167: ** NEW FEATURES:
168: ** When a "protect" or "defprot" rule is mathed,
169: ** a call to HTAA_setCurrentProtection() or
170: ** HTAA_setDefaultProtection() is made to notify
171: ** the Access Authorization module that the file is
172: ** protected, and so it knows how to handle it.
173: ** -- AL
2.1 timbl 174: */
2.15 luotonen 175: PUBLIC char * HTTranslate ARGS1(CONST char *, required)
2.1 timbl 176: {
177: rule * r;
2.11 luotonen 178: char *current = NULL;
179: StrAllocCopy(current, required);
180:
2.15 luotonen 181: #ifdef OLD_CODE
2.11 luotonen 182: HTAA_clearProtections(); /* Reset from previous call -- AL */
2.15 luotonen 183: #endif
2.11 luotonen 184:
2.1 timbl 185: for(r = rules; r; r = r->next) {
186: char * p = r->pattern;
2.11 luotonen 187: int m=0; /* Number of characters matched against wildcard */
2.1 timbl 188: CONST char * q = current;
189: for(;*p && *q; p++, q++) { /* Find first mismatch */
190: if (*p!=*q) break;
191: }
192:
193: if (*p == '*') { /* Match up to wildcard */
194: m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
195: if(m<0) continue; /* tail is too short to match */
196: if (0!=strcmp(q+m, p+1)) continue; /* Tail mismatch */
197: } else /* Not wildcard */
198: if (*p != *q) continue; /* plain mismatch: go to next rule */
199:
200: switch (r->op) { /* Perform operation */
2.11 luotonen 201:
202: #ifdef ACCESS_AUTH
203: case HT_DefProt:
204: case HT_Protect:
205: {
206: char *local_copy = NULL;
207: char *p;
208: char *eff_ids = NULL;
209: char *prot_file = NULL;
210:
211: if (TRACE) fprintf(stderr,
212: "HTRule: `%s' matched %s %s: `%s'\n",
213: current,
214: (r->op==HT_Protect ? "Protect" : "DefProt"),
215: "rule, setup",
216: (r->equiv ? r->equiv :
217: (r->op==HT_Protect ?"DEFAULT" :"NULL!!")));
218:
219: if (r->equiv) {
220: StrAllocCopy(local_copy, r->equiv);
221: p = local_copy;
222: prot_file = HTNextField(&p);
223: eff_ids = HTNextField(&p);
224: }
225:
2.15 luotonen 226: #ifdef THESE_NO_LONGER_WORK
2.11 luotonen 227: if (r->op == HT_Protect)
228: HTAA_setCurrentProtection(current, prot_file, eff_ids);
229: else
230: HTAA_setDefaultProtection(current, prot_file, eff_ids);
2.15 luotonen 231: #endif
2.11 luotonen 232: FREE(local_copy);
233:
234: /* continue translating rules */
235: }
236: break;
237: #endif ACCESS_AUTH
238:
2.1 timbl 239: case HT_Pass: /* Authorised */
240: if (!r->equiv) {
2.17 ! luotonen 241: CTRACE(stderr, "HTRule: Pass `%s'\n", current);
2.1 timbl 242: return current;
243: }
2.11 luotonen 244: /* Else fall through ...to map and pass */
2.1 timbl 245:
246: case HT_Map:
247: if (*p == *q) { /* End of both strings, no wildcard */
2.17 ! luotonen 248: CTRACE(stderr, "For `%s' using `%s'\n", current, r->equiv);
! 249: StrAllocCopy(current, r->equiv); /* use entire translation */
2.1 timbl 250: } else {
251: char * ins = strchr(r->equiv, '*'); /* Insertion point */
252: if (ins) { /* Consistent rule!!! */
253: char * temp = (char *)malloc(
254: strlen(r->equiv)-1 + m + 1);
2.9 secret 255: if (temp==NULL)
256: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1 timbl 257: strncpy(temp, r->equiv, ins-r->equiv);
258: /* Note: temp may be unterminated now! */
259: strncpy(temp+(ins-r->equiv), q, m); /* Matched bit */
260: strcpy (temp+(ins-r->equiv)+m, ins+1); /* Last bit */
2.17 ! luotonen 261: CTRACE(stderr, "For `%s' using `%s'\n",
2.1 timbl 262: current, temp);
263: free(current);
264: current = temp; /* Use this */
265:
266: } else { /* No insertion point */
267: char * temp = (char *)malloc(strlen(r->equiv)+1);
2.9 secret 268: if (temp==NULL)
269: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1 timbl 270: strcpy(temp, r->equiv);
2.17 ! luotonen 271: CTRACE(stderr, "For `%s' using `%s'\n", current, temp);
2.1 timbl 272: free(current);
273: current = temp; /* Use this */
274: } /* If no insertion point exists */
275: }
276: if (r->op == HT_Pass) {
2.17 ! luotonen 277: CTRACE(stderr, "HTRule: ...and pass `%s'\n", current);
2.1 timbl 278: return current;
279: }
280: break;
281:
2.15 luotonen 282: case HT_Exec:
2.11 luotonen 283: case HT_Invalid:
284: case HT_Fail: /* Unauthorised */
2.15 luotonen 285: default:
2.17 ! luotonen 286: CTRACE(stderr,"HTRule: *** FAIL `%s'\n", current);
! 287: return (char *)0;
2.1 timbl 288:
2.11 luotonen 289: } /* if tail matches ... switch operation */
2.1 timbl 290:
291: } /* loop over rules */
292:
293:
294: return current;
295: }
296:
2.15 luotonen 297:
298:
2.17 ! luotonen 299: /* Translate by rules HTTranslateReq()
2.15 luotonen 300: ** ------------------
301: **
302: ** On entry,
303: ** req request structure.
304: ** req->simplified simplified pathname (no ..'s etc in it),
305: ** which will be translated.
306: ** If this starts with /htbin/ it is taken
307: ** to be a script call request.
308: **
309: ** On exit,
310: ** returns YES on success, NO on failure (Forbidden).
311: ** req->translated contains the translated filename;
312: ** NULL if a script call.
313: ** req->script contains the executable script name;
314: ** NULL if not a script call.
315: */
316: PUBLIC BOOL HTTranslateReq ARGS1(HTRequest *, req)
317: {
318: rule * r;
319: char *current = NULL;
320:
321: if (!req || !req->simplified)
322: return NO;
323:
2.16 timbl 324: StrAllocCopy(current, req->simplified);
2.15 luotonen 325:
326: for(r = rules; r; r = r->next) {
327: char * p = r->pattern;
328: int m=0; /* Number of characters matched against wildcard */
329: CONST char * q = current;
330: for(;*p && *q; p++, q++) { /* Find first mismatch */
331: if (*p!=*q) break;
332: }
333:
334: if (*p == '*') { /* Match up to wildcard */
335: m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
336: if(m<0) continue; /* tail is too short to match */
337: if (0!=strcmp(q+m, p+1)) continue; /* Tail mismatch */
338: } else /* Not wildcard */
339: if (*p != *q) continue; /* plain mismatch: go to next rule */
340:
341: switch (r->op) { /* Perform operation */
342:
343: #ifdef ACCESS_AUTH
344: case HT_DefProt:
345: case HT_Protect:
346: {
347: char *local_copy = NULL;
348: char *p;
349: char *eff_ids = NULL;
350: char *prot_file = NULL;
351:
352: if (TRACE) fprintf(stderr,
353: "HTRule: `%s' matched %s %s: `%s'\n",
354: current,
355: (r->op==HT_Protect ? "Protect" : "DefProt"),
356: "rule, setup",
357: (r->equiv ? r->equiv :
358: (r->op==HT_Protect ?"DEFAULT" :"NULL!!")));
359:
360: if (r->equiv) {
361: StrAllocCopy(local_copy, r->equiv);
362: p = local_copy;
363: prot_file = HTNextField(&p);
364: eff_ids = HTNextField(&p);
365: }
366:
367: if (r->op == HT_Protect)
368: HTAA_setCurrentProtection(req, prot_file, eff_ids);
369: else
370: HTAA_setDefaultProtection(req, prot_file, eff_ids);
371:
372: FREE(local_copy);
373:
374: /* continue translating rules */
375: }
376: break;
377: #endif ACCESS_AUTH
378:
379: case HT_Exec:
380: if (!r->equiv) {
381: if (TRACE) fprintf(stderr,
382: "HTRule: Exec `%s', no extra pathinfo\n",
383: current);
384: req->script = current;
385: req->script_pathinfo = NULL;
386: return YES;
387: }
388: else if (*p == *q || !strchr(r->equiv, '*')) { /* No wildcards */
389: if (TRACE) fprintf(stderr,
390: "HTRule: Exec `%s', no extra pathinfo\n",
391: r->equiv);
392: StrAllocCopy(req->script, r->equiv);
393: req->script_pathinfo = NULL;
394: return YES;
395: }
396: else {
397: char *ins = strchr(r->equiv, '*');
398: char *pathinfo;
399: if (!(req->script = (char*)malloc(strlen(r->equiv) + m)))
400: outofmem(__FILE__, "HTTranslate");
401: strncpy(req->script, r->equiv, ins-r->equiv);
402: strncpy(req->script+(ins-r->equiv), q, m);
403: strcpy(req->script+(ins-r->equiv)+m, ins+1);
404: for (pathinfo = req->script+(ins-r->equiv)+1;
405: *pathinfo && *pathinfo != '/';
406: pathinfo++)
407: ;
2.17 ! luotonen 408: FREE(req->script_pathinfo);
! 409: FREE(req->script_pathtrans);
2.15 luotonen 410: if (*pathinfo) {
2.17 ! luotonen 411: char *tmp;
2.15 luotonen 412: StrAllocCopy(req->script_pathinfo, pathinfo);
413: *pathinfo = 0;
2.17 ! luotonen 414: tmp = HTTranslate(req->script_pathinfo);
! 415: if (tmp) {
! 416: req->script_pathtrans =
! 417: HTParse(tmp, "", PARSE_PATH | PARSE_PUNCTUATION);
! 418: free(tmp);
! 419: }
2.15 luotonen 420: }
421: return YES;
422: }
423: break;
424:
425: case HT_Pass: /* Authorised */
426: if (!r->equiv) {
427: if (TRACE) fprintf(stderr, "HTRule: Pass `%s'\n", current);
428: req->translated = current;
429: return YES;
430: }
431: /* Else fall through ...to map and pass */
432:
433: case HT_Map:
434: if (*p == *q) { /* End of both strings, no wildcard */
2.17 ! luotonen 435: CTRACE(stderr,"For `%s' using `%s'\n", current, r->equiv);
! 436: StrAllocCopy(current, r->equiv); /* use entire translation */
2.15 luotonen 437: } else {
438: char * ins = strchr(r->equiv, '*'); /* Insertion point */
439: if (ins) { /* Consistent rule!!! */
440: char * temp = (char *)malloc(
441: strlen(r->equiv)-1 + m + 1);
442: if (temp==NULL)
443: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
444: strncpy(temp, r->equiv, ins-r->equiv);
445: /* Note: temp may be unterminated now! */
446: strncpy(temp+(ins-r->equiv), q, m); /* Matched bit */
447: strcpy (temp+(ins-r->equiv)+m, ins+1); /* Last bit */
2.17 ! luotonen 448: CTRACE(stderr,"For `%s' using `%s'\n", current, temp);
2.15 luotonen 449: free(current);
450: current = temp; /* Use this */
451:
452: } else { /* No insertion point */
453: char * temp = (char *)malloc(strlen(r->equiv)+1);
454: if (temp==NULL)
455: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
456: strcpy(temp, r->equiv);
2.17 ! luotonen 457: CTRACE(stderr, "For `%s' using `%s'\n", current, temp);
2.15 luotonen 458: free(current);
459: current = temp; /* Use this */
460: } /* If no insertion point exists */
461: }
462: if (r->op == HT_Pass) {
463: if (TRACE) fprintf(stderr, "HTRule: Pass `%s'\n", current);
464: req->translated = current;
465: return YES;
466: }
467: break;
468:
469: case HT_Invalid:
470: case HT_Fail: /* Unauthorised */
2.17 ! luotonen 471: CTRACE(stderr, "HTRule: *** FAIL `%s'\n", current);
! 472: return NO;
! 473: break;
2.15 luotonen 474: } /* if tail matches ... switch operation */
475:
476: } /* loop over rules */
477:
478: /* Actually here failing might be more appropriate?? */
479: req->translated = current;
480: return YES;
481: }
482:
483:
484:
2.7 timbl 485: /* Load one line of configuration
486: ** ------------------------------
487: **
488: ** Call this, for example, to load a X resource with config info.
489: **
490: ** returns 0 OK, < 0 syntax error.
491: */
2.15 luotonen 492: PUBLIC int HTSetConfiguration ARGS1(CONST char *, config)
2.7 timbl 493: {
494: HTRuleOp op;
495: char * line = NULL;
496: char * pointer = line;
497: char *word1, *word2, *word3;
498: float quality, secs, secs_per_byte;
499: int status;
500:
501: StrAllocCopy(line, config);
502: {
503: char * p = strchr(line, '#'); /* Chop off comments */
504: if (p) *p = 0;
505: }
506: pointer = line;
507: word1 = HTNextField(&pointer);
508: if (!word1) {
509: free(line);
510: return 0;
511: } ; /* Comment only or blank */
2.11 luotonen 512:
2.7 timbl 513: word2 = HTNextField(&pointer);
2.11 luotonen 514:
515: if (0==strcasecomp(word1, "defprot") ||
516: 0==strcasecomp(word1, "protect"))
517: word3 = pointer; /* The rest of the line to be parsed by AA module */
518: else
519: word3 = HTNextField(&pointer); /* Just the next word */
520:
2.7 timbl 521: if (!word2) {
522: fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
523: free(line);
524: return -2; /*syntax error */
525: }
526:
2.17 ! luotonen 527: if (0==strcasecomp(word1, "suffix") ||
! 528: 0==strcasecomp(word1, "addtype")) {
2.8 timbl 529: char * encoding = HTNextField(&pointer);
530: if (pointer) status = sscanf(pointer, "%f", &quality);
531: else status = 0;
2.17 ! luotonen 532: HTAddType(word2, word3,
2.8 timbl 533: encoding ? encoding : "binary",
534: status >= 1? quality : 1.0);
2.7 timbl 535:
2.17 ! luotonen 536: } else if (0==strcasecomp(word1, "addencoding") ||
! 537: 0==strcasecomp(word1, "encoding")) {
! 538: if (pointer)
! 539: status = sscanf(pointer, "%f", &quality);
! 540: else status = 0;
! 541: HTAddEncoding(word2, word3,
! 542: status >= 1 ? quality : 1.0);
! 543:
! 544: } else if (0==strcasecomp(word1, "addlanguage") ||
! 545: 0==strcasecomp(word1, "language")) {
! 546: if (pointer)
! 547: status = sscanf(pointer, "%f", &quality);
! 548: else status = 0;
! 549: HTAddLanguage(word2, word3,
! 550: status >= 1 ? quality : 1.0);
! 551:
2.7 timbl 552: } else if (0==strcasecomp(word1, "presentation")) {
2.8 timbl 553: if (pointer) status = sscanf(pointer, "%f%f%f",
554: &quality, &secs, &secs_per_byte);
555: else status = 0;
2.14 timbl 556: if (!HTConversions) HTConversions = HTList_new();
557: HTSetPresentation(HTConversions, word2, word3,
2.7 timbl 558: status >= 1? quality : 1.0,
2.11 luotonen 559: status >= 2 ? secs : 0.0,
2.7 timbl 560: status >= 3 ? secs_per_byte : 0.0 );
2.12 luotonen 561:
2.17 ! luotonen 562: } else if (0==strncasecomp(word1, "putscript", 9) ||
! 563: 0==strncasecomp(word1, "put-script", 10)) {
! 564: StrAllocCopy(HTPutScript, word2);
! 565:
! 566: } else if (0==strncasecomp(word1, "postscript", 10) ||
! 567: 0==strncasecomp(word1, "post-script", 11)) {
! 568: StrAllocCopy(HTPostScript, word2);
! 569:
2.13 luotonen 570: } else if (0==strncasecomp(word1, "htbin", 5) ||
571: 0==strncasecomp(word1, "bindir", 6)) {
2.15 luotonen 572: char *bindir = (char*)malloc(strlen(word2) + 3);
573: if (!bindir) outofmem(__FILE__, "HTSetConfiguration");
574: strcpy(bindir, word2);
575: strcat(bindir, "/*");
576: HTAddRule(HT_Exec, "/htbin/*", bindir);
577:
578: /*
579: ** Physical /htbin location -- this is almost obsolite
580: ** (only search may need it).
581: */
582: StrAllocCopy(HTBinDir, word2);
2.13 luotonen 583:
584: } else if (0==strncasecomp(word1, "search", 6)) {
2.15 luotonen 585: if (strchr(word2, '/'))
586: StrAllocCopy(HTSearchScript, word2); /* Full search script path */
587: else if (HTBinDir) {
588: if (!(HTSearchScript =
589: (char*)malloc(strlen(HTBinDir) + strlen(word2) + 2)))
590: outofmem(__FILE__, "HTSetConfiguration");
591: strcpy(HTSearchScript, HTBinDir);
592: strcat(HTSearchScript, "/");
593: strcat(HTSearchScript, word2);
594: }
595: else if (TRACE) fprintf(stderr,
596: "HTRule: Search rule without HTBin rule before ignored\n");
597: if (TRACE) {
598: if (HTSearchScript)
599: fprintf(stderr, "HTRule: Search script set to `%s'\n",
600: HTSearchScript);
601: else fprintf(stderr, "HTRule: Search script not set\n");
602: }
2.12 luotonen 603:
2.7 timbl 604: } else {
605: op = 0==strcasecomp(word1, "map") ? HT_Map
606: : 0==strcasecomp(word1, "pass") ? HT_Pass
607: : 0==strcasecomp(word1, "fail") ? HT_Fail
2.17 ! luotonen 608: : 0==strcasecomp(word1, "exec") ? HT_Exec
2.11 luotonen 609: : 0==strcasecomp(word1, "defprot") ? HT_DefProt
610: : 0==strcasecomp(word1, "protect") ? HT_Protect
2.7 timbl 611: : HT_Invalid;
612: if (op==HT_Invalid) {
2.17 ! luotonen 613: CTRACE(stderr, "HTRule: Bad rule `%s'\n", config);
2.7 timbl 614: } else {
615: HTAddRule(op, word2, word3);
616: }
617: }
618: free(line);
619: return 0;
620: }
621:
2.1 timbl 622:
2.11 luotonen 623: /* Load the rules from a file HTLoadRules()
2.1 timbl 624: ** --------------------------
625: **
626: ** On entry,
627: ** Rules can be in any state
628: ** On exit,
629: ** Any existing rules will have been kept.
2.7 timbl 630: ** Any new rules will have been loaded.
631: ** Returns 0 if no error, 0 if error!
2.1 timbl 632: **
633: ** Bugs:
634: ** The strings may not contain spaces.
635: */
636:
637: int HTLoadRules ARGS1(CONST char *, filename)
638: {
639: FILE * fp = fopen(filename, "r");
640: char line[LINE_LENGTH+1];
641:
642: if (!fp) {
2.17 ! luotonen 643: CTRACE(stderr, "HTRules: Can't open rules file %s\n", filename);
2.1 timbl 644: return -1; /* File open error */
645: }
646: for(;;) {
647: if (!fgets(line, LINE_LENGTH+1, fp)) break; /* EOF or error */
2.7 timbl 648: (void) HTSetConfiguration(line);
2.1 timbl 649: }
650: fclose(fp);
2.7 timbl 651: return 0; /* No error or syntax errors ignored */
2.1 timbl 652: }
2.11 luotonen 653:
654:
Webmaster