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

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

Webmaster