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