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