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