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