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