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

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

Webmaster