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