Annotation of libwww/Library/src/HTReqMan.c, revision 2.34
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 */
2.32 frystyk 31: #include "sysdep.h"
2.1 frystyk 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: {
2.29 frystyk 67: HTRequest * me;
68: if ((me = (HTRequest *) HT_CALLOC(1, sizeof(HTRequest))) == NULL)
69: HT_OUTOFMEM("HTRequest_new()");
2.1 frystyk 70:
2.7 frystyk 71: /* Force Reload */
2.1 frystyk 72: me->reload = HT_ANY_VERSION;
73:
74: /* Format of output */
75: me->output_format = WWW_PRESENT; /* default it to present to user */
2.21 frystyk 76: me->debug_format = WWW_DEBUG; /* default format of error messages */
2.1 frystyk 77:
78: /* HTTP headers */
79: me->GenMask = DEFAULT_GENERAL_HEADERS;
80: me->RequestMask = DEFAULT_REQUEST_HEADERS;
2.22 frystyk 81: me->ResponseMask = DEFAULT_RESPONSE_HEADERS;
2.1 frystyk 82: me->EntityMask = DEFAULT_ENTITY_HEADERS;
83:
84: /* Default retry after value */
85: me->retry_after = -1;
2.19 frystyk 86: me->priority = HT_PRIORITY_MAX;
2.1 frystyk 87:
88: /* Content negotiation */
89: me->ContentNegotiation = NO; /* Do this by default */
90:
2.13 frystyk 91: #ifdef WWW_WIN_ASYNC
92: HTEvent_winHandle(me);
2.1 frystyk 93: #endif
94: return me;
95: }
96:
2.28 frystyk 97: /* HTRequest_clear
98: ** ---------------
99: ** Clears all protocol specific information so that the request object
100: ** can be used for another request.
101: ** Returns YES if OK, else NO
102: */
103: PUBLIC BOOL HTRequest_clear (HTRequest * me)
104: {
105: if (me) {
106: me->boundary = NULL;
107: me->error_stack = NULL;
108: me->net = NULL;
2.31 frystyk 109: me->scheme = NULL;
110: me->realm = NULL;
111: me->challenge = NULL;
112: me->credentials = NULL;
2.28 frystyk 113: return YES;
114: }
115: return NO;
116: }
117:
2.18 frystyk 118: /* HTRequest_dup
119: ** -------------
120: ** Creates a new HTRequest object as a duplicate of the src request.
121: ** Returns YES if OK, else NO
122: */
123: PUBLIC HTRequest * HTRequest_dup (HTRequest * src)
124: {
125: HTRequest * me;
2.33 eric 126: if (!src) return 0;
2.29 frystyk 127: if ((me = (HTRequest *) HT_MALLOC(sizeof(HTRequest))) == NULL)
128: HT_OUTOFMEM("HTRequest_dup");
2.18 frystyk 129: memcpy(me, src, sizeof(HTRequest));
130: return me;
131: }
2.1 frystyk 132:
2.23 frystyk 133: /* HTRequest_dupInternal
134: ** ---------------------
135: ** Creates a new HTRequest object as a duplicate of the src request.
136: ** The difference to the HTRequest_dup function is that we don't copy the
137: ** error_stack and other information that the application keeps in its
138: ** copy of the request object. Otherwise it will be freed multiple times
139: ** Returns YES if OK, else NO
140: */
141: PUBLIC HTRequest * HTRequest_dupInternal (HTRequest * src)
142: {
143: HTRequest * me;
2.33 eric 144: if (!src) return 0;
2.29 frystyk 145: if ((me = (HTRequest *) HT_MALLOC(sizeof(HTRequest))) == NULL)
146: HT_OUTOFMEM("HTRequest_dup");
2.23 frystyk 147: memcpy(me, src, sizeof(HTRequest));
2.28 frystyk 148: HTRequest_clear(me);
2.23 frystyk 149: return me;
150: }
151:
2.1 frystyk 152: /* Delete a request structure
153: ** --------------------------
154: */
2.3 frystyk 155: PUBLIC void HTRequest_delete (HTRequest * request)
2.1 frystyk 156: {
157: if (request) {
2.29 frystyk 158: HT_FREE(request->boundary);
2.11 frystyk 159: if (request->error_stack) HTError_deleteAll(request->error_stack);
2.31 frystyk 160: if (request->net) request->net->request = NULL;
2.13 frystyk 161:
2.31 frystyk 162: HT_FREE(request->scheme); /* Current authentication scheme */
163: if (request->challenge) HTAssocList_delete(request->challenge);
164: if (request->credentials) HTAssocList_delete(request->credentials);
2.29 frystyk 165: HT_FREE(request);
2.1 frystyk 166: }
167: }
168:
169: /*
170: ** Method
171: */
2.3 frystyk 172: PUBLIC void HTRequest_setMethod (HTRequest *request, HTMethod method)
2.1 frystyk 173: {
174: if (request) request->method = method;
175: }
176:
2.3 frystyk 177: PUBLIC HTMethod HTRequest_method (HTRequest *request)
2.1 frystyk 178: {
179: return request ? request->method : METHOD_INVALID;
180: }
181:
182: /*
183: ** Reload Mode
184: */
2.3 frystyk 185: PUBLIC void HTRequest_setReloadMode (HTRequest *request, HTReload mode)
2.1 frystyk 186: {
187: if (request) request->reload = mode;
188: }
189:
2.3 frystyk 190: PUBLIC HTReload HTRequest_reloadMode (HTRequest *request)
2.1 frystyk 191: {
192: return request ? request->reload : HT_ANY_VERSION;
193: }
194:
195: /*
196: ** Accept Format Types
197: ** list can be NULL
198: */
2.6 frystyk 199: PUBLIC void HTRequest_setConversion (HTRequest *request, HTList *type,
200: BOOL override)
2.1 frystyk 201: {
202: if (request) {
203: request->conversions = type;
204: request->conv_local = override;
205: }
206: }
207:
2.6 frystyk 208: PUBLIC HTList * HTRequest_conversion (HTRequest *request)
2.1 frystyk 209: {
210: return request ? request->conversions : NULL;
211: }
212:
213: /*
214: ** Accept Encoding
215: ** list can be NULL
216: */
2.3 frystyk 217: PUBLIC void HTRequest_setEncoding (HTRequest *request, HTList *enc,
218: BOOL override)
2.1 frystyk 219: {
220: if (request) {
221: request->encodings = enc;
222: request->enc_local = override;
223: }
224: }
225:
2.3 frystyk 226: PUBLIC HTList * HTRequest_encoding (HTRequest *request)
2.1 frystyk 227: {
228: return request ? request->encodings : NULL;
229: }
230:
231: /*
232: ** Accept Language
233: ** list can be NULL
234: */
2.3 frystyk 235: PUBLIC void HTRequest_setLanguage (HTRequest *request, HTList *lang,
236: BOOL override)
2.1 frystyk 237: {
238: if (request) {
239: request->languages = lang;
240: request->lang_local = override;
241: }
242: }
243:
2.3 frystyk 244: PUBLIC HTList * HTRequest_language (HTRequest *request)
2.1 frystyk 245: {
246: return request ? request->languages : NULL;
247: }
248:
249: /*
250: ** Accept Charset
251: ** list can be NULL
252: */
2.3 frystyk 253: PUBLIC void HTRequest_setCharset (HTRequest *request, HTList *charset,
254: BOOL override)
2.1 frystyk 255: {
256: if (request) {
257: request->charsets = charset;
258: request->char_local = override;
259: }
260: }
261:
2.3 frystyk 262: PUBLIC HTList * HTRequest_charset (HTRequest *request)
2.1 frystyk 263: {
264: return request ? request->charsets : NULL;
265: }
266:
267: /*
2.9 frystyk 268: ** Extra Header Generators. list can be NULL
269: */
270: PUBLIC void HTRequest_setGenerator (HTRequest *request, HTList *generator,
271: BOOL override)
272: {
273: if (request) {
274: request->generators = generator;
275: request->gens_local = override;
276: }
277: }
278:
279: PUBLIC HTList * HTRequest_generator (HTRequest *request, BOOL *override)
280: {
281: if (request) {
282: *override = request->gens_local;
283: return request->generators;
284: }
285: return NULL;
286: }
287:
288: /*
289: ** Extra Header Parsers. list can be NULL
290: */
291: PUBLIC void HTRequest_setParser (HTRequest *request, HTList *parser,
292: BOOL override)
293: {
294: if (request) {
295: request->parsers = parser;
296: request->pars_local = override;
297: }
298: }
299:
300: PUBLIC HTList * HTRequest_parser (HTRequest *request, BOOL *override)
301: {
302: if (request) {
303: *override = request->pars_local;
304: return request->parsers;
305: }
306: return NULL;
307: }
308:
309: /*
2.1 frystyk 310: ** Set General Headers
311: */
2.3 frystyk 312: PUBLIC void HTRequest_setGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 313: {
314: if (request) request->GenMask = gnhd;
315: }
316:
2.3 frystyk 317: PUBLIC void HTRequest_addGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 318: {
319: if (request) request->GenMask |= gnhd;
320: }
321:
2.3 frystyk 322: PUBLIC HTGnHd HTRequest_gnHd (HTRequest *request)
2.1 frystyk 323: {
324: return request ? request->GenMask : 0;
325: }
326:
327: /*
328: ** Set Request Headers
329: */
2.3 frystyk 330: PUBLIC void HTRequest_setRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 331: {
332: if (request) request->RequestMask = rqhd;
333: }
334:
2.3 frystyk 335: PUBLIC void HTRequest_addRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 336: {
337: if (request) request->RequestMask |= rqhd;
338: }
339:
2.3 frystyk 340: PUBLIC HTRqHd HTRequest_rqHd (HTRequest *request)
2.1 frystyk 341: {
342: return request ? request->RequestMask : 0;
2.22 frystyk 343: }
344:
345: /*
346: ** Set Response Headers
347: */
348: PUBLIC void HTRequest_setRsHd (HTRequest *request, HTRsHd rshd)
349: {
350: if (request) request->ResponseMask = rshd;
351: }
352:
353: PUBLIC void HTRequest_addRsHd (HTRequest *request, HTRsHd rshd)
354: {
355: if (request) request->ResponseMask |= rshd;
356: }
357:
358: PUBLIC HTRsHd HTRequest_rsHd (HTRequest *request)
359: {
360: return request ? request->ResponseMask : 0;
2.1 frystyk 361: }
362:
363: /*
364: ** Set Entity Headers (for the object)
365: */
2.3 frystyk 366: PUBLIC void HTRequest_setEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 367: {
368: if (request) request->EntityMask = enhd;
369: }
370:
2.3 frystyk 371: PUBLIC void HTRequest_addEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 372: {
373: if (request) request->EntityMask |= enhd;
374: }
375:
2.3 frystyk 376: PUBLIC HTEnHd HTRequest_enHd (HTRequest *request)
2.1 frystyk 377: {
378: return request ? request->EntityMask : 0;
379: }
380:
2.18 frystyk 381: /*
2.1 frystyk 382: ** Anchor
383: */
2.3 frystyk 384: PUBLIC void HTRequest_setAnchor (HTRequest *request, HTAnchor *anchor)
2.1 frystyk 385: {
386: if (request && anchor) {
387: request->anchor = HTAnchor_parent(anchor);
388: request->childAnchor = ((HTAnchor *) request->anchor != anchor) ?
389: (HTChildAnchor *) anchor : NULL;
390: }
391: }
392:
2.3 frystyk 393: PUBLIC HTParentAnchor * HTRequest_anchor (HTRequest *request)
2.1 frystyk 394: {
395: return request ? request->anchor : NULL;
396: }
397:
398: /*
399: ** Parent anchor for Referer field
400: */
2.3 frystyk 401: PUBLIC void HTRequest_setParent (HTRequest *request, HTParentAnchor *parent)
2.1 frystyk 402: {
403: if (request) request->parentAnchor = parent;
404: }
405:
2.3 frystyk 406: PUBLIC HTParentAnchor * HTRequest_parent (HTRequest *request)
2.1 frystyk 407: {
408: return request ? request->parentAnchor : NULL;
409: }
410:
411: /*
412: ** Output stream
413: */
2.3 frystyk 414: PUBLIC void HTRequest_setOutputStream (HTRequest *request, HTStream *output)
2.1 frystyk 415: {
416: if (request) request->output_stream = output;
417: }
418:
2.4 frystyk 419: PUBLIC HTStream *HTRequest_outputStream (HTRequest *request)
2.1 frystyk 420: {
421: return request ? request->output_stream : NULL;
422: }
423:
424: /*
425: ** Output format
426: */
2.3 frystyk 427: PUBLIC void HTRequest_setOutputFormat (HTRequest *request, HTFormat format)
2.1 frystyk 428: {
429: if (request) request->output_format = format;
430: }
431:
2.4 frystyk 432: PUBLIC HTFormat HTRequest_outputFormat (HTRequest *request)
2.1 frystyk 433: {
434: return request ? request->output_format : NULL;
435: }
436:
437: /*
438: ** Debug stream
439: */
2.3 frystyk 440: PUBLIC void HTRequest_setDebugStream (HTRequest *request, HTStream *debug)
2.1 frystyk 441: {
442: if (request) request->debug_stream = debug;
443: }
444:
2.4 frystyk 445: PUBLIC HTStream *HTRequest_debugStream (HTRequest *request)
2.1 frystyk 446: {
447: return request ? request->debug_stream : NULL;
448: }
449:
450: /*
451: ** Debug Format
452: */
2.3 frystyk 453: PUBLIC void HTRequest_setDebugFormat (HTRequest *request, HTFormat format)
2.1 frystyk 454: {
455: if (request) request->debug_format = format;
456: }
457:
2.4 frystyk 458: PUBLIC HTFormat HTRequest_debugFormat (HTRequest *request)
2.1 frystyk 459: {
460: return request ? request->debug_format : NULL;
461: }
462:
463: /*
2.34 ! hallam 464: ** Net before and after callbacks. list can be NULL
! 465: */
! 466: PUBLIC void HTRequest_setBefore (HTRequest *request, HTList *befores,
! 467: BOOL override)
! 468: {
! 469: if (request) {
! 470: request->befores = befores;
! 471: request->befores_local = override;
! 472: }
! 473: }
! 474:
! 475: PUBLIC HTList * HTRequest_before (HTRequest *request, BOOL *override)
! 476: {
! 477: if (request) {
! 478: *override = request->befores_local;
! 479: return request->befores;
! 480: }
! 481: return NULL;
! 482: }
! 483:
! 484: PUBLIC void HTRequest_setAfter (HTRequest *request, HTList *afters,
! 485: BOOL override)
! 486: {
! 487: if (request) {
! 488: request->afters = afters;
! 489: request->afters_local = override;
! 490: }
! 491: }
! 492:
! 493: PUBLIC HTList * HTRequest_after (HTRequest *request, BOOL *override)
! 494: {
! 495: if (request) {
! 496: *override = request->afters_local;
! 497: return request->afters;
! 498: }
! 499: return NULL;
! 500: }
! 501:
! 502: /*
2.1 frystyk 503: ** Call back function for context swapping
504: */
2.3 frystyk 505: PUBLIC void HTRequest_setCallback (HTRequest *request, HTRequestCallback *cbf)
2.1 frystyk 506: {
2.3 frystyk 507: if (request) request->callback = cbf;
2.1 frystyk 508: }
509:
2.3 frystyk 510: PUBLIC HTRequestCallback *HTRequest_callback (HTRequest *request)
2.1 frystyk 511: {
512: return request ? request->callback : NULL;
513: }
514:
515: /*
2.24 frystyk 516: ** Call back function for proxying
517: */
518: PUBLIC void HTRequest_setProxying (HTRequest * request, BOOL proxying)
519: {
520: if (request) request->using_proxy = proxying;
521: }
522:
523: PUBLIC BOOL HTRequest_proxying (HTRequest * request)
524: {
525: return request ? request->using_proxy : NO;
526: }
527:
528: /*
2.1 frystyk 529: ** Context pointer to be used in context call back function
530: */
2.3 frystyk 531: PUBLIC void HTRequest_setContext (HTRequest *request, void *context)
2.1 frystyk 532: {
533: if (request) request->context = context;
534: }
535:
2.3 frystyk 536: PUBLIC void *HTRequest_context (HTRequest *request)
2.1 frystyk 537: {
538: return request ? request->context : NULL;
539: }
540:
541: /*
2.23 frystyk 542: ** Socket mode: preemptive or non-preemptive (blocking or non-blocking)
2.1 frystyk 543: */
2.23 frystyk 544: PUBLIC void HTRequest_setPreemptive (HTRequest *request, BOOL mode)
2.1 frystyk 545: {
2.23 frystyk 546: if (request) request->preemptive = mode;
2.1 frystyk 547: }
548:
2.23 frystyk 549: PUBLIC BOOL HTRequest_preemptive (HTRequest *request)
2.1 frystyk 550: {
2.23 frystyk 551: return request ? request->preemptive : NO;
2.1 frystyk 552: }
553:
554: /*
555: ** Should we use content negotiation?
556: */
2.3 frystyk 557: PUBLIC void HTRequest_setNegotiation (HTRequest *request, BOOL mode)
2.1 frystyk 558: {
559: if (request) request->ContentNegotiation = mode;
560: }
561:
2.3 frystyk 562: PUBLIC BOOL HTRequest_negotiation (HTRequest *request)
2.1 frystyk 563: {
564: return request ? request->ContentNegotiation : NO;
565: }
566:
567: /*
568: ** Bytes read in this request
569: */
2.3 frystyk 570: PUBLIC long HTRequest_bytesRead(HTRequest * request)
2.1 frystyk 571: {
572: return request ? HTNet_bytesRead(request->net) : -1;
573: }
574:
575: /*
2.23 frystyk 576: ** Bytes written in this request
577: */
578: PUBLIC long HTRequest_bytesWritten (HTRequest * request)
579: {
580: return request ? HTNet_bytesWritten(request->net) : -1;
581: }
582:
583: /*
2.1 frystyk 584: ** Kill this request
585: */
2.3 frystyk 586: PUBLIC BOOL HTRequest_kill(HTRequest * request)
2.1 frystyk 587: {
588: return request ? HTNet_kill(request->net) : NO;
589: }
590:
2.11 frystyk 591: /* Error Management
592: ** ----------------
2.1 frystyk 593: ** Returns the error stack if a stream is
594: */
2.11 frystyk 595: PUBLIC HTList * HTRequest_error (HTRequest * request)
2.1 frystyk 596: {
597: return request ? request->error_stack : NULL;
598: }
599:
2.11 frystyk 600: PUBLIC void HTRequest_setError (HTRequest * request, HTList * list)
601: {
602: if (request) request->error_stack = list;
603: }
604:
605: PUBLIC BOOL HTRequest_addError (HTRequest * request,
606: HTSeverity severity,
607: BOOL ignore,
608: int element,
609: void * par,
610: unsigned int length,
611: char * where)
612: {
613: if (request) {
614: if (!request->error_stack) request->error_stack = HTList_new();
615: return HTError_add(request->error_stack, severity, ignore, element,
616: par, length, where);
617: }
618: return NO;
619: }
620:
621: PUBLIC BOOL HTRequest_addSystemError (HTRequest * request,
622: HTSeverity severity,
623: int errornumber,
624: BOOL ignore,
625: char * syscall)
626: {
627: if (request) {
628: if (!request->error_stack) request->error_stack = HTList_new();
629: return HTError_addSystem(request->error_stack, severity, errornumber,
630: ignore, syscall);
631: }
632: return NO;
633: }
634:
2.1 frystyk 635: /*
636: ** When to retry a request if HT_RETRY
637: ** Returns -1 if not available
638: */
639: PUBLIC time_t HTRequest_retryTime (HTRequest * request)
640: {
641: return request ? request->retry_after : -1;
642: }
643:
644: /*
2.23 frystyk 645: ** Redirection informantion
646: */
647: PUBLIC HTAnchor * HTRequest_redirection (HTRequest * request)
648: {
649: return (request ? request->redirectionAnchor : NULL);
650: }
651:
652: /*
2.1 frystyk 653: ** Set max number of automatic reload. Default is HT_MAX_RELOADS
654: */
2.3 frystyk 655: PUBLIC BOOL HTRequest_setMaxRetry (int newmax)
2.1 frystyk 656: {
657: if (newmax > 0) {
658: HTMaxRetry = newmax;
659: return YES;
660: }
661: return NO;
662: }
663:
2.3 frystyk 664: PUBLIC int HTRequest_maxRetry (void)
2.1 frystyk 665: {
666: return HTMaxRetry;
667: }
668:
669: /*
670: ** Should we try again?
671: ** --------------------
672: ** Returns YES if we are to retry the load, NO otherwise. We check
673: ** this so that we don't go into an infinte loop
674: */
2.3 frystyk 675: PUBLIC BOOL HTRequest_retry (HTRequest *request)
2.1 frystyk 676: {
677: return (request && request->retrys < HTMaxRetry-1);
678: }
679:
2.9 frystyk 680: /*
681: ** Priority to be inherited by all HTNet object hanging off this request
682: ** The priority can later be chaned by calling the HTNet object directly
683: */
684: PUBLIC BOOL HTRequest_setPriority (HTRequest * request, HTPriority priority)
685: {
686: if (request) {
687: request->priority = priority;
688: return YES;
689: }
690: return NO;
691: }
692:
693: PUBLIC HTPriority HTRequest_priority (HTRequest * request)
694: {
2.19 frystyk 695: return (request ? request->priority : HT_PRIORITY_INV);
2.9 frystyk 696: }
697:
2.18 frystyk 698: /*
2.31 frystyk 699: ** Access Authentication Credentials
700: */
701: PUBLIC BOOL HTRequest_setCredentials (HTRequest * request, HTAssocList * list)
702: {
703: if (request) {
704: request->credentials = list;
705: return YES;
706: }
707: return NO;
708: }
709:
710: PUBLIC HTAssocList * HTRequest_credentials (HTRequest * request)
711: {
712: return (request ? request->credentials : NULL);
713: }
714:
715: /*
716: ** Access Authentication Challenges
717: */
718: PUBLIC BOOL HTRequest_setChallenge (HTRequest * request, HTAssocList * list)
719: {
720: if (request) {
721: request->challenge = list;
722: return YES;
723: }
724: return NO;
725: }
726:
727: PUBLIC HTAssocList * HTRequest_challenge (HTRequest * request)
728: {
729: return (request ? request->challenge : NULL);
730: }
731:
732: /*
733: ** Access Authentication Realms
2.18 frystyk 734: */
2.31 frystyk 735: PUBLIC BOOL HTRequest_setRealm (HTRequest * request, char * realm)
2.18 frystyk 736: {
737: if (request) {
2.31 frystyk 738: request->realm = realm;
2.18 frystyk 739: return YES;
740: }
741: return NO;
742: }
743:
2.32 frystyk 744: PUBLIC const char * HTRequest_realm (HTRequest * request)
2.18 frystyk 745: {
2.31 frystyk 746: return (request ? request->realm : NULL);
2.18 frystyk 747: }
748:
2.1 frystyk 749: /* ------------------------------------------------------------------------- */
750: /* POST WEB METHODS */
751: /* ------------------------------------------------------------------------- */
752:
753: /*
754: ** Add a destination request to this source request structure so that we
755: ** build the internal request representation of the POST web
756: ** Returns YES if OK, else NO
757: */
2.23 frystyk 758: PUBLIC BOOL HTRequest_addDestination (HTRequest * src, HTRequest * dest)
2.1 frystyk 759: {
760: if (src && dest) {
2.23 frystyk 761: dest->source = src->source = src;
2.1 frystyk 762: if (!src->mainDestination) {
763: src->mainDestination = dest;
764: src->destRequests = 1;
2.23 frystyk 765: if (WWWTRACE)
2.30 eric 766: HTTrace("POSTWeb..... Adding dest %p to src %p\n",
2.23 frystyk 767: dest, src);
2.1 frystyk 768: return YES;
769: } else {
2.23 frystyk 770: if (!src->destinations) src->destinations = HTList_new();
2.1 frystyk 771: if (HTList_addObject(src->destinations, (void *) dest)==YES) {
772: src->destRequests++;
2.23 frystyk 773: if (WWWTRACE)
2.30 eric 774: HTTrace("POSTWeb..... Adding dest %p to src %p\n",
2.23 frystyk 775: dest, src);
2.1 frystyk 776: return YES;
777: }
778: }
779: }
780: return NO;
781: }
782:
783: /*
784: ** Remove a destination request from this source request structure
2.23 frystyk 785: ** Remember only to delete the internal request objects as the other
786: ** comes from the application!
2.1 frystyk 787: ** Returns YES if OK, else NO
788: */
2.23 frystyk 789: PUBLIC BOOL HTRequest_removeDestination (HTRequest * dest)
2.1 frystyk 790: {
791: BOOL found=NO;
792: if (dest && dest->source) {
793: HTRequest *src = dest->source;
794: if (src->mainDestination == dest) {
795: dest->source = NULL;
796: src->mainDestination = NULL;
797: src->destRequests--;
798: found = YES;
2.23 frystyk 799: } else if (src->destinations) {
2.1 frystyk 800: if (HTList_removeObject(src->destinations, (void *) dest)) {
801: src->destRequests--;
802: found = YES;
803: }
804: }
805: if (found) {
2.23 frystyk 806: if (dest->internal) HTRequest_delete(dest);
2.5 frystyk 807: if (WWWTRACE)
2.30 eric 808: HTTrace("POSTWeb..... Deleting dest %p from src %p\n",
2.23 frystyk 809: dest, src);
2.1 frystyk 810: }
2.23 frystyk 811: if (src->destRequests <= 0) {
2.5 frystyk 812: if (WWWTRACE)
2.30 eric 813: HTTrace("POSTWeb..... terminated\n");
2.23 frystyk 814: if (src->internal) HTRequest_delete(src);
2.1 frystyk 815: }
816: }
817: return found;
818: }
819:
820: /*
2.23 frystyk 821: ** Check to see whether all destinations are ready. If so then enable the
822: ** source as ready for reading.
823: ** Returns YES if all dests are ready, NO otherwise
824: */
825: PUBLIC BOOL HTRequest_destinationsReady (HTRequest * me)
826: {
827: HTRequest * source = me ? me->source : NULL;
828: if (source) {
829: if (source->destStreams == source->destRequests) {
830: HTNet * net = source->net;
831: if (WWWTRACE)
2.30 eric 832: HTTrace("POSTWeb..... All destinations are ready!\n");
2.23 frystyk 833: if (net) /* Might already have finished */
834: HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
835: net->cbf, net->priority);
836: return YES;
837: }
838: }
839: return NO;
840: }
841:
842: /*
843: ** Find the source request object and make the link between the
2.1 frystyk 844: ** source output stream and the destination input stream. There can be
845: ** a conversion between the two streams!
846: ** Returns YES if link is made, NO otherwise
847: */
2.3 frystyk 848: PUBLIC BOOL HTRequest_linkDestination (HTRequest *dest)
2.1 frystyk 849: {
850: if (dest && dest->input_stream && dest->source && dest!=dest->source) {
851: HTRequest *source = dest->source;
852: HTStream *pipe = HTStreamStack(source->output_format,
853: dest->input_format,
854: dest->input_stream,
855: dest, YES);
856:
857: /* Check if we are the only one - else spawn off T streams */
858: /* @@@ We don't do this yet @@@ */
859:
2.23 frystyk 860: /* Now set up output stream of the source */
861: if (source->output_stream)
862: (*source->output_stream->isa->_free)(source->output_stream);
2.1 frystyk 863: source->output_stream = pipe ? pipe : dest->input_stream;
864:
2.23 frystyk 865: if (WWWTRACE)
2.30 eric 866: HTTrace("POSTWeb..... Linking dest %p to src %p\n",
2.23 frystyk 867: dest, source);
2.1 frystyk 868: if (++source->destStreams == source->destRequests) {
869: HTNet *net = source->net;
2.23 frystyk 870: if (WWWTRACE)
2.30 eric 871: HTTrace("POSTWeb..... All destinations ready!\n");
2.1 frystyk 872: if (net) /* Might already have finished */
873: HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
874: net->cbf, net->priority);
875: return YES;
876: }
877: }
878: return NO;
879: }
880:
881: /*
882: ** Remove a feed stream to a destination request from this source
883: ** request structure. When all feeds are removed the request tree is
884: ** ready to take down and the operation can be terminated.
885: ** Returns YES if removed, else NO
886: */
2.3 frystyk 887: PUBLIC BOOL HTRequest_unlinkDestination (HTRequest *dest)
2.1 frystyk 888: {
889: BOOL found = NO;
890: if (dest && dest->source && dest != dest->source) {
891: HTRequest *src = dest->source;
892: if (src->mainDestination == dest) {
893: src->output_stream = NULL;
894: if (dest->input_stream)
895: (*dest->input_stream->isa->_free)(dest->input_stream);
896: found = YES;
897: } else if (src->destinations) {
898:
899: /* LOOK THROUGH THE LIST AND FIND THE RIGHT ONE */
900:
901: }
902: if (found) {
903: src->destStreams--;
2.23 frystyk 904: if (WWWTRACE)
2.30 eric 905: HTTrace("POSTWeb..... Unlinking dest %p from src %p\n",
2.23 frystyk 906: dest, src);
2.1 frystyk 907: return YES;
908: }
909: }
910: return NO;
911: }
912:
913: /*
914: ** Removes all request structures in this PostWeb.
915: */
2.3 frystyk 916: PUBLIC BOOL HTRequest_removePostWeb (HTRequest *me)
2.1 frystyk 917: {
918: if (me && me->source) {
919: HTRequest *source = me->source;
920:
921: /* Kill main destination */
922: if (source->mainDestination)
923: HTRequest_removeDestination(source->mainDestination);
924:
925: /* Kill all other destinations */
926: if (source->destinations) {
927: HTList *cur = source->destinations;
928: HTRequest *pres;
929: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
930: HTRequest_removeDestination(pres);
931: }
932:
933: /* Remove source request */
934: HTRequest_removeDestination(source);
935: return YES;
936: }
937: return NO;
938: }
939:
940: /*
941: ** Kills all threads in a POST WEB connected to this request but
2.23 frystyk 942: ** NOT this request itself. We also keep the request structures.
943: ** Some requests might be preemptive, for example a SMTP request (when
2.1 frystyk 944: ** that has been implemented). However, this will be handled internally
945: ** in the load function.
946: */
2.3 frystyk 947: PUBLIC BOOL HTRequest_killPostWeb (HTRequest *me)
2.1 frystyk 948: {
949: if (me && me->source) {
950: HTRequest *source = me->source;
2.30 eric 951: if (WWWTRACE) HTTrace("POSTWeb..... Killing\n");
2.1 frystyk 952:
2.23 frystyk 953: /*
954: ** Kill source. The stream tree is now freed so we have to build
955: ** that again. This is done in HTRequest_linkDestination()
956: */
957: if (me != source) {
958: HTNet_kill(source->net);
959: source->output_stream = NULL;
960: }
2.1 frystyk 961:
962: /* Kill all other destinations */
963: if (source->destinations) {
964: HTList *cur = source->destinations;
965: HTRequest *pres;
966: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
2.23 frystyk 967: if (me != pres) HTNet_kill(pres->net);
2.1 frystyk 968: }
2.23 frystyk 969:
970: /* Kill main destination */
971: if (source->mainDestination && me != source->mainDestination)
972: HTNet_kill(source->mainDestination->net);
2.1 frystyk 973: return YES;
974: }
975: return NO;
976: }
977:
978: /* --------------------------------------------------------------------------*/
979: /* Physical Anchor Address Manager */
980: /* --------------------------------------------------------------------------*/
2.16 frystyk 981: #if 0
2.1 frystyk 982: /* Find physical name and access protocol
983: ** --------------------------------------
984: **
985: ** Checks for Cache, proxy, and gateway (in that order)
986: **
987: ** On exit,
988: ** returns HT_NO_ACCESS no protocol module found
989: ** HT_FORBIDDEN Error has occured.
990: ** HT_OK Success
991: **
992: */
993: PRIVATE int get_physical (HTRequest *req)
994: {
995: char * addr = HTAnchor_address((HTAnchor*)req->anchor); /* free me */
2.14 frystyk 996: HTList *list = HTRule_global();
997: char * physical = HTRule_translate(list, addr, NO);
998: if (!physical) {
2.29 frystyk 999: HT_FREE(addr);
2.14 frystyk 1000: return HT_FORBIDDEN;
2.1 frystyk 1001: }
2.14 frystyk 1002: HTAnchor_setPhysical(req->anchor, physical);
2.29 frystyk 1003: HT_FREE(physical);
2.1 frystyk 1004:
1005: /*
1006: ** Check local Disk Cache (if we are not forced to reload), then
1007: ** for proxy, and finally gateways
1008: */
1009: {
1010: char *newaddr=NULL;
1011: if (req->reload != HT_FORCE_RELOAD &&
1012: (newaddr = HTCache_getReference(addr))) {
1013: if (req->reload != HT_CACHE_REFRESH) {
1014: HTAnchor_setPhysical(req->anchor, newaddr);
1015: HTAnchor_setCacheHit(req->anchor, YES);
1016: } else { /* If refresh version in file cache */
1017: req->RequestMask |= (HT_IMS + HT_NO_CACHE);
1018: }
2.8 frystyk 1019: } else if ((newaddr = HTProxy_find(addr))) {
2.1 frystyk 1020: StrAllocCat(newaddr, addr);
1021: req->using_proxy = YES;
1022: HTAnchor_setPhysical(req->anchor, newaddr);
2.8 frystyk 1023: } else if ((newaddr = HTGateway_find(addr))) {
2.1 frystyk 1024: char * path = HTParse(addr, "",
1025: PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
1026: /* Chop leading / off to make host into part of path */
1027: char * gatewayed = HTParse(path+1, newaddr, PARSE_ALL);
1028: HTAnchor_setPhysical(req->anchor, gatewayed);
2.29 frystyk 1029: HT_FREE(path);
1030: HT_FREE(gatewayed);
2.1 frystyk 1031: } else {
1032: req->using_proxy = NO; /* We don't use proxy or gateway */
1033: }
2.29 frystyk 1034: HT_FREE(newaddr);
2.1 frystyk 1035: }
2.29 frystyk 1036: HT_FREE(addr);
2.1 frystyk 1037:
1038: /* Set the access scheme on our way out */
2.12 frystyk 1039: return (HTProtocol_find(req, req->anchor)==YES) ? HT_OK : HT_NO_ACCESS;
2.1 frystyk 1040: }
2.16 frystyk 1041: #endif
2.1 frystyk 1042:
1043: /* --------------------------------------------------------------------------*/
1044: /* Document Loader */
1045: /* --------------------------------------------------------------------------*/
1046:
1047: /* Request a resource
1048: ** ------------------
1049: ** This is an internal routine, which has an address AND a matching
1050: ** anchor. (The public routines are called with one OR the other.)
1051: ** Returns:
1052: ** YES if request has been registered (success)
1053: ** NO an error occured
1054: */
2.9 frystyk 1055: PUBLIC BOOL HTLoad (HTRequest * request, BOOL recursive)
2.1 frystyk 1056: {
1057: if (!request || !request->anchor) {
2.30 eric 1058: if (PROT_TRACE) HTTrace("Load Start.. Bad argument\n");
2.1 frystyk 1059: return NO;
1060: }
2.14 frystyk 1061: if (request->method == METHOD_INVALID) request->method = METHOD_GET;
2.16 frystyk 1062: if (!recursive && request->error_stack) {
1063: HTError_deleteAll(request->error_stack);
1064: request->error_stack = NULL;
1065: }
2.18 frystyk 1066: return HTNet_newClient(request);
2.1 frystyk 1067: }
1068:
Webmaster