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