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

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

Webmaster