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