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

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

Webmaster