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

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

Webmaster