Annotation of libwww/Library/src/HTRules.c, revision 2.30
2.26 frystyk 1: /* HTRules.c
2: ** CONFIGURATION MANAGER FOR CLIENTS
3: **
4: ** (c) COPYRIGHT CERN 1994.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.1 timbl 6: **
2.19 luotonen 7: ** This module is replaced by HTConfig.c in httpd.
2.1 timbl 8: **
9: ** History:
10: ** 3 Jun 91 Written TBL
11: ** 10 Aug 91 Authorisation added after Daniel Martin (pass, fail)
12: ** Rule order in file changed
13: ** Comments allowed with # on 1st char of rule line
14: ** 17 Jun 92 Bug fix: pass and fail failed if didn't contain '*' TBL
2.9 secret 15: ** 1 Sep 93 Bug fix: no memory check - Nathan Torkington
16: ** BYTE_ADDRESSING removed - Arthur Secret
2.12 luotonen 17: ** 11 Sep 93 MD Changed %i into %d in debug printf.
2.10 duns 18: ** VMS does not recognize %i.
19: ** Bug Fix: in case of PASS, only one parameter to printf.
2.12 luotonen 20: ** 19 Sep 93 AL Added Access Authorization stuff.
21: ** 1 Nov 93 AL Added htbin.
2.15 luotonen 22: ** 30 Nov 93 AL Added HTTranslateReq().
2.19 luotonen 23: ** 4 Feb 94 AL Took away all the daemon-specific stuff.
2.25 howcome 24: ** 28 Sep 94 HWL Added field to HTSetPresentation call
2.11 luotonen 25: **
2.1 timbl 26: */
27:
2.28 frystyk 28: /* Library include files */
29: #include "tcp.h"
30: #include "HTUtils.h"
31: #include "HTString.h"
2.1 timbl 32: #include "HTFile.h"
2.26 frystyk 33: #include "HTParse.h"
2.18 luotonen 34: #include "HTAAUtil.h"
2.26 frystyk 35: #include "HTRules.h" /* Implemented here */
2.1 timbl 36:
37: #define LINE_LENGTH 256
38:
39: typedef struct _rule {
40: struct _rule * next;
41: HTRuleOp op;
42: char * pattern;
43: char * equiv;
44: } rule;
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.15 luotonen 68: PUBLIC int HTAddRule ARGS3(HTRuleOp, op,
69: CONST char *, pattern,
70: CONST char *, equiv)
2.9 secret 71: { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */
72: rule * temp;
73: char * pPattern;
74:
75: temp = (rule *)malloc(sizeof(*temp));
76: if (temp==NULL)
77: outofmem(__FILE__, "HTAddRule");
78: pPattern = (char *)malloc(strlen(pattern)+1);
79: if (pPattern==NULL)
80: outofmem(__FILE__, "HTAddRule");
2.1 timbl 81: if (equiv) { /* Two operands */
82: char * pEquiv = (char *)malloc(strlen(equiv)+1);
2.9 secret 83: if (pEquiv==NULL)
84: outofmem(__FILE__, "HTAddRule");
2.1 timbl 85: temp->equiv = pEquiv;
86: strcpy(pEquiv, equiv);
87: } else {
88: temp->equiv = 0;
89: }
90: temp->pattern = pPattern;
91: temp->op = op;
92:
93: strcpy(pPattern, pattern);
2.10 duns 94: if (TRACE) {
95: if (equiv)
2.28 frystyk 96: fprintf(TDEST, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv);
2.10 duns 97: else
2.28 frystyk 98: fprintf(TDEST, "Rule: For `%s' op %d\n", pattern, op);
2.10 duns 99: }
2.1 timbl 100:
101: #ifdef PUT_ON_HEAD
102: temp->next = rules;
103: rules = temp;
104: #else
105: temp->next = 0;
106: if (rule_tail) rule_tail->next = temp;
107: else rules = temp;
108: rule_tail = temp;
109: #endif
110:
111:
112: return 0;
113: }
114:
115:
116: /* Clear all rules HTClearRules()
117: ** ---------------
118: **
119: ** On exit,
120: ** There are no rules
121: ** returns 0 if success, -1 if error.
122: **
123: ** See also
124: ** HTAddRule()
125: */
2.15 luotonen 126: PUBLIC int HTClearRules NOARGS
2.1 timbl 127: {
128: while (rules) {
129: rule * temp = rules;
130: rules = temp->next;
131: free(temp->pattern);
132: free(temp->equiv);
133: free(temp);
134: }
135: #ifndef PUT_ON_HEAD
136: rule_tail = 0;
137: #endif
138:
139: return 0;
140: }
141:
142:
2.18 luotonen 143:
2.1 timbl 144: /* Translate by rules HTTranslate()
145: ** ------------------
146: **
2.15 luotonen 147: ** The most recently defined rules are applied last.
2.1 timbl 148: **
149: ** On entry,
150: ** required points to a string whose equivalent value is neeed
151: ** On exit,
152: ** returns the address of the equivalent string allocated from
153: ** the heap which the CALLER MUST FREE. If no translation
154: ** occured, then it is a copy of te original.
155: */
2.15 luotonen 156: PUBLIC char * HTTranslate ARGS1(CONST char *, required)
2.1 timbl 157: {
158: rule * r;
2.11 luotonen 159: char *current = NULL;
160: StrAllocCopy(current, required);
161:
2.1 timbl 162: for(r = rules; r; r = r->next) {
163: char * p = r->pattern;
2.11 luotonen 164: int m=0; /* Number of characters matched against wildcard */
2.1 timbl 165: CONST char * q = current;
166: for(;*p && *q; p++, q++) { /* Find first mismatch */
167: if (*p!=*q) break;
168: }
169:
170: if (*p == '*') { /* Match up to wildcard */
171: m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
172: if(m<0) continue; /* tail is too short to match */
173: if (0!=strcmp(q+m, p+1)) continue; /* Tail mismatch */
174: } else /* Not wildcard */
175: if (*p != *q) continue; /* plain mismatch: go to next rule */
176:
177: switch (r->op) { /* Perform operation */
2.11 luotonen 178:
2.1 timbl 179: case HT_Pass: /* Authorised */
180: if (!r->equiv) {
2.28 frystyk 181: if (PROT_TRACE)
182: fprintf(TDEST, "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.28 frystyk 189: if (PROT_TRACE)
190: fprintf(TDEST, "For `%s' using `%s'\n",current,r->equiv);
2.17 luotonen 191: StrAllocCopy(current, r->equiv); /* use entire translation */
2.1 timbl 192: } else {
193: char * ins = strchr(r->equiv, '*'); /* Insertion point */
194: if (ins) { /* Consistent rule!!! */
195: char * temp = (char *)malloc(
196: strlen(r->equiv)-1 + m + 1);
2.9 secret 197: if (temp==NULL)
198: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1 timbl 199: strncpy(temp, r->equiv, ins-r->equiv);
200: /* Note: temp may be unterminated now! */
201: strncpy(temp+(ins-r->equiv), q, m); /* Matched bit */
202: strcpy (temp+(ins-r->equiv)+m, ins+1); /* Last bit */
2.28 frystyk 203: if (PROT_TRACE)
204: fprintf(TDEST, "For `%s' using `%s'\n",
205: current, temp);
2.1 timbl 206: free(current);
207: current = temp; /* Use this */
208:
209: } else { /* No insertion point */
210: char * temp = (char *)malloc(strlen(r->equiv)+1);
2.9 secret 211: if (temp==NULL)
212: outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1 timbl 213: strcpy(temp, r->equiv);
2.28 frystyk 214: if (PROT_TRACE)
215: fprintf(TDEST, "For `%s' using `%s'\n", current,
216: temp);
2.1 timbl 217: free(current);
218: current = temp; /* Use this */
219: } /* If no insertion point exists */
220: }
221: if (r->op == HT_Pass) {
2.28 frystyk 222: if (PROT_TRACE)
223: fprintf(TDEST, "HTRule: ...and pass `%s'\n", current);
2.20 luotonen 224: return current;
2.1 timbl 225: }
226: break;
227:
2.11 luotonen 228: case HT_Fail: /* Unauthorised */
2.15 luotonen 229: default:
2.28 frystyk 230: if (PROT_TRACE)
231: fprintf(TDEST,"HTRule: *** FAIL `%s'\n", current);
2.17 luotonen 232: return (char *)0;
2.1 timbl 233:
2.11 luotonen 234: } /* if tail matches ... switch operation */
2.1 timbl 235:
236: } /* loop over rules */
237:
2.22 luotonen 238: return current; /* For clients default is to pass */
2.15 luotonen 239: }
240:
241:
242:
2.7 timbl 243: /* Load one line of configuration
244: ** ------------------------------
245: **
246: ** Call this, for example, to load a X resource with config info.
247: **
248: ** returns 0 OK, < 0 syntax error.
249: */
2.15 luotonen 250: PUBLIC int HTSetConfiguration ARGS1(CONST char *, config)
2.7 timbl 251: {
252: HTRuleOp op;
253: char * line = NULL;
254: char * pointer = line;
255: char *word1, *word2, *word3;
2.29 frystyk 256: double quality, secs, secs_per_byte;
2.7 timbl 257: int status;
258:
259: StrAllocCopy(line, config);
260: {
261: char * p = strchr(line, '#'); /* Chop off comments */
262: if (p) *p = 0;
263: }
264: pointer = line;
265: word1 = HTNextField(&pointer);
266: if (!word1) {
267: free(line);
268: return 0;
269: } ; /* Comment only or blank */
2.11 luotonen 270:
2.7 timbl 271: word2 = HTNextField(&pointer);
2.19 luotonen 272: word3 = HTNextField(&pointer);
2.11 luotonen 273:
2.7 timbl 274: if (!word2) {
2.28 frystyk 275: fprintf(TDEST, "HTRule: Insufficient operands: %s\n", line);
2.7 timbl 276: free(line);
277: return -2; /*syntax error */
278: }
279:
2.17 luotonen 280: if (0==strcasecomp(word1, "suffix") ||
281: 0==strcasecomp(word1, "addtype")) {
2.8 timbl 282: char * encoding = HTNextField(&pointer);
2.29 frystyk 283: if (pointer) status = sscanf(pointer, "%lf", &quality);
2.8 timbl 284: else status = 0;
2.17 luotonen 285: HTAddType(word2, word3,
2.8 timbl 286: encoding ? encoding : "binary",
287: status >= 1? quality : 1.0);
2.7 timbl 288:
2.23 luotonen 289: } else if (0==strcasecomp(word1, "addencoding")) {
2.17 luotonen 290: if (pointer)
2.29 frystyk 291: status = sscanf(pointer, "%lf", &quality);
2.17 luotonen 292: else status = 0;
293: HTAddEncoding(word2, word3,
294: status >= 1 ? quality : 1.0);
295:
2.23 luotonen 296: } else if (0==strcasecomp(word1, "addlanguage")) {
2.17 luotonen 297: if (pointer)
2.29 frystyk 298: status = sscanf(pointer, "%lf", &quality);
2.17 luotonen 299: else status = 0;
300: HTAddLanguage(word2, word3,
301: status >= 1 ? quality : 1.0);
302:
2.7 timbl 303: } else if (0==strcasecomp(word1, "presentation")) {
2.29 frystyk 304: if (pointer) status = sscanf(pointer, "%lf%lf%lf",
2.8 timbl 305: &quality, &secs, &secs_per_byte);
306: else status = 0;
2.28 frystyk 307: HTSetPresentation(HTConversions, word2, word3, NULL,
2.7 timbl 308: status >= 1? quality : 1.0,
2.11 luotonen 309: status >= 2 ? secs : 0.0,
2.7 timbl 310: status >= 3 ? secs_per_byte : 0.0 );
2.12 luotonen 311:
2.7 timbl 312: } else {
313: op = 0==strcasecomp(word1, "map") ? HT_Map
314: : 0==strcasecomp(word1, "pass") ? HT_Pass
315: : 0==strcasecomp(word1, "fail") ? HT_Fail
2.19 luotonen 316: : HT_Invalid;
2.7 timbl 317: if (op==HT_Invalid) {
2.28 frystyk 318: if (PROT_TRACE)
319: fprintf(TDEST, "HTRule: Bad rule `%s'\n", config);
2.7 timbl 320: } else {
321: HTAddRule(op, word2, word3);
322: }
323: }
324: free(line);
325: return 0;
326: }
327:
2.1 timbl 328:
2.11 luotonen 329: /* Load the rules from a file HTLoadRules()
2.1 timbl 330: ** --------------------------
331: **
332: ** On entry,
333: ** Rules can be in any state
334: ** On exit,
335: ** Any existing rules will have been kept.
2.7 timbl 336: ** Any new rules will have been loaded.
337: ** Returns 0 if no error, 0 if error!
2.1 timbl 338: **
339: ** Bugs:
340: ** The strings may not contain spaces.
341: */
342:
343: int HTLoadRules ARGS1(CONST char *, filename)
344: {
345: FILE * fp = fopen(filename, "r");
346: char line[LINE_LENGTH+1];
347:
348: if (!fp) {
2.28 frystyk 349: if (PROT_TRACE)
350: fprintf(TDEST, "HTRules: Can't open rules file %s\n", filename);
2.1 timbl 351: return -1; /* File open error */
352: }
353: for(;;) {
354: if (!fgets(line, LINE_LENGTH+1, fp)) break; /* EOF or error */
2.7 timbl 355: (void) HTSetConfiguration(line);
2.1 timbl 356: }
357: fclose(fp);
2.7 timbl 358: return 0; /* No error or syntax errors ignored */
2.1 timbl 359: }
2.11 luotonen 360:
Webmaster