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

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.41    ! frystyk   372:     HTAlertCallback *cbf = HTAlert_find(HT_A_CONFIRM);
2.40      frystyk   373:     HTStream * me;
2.41    ! frystyk   374:     if (cbf && (*cbf)(request, HT_A_CONFIRM, HT_MSG_RULES, NULL, NULL, NULL)) {
2.40      frystyk   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