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

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

Webmaster