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