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