Annotation of libwww/Library/src/HTReqMan.c, revision 2.34

2.1       frystyk     1: /*                                                                  HTReqMan.c
                      2: **     REQUEST MANAGER
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: ** Authors
                      8: **     TBL     Tim Berners-Lee timbl@w3.org
                      9: **     JFG     Jean-Francois Groff jfg@dxcern.cern.ch
                     10: **     DD      Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
                     11: **     HFN     Henrik Frystyk, frystyk@w3.org
                     12: ** History
                     13: **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
                     14: **     26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
                     15: **      6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
                     16: **     17 Dec 92 Tn3270 added, bug fix. DD
                     17: **      4 Feb 93 Access registration, Search escapes bad chars TBL
                     18: **               PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
                     19: **     28 May 93 WAIS gateway explicit if no WAIS library linked in.
                     20: **        Dec 93 Bug change around, more reentrant, etc
                     21: **     09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
                     22: **      8 Jul 94 Insulate free() from _free structure element.
                     23: **     02 Sep 95 Rewritten and spawned from HTAccess.c, HFN
                     24: */
                     25: 
                     26: #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
                     27: #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
                     28: #endif
                     29: 
                     30: /* Library include files */
2.32      frystyk    31: #include "sysdep.h"
2.1       frystyk    32: #include "HTUtils.h"
                     33: #include "HTString.h"
                     34: #include "HTParse.h"
                     35: #include "HTAlert.h"
                     36: #include "HTError.h"
                     37: #include "HTList.h"
                     38: #include "HTCache.h"
2.2       frystyk    39: #include "HTNetMan.h"
2.1       frystyk    40: #include "HTEvntrg.h"
                     41: #include "HTProt.h"
                     42: #include "HTProxy.h"
                     43: #include "HTReqMan.h"                                   /* Implemented here */
                     44: 
2.14      frystyk    45: #include "HTRules.h"
                     46: 
2.1       frystyk    47: #ifndef HT_MAX_RELOADS
                     48: #define HT_MAX_RELOADS 6
                     49: #endif
2.13      frystyk    50: 
2.1       frystyk    51: PRIVATE int HTMaxRetry = HT_MAX_RELOADS;
                     52: 
                     53: struct _HTStream {
                     54:        HTStreamClass * isa;
                     55:        /* ... */
                     56: };
                     57: 
                     58: /* --------------------------------------------------------------------------*/
                     59: /*                     Management of the HTRequest structure                */
                     60: /* --------------------------------------------------------------------------*/
                     61: 
                     62: /*  Create  a request structure
                     63: **  ---------------------------
                     64: */
2.3       frystyk    65: PUBLIC HTRequest * HTRequest_new (void)
2.1       frystyk    66: {
2.29      frystyk    67:     HTRequest * me;
                     68:     if ((me = (HTRequest *) HT_CALLOC(1, sizeof(HTRequest))) == NULL)
                     69:         HT_OUTOFMEM("HTRequest_new()");
2.1       frystyk    70:     
2.7       frystyk    71:    /* Force Reload */
2.1       frystyk    72:     me->reload = HT_ANY_VERSION;
                     73: 
                     74:     /* Format of output */
                     75:     me->output_format  = WWW_PRESENT;      /* default it to present to user */
2.21      frystyk    76:     me->debug_format   = WWW_DEBUG;     /* default format of error messages */
2.1       frystyk    77: 
                     78:     /* HTTP headers */
                     79:     me->GenMask                = DEFAULT_GENERAL_HEADERS;
                     80:     me->RequestMask    = DEFAULT_REQUEST_HEADERS;
2.22      frystyk    81:     me->ResponseMask   = DEFAULT_RESPONSE_HEADERS;
2.1       frystyk    82:     me->EntityMask     = DEFAULT_ENTITY_HEADERS;
                     83: 
                     84:     /* Default retry after value */
                     85:     me->retry_after = -1;
2.19      frystyk    86:     me->priority = HT_PRIORITY_MAX;
2.1       frystyk    87: 
                     88:     /* Content negotiation */
                     89:     me->ContentNegotiation = NO;                      /* Do this by default */
                     90: 
2.13      frystyk    91: #ifdef WWW_WIN_ASYNC
                     92:     HTEvent_winHandle(me);
2.1       frystyk    93: #endif
                     94:     return me;
                     95: }
                     96: 
2.28      frystyk    97: /*     HTRequest_clear
                     98: **     ---------------
                     99: **     Clears all protocol specific information so that the request object
                    100: **     can be used for another request.
                    101: **     Returns YES if OK, else NO
                    102: */
                    103: PUBLIC BOOL HTRequest_clear (HTRequest * me)
                    104: {
                    105:     if (me) {
                    106:        me->boundary = NULL;
                    107:        me->error_stack = NULL;
                    108:        me->net = NULL;
2.31      frystyk   109:        me->scheme = NULL;
                    110:        me->realm = NULL;
                    111:        me->challenge = NULL;
                    112:        me->credentials = NULL;
2.28      frystyk   113:        return YES;
                    114:     }
                    115:     return NO;
                    116: }
                    117: 
2.18      frystyk   118: /*     HTRequest_dup
                    119: **     -------------
                    120: **     Creates a new HTRequest object as a duplicate of the src request.
                    121: **     Returns YES if OK, else NO
                    122: */
                    123: PUBLIC HTRequest * HTRequest_dup (HTRequest * src)
                    124: {
                    125:     HTRequest * me;
2.33      eric      126:     if (!src) return 0;
2.29      frystyk   127:     if ((me = (HTRequest  *) HT_MALLOC(sizeof(HTRequest))) == NULL)
                    128:         HT_OUTOFMEM("HTRequest_dup");
2.18      frystyk   129:     memcpy(me, src, sizeof(HTRequest));
                    130:     return me;
                    131: }
2.1       frystyk   132: 
2.23      frystyk   133: /*     HTRequest_dupInternal
                    134: **     ---------------------
                    135: **     Creates a new HTRequest object as a duplicate of the src request.
                    136: **     The difference to the HTRequest_dup function is that we don't copy the
                    137: **     error_stack and other information that the application keeps in its
                    138: **     copy of the request object. Otherwise it will be freed multiple times
                    139: **     Returns YES if OK, else NO
                    140: */
                    141: PUBLIC HTRequest * HTRequest_dupInternal (HTRequest * src)
                    142: {
                    143:     HTRequest * me;
2.33      eric      144:     if (!src) return 0;
2.29      frystyk   145:     if ((me = (HTRequest  *) HT_MALLOC(sizeof(HTRequest))) == NULL)
                    146:         HT_OUTOFMEM("HTRequest_dup");
2.23      frystyk   147:     memcpy(me, src, sizeof(HTRequest));
2.28      frystyk   148:     HTRequest_clear(me);
2.23      frystyk   149:     return me;
                    150: }
                    151: 
2.1       frystyk   152: /*  Delete a request structure
                    153: **  --------------------------
                    154: */
2.3       frystyk   155: PUBLIC void HTRequest_delete (HTRequest * request)
2.1       frystyk   156: {
                    157:     if (request) {
2.29      frystyk   158:        HT_FREE(request->boundary);
2.11      frystyk   159:        if (request->error_stack) HTError_deleteAll(request->error_stack);
2.31      frystyk   160:        if (request->net) request->net->request = NULL;
2.13      frystyk   161: 
2.31      frystyk   162:        HT_FREE(request->scheme);           /* Current authentication scheme */
                    163:        if (request->challenge) HTAssocList_delete(request->challenge);
                    164:        if (request->credentials) HTAssocList_delete(request->credentials);
2.29      frystyk   165:        HT_FREE(request);
2.1       frystyk   166:     }
                    167: }
                    168: 
                    169: /*
                    170: **     Method
                    171: */
2.3       frystyk   172: PUBLIC void HTRequest_setMethod (HTRequest *request, HTMethod method)
2.1       frystyk   173: {
                    174:     if (request) request->method = method;
                    175: }
                    176: 
2.3       frystyk   177: PUBLIC HTMethod HTRequest_method (HTRequest *request)
2.1       frystyk   178: {
                    179:     return request ? request->method : METHOD_INVALID;
                    180: }
                    181: 
                    182: /*
                    183: **     Reload Mode
                    184: */
2.3       frystyk   185: PUBLIC void HTRequest_setReloadMode (HTRequest *request, HTReload mode)
2.1       frystyk   186: {
                    187:     if (request) request->reload = mode;
                    188: }
                    189: 
2.3       frystyk   190: PUBLIC HTReload HTRequest_reloadMode (HTRequest *request)
2.1       frystyk   191: {
                    192:     return request ? request->reload : HT_ANY_VERSION;
                    193: }
                    194: 
                    195: /*
                    196: **     Accept Format Types
                    197: **     list can be NULL
                    198: */
2.6       frystyk   199: PUBLIC void HTRequest_setConversion (HTRequest *request, HTList *type,
                    200:                                     BOOL override)
2.1       frystyk   201: {
                    202:     if (request) {
                    203:        request->conversions = type;
                    204:        request->conv_local = override;
                    205:     }
                    206: }
                    207: 
2.6       frystyk   208: PUBLIC HTList * HTRequest_conversion (HTRequest *request)
2.1       frystyk   209: {
                    210:     return request ? request->conversions : NULL;
                    211: }
                    212: 
                    213: /*
                    214: **     Accept Encoding 
                    215: **     list can be NULL
                    216: */
2.3       frystyk   217: PUBLIC void HTRequest_setEncoding (HTRequest *request, HTList *enc,
                    218:                                   BOOL override)
2.1       frystyk   219: {
                    220:     if (request) {
                    221:        request->encodings = enc;
                    222:        request->enc_local = override;
                    223:     }
                    224: }
                    225: 
2.3       frystyk   226: PUBLIC HTList * HTRequest_encoding (HTRequest *request)
2.1       frystyk   227: {
                    228:     return request ? request->encodings : NULL;
                    229: }
                    230: 
                    231: /*
                    232: **     Accept Language
                    233: **     list can be NULL
                    234: */
2.3       frystyk   235: PUBLIC void HTRequest_setLanguage (HTRequest *request, HTList *lang,
                    236:                                   BOOL override)
2.1       frystyk   237: {
                    238:     if (request) {
                    239:        request->languages = lang;
                    240:        request->lang_local = override;
                    241:     }
                    242: }
                    243: 
2.3       frystyk   244: PUBLIC HTList * HTRequest_language (HTRequest *request)
2.1       frystyk   245: {
                    246:     return request ? request->languages : NULL;
                    247: }
                    248: 
                    249: /*
                    250: **     Accept Charset
                    251: **     list can be NULL
                    252: */
2.3       frystyk   253: PUBLIC void HTRequest_setCharset (HTRequest *request, HTList *charset,
                    254:                                  BOOL override)
2.1       frystyk   255: {
                    256:     if (request) {
                    257:        request->charsets = charset;
                    258:        request->char_local = override;
                    259:     }
                    260: }
                    261: 
2.3       frystyk   262: PUBLIC HTList * HTRequest_charset (HTRequest *request)
2.1       frystyk   263: {
                    264:     return request ? request->charsets : NULL;
                    265: }
                    266: 
                    267: /*
2.9       frystyk   268: **     Extra Header Generators. list can be NULL
                    269: */
                    270: PUBLIC void HTRequest_setGenerator (HTRequest *request, HTList *generator,
                    271:                                    BOOL override)
                    272: {
                    273:     if (request) {
                    274:        request->generators = generator;
                    275:        request->gens_local = override;
                    276:     }
                    277: }
                    278: 
                    279: PUBLIC HTList * HTRequest_generator (HTRequest *request, BOOL *override)
                    280: {
                    281:     if (request) {
                    282:        *override = request->gens_local;
                    283:        return request->generators;
                    284:     }
                    285:     return NULL;
                    286: }
                    287: 
                    288: /*
                    289: **     Extra Header Parsers. list can be NULL
                    290: */
                    291: PUBLIC void HTRequest_setParser (HTRequest *request, HTList *parser,
                    292:                                 BOOL override)
                    293: {
                    294:     if (request) {
                    295:        request->parsers = parser;
                    296:        request->pars_local = override;
                    297:     }
                    298: }
                    299: 
                    300: PUBLIC HTList * HTRequest_parser (HTRequest *request, BOOL *override)
                    301: {
                    302:     if (request) {
                    303:        *override = request->pars_local;
                    304:        return request->parsers;
                    305:     }
                    306:     return NULL;
                    307: }
                    308: 
                    309: /*
2.1       frystyk   310: **     Set General Headers
                    311: */
2.3       frystyk   312: PUBLIC void HTRequest_setGnHd (HTRequest *request, HTGnHd gnhd)
2.1       frystyk   313: {
                    314:     if (request) request->GenMask = gnhd;
                    315: }
                    316: 
2.3       frystyk   317: PUBLIC void HTRequest_addGnHd (HTRequest *request, HTGnHd gnhd)
2.1       frystyk   318: {
                    319:     if (request) request->GenMask |= gnhd;
                    320: }
                    321: 
2.3       frystyk   322: PUBLIC HTGnHd HTRequest_gnHd (HTRequest *request)
2.1       frystyk   323: {
                    324:     return request ? request->GenMask : 0;
                    325: }
                    326: 
                    327: /*
                    328: **     Set Request Headers
                    329: */
2.3       frystyk   330: PUBLIC void HTRequest_setRqHd (HTRequest *request, HTRqHd rqhd)
2.1       frystyk   331: {
                    332:     if (request) request->RequestMask = rqhd;
                    333: }
                    334: 
2.3       frystyk   335: PUBLIC void HTRequest_addRqHd (HTRequest *request, HTRqHd rqhd)
2.1       frystyk   336: {
                    337:     if (request) request->RequestMask |= rqhd;
                    338: }
                    339: 
2.3       frystyk   340: PUBLIC HTRqHd HTRequest_rqHd (HTRequest *request)
2.1       frystyk   341: {
                    342:     return request ? request->RequestMask : 0;
2.22      frystyk   343: }
                    344: 
                    345: /*
                    346: **     Set Response Headers
                    347: */
                    348: PUBLIC void HTRequest_setRsHd (HTRequest *request, HTRsHd rshd)
                    349: {
                    350:     if (request) request->ResponseMask = rshd;
                    351: }
                    352: 
                    353: PUBLIC void HTRequest_addRsHd (HTRequest *request, HTRsHd rshd)
                    354: {
                    355:     if (request) request->ResponseMask |= rshd;
                    356: }
                    357: 
                    358: PUBLIC HTRsHd HTRequest_rsHd (HTRequest *request)
                    359: {
                    360:     return request ? request->ResponseMask : 0;
2.1       frystyk   361: }
                    362: 
                    363: /*
                    364: **     Set Entity Headers (for the object)
                    365: */
2.3       frystyk   366: PUBLIC void HTRequest_setEnHd (HTRequest *request, HTEnHd enhd)
2.1       frystyk   367: {
                    368:     if (request) request->EntityMask = enhd;
                    369: }
                    370: 
2.3       frystyk   371: PUBLIC void HTRequest_addEnHd (HTRequest *request, HTEnHd enhd)
2.1       frystyk   372: {
                    373:     if (request) request->EntityMask |= enhd;
                    374: }
                    375: 
2.3       frystyk   376: PUBLIC HTEnHd HTRequest_enHd (HTRequest *request)
2.1       frystyk   377: {
                    378:     return request ? request->EntityMask : 0;
                    379: }
                    380: 
2.18      frystyk   381: /*
2.1       frystyk   382: **     Anchor
                    383: */
2.3       frystyk   384: PUBLIC void HTRequest_setAnchor (HTRequest *request, HTAnchor *anchor)
2.1       frystyk   385: {
                    386:     if (request && anchor) {
                    387:        request->anchor = HTAnchor_parent(anchor);
                    388:        request->childAnchor = ((HTAnchor *) request->anchor != anchor) ?
                    389:            (HTChildAnchor *) anchor : NULL;
                    390:     }
                    391: }
                    392: 
2.3       frystyk   393: PUBLIC HTParentAnchor * HTRequest_anchor (HTRequest *request)
2.1       frystyk   394: {
                    395:     return request ? request->anchor : NULL;
                    396: }
                    397: 
                    398: /*
                    399: **     Parent anchor for Referer field
                    400: */
2.3       frystyk   401: PUBLIC void HTRequest_setParent (HTRequest *request, HTParentAnchor *parent)
2.1       frystyk   402: {
                    403:     if (request) request->parentAnchor = parent;
                    404: }
                    405: 
2.3       frystyk   406: PUBLIC HTParentAnchor * HTRequest_parent (HTRequest *request)
2.1       frystyk   407: {
                    408:     return request ? request->parentAnchor : NULL;
                    409: }
                    410: 
                    411: /*
                    412: **     Output stream
                    413: */
2.3       frystyk   414: PUBLIC void HTRequest_setOutputStream (HTRequest *request, HTStream *output)
2.1       frystyk   415: {
                    416:     if (request) request->output_stream = output;
                    417: }
                    418: 
2.4       frystyk   419: PUBLIC HTStream *HTRequest_outputStream (HTRequest *request)
2.1       frystyk   420: {
                    421:     return request ? request->output_stream : NULL;
                    422: }
                    423: 
                    424: /*
                    425: **     Output format
                    426: */
2.3       frystyk   427: PUBLIC void HTRequest_setOutputFormat (HTRequest *request, HTFormat format)
2.1       frystyk   428: {
                    429:     if (request) request->output_format = format;
                    430: }
                    431: 
2.4       frystyk   432: PUBLIC HTFormat HTRequest_outputFormat (HTRequest *request)
2.1       frystyk   433: {
                    434:     return request ? request->output_format : NULL;
                    435: }
                    436: 
                    437: /*
                    438: **     Debug stream
                    439: */
2.3       frystyk   440: PUBLIC void HTRequest_setDebugStream (HTRequest *request, HTStream *debug)
2.1       frystyk   441: {
                    442:     if (request) request->debug_stream = debug;
                    443: }
                    444: 
2.4       frystyk   445: PUBLIC HTStream *HTRequest_debugStream (HTRequest *request)
2.1       frystyk   446: {
                    447:     return request ? request->debug_stream : NULL;
                    448: }
                    449: 
                    450: /*
                    451: **     Debug Format
                    452: */
2.3       frystyk   453: PUBLIC void HTRequest_setDebugFormat (HTRequest *request, HTFormat format)
2.1       frystyk   454: {
                    455:     if (request) request->debug_format = format;
                    456: }
                    457: 
2.4       frystyk   458: PUBLIC HTFormat HTRequest_debugFormat (HTRequest *request)
2.1       frystyk   459: {
                    460:     return request ? request->debug_format : NULL;
                    461: }
                    462: 
                    463: /*
2.34    ! hallam    464: **     Net before and after callbacks. list can be NULL
        !           465: */
        !           466: PUBLIC void HTRequest_setBefore (HTRequest *request, HTList *befores,
        !           467:                                 BOOL override)
        !           468: {
        !           469:     if (request) {
        !           470:        request->befores = befores;
        !           471:        request->befores_local = override;
        !           472:     }
        !           473: }
        !           474: 
        !           475: PUBLIC HTList * HTRequest_before (HTRequest *request, BOOL *override)
        !           476: {
        !           477:     if (request) {
        !           478:        *override = request->befores_local;
        !           479:        return request->befores;
        !           480:     }
        !           481:     return NULL;
        !           482: }
        !           483: 
        !           484: PUBLIC void HTRequest_setAfter (HTRequest *request, HTList *afters,
        !           485:                                BOOL override)
        !           486: {
        !           487:     if (request) {
        !           488:        request->afters = afters;
        !           489:        request->afters_local = override;
        !           490:     }
        !           491: }
        !           492: 
        !           493: PUBLIC HTList * HTRequest_after (HTRequest *request, BOOL *override)
        !           494: {
        !           495:     if (request) {
        !           496:        *override = request->afters_local;
        !           497:        return request->afters;
        !           498:     }
        !           499:     return NULL;
        !           500: }
        !           501: 
        !           502: /*
2.1       frystyk   503: **     Call back function for context swapping
                    504: */
2.3       frystyk   505: PUBLIC void HTRequest_setCallback (HTRequest *request, HTRequestCallback *cbf)
2.1       frystyk   506: {
2.3       frystyk   507:     if (request) request->callback = cbf;
2.1       frystyk   508: }
                    509: 
2.3       frystyk   510: PUBLIC HTRequestCallback *HTRequest_callback (HTRequest *request)
2.1       frystyk   511: {
                    512:     return request ? request->callback : NULL;
                    513: }
                    514: 
                    515: /*
2.24      frystyk   516: **     Call back function for proxying
                    517: */
                    518: PUBLIC void HTRequest_setProxying (HTRequest * request, BOOL proxying)
                    519: {
                    520:     if (request) request->using_proxy = proxying;
                    521: }
                    522: 
                    523: PUBLIC BOOL HTRequest_proxying (HTRequest * request)
                    524: {
                    525:     return request ? request->using_proxy : NO;
                    526: }
                    527: 
                    528: /*
2.1       frystyk   529: **     Context pointer to be used in context call back function
                    530: */
2.3       frystyk   531: PUBLIC void HTRequest_setContext (HTRequest *request, void *context)
2.1       frystyk   532: {
                    533:     if (request) request->context = context;
                    534: }
                    535: 
2.3       frystyk   536: PUBLIC void *HTRequest_context (HTRequest *request)
2.1       frystyk   537: {
                    538:     return request ? request->context : NULL;
                    539: }
                    540: 
                    541: /*
2.23      frystyk   542: **     Socket mode: preemptive or non-preemptive (blocking or non-blocking)
2.1       frystyk   543: */
2.23      frystyk   544: PUBLIC void HTRequest_setPreemptive (HTRequest *request, BOOL mode)
2.1       frystyk   545: {
2.23      frystyk   546:     if (request) request->preemptive = mode;
2.1       frystyk   547: }
                    548: 
2.23      frystyk   549: PUBLIC BOOL HTRequest_preemptive (HTRequest *request)
2.1       frystyk   550: {
2.23      frystyk   551:     return request ? request->preemptive : NO;
2.1       frystyk   552: }
                    553: 
                    554: /*
                    555: **     Should we use content negotiation?
                    556: */
2.3       frystyk   557: PUBLIC void HTRequest_setNegotiation (HTRequest *request, BOOL mode)
2.1       frystyk   558: {
                    559:     if (request) request->ContentNegotiation = mode;
                    560: }
                    561: 
2.3       frystyk   562: PUBLIC BOOL HTRequest_negotiation (HTRequest *request)
2.1       frystyk   563: {
                    564:     return request ? request->ContentNegotiation : NO;
                    565: }
                    566: 
                    567: /*
                    568: **     Bytes read in this request
                    569: */
2.3       frystyk   570: PUBLIC long HTRequest_bytesRead(HTRequest * request)
2.1       frystyk   571: {
                    572:     return request ? HTNet_bytesRead(request->net) : -1;
                    573: }
                    574: 
                    575: /*
2.23      frystyk   576: **     Bytes written in this request
                    577: */
                    578: PUBLIC long HTRequest_bytesWritten (HTRequest * request)
                    579: {
                    580:     return request ? HTNet_bytesWritten(request->net) : -1;
                    581: }
                    582: 
                    583: /*
2.1       frystyk   584: **     Kill this request
                    585: */
2.3       frystyk   586: PUBLIC BOOL HTRequest_kill(HTRequest * request)
2.1       frystyk   587: {
                    588:     return request ? HTNet_kill(request->net) : NO;
                    589: }
                    590: 
2.11      frystyk   591: /*     Error Management
                    592: **     ----------------
2.1       frystyk   593: **     Returns the error stack if a stream is 
                    594: */
2.11      frystyk   595: PUBLIC HTList * HTRequest_error (HTRequest * request)
2.1       frystyk   596: {
                    597:     return request ? request->error_stack : NULL;
                    598: }
                    599: 
2.11      frystyk   600: PUBLIC void HTRequest_setError (HTRequest * request, HTList * list)
                    601: {
                    602:     if (request) request->error_stack = list;
                    603: }
                    604: 
                    605: PUBLIC BOOL HTRequest_addError (HTRequest *    request,
                    606:                                HTSeverity      severity,
                    607:                                BOOL            ignore,
                    608:                                int             element,
                    609:                                void *          par,
                    610:                                unsigned int    length,
                    611:                                char *          where)
                    612: {
                    613:     if (request) {
                    614:        if (!request->error_stack) request->error_stack = HTList_new();
                    615:        return HTError_add(request->error_stack, severity, ignore, element,
                    616:                           par, length, where);
                    617:     }
                    618:     return NO;
                    619: }
                    620: 
                    621: PUBLIC BOOL HTRequest_addSystemError (HTRequest *      request,
                    622:                                      HTSeverity        severity,
                    623:                                      int               errornumber,
                    624:                                      BOOL              ignore,
                    625:                                      char *            syscall)
                    626: {
                    627:     if (request) {
                    628:        if (!request->error_stack) request->error_stack = HTList_new();
                    629:        return HTError_addSystem(request->error_stack, severity, errornumber,
                    630:                                 ignore, syscall);
                    631:     }
                    632:     return NO;
                    633: }
                    634: 
2.1       frystyk   635: /*
                    636: **     When to retry a request if HT_RETRY
                    637: **     Returns -1 if not available
                    638: */
                    639: PUBLIC time_t HTRequest_retryTime (HTRequest * request)
                    640: {
                    641:     return request ? request->retry_after : -1;
                    642: }
                    643: 
                    644: /*
2.23      frystyk   645: **    Redirection informantion
                    646: */
                    647: PUBLIC HTAnchor * HTRequest_redirection (HTRequest * request)
                    648: {
                    649:     return (request ? request->redirectionAnchor : NULL);
                    650: }
                    651: 
                    652: /*
2.1       frystyk   653: **  Set max number of automatic reload. Default is HT_MAX_RELOADS
                    654: */
2.3       frystyk   655: PUBLIC BOOL HTRequest_setMaxRetry (int newmax)
2.1       frystyk   656: {
                    657:     if (newmax > 0) {
                    658:        HTMaxRetry = newmax;
                    659:        return YES;
                    660:     }
                    661:     return NO;
                    662: }
                    663: 
2.3       frystyk   664: PUBLIC int HTRequest_maxRetry (void)
2.1       frystyk   665: {
                    666:     return HTMaxRetry;
                    667: }
                    668: 
                    669: /*
                    670: **     Should we try again?
                    671: **     --------------------
                    672: **     Returns YES if we are to retry the load, NO otherwise. We check
                    673: **     this so that we don't go into an infinte loop
                    674: */
2.3       frystyk   675: PUBLIC BOOL HTRequest_retry (HTRequest *request)
2.1       frystyk   676: {
                    677:     return (request && request->retrys < HTMaxRetry-1);
                    678: }
                    679: 
2.9       frystyk   680: /*
                    681: **  Priority to be inherited by all HTNet object hanging off this request
                    682: **  The priority can later be chaned by calling the HTNet object directly
                    683: */
                    684: PUBLIC BOOL HTRequest_setPriority (HTRequest * request, HTPriority priority)
                    685: {
                    686:     if (request) {
                    687:        request->priority = priority;
                    688:        return YES;
                    689:     }
                    690:     return NO;
                    691: }
                    692: 
                    693: PUBLIC HTPriority HTRequest_priority (HTRequest * request)
                    694: {
2.19      frystyk   695:     return (request ? request->priority : HT_PRIORITY_INV);
2.9       frystyk   696: }
                    697: 
2.18      frystyk   698: /*
2.31      frystyk   699: **  Access Authentication Credentials
                    700: */
                    701: PUBLIC BOOL HTRequest_setCredentials (HTRequest * request, HTAssocList * list)
                    702: {
                    703:     if (request) {
                    704:        request->credentials = list;
                    705:        return YES;
                    706:     }
                    707:     return NO;
                    708: }
                    709: 
                    710: PUBLIC HTAssocList * HTRequest_credentials (HTRequest * request)
                    711: {
                    712:     return (request ? request->credentials : NULL);
                    713: }
                    714: 
                    715: /*
                    716: **  Access Authentication Challenges
                    717: */
                    718: PUBLIC BOOL HTRequest_setChallenge (HTRequest * request, HTAssocList * list)
                    719: {
                    720:     if (request) {
                    721:        request->challenge = list;
                    722:        return YES;
                    723:     }
                    724:     return NO;
                    725: }
                    726: 
                    727: PUBLIC HTAssocList * HTRequest_challenge (HTRequest * request)
                    728: {
                    729:     return (request ? request->challenge : NULL);
                    730: }
                    731: 
                    732: /*
                    733: **  Access Authentication Realms
2.18      frystyk   734: */
2.31      frystyk   735: PUBLIC BOOL HTRequest_setRealm (HTRequest * request, char * realm)
2.18      frystyk   736: {
                    737:     if (request) {
2.31      frystyk   738:        request->realm = realm;
2.18      frystyk   739:        return YES;
                    740:     }
                    741:     return NO;
                    742: }
                    743: 
2.32      frystyk   744: PUBLIC const char * HTRequest_realm (HTRequest * request)
2.18      frystyk   745: {
2.31      frystyk   746:     return (request ? request->realm : NULL);
2.18      frystyk   747: }
                    748: 
2.1       frystyk   749: /* ------------------------------------------------------------------------- */
                    750: /*                             POST WEB METHODS                             */
                    751: /* ------------------------------------------------------------------------- */
                    752: 
                    753: /*
                    754: **  Add a destination request to this source request structure so that we
                    755: **  build the internal request representation of the POST web
                    756: **  Returns YES if OK, else NO
                    757: */
2.23      frystyk   758: PUBLIC BOOL HTRequest_addDestination (HTRequest * src, HTRequest * dest)
2.1       frystyk   759: {
                    760:     if (src && dest) {
2.23      frystyk   761:        dest->source = src->source = src;
2.1       frystyk   762:        if (!src->mainDestination) {
                    763:            src->mainDestination = dest;
                    764:            src->destRequests = 1;
2.23      frystyk   765:            if (WWWTRACE)
2.30      eric      766:                HTTrace("POSTWeb..... Adding dest %p to src %p\n",
2.23      frystyk   767:                         dest, src);
2.1       frystyk   768:            return YES;
                    769:        } else {
2.23      frystyk   770:            if (!src->destinations) src->destinations = HTList_new();
2.1       frystyk   771:            if (HTList_addObject(src->destinations, (void *) dest)==YES) {
                    772:                src->destRequests++;
2.23      frystyk   773:                if (WWWTRACE)
2.30      eric      774:                    HTTrace("POSTWeb..... Adding dest %p to src %p\n",
2.23      frystyk   775:                             dest, src);
2.1       frystyk   776:                return YES;
                    777:            }
                    778:        }
                    779:     }
                    780:     return NO;
                    781: }
                    782: 
                    783: /*
                    784: **  Remove a destination request from this source request structure
2.23      frystyk   785: **  Remember only to delete the internal request objects as the other
                    786: **  comes from the application!
2.1       frystyk   787: **  Returns YES if OK, else NO
                    788: */
2.23      frystyk   789: PUBLIC BOOL HTRequest_removeDestination (HTRequest * dest)
2.1       frystyk   790: {
                    791:     BOOL found=NO;
                    792:     if (dest && dest->source) {
                    793:        HTRequest *src = dest->source;
                    794:        if (src->mainDestination == dest) {
                    795:            dest->source = NULL;
                    796:            src->mainDestination = NULL;
                    797:            src->destRequests--;
                    798:            found = YES;
2.23      frystyk   799:        } else if (src->destinations) {
2.1       frystyk   800:            if (HTList_removeObject(src->destinations, (void *) dest)) {
                    801:                src->destRequests--;
                    802:                found = YES;
                    803:            }
                    804:        }
                    805:        if (found) {
2.23      frystyk   806:            if (dest->internal) HTRequest_delete(dest);
2.5       frystyk   807:            if (WWWTRACE)
2.30      eric      808:                HTTrace("POSTWeb..... Deleting dest %p from src %p\n",
2.23      frystyk   809:                         dest, src);
2.1       frystyk   810:        }
2.23      frystyk   811:        if (src->destRequests <= 0) {
2.5       frystyk   812:            if (WWWTRACE)
2.30      eric      813:                HTTrace("POSTWeb..... terminated\n");
2.23      frystyk   814:            if (src->internal) HTRequest_delete(src);
2.1       frystyk   815:        }
                    816:     }
                    817:     return found;
                    818: }
                    819: 
                    820: /*
2.23      frystyk   821: **  Check to see whether all destinations are ready. If so then enable the
                    822: **  source as ready for reading.
                    823: **  Returns YES if all dests are ready, NO otherwise
                    824: */
                    825: PUBLIC BOOL HTRequest_destinationsReady (HTRequest * me)
                    826: {
                    827:     HTRequest * source = me ? me->source : NULL;
                    828:     if (source) {
                    829:        if (source->destStreams == source->destRequests) {
                    830:            HTNet * net = source->net;
                    831:            if (WWWTRACE)
2.30      eric      832:                HTTrace("POSTWeb..... All destinations are ready!\n");
2.23      frystyk   833:            if (net)                          /* Might already have finished */
                    834:                HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
                    835:                                 net->cbf, net->priority);
                    836:            return YES;
                    837:        }
                    838:     }
                    839:     return NO;
                    840: }
                    841: 
                    842: /*
                    843: **  Find the source request object and make the link between the 
2.1       frystyk   844: **  source output stream and the destination input stream. There can be
                    845: **  a conversion between the two streams!
                    846: **  Returns YES if link is made, NO otherwise
                    847: */
2.3       frystyk   848: PUBLIC BOOL HTRequest_linkDestination (HTRequest *dest)
2.1       frystyk   849: {
                    850:     if (dest && dest->input_stream && dest->source && dest!=dest->source) {
                    851:        HTRequest *source = dest->source;
                    852:        HTStream *pipe = HTStreamStack(source->output_format,
                    853:                                       dest->input_format,
                    854:                                       dest->input_stream,
                    855:                                       dest, YES);
                    856: 
                    857:        /* Check if we are the only one - else spawn off T streams */
                    858:        /* @@@ We don't do this yet @@@ */
                    859: 
2.23      frystyk   860:        /* Now set up output stream of the source */
                    861:        if (source->output_stream)
                    862:            (*source->output_stream->isa->_free)(source->output_stream);
2.1       frystyk   863:        source->output_stream = pipe ? pipe : dest->input_stream;
                    864: 
2.23      frystyk   865:        if (WWWTRACE)
2.30      eric      866:            HTTrace("POSTWeb..... Linking dest %p to src %p\n",
2.23      frystyk   867:                     dest, source);
2.1       frystyk   868:        if (++source->destStreams == source->destRequests) {
                    869:            HTNet *net = source->net;
2.23      frystyk   870:            if (WWWTRACE)
2.30      eric      871:                HTTrace("POSTWeb..... All destinations ready!\n");
2.1       frystyk   872:            if (net)                          /* Might already have finished */
                    873:                HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
                    874:                                 net->cbf, net->priority);
                    875:            return YES;
                    876:        }
                    877:     }
                    878:     return NO;
                    879: }
                    880: 
                    881: /*
                    882: **  Remove a feed stream to a destination request from this source
                    883: **  request structure. When all feeds are removed the request tree is
                    884: **  ready to take down and the operation can be terminated.
                    885: **  Returns YES if removed, else NO
                    886: */
2.3       frystyk   887: PUBLIC BOOL HTRequest_unlinkDestination (HTRequest *dest)
2.1       frystyk   888: {
                    889:     BOOL found = NO;
                    890:     if (dest && dest->source && dest != dest->source) {
                    891:        HTRequest *src = dest->source;
                    892:        if (src->mainDestination == dest) {
                    893:            src->output_stream = NULL;
                    894:            if (dest->input_stream)
                    895:                (*dest->input_stream->isa->_free)(dest->input_stream);
                    896:            found = YES;
                    897:        } else if (src->destinations) {
                    898: 
                    899:            /* LOOK THROUGH THE LIST AND FIND THE RIGHT ONE */
                    900: 
                    901:        }       
                    902:        if (found) {
                    903:            src->destStreams--;
2.23      frystyk   904:            if (WWWTRACE)
2.30      eric      905:                HTTrace("POSTWeb..... Unlinking dest %p from src %p\n",
2.23      frystyk   906:                         dest, src);
2.1       frystyk   907:            return YES;
                    908:        }
                    909:     }
                    910:     return NO;
                    911: }
                    912: 
                    913: /*
                    914: **  Removes all request structures in this PostWeb.
                    915: */
2.3       frystyk   916: PUBLIC BOOL HTRequest_removePostWeb (HTRequest *me)
2.1       frystyk   917: {
                    918:     if (me && me->source) {
                    919:        HTRequest *source = me->source;
                    920: 
                    921:        /* Kill main destination */
                    922:        if (source->mainDestination)
                    923:            HTRequest_removeDestination(source->mainDestination);
                    924: 
                    925:        /* Kill all other destinations */
                    926:        if (source->destinations) {
                    927:            HTList *cur = source->destinations;
                    928:            HTRequest *pres;
                    929:            while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
                    930:                HTRequest_removeDestination(pres);
                    931:        }
                    932: 
                    933:        /* Remove source request */
                    934:        HTRequest_removeDestination(source);
                    935:        return YES;
                    936:     }
                    937:     return NO;
                    938: }
                    939: 
                    940: /*
                    941: **  Kills all threads in a POST WEB connected to this request but
2.23      frystyk   942: **  NOT this request itself. We also keep the request structures.
                    943: **  Some requests might be preemptive, for example a SMTP request (when
2.1       frystyk   944: **  that has been implemented). However, this will be handled internally
                    945: **  in the load function.
                    946: */
2.3       frystyk   947: PUBLIC BOOL HTRequest_killPostWeb (HTRequest *me)
2.1       frystyk   948: {
                    949:     if (me && me->source) {
                    950:        HTRequest *source = me->source;
2.30      eric      951:        if (WWWTRACE) HTTrace("POSTWeb..... Killing\n");
2.1       frystyk   952: 
2.23      frystyk   953:        /*
                    954:        ** Kill source. The stream tree is now freed so we have to build
                    955:        ** that again. This is done in HTRequest_linkDestination()
                    956:        */
                    957:        if (me != source) {
                    958:            HTNet_kill(source->net);
                    959:            source->output_stream = NULL;
                    960:        }
2.1       frystyk   961: 
                    962:        /* Kill all other destinations */
                    963:        if (source->destinations) {
                    964:            HTList *cur = source->destinations;
                    965:            HTRequest *pres;
                    966:            while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
2.23      frystyk   967:                if (me != pres) HTNet_kill(pres->net);
2.1       frystyk   968:        }
2.23      frystyk   969: 
                    970:        /* Kill main destination */
                    971:        if (source->mainDestination && me != source->mainDestination)
                    972:            HTNet_kill(source->mainDestination->net);
2.1       frystyk   973:        return YES;
                    974:     }
                    975:     return NO;
                    976: }
                    977: 
                    978: /* --------------------------------------------------------------------------*/
                    979: /*                     Physical Anchor Address Manager                      */
                    980: /* --------------------------------------------------------------------------*/
2.16      frystyk   981: #if 0
2.1       frystyk   982: /*             Find physical name and access protocol
                    983: **             --------------------------------------
                    984: **
                    985: **     Checks for Cache, proxy, and gateway (in that order)
                    986: **
                    987: ** On exit,    
                    988: **     returns         HT_NO_ACCESS            no protocol module found
                    989: **                     HT_FORBIDDEN            Error has occured.
                    990: **                     HT_OK                   Success
                    991: **
                    992: */
                    993: PRIVATE int get_physical (HTRequest *req)
                    994: {    
                    995:     char * addr = HTAnchor_address((HTAnchor*)req->anchor);    /* free me */
2.14      frystyk   996:     HTList *list = HTRule_global();
                    997:     char * physical = HTRule_translate(list, addr, NO);
                    998:     if (!physical) {
2.29      frystyk   999:        HT_FREE(addr);
2.14      frystyk  1000:        return HT_FORBIDDEN;
2.1       frystyk  1001:     }
2.14      frystyk  1002:     HTAnchor_setPhysical(req->anchor, physical);
2.29      frystyk  1003:     HT_FREE(physical);
2.1       frystyk  1004: 
                   1005:     /*
                   1006:     ** Check local Disk Cache (if we are not forced to reload), then
                   1007:     ** for proxy, and finally gateways
                   1008:     */
                   1009:     {
                   1010:        char *newaddr=NULL;
                   1011:        if (req->reload != HT_FORCE_RELOAD &&
                   1012:            (newaddr = HTCache_getReference(addr))) {
                   1013:            if (req->reload != HT_CACHE_REFRESH) {
                   1014:                HTAnchor_setPhysical(req->anchor, newaddr);
                   1015:                HTAnchor_setCacheHit(req->anchor, YES);
                   1016:            } else {                     /* If refresh version in file cache */
                   1017:                req->RequestMask |= (HT_IMS + HT_NO_CACHE);
                   1018:            }
2.8       frystyk  1019:        } else if ((newaddr = HTProxy_find(addr))) {
2.1       frystyk  1020:            StrAllocCat(newaddr, addr);
                   1021:            req->using_proxy = YES;
                   1022:            HTAnchor_setPhysical(req->anchor, newaddr);
2.8       frystyk  1023:        } else if ((newaddr = HTGateway_find(addr))) {
2.1       frystyk  1024:            char * path = HTParse(addr, "",
                   1025:                                  PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
                   1026:                /* Chop leading / off to make host into part of path */
                   1027:            char * gatewayed = HTParse(path+1, newaddr, PARSE_ALL);
                   1028:             HTAnchor_setPhysical(req->anchor, gatewayed);
2.29      frystyk  1029:            HT_FREE(path);
                   1030:            HT_FREE(gatewayed);
2.1       frystyk  1031:        } else {
                   1032:            req->using_proxy = NO;          /* We don't use proxy or gateway */
                   1033:        }
2.29      frystyk  1034:        HT_FREE(newaddr);
2.1       frystyk  1035:     }
2.29      frystyk  1036:     HT_FREE(addr);
2.1       frystyk  1037: 
                   1038:     /* Set the access scheme on our way out */
2.12      frystyk  1039:     return (HTProtocol_find(req, req->anchor)==YES) ? HT_OK : HT_NO_ACCESS;
2.1       frystyk  1040: }
2.16      frystyk  1041: #endif
2.1       frystyk  1042: 
                   1043: /* --------------------------------------------------------------------------*/
                   1044: /*                             Document Loader                              */
                   1045: /* --------------------------------------------------------------------------*/
                   1046: 
                   1047: /*     Request a resource
                   1048: **     ------------------
                   1049: **     This is an internal routine, which has an address AND a matching
                   1050: **     anchor.  (The public routines are called with one OR the other.)
                   1051: **     Returns:
                   1052: **             YES     if request has been registered (success)
                   1053: **             NO      an error occured
                   1054: */
2.9       frystyk  1055: PUBLIC BOOL HTLoad (HTRequest * request, BOOL recursive)
2.1       frystyk  1056: {
                   1057:     if (!request || !request->anchor) {
2.30      eric     1058:         if (PROT_TRACE) HTTrace("Load Start.. Bad argument\n");
2.1       frystyk  1059:         return NO;
                   1060:     }
2.14      frystyk  1061:     if (request->method == METHOD_INVALID) request->method = METHOD_GET;
2.16      frystyk  1062:     if (!recursive && request->error_stack) {
                   1063:        HTError_deleteAll(request->error_stack);
                   1064:        request->error_stack = NULL;
                   1065:     }
2.18      frystyk  1066:     return HTNet_newClient(request);
2.1       frystyk  1067: }
                   1068: 

Webmaster