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