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

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

Webmaster