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

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

Webmaster