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

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

Webmaster