Annotation of libwww/Library/src/HTRules.c, revision 2.18

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
2.9       secret     11: **       1 Sep 93       Bug fix: no memory check - Nathan Torkington
                     12: **                      BYTE_ADDRESSING removed - Arthur Secret
2.12      luotonen   13: **     11 Sep 93  MD   Changed %i into %d in debug printf. 
2.10      duns       14: **                     VMS does not recognize %i.
                     15: **                     Bug Fix: in case of PASS, only one parameter to printf.
2.12      luotonen   16: **     19 Sep 93  AL   Added Access Authorization stuff.
                     17: **      1 Nov 93  AL   Added htbin.
2.15      luotonen   18: **     30 Nov 93  AL   Added HTTranslateReq().
2.11      luotonen   19: **
2.1       timbl      20: */
                     21: 
                     22: /* (c) CERN WorldWideWeb project 1990,91. See Copyright.html for details */
                     23: #include "HTRules.h"
                     24: 
                     25: #include <stdio.h>
                     26: #include "tcp.h"
                     27: #include "HTFile.h"
2.17      luotonen   28: #include "HTParse.h"   /* HTParse() */
2.18    ! luotonen   29: #include "HTAAUtil.h"
        !            30: 
        !            31: #ifndef VMS
        !            32: #include <pwd.h>       /* Unix password file routine: getpwnam() */
        !            33: #endif /* not VMS */
        !            34: 
2.1       timbl      35: 
                     36: #define LINE_LENGTH 256
                     37: 
                     38: 
                     39: typedef struct _rule {
                     40:        struct _rule *  next;
                     41:        HTRuleOp        op;
                     42:        char *          pattern;
                     43:        char *          equiv;
                     44: } rule;
                     45: 
2.17      luotonen   46: /*     Global variables
2.12      luotonen   47: **     ----------------
                     48: */
2.17      luotonen   49: PUBLIC char * HTBinDir = NULL;         /* Physical /htbin directory    */
                     50:                                         /* path (this is obsolite, and */
                     51:                                         /* only used if HTSearchScript */
                     52:                                         /* is given as non-absolute -- */
                     53:                                         /* and this is only for rule   */
                     54:                                         /* file backward-compatibility.        */
                     55: PUBLIC char * HTSearchScript = NULL;   /* Search script name.          */
                     56: PUBLIC char * HTPutScript = NULL;      /* Script to handle PUT         */
                     57: PUBLIC char * HTPostScript = NULL;     /* Script to handle POST        */
2.18    ! luotonen   58: PRIVATE char * HTUserDir = NULL;       /* User supported directory name*/
        !            59: 
2.12      luotonen   60: 
2.13      luotonen   61: 
2.1       timbl      62: /*     Module-wide variables
                     63: **     ---------------------
                     64: */
                     65: 
                     66: PRIVATE rule * rules = 0;      /* Pointer to first on list */
                     67: #ifndef PUT_ON_HEAD
                     68: PRIVATE rule * rule_tail = 0;  /* Pointer to last on list */
                     69: #endif
                     70: 
2.11      luotonen   71: 
2.1       timbl      72: /*     Add rule to the list                                    HTAddRule()
                     73: **     --------------------
                     74: **
                     75: **  On entry,
                     76: **     pattern         points to 0-terminated string containing a single "*"
                     77: **     equiv           points to the equivalent string with * for the
                     78: **                     place where the text matched by * goes.
                     79: **  On exit,
                     80: **     returns         0 if success, -1 if error.
                     81: */
2.9       secret     82: 
2.15      luotonen   83: PUBLIC int HTAddRule ARGS3(HTRuleOp,           op,
                     84:                           CONST char *,        pattern,
                     85:                           CONST char *,        equiv)
2.9       secret     86: { /* BYTE_ADDRESSING removed and memory check - AS - 1 Sep 93 */
                     87:     rule *      temp;
                     88:     char *      pPattern;
                     89: 
                     90:     temp = (rule *)malloc(sizeof(*temp));
                     91:     if (temp==NULL) 
                     92:        outofmem(__FILE__, "HTAddRule"); 
                     93:     pPattern = (char *)malloc(strlen(pattern)+1);
                     94:     if (pPattern==NULL) 
                     95:        outofmem(__FILE__, "HTAddRule"); 
2.1       timbl      96:     if (equiv) {               /* Two operands */
                     97:        char *  pEquiv = (char *)malloc(strlen(equiv)+1);
2.9       secret     98:        if (pEquiv==NULL) 
                     99:            outofmem(__FILE__, "HTAddRule"); 
2.1       timbl     100:         temp->equiv = pEquiv;
                    101:         strcpy(pEquiv, equiv);
                    102:     } else {
                    103:         temp->equiv = 0;
                    104:     }
                    105:     temp->pattern = pPattern;
                    106:     temp->op = op;
                    107: 
                    108:     strcpy(pPattern, pattern);
2.10      duns      109:     if (TRACE) {
                    110:        if (equiv)
2.17      luotonen  111:           fprintf(stderr, "Rule: For `%s' op %d `%s'\n", pattern, op, equiv);
2.10      duns      112:        else
2.17      luotonen  113:           fprintf(stderr, "Rule: For `%s' op %d\n", pattern, op);
2.10      duns      114:     }
2.1       timbl     115: 
                    116: #ifdef PUT_ON_HEAD
                    117:     temp->next = rules;
                    118:     rules = temp;
                    119: #else
                    120:     temp->next = 0;
                    121:     if (rule_tail) rule_tail->next = temp;
                    122:     else rules = temp;
                    123:     rule_tail = temp;
                    124: #endif
                    125: 
                    126:         
                    127:     return 0;
                    128: }
                    129: 
                    130: 
                    131: /*     Clear all rules                                         HTClearRules()
                    132: **     ---------------
                    133: **
                    134: ** On exit,
                    135: **     There are no rules
                    136: **     returns         0 if success, -1 if error.
                    137: **
                    138: ** See also
                    139: **     HTAddRule()
                    140: */
2.15      luotonen  141: PUBLIC int HTClearRules NOARGS
2.1       timbl     142: {
                    143:     while (rules) {
                    144:        rule * temp = rules;
                    145:        rules = temp->next;
                    146:        free(temp->pattern);
                    147:        free(temp->equiv);
                    148:        free(temp);
                    149:     }
                    150: #ifndef PUT_ON_HEAD
                    151:     rule_tail = 0;
                    152: #endif
                    153: 
                    154:     return 0;
                    155: }
                    156: 
                    157: 
2.18    ! luotonen  158: PRIVATE char * wrap ARGS1(char *, s)
        !           159: {
        !           160:     if (s && *s=='/') {
        !           161:        char * n = (char*)malloc(strlen(s) + 6);
        !           162:        if (!n) outofmem(__FILE__, "HTRules:wrap");
        !           163:        sprintf(n, "file:%s", s);
        !           164:        free(s);
        !           165:        return n;
        !           166:     }
        !           167:     return s;
        !           168: }
        !           169: 
        !           170: 
        !           171: PRIVATE char * unwrap ARGS1(char *, s)
        !           172: {
        !           173:     if (s && !strncmp(s, "file:", 5)) {
        !           174:        char * t;
        !           175:        char * n = NULL;
        !           176: 
        !           177:        if (!strncmp(s, "file://", 7))
        !           178:            t = strchr(s+7, '/');
        !           179:        else t = s+5;
        !           180: 
        !           181:        if (!t) {
        !           182:            free(s);
        !           183:            return NULL;
        !           184:        }
        !           185:        StrAllocCopy(n, t);
        !           186:        free(s);
        !           187:        return n;
        !           188:     }
        !           189:     return s;
        !           190: }
        !           191: 
        !           192: 
        !           193: 
2.1       timbl     194: /*     Translate by rules                                      HTTranslate()
                    195: **     ------------------
                    196: **
2.15      luotonen  197: ** ATTENTION:
                    198: **     THIS FUNCTION HAS BEEN OBSOLITED BY HTTranslateReq()
                    199: **     ON SERVER SIDE -- ON BROWSER SIDE THIS IS STILL USED!
                    200: **     Don't add new server features to this, this already has
                    201: **     more than it can handle cleanly.
                    202: **
                    203: **     The most recently defined rules are applied last.
2.1       timbl     204: **
                    205: ** On entry,
                    206: **     required        points to a string whose equivalent value is neeed
                    207: ** On exit,
                    208: **     returns         the address of the equivalent string allocated from
                    209: **                     the heap which the CALLER MUST FREE. If no translation
                    210: **                     occured, then it is a copy of te original.
2.11      luotonen  211: ** NEW FEATURES:
                    212: **                     When a "protect" or "defprot" rule is mathed,
                    213: **                     a call to HTAA_setCurrentProtection() or
                    214: **                     HTAA_setDefaultProtection() is made to notify
                    215: **                     the Access Authorization module that the file is
                    216: **                     protected, and so it knows how to handle it.
                    217: **                                                             -- AL
2.1       timbl     218: */
2.15      luotonen  219: PUBLIC char * HTTranslate ARGS1(CONST char *, required)
2.1       timbl     220: {
                    221:     rule * r;
2.11      luotonen  222:     char *current = NULL;
                    223:     StrAllocCopy(current, required);
                    224: 
2.15      luotonen  225: #ifdef OLD_CODE
2.11      luotonen  226:     HTAA_clearProtections();   /* Reset from previous call -- AL */
2.15      luotonen  227: #endif
2.11      luotonen  228: 
2.1       timbl     229:     for(r = rules; r; r = r->next) {
                    230:         char * p = r->pattern;
2.11      luotonen  231:        int m=0;   /* Number of characters matched against wildcard */
2.1       timbl     232:        CONST char * q = current;
                    233:        for(;*p && *q; p++, q++) {   /* Find first mismatch */
                    234:            if (*p!=*q) break;
                    235:        }
                    236: 
                    237:        if (*p == '*') {                /* Match up to wildcard */
                    238:            m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
                    239:            if(m<0) continue;           /* tail is too short to match */
                    240:            if (0!=strcmp(q+m, p+1)) continue;  /* Tail mismatch */
                    241:        } else                          /* Not wildcard */
                    242:            if (*p != *q) continue;     /* plain mismatch: go to next rule */
                    243: 
                    244:        switch (r->op) {                /* Perform operation */
2.11      luotonen  245: 
                    246: #ifdef ACCESS_AUTH
                    247:        case HT_DefProt:
                    248:        case HT_Protect:
                    249:            {
                    250:                char *local_copy = NULL;
                    251:                char *p;
                    252:                char *eff_ids = NULL;
                    253:                char *prot_file = NULL;
                    254: 
                    255:                if (TRACE) fprintf(stderr,
                    256:                                   "HTRule: `%s' matched %s %s: `%s'\n",
                    257:                                   current,
                    258:                                   (r->op==HT_Protect ? "Protect" : "DefProt"),
                    259:                                   "rule, setup",
                    260:                                   (r->equiv ? r->equiv :
                    261:                                    (r->op==HT_Protect ?"DEFAULT" :"NULL!!")));
                    262: 
                    263:                if (r->equiv) {
                    264:                    StrAllocCopy(local_copy, r->equiv);
                    265:                    p = local_copy;
                    266:                    prot_file = HTNextField(&p);
                    267:                    eff_ids = HTNextField(&p);
                    268:                }
                    269: 
2.15      luotonen  270: #ifdef THESE_NO_LONGER_WORK
2.11      luotonen  271:                if (r->op == HT_Protect)
                    272:                    HTAA_setCurrentProtection(current, prot_file, eff_ids);
                    273:                else
                    274:                    HTAA_setDefaultProtection(current, prot_file, eff_ids);
2.15      luotonen  275: #endif
2.11      luotonen  276:                FREE(local_copy);
                    277: 
                    278:                /* continue translating rules */
                    279:            }
                    280:            break;
                    281: #endif ACCESS_AUTH
                    282: 
2.1       timbl     283:        case HT_Pass:                           /* Authorised */
                    284:                if (!r->equiv) {
2.17      luotonen  285:                    CTRACE(stderr, "HTRule: Pass `%s'\n", current);
2.18    ! luotonen  286:                    return wrap(current);
2.1       timbl     287:                }
2.11      luotonen  288:                /* Else fall through ...to map and pass */
2.1       timbl     289:                
                    290:        case HT_Map:
                    291:            if (*p == *q) { /* End of both strings, no wildcard */
2.17      luotonen  292:                CTRACE(stderr, "For `%s' using `%s'\n", current, r->equiv);  
                    293:                StrAllocCopy(current, r->equiv); /* use entire translation */
2.1       timbl     294:            } else {
                    295:                  char * ins = strchr(r->equiv, '*');   /* Insertion point */
                    296:                  if (ins) {    /* Consistent rule!!! */
                    297:                        char * temp = (char *)malloc(
                    298:                                strlen(r->equiv)-1 + m + 1);
2.9       secret    299:                        if (temp==NULL) 
                    300:                            outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1       timbl     301:                        strncpy(temp,   r->equiv, ins-r->equiv);
                    302:                        /* Note: temp may be unterminated now! */
                    303:                        strncpy(temp+(ins-r->equiv), q, m);  /* Matched bit */
                    304:                        strcpy (temp+(ins-r->equiv)+m, ins+1);  /* Last bit */
2.17      luotonen  305:                        CTRACE(stderr, "For `%s' using `%s'\n",
2.1       timbl     306:                                                current, temp);
                    307:                        free(current);
                    308:                        current = temp;                 /* Use this */
                    309: 
                    310:                    } else {    /* No insertion point */
                    311:                        char * temp = (char *)malloc(strlen(r->equiv)+1);
2.9       secret    312:                        if (temp==NULL) 
                    313:                            outofmem(__FILE__, "HTTranslate"); /* NT & AS */
2.1       timbl     314:                        strcpy(temp, r->equiv);
2.17      luotonen  315:                        CTRACE(stderr, "For `%s' using `%s'\n", current, temp);
2.1       timbl     316:                        free(current);
                    317:                        current = temp;                 /* Use this */
                    318:                    } /* If no insertion point exists */
                    319:                }
                    320:                if (r->op == HT_Pass) {
2.17      luotonen  321:                    CTRACE(stderr, "HTRule: ...and pass `%s'\n", current);
2.18    ! luotonen  322:                    return wrap(current);
2.1       timbl     323:                }
                    324:                break;
                    325: 
2.15      luotonen  326:        case HT_Exec:
2.11      luotonen  327:        case HT_Invalid:
                    328:        case HT_Fail:                           /* Unauthorised */
2.15      luotonen  329:        default:
2.17      luotonen  330:            CTRACE(stderr,"HTRule: *** FAIL `%s'\n", current);
                    331:            return (char *)0;
2.1       timbl     332:                                    
2.11      luotonen  333:        } /* if tail matches ... switch operation */
2.1       timbl     334: 
                    335:     } /* loop over rules */
                    336: 
                    337: 
2.18    ! luotonen  338:     return wrap(current);
2.1       timbl     339: }
                    340: 
2.15      luotonen  341: 
                    342: 
2.17      luotonen  343: /*     Translate by rules                              HTTranslateReq()
2.15      luotonen  344: **     ------------------
                    345: **
                    346: ** On entry,
                    347: **     req             request structure.
2.18    ! luotonen  348: **     req->arg_path   simplified pathname (no ..'s etc in it),
2.15      luotonen  349: **                     which will be translated.
                    350: **                     If this starts with /htbin/ it is taken
                    351: **                     to be a script call request.
                    352: **
                    353: ** On exit,
                    354: **     returns         YES on success, NO on failure (Forbidden).
                    355: **     req->translated contains the translated filename;
                    356: **                     NULL if a script call.
                    357: **     req->script     contains the executable script name;
                    358: **                     NULL if not a script call.
                    359: */
                    360: PUBLIC BOOL HTTranslateReq ARGS1(HTRequest *, req)
                    361: {
                    362:     rule * r;
                    363:     char *current = NULL;
                    364: 
2.18    ! luotonen  365:     if (!req  ||  !req->arg_path)
2.15      luotonen  366:        return NO;
                    367: 
2.18    ! luotonen  368:     StrAllocCopy(current, req->arg_path);
        !           369: 
        !           370:     if (HTUserDir && current[0] == '/' && current[1] == '~') { /* User dir */
        !           371:        char * username = current+2;
        !           372:        char * end = strchr(username, '/');
        !           373: 
        !           374:        if (end)  *end++ = 0;
        !           375: 
        !           376:        if (*username) {
        !           377:            struct passwd * pw = getpwnam(username);
        !           378: 
        !           379:            if (pw && pw->pw_dir) {
        !           380:                int homelen = strlen(pw->pw_dir);
        !           381:                char * d = (char*)malloc(homelen +
        !           382:                                         strlen(HTUserDir) +
        !           383:                                         (end ? strlen(end) : 0) + 3);
        !           384:                strcpy(d, pw->pw_dir);
        !           385:                if (pw->pw_dir[homelen-1] != '/' && HTUserDir[0] != '/')
        !           386:                    strcat(d, "/");
        !           387:                strcat(d, HTUserDir);
        !           388:                if (end) {
        !           389:                    if (HTUserDir[strlen(HTUserDir)-1] != '/')
        !           390:                        strcat(d, "/");
        !           391:                    strcat(d, end);
        !           392:                }
        !           393:                CTRACE(stderr, "\"%s\" --user--> \"%s\"\n", current, d);
        !           394:                free(current);
        !           395:                current = d;
        !           396:            }
        !           397:            else CTRACE(stderr, "HTRule: User dir for '%s' not found\n",
        !           398:                        current);
        !           399:        }
        !           400:        else CTRACE(stderr, "HTRule: Invalid user dir request '%s'\n",
        !           401:                    current);
        !           402:     }
2.15      luotonen  403: 
                    404:     for(r = rules; r; r = r->next) {
                    405:         char * p = r->pattern;
                    406:        int m=0;   /* Number of characters matched against wildcard */
                    407:        CONST char * q = current;
                    408:        for(;*p && *q; p++, q++) {   /* Find first mismatch */
                    409:            if (*p!=*q) break;
                    410:        }
                    411: 
                    412:        if (*p == '*') {                /* Match up to wildcard */
                    413:            m = strlen(q) - strlen(p+1); /* Amount to match to wildcard */
                    414:            if(m<0) continue;           /* tail is too short to match */
                    415:            if (0!=strcmp(q+m, p+1)) continue;  /* Tail mismatch */
                    416:        } else                          /* Not wildcard */
                    417:            if (*p != *q) continue;     /* plain mismatch: go to next rule */
                    418: 
                    419:        switch (r->op) {                /* Perform operation */
                    420: 
                    421: #ifdef ACCESS_AUTH
                    422:        case HT_DefProt:
                    423:        case HT_Protect:
                    424:            {
                    425:                char *local_copy = NULL;
                    426:                char *p;
                    427:                char *eff_ids = NULL;
                    428:                char *prot_file = NULL;
                    429: 
                    430:                if (TRACE) fprintf(stderr,
                    431:                                   "HTRule: `%s' matched %s %s: `%s'\n",
                    432:                                   current,
                    433:                                   (r->op==HT_Protect ? "Protect" : "DefProt"),
                    434:                                   "rule, setup",
                    435:                                   (r->equiv ? r->equiv :
                    436:                                    (r->op==HT_Protect ?"DEFAULT" :"NULL!!")));
                    437: 
                    438:                if (r->equiv) {
                    439:                    StrAllocCopy(local_copy, r->equiv);
                    440:                    p = local_copy;
                    441:                    prot_file = HTNextField(&p);
                    442:                    eff_ids = HTNextField(&p);
                    443:                }
                    444: 
                    445:                if (r->op == HT_Protect)
                    446:                    HTAA_setCurrentProtection(req, prot_file, eff_ids);
                    447:                else
                    448:                    HTAA_setDefaultProtection(req, prot_file, eff_ids);
                    449: 
                    450:                FREE(local_copy);
                    451: 
                    452:                /* continue translating rules */
                    453:            }
                    454:            break;
                    455: #endif ACCESS_AUTH
                    456: 
                    457:        case HT_Exec:
                    458:            if (!r->equiv) {
                    459:                if (TRACE) fprintf(stderr,
                    460:                                   "HTRule: Exec `%s', no extra pathinfo\n",
                    461:                                   current);
                    462:                req->script = current;
                    463:                req->script_pathinfo = NULL;
2.18    ! luotonen  464:                req->script_pathtrans = NULL;
2.15      luotonen  465:                return YES;
                    466:            }
                    467:            else if (*p == *q || !strchr(r->equiv, '*')) { /* No wildcards */
                    468:                if (TRACE) fprintf(stderr,
                    469:                                   "HTRule: Exec `%s', no extra pathinfo\n",
                    470:                                   r->equiv);
                    471:                StrAllocCopy(req->script, r->equiv);
                    472:                req->script_pathinfo = NULL;
2.18    ! luotonen  473:                req->script_pathtrans = NULL;
2.15      luotonen  474:                return YES;
                    475:            }
                    476:            else {
                    477:                char *ins = strchr(r->equiv, '*');
                    478:                char *pathinfo;
2.18    ! luotonen  479: 
        !           480:                req->script = (char*)malloc(strlen(r->equiv) + m);
        !           481:                if (!req->script) outofmem(__FILE__, "HTTranslateReq");
        !           482: 
2.15      luotonen  483:                strncpy(req->script, r->equiv, ins-r->equiv);
                    484:                strncpy(req->script+(ins-r->equiv), q, m);
                    485:                strcpy(req->script+(ins-r->equiv)+m, ins+1);
                    486:                for (pathinfo = req->script+(ins-r->equiv)+1;
                    487:                     *pathinfo && *pathinfo != '/';
                    488:                     pathinfo++)
                    489:                    ;
2.17      luotonen  490:                FREE(req->script_pathinfo);
                    491:                FREE(req->script_pathtrans);
2.15      luotonen  492:                if (*pathinfo) {
                    493:                    StrAllocCopy(req->script_pathinfo, pathinfo);
                    494:                    *pathinfo = 0;
2.18    ! luotonen  495:                    req->script_pathtrans =
        !           496:                        unwrap(HTTranslate(req->script_pathinfo));
2.15      luotonen  497:                }
                    498:                return YES;
                    499:            }
                    500:            break;
2.18    ! luotonen  501: 
        !           502:          case HT_Redirect:
        !           503:            if (!r->equiv) {
        !           504:                CTRACE(stderr,
        !           505:                       "HTRule: ERROR: No destination for redirect %s\n",
        !           506:                       r->pattern);
        !           507:                req->reason = HTAA_INVALID_REDIRECT;
        !           508:                return NO;
        !           509:            }
        !           510:            else req->reason = HTAA_OK_REDIRECT;
        !           511:            /* And fall through to HT_Map... */
        !           512: 
2.15      luotonen  513:        case HT_Pass:                           /* Authorised */
                    514:                if (!r->equiv) {
                    515:                    if (TRACE) fprintf(stderr, "HTRule: Pass `%s'\n", current);
2.18    ! luotonen  516:                    req->translated = unwrap(current);
2.15      luotonen  517:                    return YES;
                    518:                }
                    519:                /* Else fall through ...to map and pass */
                    520:                
                    521:        case HT_Map:
                    522:            if (*p == *q) { /* End of both strings, no wildcard */
2.17      luotonen  523:                CTRACE(stderr,"For `%s' using `%s'\n", current, r->equiv);  
                    524:                StrAllocCopy(current, r->equiv); /* use entire translation */
2.15      luotonen  525:            } else {
2.18    ! luotonen  526:                char * ins = strchr(r->equiv, '*');     /* Insertion point */
        !           527:                if (ins) {      /* Consistent rule!!! */
        !           528:                    char * temp=(char*)malloc(strlen(r->equiv)-1 + m + 1);
        !           529:                    if (!temp) outofmem(__FILE__, "HTTranslateReq");
        !           530: 
        !           531:                    strncpy(temp,       r->equiv, ins-r->equiv);
        !           532:                    /* Note: temp may be unterminated now! */
        !           533:                    strncpy(temp+(ins-r->equiv), q, m);  /* Matched bit */
        !           534:                    strcpy (temp+(ins-r->equiv)+m, ins+1);      /* Last bit */
        !           535:                    CTRACE(stderr,"\"%s\" --map*-> \"%s\"\n",current,temp);
        !           536:                    free(current);
        !           537:                    current = temp;                     /* Use this */
        !           538: 
        !           539:                } else {        /* No insertion point */
        !           540:                    char * temp = (char *)malloc(strlen(r->equiv)+1);
        !           541:                    if (temp==NULL) 
        !           542:                        outofmem(__FILE__, "HTTranslateReq"); /* NT & AS */
        !           543:                    strcpy(temp, r->equiv);
        !           544:                    CTRACE(stderr,"\"%s\" --map--> \"%s\"\n",current,temp);
        !           545:                    free(current);
        !           546:                    current = temp;                     /* Use this */
        !           547:                } /* If no insertion point exists */
        !           548:            }
        !           549:            if (r->op == HT_Pass) {
        !           550:                CTRACE(stderr, "HTRule: Pass `%s'\n", current);
        !           551:                req->translated = unwrap(current);
        !           552:                return YES;
        !           553:            }
        !           554:            else if (r->op == HT_Redirect) {
        !           555:                CTRACE(stderr, "HTRule: Redirected to `%s'\n", current);
        !           556:                req->location = current;
        !           557:                return YES;
        !           558:            }
        !           559:            break;
2.15      luotonen  560: 
                    561:        case HT_Invalid:
                    562:        case HT_Fail:                           /* Unauthorised */
2.17      luotonen  563:            CTRACE(stderr, "HTRule: *** FAIL `%s'\n", current);
                    564:            return NO;
                    565:            break;
2.15      luotonen  566:        } /* if tail matches ... switch operation */
                    567: 
                    568:     } /* loop over rules */
                    569: 
                    570:     /* Actually here failing might be more appropriate?? */
2.18    ! luotonen  571:     req->translated = unwrap(current);
2.15      luotonen  572:     return YES;
                    573: }
                    574: 
                    575: 
                    576: 
2.7       timbl     577: /*     Load one line of configuration
                    578: **     ------------------------------
                    579: **
                    580: **     Call this, for example, to load a X resource with config info.
                    581: **
                    582: ** returns     0 OK, < 0 syntax error.
                    583: */
2.15      luotonen  584: PUBLIC int HTSetConfiguration ARGS1(CONST char *, config)
2.7       timbl     585: {
                    586:     HTRuleOp op;
                    587:     char * line = NULL;
                    588:     char * pointer = line;
                    589:     char *word1, *word2, *word3;
                    590:     float quality, secs, secs_per_byte;
                    591:     int status;
                    592:     
                    593:     StrAllocCopy(line, config);
                    594:     {
                    595:        char * p = strchr(line, '#');   /* Chop off comments */
                    596:        if (p) *p = 0;
                    597:     }
                    598:     pointer = line;
                    599:     word1 = HTNextField(&pointer);
                    600:     if (!word1) {
                    601:        free(line);
                    602:        return 0;
                    603:     } ;        /* Comment only or blank */
2.11      luotonen  604: 
2.7       timbl     605:     word2 = HTNextField(&pointer);
2.11      luotonen  606: 
                    607:     if (0==strcasecomp(word1, "defprot") ||
                    608:        0==strcasecomp(word1, "protect"))
                    609:        word3 = pointer;  /* The rest of the line to be parsed by AA module */
                    610:     else
                    611:        word3 = HTNextField(&pointer);  /* Just the next word */
                    612: 
2.7       timbl     613:     if (!word2) {
                    614:        fprintf(stderr, "HTRule: Insufficient operands: %s\n", line);
                    615:        free(line);
                    616:        return -2;      /*syntax error */
                    617:     }
                    618: 
2.17      luotonen  619:     if (0==strcasecomp(word1, "suffix") ||
                    620:        0==strcasecomp(word1, "addtype")) {
2.8       timbl     621:         char * encoding = HTNextField(&pointer);
                    622:        if (pointer) status = sscanf(pointer, "%f", &quality);
                    623:        else status = 0;
2.17      luotonen  624:        HTAddType(word2,        word3,
2.8       timbl     625:                                encoding ? encoding : "binary",
                    626:                                status >= 1? quality : 1.0);
2.7       timbl     627: 
2.17      luotonen  628:     } else if (0==strcasecomp(word1, "addencoding") ||
                    629:               0==strcasecomp(word1, "encoding")) {
                    630:        if (pointer)
                    631:            status = sscanf(pointer, "%f", &quality);
                    632:        else status = 0;
                    633:        HTAddEncoding(word2, word3,
                    634:                      status >= 1 ? quality : 1.0);
                    635: 
                    636:     } else if (0==strcasecomp(word1, "addlanguage") ||
                    637:               0==strcasecomp(word1, "language")) {
                    638:        if (pointer)
                    639:            status = sscanf(pointer, "%f", &quality);
                    640:        else status = 0;
                    641:        HTAddLanguage(word2, word3,
                    642:                      status >= 1 ? quality : 1.0);
                    643: 
2.7       timbl     644:     } else if (0==strcasecomp(word1, "presentation")) {
2.8       timbl     645:         if (pointer) status = sscanf(pointer, "%f%f%f",
                    646:                            &quality, &secs, &secs_per_byte);
                    647:         else status = 0;
2.14      timbl     648:        if (!HTConversions) HTConversions = HTList_new();
                    649:        HTSetPresentation(HTConversions, word2, word3,
2.7       timbl     650:                    status >= 1? quality                : 1.0,
2.11      luotonen  651:                    status >= 2 ? secs                  : 0.0,
2.7       timbl     652:                    status >= 3 ? secs_per_byte         : 0.0 );
2.12      luotonen  653: 
2.17      luotonen  654:     } else if (0==strncasecomp(word1, "putscript", 9) ||
                    655:               0==strncasecomp(word1, "put-script", 10)) {
                    656:        StrAllocCopy(HTPutScript, word2);
                    657: 
                    658:     } else if (0==strncasecomp(word1, "postscript", 10) ||
                    659:               0==strncasecomp(word1, "post-script", 11)) {
                    660:        StrAllocCopy(HTPostScript, word2);
                    661: 
2.18    ! luotonen  662:     } else if (0==strncasecomp(word1, "userdir", 7)) {
        !           663:        CTRACE(stderr,
        !           664:               "User supported directories are '%s' under each user's home\n",
        !           665:               word2);
        !           666:        StrAllocCopy(HTUserDir, word2);
        !           667: 
2.13      luotonen  668:     } else if (0==strncasecomp(word1, "htbin", 5) ||
                    669:               0==strncasecomp(word1, "bindir", 6)) {
2.15      luotonen  670:        char *bindir = (char*)malloc(strlen(word2) + 3);
                    671:        if (!bindir) outofmem(__FILE__, "HTSetConfiguration");
                    672:        strcpy(bindir, word2);
                    673:        strcat(bindir, "/*");
                    674:        HTAddRule(HT_Exec, "/htbin/*", bindir);
                    675: 
                    676:        /*
                    677:        ** Physical /htbin location -- this is almost obsolite
                    678:        ** (only search may need it).
                    679:        */
                    680:        StrAllocCopy(HTBinDir, word2);
2.13      luotonen  681: 
                    682:     } else if (0==strncasecomp(word1, "search", 6)) {
2.15      luotonen  683:        if (strchr(word2, '/'))
                    684:            StrAllocCopy(HTSearchScript, word2); /* Full search script path */
                    685:        else if (HTBinDir) {
                    686:            if (!(HTSearchScript =
                    687:                  (char*)malloc(strlen(HTBinDir) + strlen(word2) + 2)))
                    688:                outofmem(__FILE__, "HTSetConfiguration");
                    689:            strcpy(HTSearchScript, HTBinDir);
                    690:            strcat(HTSearchScript, "/");
                    691:            strcat(HTSearchScript, word2);
                    692:        }
                    693:        else if (TRACE) fprintf(stderr,
                    694:                "HTRule: Search rule without HTBin rule before ignored\n");
                    695:        if (TRACE) {
                    696:            if (HTSearchScript)
                    697:                fprintf(stderr, "HTRule: Search script set to `%s'\n",
                    698:                        HTSearchScript);
                    699:            else fprintf(stderr, "HTRule: Search script not set\n");
                    700:        }
2.12      luotonen  701: 
2.7       timbl     702:     } else {
                    703:        op =    0==strcasecomp(word1, "map")  ? HT_Map
                    704:            :   0==strcasecomp(word1, "pass") ? HT_Pass
                    705:            :   0==strcasecomp(word1, "fail") ? HT_Fail
2.17      luotonen  706:            :   0==strcasecomp(word1, "exec") ? HT_Exec
2.18    ! luotonen  707:            :   0==strcasecomp(word1, "redirect")? HT_Redirect
2.11      luotonen  708:            :   0==strcasecomp(word1, "defprot") ? HT_DefProt
                    709:            :   0==strcasecomp(word1, "protect") ? HT_Protect
2.7       timbl     710:            :                                           HT_Invalid;
                    711:        if (op==HT_Invalid) {
2.17      luotonen  712:            CTRACE(stderr, "HTRule: Bad rule `%s'\n", config);
2.7       timbl     713:        } else {  
                    714:            HTAddRule(op, word2, word3);
                    715:        } 
                    716:     }
                    717:     free(line);
                    718:     return 0;
                    719: }
                    720: 
2.1       timbl     721: 
2.11      luotonen  722: /*     Load the rules from a file                              HTLoadRules()
2.1       timbl     723: **     --------------------------
                    724: **
                    725: ** On entry,
                    726: **     Rules can be in any state
                    727: ** On exit,
                    728: **     Any existing rules will have been kept.
2.7       timbl     729: **     Any new rules will have been loaded.
                    730: **     Returns         0 if no error, 0 if error!
2.1       timbl     731: **
                    732: ** Bugs:
                    733: **     The strings may not contain spaces.
                    734: */
                    735: 
                    736: int HTLoadRules ARGS1(CONST char *, filename)
                    737: {
                    738:     FILE * fp = fopen(filename, "r");
                    739:     char line[LINE_LENGTH+1];
                    740:     
                    741:     if (!fp) {
2.17      luotonen  742:         CTRACE(stderr, "HTRules: Can't open rules file %s\n", filename);
2.1       timbl     743:        return -1; /* File open error */
                    744:     }
                    745:     for(;;) {
                    746:        if (!fgets(line, LINE_LENGTH+1, fp)) break;     /* EOF or error */
2.7       timbl     747:        (void) HTSetConfiguration(line);
2.1       timbl     748:     }
                    749:     fclose(fp);
2.7       timbl     750:     return 0;          /* No error or syntax errors ignored */
2.1       timbl     751: }
2.11      luotonen  752: 
                    753: 

Webmaster