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

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.40    ! frystyk     7: **     This module manages rule files in the Library
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.40    ! frystyk    25: **     15 Nov 95  HFN  Made a stream, fixed interface and made new translater
2.11      luotonen   26: **
2.40    ! frystyk    27: ** BUGS: We only have one wildcard match pr rule!
2.1       timbl      28: */
                     29: 
2.28      frystyk    30: /* Library include files */
2.34      frystyk    31: #include "WWWLib.h"
2.40    ! frystyk    32: #include "HTProxy.h"
2.26      frystyk    33: #include "HTRules.h"                                    /* Implemented here */
2.1       timbl      34: 
2.40    ! frystyk    35: struct _HTStream {
        !            36:     CONST HTStreamClass *      isa;
        !            37:     HTRequest *                        request;
        !            38:     HTStream *                 target;
        !            39:     HTChunk *                  buffer;
        !            40:     HTSocketEOL                        EOLstate;
        !            41: };
        !            42: 
        !            43: struct _HTRule {
        !            44:     HTRuleOp   op;
        !            45:     char *     pattern;
        !            46:     char *     replace;
        !            47:     int        insert;                /* Index into any wildcard in replace */
        !            48: };
        !            49: 
        !            50: PRIVATE HTList * rules = NULL;
        !            51: 
        !            52: /* ------------------------------------------------------------------------- */
        !            53: 
        !            54: /*
        !            55: **     Rules are handled as list as everything else that has to do with
        !            56: **     preferences. We provide two functions for getting and setting the
        !            57: **     global rules
2.1       timbl      58: */
2.40    ! frystyk    59: PUBLIC HTList * HTRule_global (void)
        !            60: {
        !            61:     if (!rules) rules = HTList_new();
        !            62:     return rules;
        !            63: }
2.1       timbl      64: 
2.40    ! frystyk    65: PUBLIC BOOL HTRule_setGlobal(HTList * list)
        !            66: {
        !            67:     if (rules) HTRule_deleteAll(rules);
        !            68:     rules = list;
        !            69:     return YES;
        !            70: }
2.1       timbl      71: 
2.40    ! frystyk    72: /*     Add rule to the list
2.1       timbl      73: **     --------------------
2.40    ! frystyk    74: **     This function adds a rule to the list of rules. The
        !            75: **     pattern is a 0-terminated string containing a single
        !            76: **     "*". <CODE>equiv</CODE> points to the equivalent string with * for the
        !            77: **     place where the text matched by * goes.
2.1       timbl      78: **  On entry,
                     79: **     pattern         points to 0-terminated string containing a single "*"
2.40    ! frystyk    80: **     replace         points to the equivalent string with * for the
2.1       timbl      81: **                     place where the text matched by * goes.
                     82: **  On exit,
2.40    ! frystyk    83: **     returns         YES if OK, else NO
2.1       timbl      84: */
2.40    ! frystyk    85: PUBLIC BOOL HTRule_add (HTList * list, HTRuleOp op,
        !            86:                        CONST char * pattern, CONST char * replace)
2.39      frystyk    87: {
2.40    ! frystyk    88:     if (list && pattern) {
        !            89:        HTRule * me = (HTRule *) calloc(1, sizeof(HTRule));
        !            90:        if (!me) outofmem(__FILE__, "HTRule_add");
        !            91:        me->op = op;
        !            92:        StrAllocCopy(me->pattern, pattern);
        !            93:        if (replace) {
        !            94:            char *ptr = strchr(replace, '*');
        !            95:            StrAllocCopy(me->replace, replace);
        !            96:            me->insert = ptr ? ptr-replace : -1;
        !            97:            if (APP_TRACE)
        !            98:                TTYPrint(TDEST, "Rule Add.... For `%s\' op %d `%s\'\n",
        !            99:                         pattern, op, replace);
        !           100:        } else
        !           101:            TTYPrint(TDEST, "Rule Add.... For `%s\' op %d\n", pattern, op);
        !           102:        return HTList_appendObject(rules, (void *) me);
2.10      duns      103:     }
2.40    ! frystyk   104:     return NO;
2.1       timbl     105: }
                    106: 
2.40    ! frystyk   107: /*     Delete all rules
        !           108: **     ----------------
        !           109: **     Deletes all the rules registered by this module
2.1       timbl     110: */
2.40    ! frystyk   111: PUBLIC BOOL HTRule_deleteAll (HTList * list)
2.1       timbl     112: {
2.40    ! frystyk   113:     if (list) {
        !           114:        HTList *cur = list;
        !           115:        HTRule *pres;
        !           116:        while ((pres = (HTRule *) HTList_nextObject(cur))) {
        !           117:            FREE(pres->pattern);
        !           118:            FREE(pres->replace);
        !           119:            free(pres);
        !           120:        }
        !           121:        return HTList_delete(list);
2.1       timbl     122:     }
2.40    ! frystyk   123:     return NO;
2.1       timbl     124: }
                    125: 
2.40    ! frystyk   126: /*     Translate by rules
2.1       timbl     127: **     ------------------
2.15      luotonen  128: **     The most recently defined rules are applied last.
2.40    ! frystyk   129: **     This function walks through the list of rules and translates the
        !           130: **     reference when matches are found. The list is traversed in order
        !           131: **     starting from the head of the list. It returns the address of the
        !           132: **     equivalent string allocated from the heap which the CALLER MUST
        !           133: **     FREE.
2.1       timbl     134: */
2.40    ! frystyk   135: PUBLIC char * HTRule_translate (HTList * list, CONST char * token,
        !           136:                                BOOL ignore_case)
2.1       timbl     137: {
2.40    ! frystyk   138:     HTRule * pres;
        !           139:     char * replace = NULL;
        !           140:     if (!token || !list) return NULL;
        !           141:     if (APP_TRACE) TTYPrint(TDEST, "Rule Apply.. Translating '%s\'\n", token);
        !           142:     while ((pres = (HTRule *) HTList_nextObject(list))) {
        !           143:        char * rest = ignore_case ? HTStrCaseMatch(pres->pattern, token) :
        !           144:            HTStrMatch(pres->pattern, token);
        !           145:        if (!rest) continue;                              /* No match at all */
        !           146:     
        !           147:        /* We found a match for this entry, now do operation */
        !           148:        switch (pres->op) {
        !           149: 
        !           150:           case HT_Pass:
        !           151:          case HT_Map:
        !           152:            if (!pres->replace) {                              /* No replace */
        !           153:                StrAllocCopy(replace, token);
        !           154: 
        !           155:            } else if (*rest && pres->insert >= 0) {
        !           156:                replace = (char *) malloc(strlen(pres->replace)+strlen(rest));
        !           157:                if (!replace) outofmem(__FILE__, "HTRule_translate");
        !           158:                strcpy(replace, pres->replace);
        !           159:                strcpy(replace+pres->insert, rest);
        !           160: 
        !           161:            } else {                   /* Perfect match or no insetion point */
        !           162:                StrAllocCopy(replace, pres->replace);
        !           163:            }
        !           164: 
        !           165:            if (pres->op == HT_Pass) {
        !           166:                if (APP_TRACE)
        !           167:                    TTYPrint(TDEST, "............ into `%s'\n", replace);
        !           168:                return replace;
        !           169:            }
        !           170:            break;
        !           171:            
        !           172:          case HT_Fail:
        !           173: 
        !           174:          default:
        !           175:            if (APP_TRACE) TTYPrint(TDEST,"............ FAIL `%s'\n", token);
        !           176:            return NULL;
2.1       timbl     177:        }
2.40    ! frystyk   178:     }
        !           179:     if (!replace) StrAllocCopy(replace, token);
        !           180:     return replace;
2.15      luotonen  181: }
                    182: 
2.7       timbl     183: /*     Load one line of configuration
                    184: **     ------------------------------
                    185: **     Call this, for example, to load a X resource with config info.
2.40    ! frystyk   186: **     Returns YES if line OK, else NO
2.7       timbl     187: */
2.40    ! frystyk   188: PUBLIC BOOL HTRule_parseLine (HTList * list, CONST char * config)
2.7       timbl     189: {
                    190:     HTRuleOp op;
                    191:     char * line = NULL;
2.40    ! frystyk   192:     char * ptr;
        !           193:     char * word1, * word2, * word3;
2.7       timbl     194:     int status;
2.40    ! frystyk   195:     if ((ptr = strchr(config, '#'))) *ptr = '\0';
        !           196:     StrAllocCopy(line, config);                                 /* Get our own copy */
        !           197:     ptr = line;
        !           198:     if ((word1 = HTNextField(&ptr)) == NULL) {                /* Empty line */
        !           199:        free(line);
        !           200:        return YES;
2.7       timbl     201:     }
2.40    ! frystyk   202:     if ((word2 = HTNextField(&ptr)) == NULL) {
        !           203:        if (APP_TRACE)
        !           204:            TTYPrint(TDEST,"Rule Parse.. Insufficient operands: `%s\'\n",line);
2.7       timbl     205:        free(line);
2.40    ! frystyk   206:        return NO;
2.7       timbl     207:     }
2.40    ! frystyk   208:     word3 = HTNextField(&ptr);
2.7       timbl     209: 
2.40    ! frystyk   210:     /* Look for things we recognize */
        !           211:     if (!strcasecomp(word1, "addtype")) {
        !           212:        double quality;
        !           213:         char * encoding = HTNextField(&ptr);
        !           214:        status = ptr ? sscanf(ptr, "%lf", &quality) : 0;
2.37      frystyk   215:        HTBind_add(word2,                               /* suffix */
                    216:                   word3,                               /* type */
                    217:                   encoding ? encoding : "binary",      /* encoding */
2.40    ! frystyk   218:                   NULL,                                /* language */
2.37      frystyk   219:                   status >= 1? quality : 1.0);         /* quality */
2.7       timbl     220: 
2.40    ! frystyk   221:     } else if (!strcasecomp(word1, "addencoding")) {
        !           222:        double quality;
        !           223:        status = ptr ? sscanf(ptr, "%lf", &quality) : 0;
        !           224:        HTBind_addEncoding(word2, word3, status >= 1 ? quality : 1.0);
        !           225: 
        !           226:     } else if (!strcasecomp(word1, "addlanguage")) {
        !           227:        double quality;
        !           228:        status = ptr ? sscanf(ptr, "%lf", &quality) : 0;
        !           229:        HTBind_addLanguage(word2, word3, status >= 1 ? quality : 1.0);
        !           230: 
        !           231:     } else if (!strcasecomp(word1, "presentation")) {
        !           232:        HTList * converters = HTFormat_conversion();
        !           233:        double quality, secs, secs_per_byte;
        !           234:         status = ptr ? sscanf(ptr,"%lf%lf%lf",&quality,&secs,&secs_per_byte):0;
2.36      frystyk   235:        HTPresentation_add(converters, word2, word3, NULL,
2.40    ! frystyk   236:                           status >= 1 ? quality : 1.0,
        !           237:                           status >= 2 ? secs : 0.0,
        !           238:                           status >= 3 ? secs_per_byte : 0.0);
        !           239: 
        !           240:     } else if (!strcasecomp(word1, "proxy")) {
        !           241:        HTProxy_add(word2, word3);
        !           242:        
        !           243:     } else if (!strcasecomp(word1, "noproxy")) {
        !           244:        int port = 0;
        !           245:         status = ptr ? sscanf(ptr, "%d", &port) : 0;
        !           246:        HTNoProxy_add(word2, word3, port);
        !           247: 
        !           248:     } else if (!strcasecomp(word1, "gateway")) {
        !           249:        HTGateway_add(word2, word3);
2.12      luotonen  250: 
2.7       timbl     251:     } else {
                    252:        op =    0==strcasecomp(word1, "map")  ? HT_Map
                    253:            :   0==strcasecomp(word1, "pass") ? HT_Pass
                    254:            :   0==strcasecomp(word1, "fail") ? HT_Fail
2.19      luotonen  255:            :                                   HT_Invalid;
2.40    ! frystyk   256:        if (op == HT_Invalid) {
        !           257:            if (APP_TRACE)
        !           258:                TTYPrint(TDEST, "Rule Parse.. Bad or unknown: `%s'\n", config);
        !           259:        } else
        !           260:            HTRule_add(list, op, word2, word3);
2.7       timbl     261:     }
                    262:     free(line);
2.40    ! frystyk   263:     return YES;
2.7       timbl     264: }
                    265: 
2.40    ! frystyk   266: /*
        !           267: **     Folding is either of CF LWS, LF LWS, CRLF LWS
        !           268: */
        !           269: PRIVATE int HTRule_put_block (HTStream * me, CONST char * b, int l)
        !           270: {
        !           271:     while (l > 0) {
        !           272:        if (me->EOLstate == EOL_FCR) {
        !           273:            if (*b == LF)                                            /* CRLF */
        !           274:                me->EOLstate = EOL_FLF;
        !           275:            else if (WHITE(*b))                            /* Folding: CR SP */
        !           276:                me->EOLstate = EOL_DOT;
        !           277:            else {                                               /* New line */
        !           278:                HTRule_parseLine(rules, HTChunkData(me->buffer));
        !           279:                me->EOLstate = EOL_BEGIN;
        !           280:                HTChunkClear(me->buffer);
        !           281:                continue;
        !           282:            }
        !           283:        } else if (me->EOLstate == EOL_FLF) {
        !           284:            if (WHITE(*b))                     /* Folding: LF SP or CR LF SP */
        !           285:                me->EOLstate = EOL_DOT;
        !           286:            else {                                              /* New line */
        !           287:                HTRule_parseLine(rules, HTChunkData(me->buffer));
        !           288:                me->EOLstate = EOL_BEGIN;
        !           289:                HTChunkClear(me->buffer);
        !           290:                continue;
        !           291:            }
        !           292:        } else if (me->EOLstate == EOL_DOT) {
        !           293:            if (WHITE(*b)) {
        !           294:                me->EOLstate = EOL_BEGIN;
        !           295:                HTChunkPutc(me->buffer, ' ');
        !           296:            } else {
        !           297:                HTRule_parseLine(rules, HTChunkData(me->buffer));
        !           298:                me->EOLstate = EOL_BEGIN;
        !           299:                HTChunkClear(me->buffer);
        !           300:                continue;
        !           301:            }
        !           302:        } else if (*b == CR) {
        !           303:            me->EOLstate = EOL_FCR;
        !           304:        } else if (*b == LF) {
        !           305:            me->EOLstate = EOL_FLF;                            /* Line found */
        !           306:        } else
        !           307:            HTChunkPutc(me->buffer, *b);
        !           308:        l--; b++;
        !           309:     }
        !           310:     return HT_OK;
        !           311: }
2.1       timbl     312: 
2.40    ! frystyk   313: PRIVATE int HTRule_put_character (HTStream * me, char c)
        !           314: {
        !           315:     return HTRule_put_block(me, &c, 1);
        !           316: }
        !           317: 
        !           318: PRIVATE int HTRule_put_string (HTStream * me, CONST char * s)
        !           319: {
        !           320:     return HTRule_put_block(me, s, (int) strlen(s));
        !           321: }
        !           322: 
        !           323: PRIVATE int HTRule_flush (HTStream * me)
        !           324: {
        !           325:     return (*me->target->isa->flush)(me->target);
        !           326: }
        !           327: 
        !           328: PRIVATE int HTRule_free (HTStream * me)
        !           329: {
        !           330:     int status = HT_OK;
        !           331:     if (me->target) {
        !           332:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
        !           333:            return HT_WOULD_BLOCK;
        !           334:     }
        !           335:     if (APP_TRACE)
        !           336:        TTYPrint(TDEST, "Rules....... FREEING....\n");
        !           337:     HTChunkFree(me->buffer);
        !           338:     free(me);
        !           339:     return status;
        !           340: }
        !           341: 
        !           342: PRIVATE int HTRule_abort (HTStream * me, HTList * e)
        !           343: {
        !           344:     int status = HT_ERROR;
        !           345:     if (me->target) status = (*me->target->isa->abort)(me->target, e);
        !           346:     if (APP_TRACE) TTYPrint(TDEST, "Rules....... ABORTING...\n");
        !           347:     HTChunkFree(me->buffer);
        !           348:     free(me);
        !           349:     return status;
        !           350: }
        !           351: 
        !           352: /*     Structured Object Class
        !           353: **     -----------------------
2.1       timbl     354: */
2.40    ! frystyk   355: PRIVATE CONST HTStreamClass HTRuleClass =
        !           356: {              
        !           357:     "RuleParser",
        !           358:     HTRule_flush,
        !           359:     HTRule_free,
        !           360:     HTRule_abort,
        !           361:     HTRule_put_character,
        !           362:     HTRule_put_string,
        !           363:     HTRule_put_block
        !           364: };
        !           365: 
        !           366: PUBLIC HTStream * HTRules (HTRequest * request,
        !           367:                           void *       param,
        !           368:                           HTFormat     input_format,
        !           369:                           HTFormat     output_format,
        !           370:                           HTStream *   output_stream)
2.1       timbl     371: {
2.40    ! frystyk   372:     BOOL confirm = HTConfirm(request, "A new set of rules is to be added to your setup - continue?");
        !           373:     HTStream * me;
        !           374:     if (confirm) {
        !           375:        if ((me = (HTStream *) calloc(1, sizeof(HTStream))) == NULL)
        !           376:            outofmem(__FILE__, "HTRules");
        !           377:        me->isa = &HTRuleClass;
        !           378:        me->request = request;
        !           379:        me->target = output_stream;
        !           380:        me->buffer = HTChunkCreate(512);
        !           381:        me->EOLstate = EOL_BEGIN;
        !           382:        if (!rules) rules = HTList_new();
        !           383:     } else
        !           384:        me = HTBlackHole();
        !           385:     return me;
2.1       timbl     386: }
2.11      luotonen  387: 

Webmaster