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