Annotation of libwww/Library/src/HTRules.c, revision 2.7
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
11: */
12:
13: /* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
14: #include "HTRules.h"
15:
16: #include <stdio.h>
17: #include "tcp.h"
18: #include "HTFile.h"
19:
20: #define LINE_LENGTH 256
21:
22:
23: typedef struct _rule {
24: struct _rule * next;
25: HTRuleOp op;
26: char * pattern;
27: char * equiv;
28: } rule;
29:
30: /* Module-wide variables
31: ** ---------------------
32: */
33:
34: PRIVATE rule * rules = 0; /* Pointer to first on list */
35: #ifndef PUT_ON_HEAD
36: PRIVATE rule * rule_tail = 0; /* Pointer to last on list */
37: #endif
38:
39: /* Add rule to the list HTAddRule()
40: ** --------------------
41: **
42: ** On entry,
43: ** pattern points to 0-terminated string containing a single "*"
44: ** equiv points to the equivalent string with * for the
45: ** place where the text matched by * goes.
46: ** On exit,
47: ** returns 0 if success, -1 if error.
48: */
49: /* Note that if BYTE_ADDRESSING is set, the three blocks required
50: ** are allocated and deallocated as one. This will save time and
51: ** storage, when malloc's allocation units are large.
52: */
53: #ifdef __STDC__
54: PUBLIC int HTAddRule (HTRuleOp op, const char * pattern, const char * equiv)
55: #else
56: int HTAddRule(op, pattern, equiv)
57: HTRuleOp op;
58: char * pattern;
59: char * equiv;
60: #endif
61: {
62: #ifdef BYTE_ADDRESSING /* economise on malloc() blocks */
63: int length_of_pattern = strlen(pattern)+1;
64: rule * temp = malloc(sizeof(*temp) +
65: size_of_pattern + strlen(equiv) + 1);
66: char * pPattern = (char *) &temp[1];
67: #else
68: rule * temp = (rule *)malloc(sizeof(*temp));
69: char * pPattern = (char *)malloc(strlen(pattern)+1);
70: #endif
71:
72: if (equiv) { /* Two operands */
73: #ifdef BYTE_ADDRESSING /* economise on malloc() blocks */
74: char * pEquiv = pPattern + length_of_pattern;
75: #else
76: char * pEquiv = (char *)malloc(strlen(equiv)+1);
77: #endif
78: temp->equiv = pEquiv;
79: strcpy(pEquiv, equiv);
80: } else {
81: temp->equiv = 0;
82: }
83: temp->pattern = pPattern;
84: temp->op = op;
85:
86: strcpy(pPattern, pattern);
87: if (TRACE) printf("Rule: For `%s' op %i `%s'\n", pattern, op, equiv);
88:
89: #ifdef PUT_ON_HEAD
90: temp->next = rules;
91: rules = temp;
92: #else
93: temp->next = 0;
94: if (rule_tail) rule_tail->next = temp;
95: else rules = temp;
96: rule_tail = temp;
97: #endif
98:
99:
100: return 0;
101: }
102:
103:
104: /* Clear all rules HTClearRules()
105: ** ---------------
106: **
107: ** On exit,
108: ** There are no rules
109: ** returns 0 if success, -1 if error.
110: **
111: ** See also
112: ** HTAddRule()
113: */
114: #ifdef __STDC__
115: int HTClearRules(void)
116: #else
117: int HTClearRules()
118: #endif
119: {
120: while (rules) {
121: rule * temp = rules;
122: rules = temp->next;
123: #ifdef BYTE_ADDRESSING
124: free(temp);
125: #else
126: free(temp->pattern);
127: free(temp->equiv);
128: free(temp);
129: #endif
130: }
131: #ifndef PUT_ON_HEAD
132: rule_tail = 0;
133: #endif
134:
135: return 0;
136: }
137:
138:
139: /* Translate by rules HTTranslate()
140: ** ------------------
141: **
142: ** The most recently defined rules are applied first.
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: */
151: #ifdef __STDC__
152: char * HTTranslate(const char * required)
153: #else
154: char * HTTranslate(required)
155: char * required;
156: #endif
157: {
158: rule * r;
159: char * current = (char *)malloc(strlen(required)+1);
160: strcpy(current, required);
161:
162: for(r = rules; r; r = r->next) {
163: char * p = r->pattern;
164: int m; /* Number of characters matched against wildcard */
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 */
178: case HT_Pass: /* Authorised */
179: if (!r->equiv) {
180: if (TRACE) printf("HTRule: Pass `%s'\n", current);
181: return current;
182: }
183: /* Fall through ...to map and pass */
184:
185: case HT_Map:
186: if (*p == *q) { /* End of both strings, no wildcard */
187: if (TRACE) printf(
188: "For `%s' using `%s'\n", current, r->equiv);
189: StrAllocCopy(current, r->equiv); /* use entire translation */
190: } else {
191: char * ins = strchr(r->equiv, '*'); /* Insertion point */
192: if (ins) { /* Consistent rule!!! */
193: char * temp = (char *)malloc(
194: strlen(r->equiv)-1 + m + 1);
195: strncpy(temp, r->equiv, ins-r->equiv);
196: /* Note: temp may be unterminated now! */
197: strncpy(temp+(ins-r->equiv), q, m); /* Matched bit */
198: strcpy (temp+(ins-r->equiv)+m, ins+1); /* Last bit */
199: if (TRACE) printf("For `%s' using `%s'\n",
200: current, temp);
201: free(current);
202: current = temp; /* Use this */
203:
204: } else { /* No insertion point */
205: char * temp = (char *)malloc(strlen(r->equiv)+1);
206: strcpy(temp, r->equiv);
207: if (TRACE) printf("For `%s' using `%s'\n",
208: current, temp);
209: free(current);
210: current = temp; /* Use this */
211: } /* If no insertion point exists */
212: }
213: if (r->op == HT_Pass) {
214: if (TRACE) printf("HTRule: ...and pass `%s'\n", current);
215: return current;
216: }
217: break;
218:
219: case HT_Invalid:
220: case HT_Fail: /* Unauthorised */
221: if (TRACE) printf("HTRule: *** FAIL `%s'\n", current);
222: return (char *)0;
223:
224: } /* if tail matches ... switch operation */
225:
226: } /* loop over rules */
227:
228:
229: return current;
230: }
231:
2.7 ! timbl 232: /* Load one line of configuration
! 233: ** ------------------------------
! 234: **
! 235: ** Call this, for example, to load a X resource with config info.
! 236: **
! 237: ** returns 0 OK, < 0 syntax error.
! 238: */
! 239: PUBLIC int HTSetConfiguration ARGS1(CONST char *, config)
! 240: {
! 241: HTRuleOp op;
! 242: char * line = NULL;
! 243: char * pointer = line;
! 244: char *word1, *word2, *word3;
! 245: float quality, secs, secs_per_byte;
! 246: int status;
! 247:
! 248: StrAllocCopy(line, config);
! 249: {
! 250: char * p = strchr(line, '#'); /* Chop off comments */
! 251: if (p) *p = 0;
! 252: }
! 253: pointer = line;
! 254: word1 = HTNextField(&pointer);
! 255: if (!word1) {
! 256: free(line);
! 257: return 0;
! 258: } ; /* Comment only or blank */
! 259:
! 260: word2 = HTNextField(&pointer);
! 261: word3 = HTNextField(&pointer);
! 262: if (!word2) {
! 263: fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
! 264: free(line);
! 265: return -2; /*syntax error */
! 266: }
! 267: if (pointer) status = sscanf(pointer, "%f%f%f",
! 268: &quality, &secs, &secs_per_byte);
! 269: else status = 0;
! 270:
! 271: if (0==strcasecomp(word1, "suffix")) {
! 272: HTSetSuffix(word2, word3, status >= 1? quality : 1.0);
! 273:
! 274: } else if (0==strcasecomp(word1, "presentation")) {
! 275: HTSetPresentation(word2, word3,
! 276: status >= 1? quality : 1.0,
! 277: status >= 2 ? secs : 0.0,
! 278: status >= 3 ? secs_per_byte : 0.0 );
2.1 timbl 279:
2.7 ! timbl 280: } else {
! 281: op = 0==strcasecomp(word1, "map") ? HT_Map
! 282: : 0==strcasecomp(word1, "pass") ? HT_Pass
! 283: : 0==strcasecomp(word1, "fail") ? HT_Fail
! 284: : HT_Invalid;
! 285: if (op==HT_Invalid) {
! 286: fprintf(stderr, "HTRule: Bad rule `%s'\n", config);
! 287: } else {
! 288: HTAddRule(op, word2, word3);
! 289: }
! 290: }
! 291: free(line);
! 292: return 0;
! 293: }
! 294:
2.1 timbl 295:
296: /* Load the rules from a file HtLoadRules()
297: ** --------------------------
298: **
299: ** On entry,
300: ** Rules can be in any state
301: ** On exit,
302: ** Any existing rules will have been kept.
2.7 ! timbl 303: ** Any new rules will have been loaded.
! 304: ** Returns 0 if no error, 0 if error!
2.1 timbl 305: **
306: ** Bugs:
307: ** The strings may not contain spaces.
308: */
309:
310: int HTLoadRules ARGS1(CONST char *, filename)
311: {
312: FILE * fp = fopen(filename, "r");
313: char line[LINE_LENGTH+1];
314:
315: if (!fp) {
316: if (TRACE) printf("HTRules: Can't open rules file %s\n", filename);
317: return -1; /* File open error */
318: }
319: for(;;) {
320: if (!fgets(line, LINE_LENGTH+1, fp)) break; /* EOF or error */
2.7 ! timbl 321: (void) HTSetConfiguration(line);
2.1 timbl 322: }
323: fclose(fp);
2.7 ! timbl 324: return 0; /* No error or syntax errors ignored */
2.1 timbl 325: }
Webmaster