Annotation of libwww/Library/src/HTReqMan.c, revision 2.55
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.55 ! frystyk 6: ** @(#) $Id: HTReqMan.c,v 2.54 1996/08/09 14:10:55 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"
2.1 frystyk 34: #include "HTParse.h"
35: #include "HTAlert.h"
36: #include "HTError.h"
2.2 frystyk 37: #include "HTNetMan.h"
2.39 frystyk 38: #include "HTEvent.h"
2.1 frystyk 39: #include "HTProt.h"
2.43 eric 40: #include "HTHeader.h"
2.46 frystyk 41: #include "HTLib.h"
2.1 frystyk 42: #include "HTReqMan.h" /* Implemented here */
43:
44: #ifndef HT_MAX_RELOADS
45: #define HT_MAX_RELOADS 6
46: #endif
2.13 frystyk 47:
2.1 frystyk 48: PRIVATE int HTMaxRetry = HT_MAX_RELOADS;
49:
50: struct _HTStream {
51: HTStreamClass * isa;
52: /* ... */
53: };
54:
55: /* --------------------------------------------------------------------------*/
56: /* Management of the HTRequest structure */
57: /* --------------------------------------------------------------------------*/
58:
59: /* Create a request structure
60: ** ---------------------------
61: */
2.3 frystyk 62: PUBLIC HTRequest * HTRequest_new (void)
2.1 frystyk 63: {
2.29 frystyk 64: HTRequest * me;
65: if ((me = (HTRequest *) HT_CALLOC(1, sizeof(HTRequest))) == NULL)
66: HT_OUTOFMEM("HTRequest_new()");
2.1 frystyk 67:
2.7 frystyk 68: /* Force Reload */
2.1 frystyk 69: me->reload = HT_ANY_VERSION;
70:
2.40 frystyk 71: /* Set the default user profile */
72: me->userprofile = HTLib_userProfile();
73:
2.1 frystyk 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:
2.54 frystyk 88: /* Default max forward value */
89: me->max_forwards = -1;
90:
2.1 frystyk 91: /* Content negotiation */
2.45 frystyk 92: me->ContentNegotiation = YES; /* Do this by default */
2.1 frystyk 93:
2.47 frystyk 94: if (CORE_TRACE) HTTrace("Request..... Created %p\n", me);
95:
2.38 eric 96: #if 0 /* WWW_WIN_ASYNC */
2.13 frystyk 97: HTEvent_winHandle(me);
2.1 frystyk 98: #endif
99: return me;
100: }
101:
2.28 frystyk 102: /* HTRequest_clear
103: ** ---------------
104: ** Clears all protocol specific information so that the request object
105: ** can be used for another request.
106: ** Returns YES if OK, else NO
107: */
108: PUBLIC BOOL HTRequest_clear (HTRequest * me)
109: {
110: if (me) {
111: me->error_stack = NULL;
112: me->net = NULL;
2.49 frystyk 113: me->realm = NULL;
2.31 frystyk 114: me->scheme = NULL;
115: me->challenge = NULL;
116: me->credentials = NULL;
2.47 frystyk 117: me->connected = NO;
2.28 frystyk 118: return YES;
119: }
120: return NO;
121: }
122:
2.18 frystyk 123: /* HTRequest_dup
124: ** -------------
125: ** Creates a new HTRequest object as a duplicate of the src request.
126: ** Returns YES if OK, else NO
127: */
128: PUBLIC HTRequest * HTRequest_dup (HTRequest * src)
129: {
130: HTRequest * me;
2.47 frystyk 131: if (!src) return NULL;
2.29 frystyk 132: if ((me = (HTRequest *) HT_MALLOC(sizeof(HTRequest))) == NULL)
133: HT_OUTOFMEM("HTRequest_dup");
2.18 frystyk 134: memcpy(me, src, sizeof(HTRequest));
2.47 frystyk 135: if (CORE_TRACE) HTTrace("Request..... Duplicated %p to %p\n", src, me);
2.18 frystyk 136: return me;
137: }
2.1 frystyk 138:
2.23 frystyk 139: /* HTRequest_dupInternal
140: ** ---------------------
141: ** Creates a new HTRequest object as a duplicate of the src request.
142: ** The difference to the HTRequest_dup function is that we don't copy the
143: ** error_stack and other information that the application keeps in its
144: ** copy of the request object. Otherwise it will be freed multiple times
145: ** Returns YES if OK, else NO
146: */
147: PUBLIC HTRequest * HTRequest_dupInternal (HTRequest * src)
148: {
149: HTRequest * me;
2.33 eric 150: if (!src) return 0;
2.29 frystyk 151: if ((me = (HTRequest *) HT_MALLOC(sizeof(HTRequest))) == NULL)
152: HT_OUTOFMEM("HTRequest_dup");
2.23 frystyk 153: memcpy(me, src, sizeof(HTRequest));
2.28 frystyk 154: HTRequest_clear(me);
2.23 frystyk 155: return me;
156: }
157:
2.1 frystyk 158: /* Delete a request structure
159: ** --------------------------
160: */
2.3 frystyk 161: PUBLIC void HTRequest_delete (HTRequest * request)
2.1 frystyk 162: {
163: if (request) {
2.47 frystyk 164: if (CORE_TRACE) HTTrace("Request..... Delete %p\n", request);
2.48 frystyk 165: if (request->net) HTNet_setRequest(request->net, NULL);
2.47 frystyk 166:
167: /* Should we delete the output stream? */
168: if (!request->connected && request->output_stream) {
169: if (CORE_TRACE)
170: HTTrace("Request..... Deleting dangling output stream\n");
171: (*request->output_stream->isa->_free)(request->output_stream);
172: request->output_stream = NULL;
173: }
174:
175: /* Clean up the error stack */
2.11 frystyk 176: if (request->error_stack) HTError_deleteAll(request->error_stack);
2.13 frystyk 177:
2.51 frystyk 178: /* Before and After Filters */
179: if (request->afters) HTList_delete(request->afters);
180: if (request->befores) HTList_delete(request->befores);
181:
2.49 frystyk 182: /* Access Authentication */
2.31 frystyk 183: if (request->challenge) HTAssocList_delete(request->challenge);
184: if (request->credentials) HTAssocList_delete(request->credentials);
2.49 frystyk 185: HT_FREE(request->realm);
186: HT_FREE(request->scheme);
187:
2.53 frystyk 188: /* Proxy information */
189: HT_FREE(request->proxy);
190:
2.49 frystyk 191: /* PEP Information */
192:
193: /* more */
194:
2.55 ! frystyk 195: /* Simple extension protocol */
! 196: if (request->extension) HTAssocList_delete(request->extension);
! 197:
2.29 frystyk 198: HT_FREE(request);
2.1 frystyk 199: }
200: }
201:
202: /*
203: ** Method
204: */
2.3 frystyk 205: PUBLIC void HTRequest_setMethod (HTRequest *request, HTMethod method)
2.1 frystyk 206: {
207: if (request) request->method = method;
208: }
209:
2.3 frystyk 210: PUBLIC HTMethod HTRequest_method (HTRequest *request)
2.1 frystyk 211: {
212: return request ? request->method : METHOD_INVALID;
213: }
214:
215: /*
216: ** Reload Mode
217: */
2.3 frystyk 218: PUBLIC void HTRequest_setReloadMode (HTRequest *request, HTReload mode)
2.1 frystyk 219: {
220: if (request) request->reload = mode;
221: }
222:
2.3 frystyk 223: PUBLIC HTReload HTRequest_reloadMode (HTRequest *request)
2.1 frystyk 224: {
225: return request ? request->reload : HT_ANY_VERSION;
226: }
227:
228: /*
229: ** Accept Format Types
230: ** list can be NULL
231: */
2.6 frystyk 232: PUBLIC void HTRequest_setConversion (HTRequest *request, HTList *type,
233: BOOL override)
2.1 frystyk 234: {
235: if (request) {
236: request->conversions = type;
237: request->conv_local = override;
238: }
239: }
240:
2.6 frystyk 241: PUBLIC HTList * HTRequest_conversion (HTRequest *request)
2.1 frystyk 242: {
243: return request ? request->conversions : NULL;
244: }
245:
246: /*
247: ** Accept Encoding
248: ** list can be NULL
249: */
2.3 frystyk 250: PUBLIC void HTRequest_setEncoding (HTRequest *request, HTList *enc,
251: BOOL override)
2.1 frystyk 252: {
253: if (request) {
254: request->encodings = enc;
255: request->enc_local = override;
256: }
257: }
258:
2.3 frystyk 259: PUBLIC HTList * HTRequest_encoding (HTRequest *request)
2.1 frystyk 260: {
261: return request ? request->encodings : NULL;
262: }
263:
2.37 frystyk 264: /*
265: ** Accept Transfer Encoding
266: ** list can be NULL
267: */
268: PUBLIC void HTRequest_setTransfer (HTRequest * request,
269: HTList * cte, BOOL override)
270: {
271: if (request) {
272: request->ctes = cte;
273: request->cte_local = override;
274: }
275: }
276:
277: PUBLIC HTList * HTRequest_transfer (HTRequest * request)
278: {
279: return request ? request->ctes : NULL;
280: }
281:
2.1 frystyk 282: /*
283: ** Accept Language
284: ** list can be NULL
285: */
2.3 frystyk 286: PUBLIC void HTRequest_setLanguage (HTRequest *request, HTList *lang,
287: BOOL override)
2.1 frystyk 288: {
289: if (request) {
290: request->languages = lang;
291: request->lang_local = override;
292: }
293: }
294:
2.3 frystyk 295: PUBLIC HTList * HTRequest_language (HTRequest *request)
2.1 frystyk 296: {
297: return request ? request->languages : NULL;
298: }
299:
300: /*
301: ** Accept Charset
302: ** list can be NULL
303: */
2.3 frystyk 304: PUBLIC void HTRequest_setCharset (HTRequest *request, HTList *charset,
305: BOOL override)
2.1 frystyk 306: {
307: if (request) {
308: request->charsets = charset;
309: request->char_local = override;
310: }
311: }
312:
2.3 frystyk 313: PUBLIC HTList * HTRequest_charset (HTRequest *request)
2.1 frystyk 314: {
315: return request ? request->charsets : NULL;
316: }
317:
318: /*
2.9 frystyk 319: ** Extra Header Generators. list can be NULL
320: */
321: PUBLIC void HTRequest_setGenerator (HTRequest *request, HTList *generator,
322: BOOL override)
323: {
324: if (request) {
325: request->generators = generator;
326: request->gens_local = override;
327: }
328: }
329:
330: PUBLIC HTList * HTRequest_generator (HTRequest *request, BOOL *override)
331: {
332: if (request) {
333: *override = request->gens_local;
334: return request->generators;
335: }
336: return NULL;
337: }
338:
339: /*
340: ** Extra Header Parsers. list can be NULL
341: */
2.43 eric 342: PUBLIC void HTRequest_setMIMEParseSet (HTRequest * me,
343: HTMIMEParseSet * parseSet, BOOL local)
2.9 frystyk 344: {
2.43 eric 345: if (me) {
346: me->parseSet = parseSet;
347: me->pars_local = local;
2.9 frystyk 348: }
349: }
350:
2.43 eric 351: PUBLIC HTMIMEParseSet * HTRequest_MIMEParseSet (HTRequest * me, BOOL * pLocal)
2.9 frystyk 352: {
2.43 eric 353: if (me) {
354: if (pLocal) *pLocal = me->pars_local;
355: return me->parseSet;
2.9 frystyk 356: }
357: return NULL;
2.43 eric 358: }
359:
2.9 frystyk 360: /*
2.1 frystyk 361: ** Set General Headers
362: */
2.3 frystyk 363: PUBLIC void HTRequest_setGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 364: {
365: if (request) request->GenMask = gnhd;
366: }
367:
2.3 frystyk 368: PUBLIC void HTRequest_addGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 369: {
370: if (request) request->GenMask |= gnhd;
371: }
372:
2.3 frystyk 373: PUBLIC HTGnHd HTRequest_gnHd (HTRequest *request)
2.1 frystyk 374: {
375: return request ? request->GenMask : 0;
376: }
377:
378: /*
379: ** Set Request Headers
380: */
2.3 frystyk 381: PUBLIC void HTRequest_setRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 382: {
383: if (request) request->RequestMask = rqhd;
384: }
385:
2.3 frystyk 386: PUBLIC void HTRequest_addRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 387: {
388: if (request) request->RequestMask |= rqhd;
389: }
390:
2.3 frystyk 391: PUBLIC HTRqHd HTRequest_rqHd (HTRequest *request)
2.1 frystyk 392: {
393: return request ? request->RequestMask : 0;
2.22 frystyk 394: }
395:
396: /*
397: ** Set Response Headers
398: */
399: PUBLIC void HTRequest_setRsHd (HTRequest *request, HTRsHd rshd)
400: {
401: if (request) request->ResponseMask = rshd;
402: }
403:
404: PUBLIC void HTRequest_addRsHd (HTRequest *request, HTRsHd rshd)
405: {
406: if (request) request->ResponseMask |= rshd;
407: }
408:
409: PUBLIC HTRsHd HTRequest_rsHd (HTRequest *request)
410: {
411: return request ? request->ResponseMask : 0;
2.1 frystyk 412: }
413:
414: /*
415: ** Set Entity Headers (for the object)
416: */
2.3 frystyk 417: PUBLIC void HTRequest_setEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 418: {
419: if (request) request->EntityMask = enhd;
420: }
421:
2.3 frystyk 422: PUBLIC void HTRequest_addEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 423: {
424: if (request) request->EntityMask |= enhd;
425: }
426:
2.3 frystyk 427: PUBLIC HTEnHd HTRequest_enHd (HTRequest *request)
2.1 frystyk 428: {
429: return request ? request->EntityMask : 0;
430: }
431:
2.18 frystyk 432: /*
2.1 frystyk 433: ** Anchor
434: */
2.3 frystyk 435: PUBLIC void HTRequest_setAnchor (HTRequest *request, HTAnchor *anchor)
2.1 frystyk 436: {
2.48 frystyk 437: if (request) {
2.1 frystyk 438: request->anchor = HTAnchor_parent(anchor);
439: request->childAnchor = ((HTAnchor *) request->anchor != anchor) ?
440: (HTChildAnchor *) anchor : NULL;
441: }
442: }
443:
2.3 frystyk 444: PUBLIC HTParentAnchor * HTRequest_anchor (HTRequest *request)
2.1 frystyk 445: {
446: return request ? request->anchor : NULL;
447: }
448:
449: /*
2.40 frystyk 450: ** Net
451: */
452: PUBLIC BOOL HTRequest_setNet (HTRequest * request, HTNet * net)
453: {
2.48 frystyk 454: if (request) {
2.40 frystyk 455: request->net = net;
456: return YES;
457: }
458: return NO;
459: }
460:
461: PUBLIC HTNet * HTRequest_net (HTRequest * request)
462: {
463: return request ? request->net : NULL;
464: }
465:
466: /*
467: ** User Profile
468: */
469: PUBLIC BOOL HTRequest_setUserProfile (HTRequest * request, HTUserProfile * up)
470: {
2.48 frystyk 471: if (request) {
2.40 frystyk 472: request->userprofile = up;
473: return YES;
474: }
475: return NO;
476: }
477:
478: PUBLIC HTUserProfile * HTRequest_userProfile (HTRequest * request)
479: {
480: return request ? request->userprofile : NULL;
481: }
482:
483: /*
2.1 frystyk 484: ** Parent anchor for Referer field
485: */
2.3 frystyk 486: PUBLIC void HTRequest_setParent (HTRequest *request, HTParentAnchor *parent)
2.1 frystyk 487: {
488: if (request) request->parentAnchor = parent;
489: }
490:
2.3 frystyk 491: PUBLIC HTParentAnchor * HTRequest_parent (HTRequest *request)
2.1 frystyk 492: {
493: return request ? request->parentAnchor : NULL;
494: }
495:
496: /*
497: ** Output stream
498: */
2.3 frystyk 499: PUBLIC void HTRequest_setOutputStream (HTRequest *request, HTStream *output)
2.1 frystyk 500: {
501: if (request) request->output_stream = output;
502: }
503:
2.4 frystyk 504: PUBLIC HTStream *HTRequest_outputStream (HTRequest *request)
2.1 frystyk 505: {
506: return request ? request->output_stream : NULL;
507: }
508:
509: /*
510: ** Output format
511: */
2.3 frystyk 512: PUBLIC void HTRequest_setOutputFormat (HTRequest *request, HTFormat format)
2.1 frystyk 513: {
514: if (request) request->output_format = format;
515: }
516:
2.4 frystyk 517: PUBLIC HTFormat HTRequest_outputFormat (HTRequest *request)
2.1 frystyk 518: {
519: return request ? request->output_format : NULL;
520: }
521:
522: /*
523: ** Debug stream
524: */
2.3 frystyk 525: PUBLIC void HTRequest_setDebugStream (HTRequest *request, HTStream *debug)
2.1 frystyk 526: {
527: if (request) request->debug_stream = debug;
528: }
529:
2.4 frystyk 530: PUBLIC HTStream *HTRequest_debugStream (HTRequest *request)
2.1 frystyk 531: {
532: return request ? request->debug_stream : NULL;
533: }
534:
535: /*
536: ** Debug Format
537: */
2.3 frystyk 538: PUBLIC void HTRequest_setDebugFormat (HTRequest *request, HTFormat format)
2.1 frystyk 539: {
540: if (request) request->debug_format = format;
541: }
542:
2.4 frystyk 543: PUBLIC HTFormat HTRequest_debugFormat (HTRequest *request)
2.1 frystyk 544: {
545: return request ? request->debug_format : NULL;
546: }
547:
2.35 frystyk 548: /*
549: ** Input stream
550: */
551: PUBLIC void HTRequest_setInputStream (HTRequest *request, HTStream *input)
552: {
553: if (request) request->input_stream = input;
554: }
555:
556: PUBLIC HTStream *HTRequest_inputStream (HTRequest *request)
557: {
558: return request ? request->input_stream : NULL;
559: }
560:
2.1 frystyk 561: /*
2.51 frystyk 562: ** Net before and after callbacks
2.34 hallam 563: */
2.51 frystyk 564: PUBLIC BOOL HTRequest_addBefore (HTRequest * request, HTNetCallback * filter,
565: void * param, int status,
2.34 hallam 566: BOOL override)
567: {
568: if (request) {
569: request->befores_local = override;
2.51 frystyk 570: if (!request->befores) request->befores = HTList_new();
571: return HTNetCall_add(request->befores, filter, param, status);
572: }
573: return NO;
574: }
575:
576: PUBLIC BOOL HTRequest_deleteBefore (HTRequest * request, HTNetCallback * filter)
577: {
578: if (request && request->befores)
579: return HTNetCall_delete(request->befores, filter);
580: return NO;
581: }
582:
583: PUBLIC BOOL HTRequest_deleteBeforeAll (HTRequest * request)
584: {
585: if (request && request->befores) {
586: HTNetCall_deleteAll(request->befores);
587: request->befores = NULL;
588: request->befores_local = NO;
589: return YES;
2.34 hallam 590: }
2.51 frystyk 591: return NO;
2.34 hallam 592: }
593:
594: PUBLIC HTList * HTRequest_before (HTRequest *request, BOOL *override)
595: {
596: if (request) {
597: *override = request->befores_local;
598: return request->befores;
599: }
600: return NULL;
601: }
602:
2.51 frystyk 603: PUBLIC BOOL HTRequest_addAfter (HTRequest * request, HTNetCallback * filter,
604: void * param, int status,
2.34 hallam 605: BOOL override)
606: {
607: if (request) {
608: request->afters_local = override;
2.51 frystyk 609: if (!request->afters) request->afters = HTList_new();
610: return HTNetCall_add(request->afters, filter, param, status);
2.34 hallam 611: }
2.51 frystyk 612: return NO;
613: }
614:
615: PUBLIC BOOL HTRequest_deleteAfter (HTRequest * request, HTNetCallback * filter)
616: {
617: if (request && request->afters)
618: return HTNetCall_delete(request->afters, filter);
619: return NO;
620: }
621:
622: PUBLIC BOOL HTRequest_deleteAfterAll (HTRequest * request)
623: {
624: if (request && request->afters) {
625: HTNetCall_deleteAll(request->afters);
626: request->afters = NULL;
627: request->afters_local = NO;
628: return YES;
629: }
630: return NO;
2.34 hallam 631: }
632:
633: PUBLIC HTList * HTRequest_after (HTRequest *request, BOOL *override)
634: {
635: if (request) {
636: *override = request->afters_local;
637: return request->afters;
638: }
639: return NULL;
640: }
641:
642: /*
2.1 frystyk 643: ** Call back function for context swapping
644: */
2.3 frystyk 645: PUBLIC void HTRequest_setCallback (HTRequest *request, HTRequestCallback *cbf)
2.1 frystyk 646: {
2.3 frystyk 647: if (request) request->callback = cbf;
2.1 frystyk 648: }
649:
2.3 frystyk 650: PUBLIC HTRequestCallback *HTRequest_callback (HTRequest *request)
2.1 frystyk 651: {
652: return request ? request->callback : NULL;
653: }
654:
655: /*
656: ** Context pointer to be used in context call back function
657: */
2.3 frystyk 658: PUBLIC void HTRequest_setContext (HTRequest *request, void *context)
2.1 frystyk 659: {
660: if (request) request->context = context;
661: }
662:
2.3 frystyk 663: PUBLIC void *HTRequest_context (HTRequest *request)
2.1 frystyk 664: {
665: return request ? request->context : NULL;
666: }
667:
668: /*
2.23 frystyk 669: ** Socket mode: preemptive or non-preemptive (blocking or non-blocking)
2.1 frystyk 670: */
2.23 frystyk 671: PUBLIC void HTRequest_setPreemptive (HTRequest *request, BOOL mode)
2.1 frystyk 672: {
2.23 frystyk 673: if (request) request->preemptive = mode;
2.1 frystyk 674: }
675:
2.23 frystyk 676: PUBLIC BOOL HTRequest_preemptive (HTRequest *request)
2.1 frystyk 677: {
2.23 frystyk 678: return request ? request->preemptive : NO;
2.47 frystyk 679: }
680:
681: /*
682: ** Has output stream been connected to the channel? If not then we
683: ** must free it explicitly when deleting the request object
684: */
685: PUBLIC void HTRequest_setOutputConnected (HTRequest * request, BOOL mode)
686: {
687: if (request) request->connected = mode;
688: }
689:
690: PUBLIC BOOL HTRequest_outputConnected (HTRequest * request)
691: {
692: return request ? request->connected : NO;
2.1 frystyk 693: }
694:
695: /*
696: ** Should we use content negotiation?
697: */
2.3 frystyk 698: PUBLIC void HTRequest_setNegotiation (HTRequest *request, BOOL mode)
2.1 frystyk 699: {
700: if (request) request->ContentNegotiation = mode;
701: }
702:
2.3 frystyk 703: PUBLIC BOOL HTRequest_negotiation (HTRequest *request)
2.1 frystyk 704: {
705: return request ? request->ContentNegotiation : NO;
2.40 frystyk 706: }
707:
708: /*
2.53 frystyk 709: ** Are we using the full URL in the request or not?
2.40 frystyk 710: */
2.41 frystyk 711: PUBLIC void HTRequest_setFullURI (HTRequest *request, BOOL mode)
2.40 frystyk 712: {
2.53 frystyk 713: if (request) request->full_uri = mode;
2.40 frystyk 714: }
715:
2.41 frystyk 716: PUBLIC BOOL HTRequest_fullURI (HTRequest *request)
2.40 frystyk 717: {
2.53 frystyk 718: return request ? request->full_uri : NO;
719: }
720:
721: /*
722: ** Are we using a proxy or not and in that case, which one?
723: */
724: PUBLIC BOOL HTRequest_setProxy (HTRequest * request, const char * proxy)
725: {
726: if (request && proxy) {
727: StrAllocCopy(request->proxy, proxy);
728: return YES;
729: }
730: return NO;
731: }
732:
733: PUBLIC char * HTRequest_proxy (HTRequest * request)
734: {
735: return request ? request->proxy : NULL;
2.1 frystyk 736: }
737:
2.54 frystyk 738: PUBLIC BOOL HTRequest_deleteProxy (HTRequest * request)
739: {
740: if (request) {
741: HT_FREE(request->proxy);
742: return YES;
743: }
744: return NO;
745: }
746:
2.1 frystyk 747: /*
748: ** Bytes read in this request
749: */
2.3 frystyk 750: PUBLIC long HTRequest_bytesRead(HTRequest * request)
2.1 frystyk 751: {
752: return request ? HTNet_bytesRead(request->net) : -1;
753: }
754:
755: /*
2.23 frystyk 756: ** Bytes written in this request
757: */
758: PUBLIC long HTRequest_bytesWritten (HTRequest * request)
759: {
760: return request ? HTNet_bytesWritten(request->net) : -1;
761: }
762:
763: /*
2.1 frystyk 764: ** Kill this request
765: */
2.3 frystyk 766: PUBLIC BOOL HTRequest_kill(HTRequest * request)
2.1 frystyk 767: {
768: return request ? HTNet_kill(request->net) : NO;
769: }
770:
2.11 frystyk 771: /* Error Management
772: ** ----------------
2.1 frystyk 773: ** Returns the error stack if a stream is
774: */
2.11 frystyk 775: PUBLIC HTList * HTRequest_error (HTRequest * request)
2.1 frystyk 776: {
777: return request ? request->error_stack : NULL;
778: }
779:
2.11 frystyk 780: PUBLIC void HTRequest_setError (HTRequest * request, HTList * list)
781: {
782: if (request) request->error_stack = list;
783: }
784:
785: PUBLIC BOOL HTRequest_addError (HTRequest * request,
786: HTSeverity severity,
787: BOOL ignore,
788: int element,
789: void * par,
790: unsigned int length,
791: char * where)
792: {
793: if (request) {
794: if (!request->error_stack) request->error_stack = HTList_new();
795: return HTError_add(request->error_stack, severity, ignore, element,
796: par, length, where);
797: }
798: return NO;
799: }
800:
801: PUBLIC BOOL HTRequest_addSystemError (HTRequest * request,
802: HTSeverity severity,
803: int errornumber,
804: BOOL ignore,
805: char * syscall)
806: {
807: if (request) {
808: if (!request->error_stack) request->error_stack = HTList_new();
809: return HTError_addSystem(request->error_stack, severity, errornumber,
810: ignore, syscall);
811: }
812: return NO;
813: }
814:
2.1 frystyk 815: /*
816: ** When to retry a request if HT_RETRY
817: ** Returns -1 if not available
818: */
819: PUBLIC time_t HTRequest_retryTime (HTRequest * request)
820: {
821: return request ? request->retry_after : -1;
822: }
823:
824: /*
2.23 frystyk 825: ** Redirection informantion
826: */
827: PUBLIC HTAnchor * HTRequest_redirection (HTRequest * request)
828: {
829: return (request ? request->redirectionAnchor : NULL);
2.46 frystyk 830: }
831:
832: PUBLIC BOOL HTRequest_setRedirection (HTRequest * request, HTAnchor * anchor)
833: {
834: if (request && anchor) {
835: request->redirectionAnchor = (HTAnchor *) HTAnchor_parent(anchor);
836: return YES;
837: }
838: return NO;
2.23 frystyk 839: }
840:
841: /*
2.1 frystyk 842: ** Set max number of automatic reload. Default is HT_MAX_RELOADS
843: */
2.3 frystyk 844: PUBLIC BOOL HTRequest_setMaxRetry (int newmax)
2.1 frystyk 845: {
846: if (newmax > 0) {
847: HTMaxRetry = newmax;
848: return YES;
849: }
850: return NO;
851: }
852:
2.3 frystyk 853: PUBLIC int HTRequest_maxRetry (void)
2.1 frystyk 854: {
855: return HTMaxRetry;
856: }
857:
2.52 frystyk 858: PUBLIC int HTRequest_retrys (HTRequest * request)
859: {
860: return request ? request->retrys : 0;
861: }
862:
2.55 ! frystyk 863: PUBLIC BOOL HTRequest_addRetry (HTRequest * request)
! 864: {
! 865: return (request && request->retrys++);
! 866: }
! 867:
2.1 frystyk 868: /*
869: ** Should we try again?
870: ** --------------------
871: ** Returns YES if we are to retry the load, NO otherwise. We check
872: ** this so that we don't go into an infinte loop
873: */
2.52 frystyk 874: PUBLIC BOOL HTRequest_doRetry (HTRequest *request)
2.1 frystyk 875: {
876: return (request && request->retrys < HTMaxRetry-1);
2.54 frystyk 877: }
878:
879: /*
880: ** Handle the max forward header value
881: */
882: PUBLIC BOOL HTRequest_setMaxForwards (HTRequest * request, int maxforwards)
883: {
884: if (request && maxforwards >= 0) {
885: request->max_forwards = maxforwards;
886: HTRequest_addRqHd(request, HT_C_MAX_FORWARDS); /* Turn it on */
887: return YES;
888: }
889: return NO;
890: }
891:
892: PUBLIC int HTRequest_maxForwards (HTRequest * request)
893: {
894: return request ? request->max_forwards : -1;
2.1 frystyk 895: }
896:
2.9 frystyk 897: /*
898: ** Priority to be inherited by all HTNet object hanging off this request
899: ** The priority can later be chaned by calling the HTNet object directly
900: */
901: PUBLIC BOOL HTRequest_setPriority (HTRequest * request, HTPriority priority)
902: {
903: if (request) {
904: request->priority = priority;
905: return YES;
906: }
907: return NO;
908: }
909:
910: PUBLIC HTPriority HTRequest_priority (HTRequest * request)
911: {
2.19 frystyk 912: return (request ? request->priority : HT_PRIORITY_INV);
2.9 frystyk 913: }
914:
2.18 frystyk 915: /*
2.31 frystyk 916: ** Access Authentication Credentials
917: */
2.49 frystyk 918: PUBLIC BOOL HTRequest_deleteCredentials (HTRequest * request)
919: {
920: if (request && request->credentials) {
921: HTAssocList_delete(request->credentials);
922: request->credentials = NULL;
923: return YES;
924: }
925: return NO;
926: }
927:
928: PUBLIC BOOL HTRequest_addCredentials (HTRequest * request,
929: char * token, char * value)
2.31 frystyk 930: {
931: if (request) {
2.49 frystyk 932: if (!request->credentials) request->credentials = HTAssocList_new();
933: return HTAssocList_addObject(request->credentials, token, value);
2.31 frystyk 934: }
935: return NO;
936: }
937:
938: PUBLIC HTAssocList * HTRequest_credentials (HTRequest * request)
939: {
940: return (request ? request->credentials : NULL);
941: }
942:
943: /*
944: ** Access Authentication Challenges
945: */
2.49 frystyk 946: PUBLIC BOOL HTRequest_addChallenge (HTRequest * request,
947: char * token, char * value)
2.31 frystyk 948: {
949: if (request) {
2.49 frystyk 950: if (!request->challenge) request->challenge = HTAssocList_new();
951: return HTAssocList_addObject(request->challenge, token, value);
952: }
953: return NO;
954: }
955:
956: PUBLIC BOOL HTRequest_deleteChallenge (HTRequest * request)
957: {
958: if (request && request->challenge) {
959: HTAssocList_delete(request->challenge);
960: request->challenge = NULL;
2.31 frystyk 961: return YES;
962: }
963: return NO;
964: }
965:
966: PUBLIC HTAssocList * HTRequest_challenge (HTRequest * request)
967: {
968: return (request ? request->challenge : NULL);
969: }
970:
971: /*
972: ** Access Authentication Realms
2.18 frystyk 973: */
2.31 frystyk 974: PUBLIC BOOL HTRequest_setRealm (HTRequest * request, char * realm)
2.18 frystyk 975: {
2.49 frystyk 976: if (request && realm) {
977: StrAllocCopy(request->realm, realm);
2.18 frystyk 978: return YES;
979: }
980: return NO;
981: }
982:
2.32 frystyk 983: PUBLIC const char * HTRequest_realm (HTRequest * request)
2.18 frystyk 984: {
2.31 frystyk 985: return (request ? request->realm : NULL);
2.42 frystyk 986: }
987:
988: /*
2.49 frystyk 989: ** Access Authentication Schemes
990: */
991: PUBLIC BOOL HTRequest_setScheme (HTRequest * request, char * scheme)
992: {
993: if (request && scheme) {
994: StrAllocCopy(request->scheme, scheme);
995: return YES;
996: }
997: return NO;
998: }
999:
1000: PUBLIC const char * HTRequest_scheme (HTRequest * request)
1001: {
1002: return (request ? request->scheme : NULL);
1003: }
1004:
1005: /*
2.42 frystyk 1006: ** Source request
1007: */
1008: PUBLIC BOOL HTRequest_setSource (HTRequest * request, HTRequest * source)
1009: {
1010: if (request) {
1011: request->source = source;
1012: return YES;
1013: }
1014: return NO;
1015: }
1016:
1017: PUBLIC HTRequest * HTRequest_source (HTRequest * request)
1018: {
1019: return (request ? request->source : NULL);
1020: }
1021:
1022: PUBLIC BOOL HTRequest_isPostWeb (HTRequest * request)
1023: {
2.43 eric 1024: return (request ? request->source != NULL: NO);
2.42 frystyk 1025: }
1026:
1027: /*
1028: ** Internal request object
1029: */
1030: PUBLIC BOOL HTRequest_setInternal (HTRequest * request, BOOL mode)
1031: {
1032: if (request) {
1033: request->internal = mode;
1034: return YES;
1035: }
1036: return NO;
1037: }
1038:
1039: PUBLIC BOOL HTRequest_internal (HTRequest * request)
1040: {
1041: return (request ? request->internal : NO);
1042: }
1043:
1044: /*
1045: ** POST Call back function for sending data to the destination
1046: */
1047: PUBLIC void HTRequest_setPostCallback (HTRequest *request, HTPostCallback *cbf)
1048: {
1049: if (request) request->PostCallback = cbf;
1050: }
1051:
1052: PUBLIC HTPostCallback * HTRequest_postCallback (HTRequest * request)
1053: {
1054: return request ? request->PostCallback : NULL;
2.18 frystyk 1055: }
1056:
2.50 frystyk 1057: /*
1058: ** Entity Anchor
1059: */
1060: PUBLIC BOOL HTRequest_setEntityAnchor (HTRequest * request,
1061: HTParentAnchor * anchor)
1062: {
1063: if (request) {
1064: request->source_anchor = anchor;
1065: return YES;
1066: }
1067: return NO;
1068: }
1069:
1070: PUBLIC HTParentAnchor * HTRequest_entityAnchor (HTRequest * request)
1071: {
1072: return request ? request->source_anchor ? request->source_anchor :
1073: request->anchor : NULL;
2.55 ! frystyk 1074: }
! 1075:
! 1076: /*
! 1077: ** Simple Extension Protocol
! 1078: */
! 1079: PUBLIC BOOL HTRequest_addExtension (HTRequest * request,
! 1080: char * token, char * value)
! 1081: {
! 1082: if (request) {
! 1083: if (!request->extension) request->extension = HTAssocList_new();
! 1084: return HTAssocList_addObject(request->extension, token, value);
! 1085: }
! 1086: return NO;
! 1087: }
! 1088:
! 1089: PUBLIC BOOL HTRequest_deleteExtension (HTRequest * request)
! 1090: {
! 1091: if (request && request->extension) {
! 1092: HTAssocList_delete(request->extension);
! 1093: request->extension = NULL;
! 1094: return YES;
! 1095: }
! 1096: return NO;
! 1097: }
! 1098:
! 1099: PUBLIC HTAssocList * HTRequest_extension (HTRequest * request)
! 1100: {
! 1101: return (request ? request->extension : NULL);
2.50 frystyk 1102: }
1103:
2.1 frystyk 1104: /* ------------------------------------------------------------------------- */
1105: /* POST WEB METHODS */
1106: /* ------------------------------------------------------------------------- */
1107:
1108: /*
1109: ** Add a destination request to this source request structure so that we
1110: ** build the internal request representation of the POST web
1111: ** Returns YES if OK, else NO
1112: */
2.23 frystyk 1113: PUBLIC BOOL HTRequest_addDestination (HTRequest * src, HTRequest * dest)
2.1 frystyk 1114: {
1115: if (src && dest) {
2.23 frystyk 1116: dest->source = src->source = src;
2.1 frystyk 1117: if (!src->mainDestination) {
1118: src->mainDestination = dest;
1119: src->destRequests = 1;
2.36 frystyk 1120: if (CORE_TRACE)
2.30 eric 1121: HTTrace("POSTWeb..... Adding dest %p to src %p\n",
2.23 frystyk 1122: dest, src);
2.1 frystyk 1123: return YES;
1124: } else {
2.23 frystyk 1125: if (!src->destinations) src->destinations = HTList_new();
2.1 frystyk 1126: if (HTList_addObject(src->destinations, (void *) dest)==YES) {
1127: src->destRequests++;
2.36 frystyk 1128: if (CORE_TRACE)
2.30 eric 1129: HTTrace("POSTWeb..... Adding dest %p to src %p\n",
2.23 frystyk 1130: dest, src);
2.1 frystyk 1131: return YES;
1132: }
1133: }
1134: }
1135: return NO;
1136: }
1137:
1138: /*
1139: ** Remove a destination request from this source request structure
2.23 frystyk 1140: ** Remember only to delete the internal request objects as the other
1141: ** comes from the application!
2.1 frystyk 1142: ** Returns YES if OK, else NO
1143: */
2.23 frystyk 1144: PUBLIC BOOL HTRequest_removeDestination (HTRequest * dest)
2.1 frystyk 1145: {
1146: BOOL found=NO;
1147: if (dest && dest->source) {
1148: HTRequest *src = dest->source;
1149: if (src->mainDestination == dest) {
1150: dest->source = NULL;
1151: src->mainDestination = NULL;
1152: src->destRequests--;
1153: found = YES;
2.23 frystyk 1154: } else if (src->destinations) {
2.1 frystyk 1155: if (HTList_removeObject(src->destinations, (void *) dest)) {
1156: src->destRequests--;
1157: found = YES;
1158: }
1159: }
1160: if (found) {
2.23 frystyk 1161: if (dest->internal) HTRequest_delete(dest);
2.36 frystyk 1162: if (CORE_TRACE)
2.30 eric 1163: HTTrace("POSTWeb..... Deleting dest %p from src %p\n",
2.23 frystyk 1164: dest, src);
2.1 frystyk 1165: }
2.23 frystyk 1166: if (src->destRequests <= 0) {
2.36 frystyk 1167: if (CORE_TRACE)
2.30 eric 1168: HTTrace("POSTWeb..... terminated\n");
2.23 frystyk 1169: if (src->internal) HTRequest_delete(src);
2.1 frystyk 1170: }
1171: }
1172: return found;
1173: }
1174:
1175: /*
2.23 frystyk 1176: ** Check to see whether all destinations are ready. If so then enable the
1177: ** source as ready for reading.
1178: ** Returns YES if all dests are ready, NO otherwise
1179: */
1180: PUBLIC BOOL HTRequest_destinationsReady (HTRequest * me)
1181: {
1182: HTRequest * source = me ? me->source : NULL;
1183: if (source) {
1184: if (source->destStreams == source->destRequests) {
1185: HTNet * net = source->net;
2.36 frystyk 1186: if (CORE_TRACE)
2.30 eric 1187: HTTrace("POSTWeb..... All destinations are ready!\n");
2.23 frystyk 1188: if (net) /* Might already have finished */
2.38 eric 1189: HTEvent_register(net->sockfd, source, (SockOps) FD_READ,
2.23 frystyk 1190: net->cbf, net->priority);
1191: return YES;
1192: }
1193: }
1194: return NO;
1195: }
1196:
1197: /*
1198: ** Find the source request object and make the link between the
2.1 frystyk 1199: ** source output stream and the destination input stream. There can be
1200: ** a conversion between the two streams!
1201: ** Returns YES if link is made, NO otherwise
1202: */
2.3 frystyk 1203: PUBLIC BOOL HTRequest_linkDestination (HTRequest *dest)
2.1 frystyk 1204: {
1205: if (dest && dest->input_stream && dest->source && dest!=dest->source) {
1206: HTRequest *source = dest->source;
1207: HTStream *pipe = HTStreamStack(source->output_format,
1208: dest->input_format,
1209: dest->input_stream,
1210: dest, YES);
1211:
1212: /* Check if we are the only one - else spawn off T streams */
1213: /* @@@ We don't do this yet @@@ */
1214:
2.23 frystyk 1215: /* Now set up output stream of the source */
1216: if (source->output_stream)
1217: (*source->output_stream->isa->_free)(source->output_stream);
2.1 frystyk 1218: source->output_stream = pipe ? pipe : dest->input_stream;
1219:
2.36 frystyk 1220: if (CORE_TRACE)
2.30 eric 1221: HTTrace("POSTWeb..... Linking dest %p to src %p\n",
2.23 frystyk 1222: dest, source);
2.1 frystyk 1223: if (++source->destStreams == source->destRequests) {
1224: HTNet *net = source->net;
2.36 frystyk 1225: if (CORE_TRACE)
2.30 eric 1226: HTTrace("POSTWeb..... All destinations ready!\n");
2.1 frystyk 1227: if (net) /* Might already have finished */
2.38 eric 1228: HTEvent_register(net->sockfd, source, (SockOps) FD_READ,
2.1 frystyk 1229: net->cbf, net->priority);
1230: return YES;
1231: }
1232: }
1233: return NO;
1234: }
1235:
1236: /*
1237: ** Remove a feed stream to a destination request from this source
1238: ** request structure. When all feeds are removed the request tree is
1239: ** ready to take down and the operation can be terminated.
1240: ** Returns YES if removed, else NO
1241: */
2.3 frystyk 1242: PUBLIC BOOL HTRequest_unlinkDestination (HTRequest *dest)
2.1 frystyk 1243: {
1244: BOOL found = NO;
1245: if (dest && dest->source && dest != dest->source) {
1246: HTRequest *src = dest->source;
1247: if (src->mainDestination == dest) {
1248: src->output_stream = NULL;
1249: if (dest->input_stream)
1250: (*dest->input_stream->isa->_free)(dest->input_stream);
1251: found = YES;
1252: } else if (src->destinations) {
1253:
1254: /* LOOK THROUGH THE LIST AND FIND THE RIGHT ONE */
1255:
1256: }
1257: if (found) {
1258: src->destStreams--;
2.36 frystyk 1259: if (CORE_TRACE)
2.30 eric 1260: HTTrace("POSTWeb..... Unlinking dest %p from src %p\n",
2.23 frystyk 1261: dest, src);
2.1 frystyk 1262: return YES;
1263: }
1264: }
1265: return NO;
1266: }
1267:
1268: /*
1269: ** Removes all request structures in this PostWeb.
1270: */
2.3 frystyk 1271: PUBLIC BOOL HTRequest_removePostWeb (HTRequest *me)
2.1 frystyk 1272: {
1273: if (me && me->source) {
1274: HTRequest *source = me->source;
1275:
1276: /* Kill main destination */
1277: if (source->mainDestination)
1278: HTRequest_removeDestination(source->mainDestination);
1279:
1280: /* Kill all other destinations */
1281: if (source->destinations) {
1282: HTList *cur = source->destinations;
1283: HTRequest *pres;
1284: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
1285: HTRequest_removeDestination(pres);
1286: }
1287:
1288: /* Remove source request */
1289: HTRequest_removeDestination(source);
1290: return YES;
1291: }
1292: return NO;
1293: }
1294:
1295: /*
1296: ** Kills all threads in a POST WEB connected to this request but
2.23 frystyk 1297: ** NOT this request itself. We also keep the request structures.
1298: ** Some requests might be preemptive, for example a SMTP request (when
2.1 frystyk 1299: ** that has been implemented). However, this will be handled internally
1300: ** in the load function.
1301: */
2.3 frystyk 1302: PUBLIC BOOL HTRequest_killPostWeb (HTRequest *me)
2.1 frystyk 1303: {
1304: if (me && me->source) {
1305: HTRequest *source = me->source;
2.36 frystyk 1306: if (CORE_TRACE) HTTrace("POSTWeb..... Killing\n");
2.1 frystyk 1307:
2.23 frystyk 1308: /*
1309: ** Kill source. The stream tree is now freed so we have to build
1310: ** that again. This is done in HTRequest_linkDestination()
1311: */
1312: if (me != source) {
1313: HTNet_kill(source->net);
1314: source->output_stream = NULL;
1315: }
2.1 frystyk 1316:
1317: /* Kill all other destinations */
1318: if (source->destinations) {
1319: HTList *cur = source->destinations;
1320: HTRequest *pres;
1321: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
2.23 frystyk 1322: if (me != pres) HTNet_kill(pres->net);
2.1 frystyk 1323: }
2.23 frystyk 1324:
1325: /* Kill main destination */
1326: if (source->mainDestination && me != source->mainDestination)
1327: HTNet_kill(source->mainDestination->net);
2.1 frystyk 1328: return YES;
1329: }
1330: return NO;
1331: }
1332:
1333: /* --------------------------------------------------------------------------*/
1334: /* Document Loader */
1335: /* --------------------------------------------------------------------------*/
1336:
1337: /* Request a resource
1338: ** ------------------
1339: ** This is an internal routine, which has an address AND a matching
1340: ** anchor. (The public routines are called with one OR the other.)
1341: ** Returns:
1342: ** YES if request has been registered (success)
1343: ** NO an error occured
1344: */
2.9 frystyk 1345: PUBLIC BOOL HTLoad (HTRequest * request, BOOL recursive)
2.1 frystyk 1346: {
1347: if (!request || !request->anchor) {
2.36 frystyk 1348: if (CORE_TRACE) HTTrace("Load Start.. Bad argument\n");
2.1 frystyk 1349: return NO;
1350: }
2.50 frystyk 1351: HTAnchor_clearPhysical(request->anchor);
2.14 frystyk 1352: if (request->method == METHOD_INVALID) request->method = METHOD_GET;
2.16 frystyk 1353: if (!recursive && request->error_stack) {
1354: HTError_deleteAll(request->error_stack);
1355: request->error_stack = NULL;
1356: }
2.18 frystyk 1357: return HTNet_newClient(request);
2.1 frystyk 1358: }
1359:
Webmaster