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 **	@(#) $Id$
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 ** Contribution
14 **      MKP     Manuele Kirsch, Manuele.Kirsch_Pinheiro@inrialpes.fr or manuele@inf.ufrgs.br
15 ** History
16 **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
17 **	26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
18 **	 6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
19 **	17 Dec 92 Tn3270 added, bug fix. DD
20 **	 4 Feb 93 Access registration, Search escapes bad chars TBL
21 **		  PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
22 **	28 May 93 WAIS gateway explicit if no WAIS library linked in.
23 **	   Dec 93 Bug change around, more reentrant, etc
24 **	09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
25 **	 8 Jul 94 Insulate free() from _free structure element.
26 **	02 Sep 95 Rewritten and spawned from HTAccess.c, HFN
27 **      14 Fev 02 Message body added to HTRequest
28 */
29 
30 #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
31 #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
32 #endif
33 
34 /* Library include files */
35 #include "wwwsys.h"
36 #include "WWWUtil.h"
37 #include "HTParse.h"
38 #include "HTNoFree.h"
39 #include "HTAlert.h"
40 #include "HTError.h"
41 #include "HTNetMan.h"
42 #include "HTEvent.h"
43 #include "HTProt.h"
44 #include "HTHeader.h"
45 #include "HTLib.h"
46 #include "HTReqMan.h"					 /* Implemented here */
47 
48 #ifndef HT_MAX_RELOADS
49 #define HT_MAX_RELOADS	6
50 #endif
51 
52 PRIVATE int HTMaxRetry = HT_MAX_RELOADS;
53 
54 struct _HTStream {
55 	HTStreamClass * isa;
56 	/* ... */
57 };
58 
59 /* --------------------------------------------------------------------------*/
60 /*			Create and delete the HTRequest Object		     */
61 /* --------------------------------------------------------------------------*/
62 
HTRequest_new(void)63 PUBLIC HTRequest * HTRequest_new (void)
64 {
65     HTRequest * me;
66     if ((me = (HTRequest *) HT_CALLOC(1, sizeof(HTRequest))) == NULL)
67         HT_OUTOFMEM("HTRequest_new()");
68 
69    /* Force Reload */
70     me->reload = HT_CACHE_OK;
71 
72     /* no default PUT name */
73     me->default_put_name = NULL;
74 
75     /* Set the default user profile */
76     me->userprofile = HTLib_userProfile();
77 
78     /* Format of output */
79     me->output_format	= WWW_PRESENT;	    /* default it to present to user */
80     me->debug_format	= WWW_DEBUG;	 /* default format of error messages */
81 
82     /* HTTP headers */
83     me->GenMask		= DEFAULT_GENERAL_HEADERS;
84     me->RequestMask	= DEFAULT_REQUEST_HEADERS;
85     me->ResponseMask	= DEFAULT_RESPONSE_HEADERS;
86     me->EntityMask	= DEFAULT_ENTITY_HEADERS;
87 
88     /* Default retry after value */
89     me->priority = HT_PRIORITY_MAX;
90 
91     /* Default max forward value */
92     me->max_forwards = -1;
93 
94     /* Content negotiation */
95     me->ContentNegotiation = YES;		       /* Do this by default */
96 
97 #ifdef HT_EXT
98     /* Message Body */
99     me->messageBody = NULL;             /* MKP: default value is NULL - no message body set */
100     me->messageBodyLength = -1;         /* MKP: default value is -1 */
101     me->messageBodyFormat = NULL;       /* MKP: default value is NULL */
102 #endif
103 
104 
105     HTTRACE(CORE_TRACE, "Request..... Created %p\n" _ me);
106 
107     return me;
108 }
109 
110 /*	HTRequest_clear
111 **	---------------
112 **	Clears all protocol specific information so that the request object
113 **	can be used for another request.
114 **	Returns YES if OK, else NO
115 */
HTRequest_clear(HTRequest * me)116 PUBLIC BOOL HTRequest_clear (HTRequest * me)
117 {
118     if (me) {
119 	me->error_stack = NULL;
120 	me->net = NULL;
121 	me->realm = NULL;
122 	me->credentials = NULL;
123 	me->connected = NO;
124         if (me->default_put_name)
125           HTRequest_deleteDefaultPutName (me);
126 	if (me->response) {
127 	    HTResponse_delete(me->response);
128 	    me->response = NULL;
129 	}
130 
131 #ifdef HT_EXT
132         if (me->messageBody)                    /* MKP: clear message body */
133             HTRequest_deleteMessageBody(me);
134         me->messageBodyFormat = NULL;
135         me->messageBodyLength = -1;
136 #endif
137 
138 	return YES;
139     }
140     return NO;
141 }
142 
143 /*	HTRequest_dup
144 **	-------------
145 **	Creates a new HTRequest object as a duplicate of the src request.
146 **	Returns YES if OK, else NO
147 */
HTRequest_dup(HTRequest * src)148 PUBLIC HTRequest * HTRequest_dup (HTRequest * src)
149 {
150     HTRequest * me;
151     if (!src) return NULL;
152     if ((me = (HTRequest  *) HT_MALLOC(sizeof(HTRequest))) == NULL)
153         HT_OUTOFMEM("HTRequest_dup");
154     memcpy(me, src, sizeof(HTRequest));
155     HTTRACE(CORE_TRACE, "Request..... Duplicated %p to %p\n" _ src _ me);
156     return me;
157 }
158 
159 /*	HTRequest_dupInternal
160 **	---------------------
161 **	Creates a new HTRequest object as a duplicate of the src request.
162 **	The difference to the HTRequest_dup function is that we don't copy the
163 **	error_stack and other information that the application keeps in its
164 **	copy of the request object. Otherwise it will be freed multiple times
165 **	Returns YES if OK, else NO
166 */
HTRequest_dupInternal(HTRequest * src)167 PUBLIC HTRequest * HTRequest_dupInternal (HTRequest * src)
168 {
169     HTRequest * me;
170     if (!src) return 0;
171     if ((me = (HTRequest  *) HT_MALLOC(sizeof(HTRequest))) == NULL)
172         HT_OUTOFMEM("HTRequest_dup");
173     memcpy(me, src, sizeof(HTRequest));
174     HTRequest_clear(me);
175     return me;
176 }
177 
HTRequest_delete(HTRequest * me)178 PUBLIC void HTRequest_delete (HTRequest * me)
179 {
180     if (me) {
181 	HTTRACE(CORE_TRACE, "Request..... Delete %p\n" _ me);
182 	if (me->net) HTNet_setRequest(me->net, NULL);
183 
184 	/*
185 	** Make sure we don't delete the same stream twice, when the output
186 	** stream and the debug stream are the same.
187 	*/
188 	if (me->orig_output_stream == me->orig_debug_stream)
189 	{
190 	    me->orig_debug_stream = NULL;
191 	}
192 
193 	/* Should we delete the output stream? */
194 	if (me->orig_output_stream) {
195 	    HTTRACE(CORE_TRACE, "Request..... Deleting dangling output stream\n");
196 	    (*me->orig_output_stream->isa->_free)(me->orig_output_stream);
197 	    me->orig_output_stream = NULL;
198 	    HTNoFreeStream_delete(me->output_stream);
199 	    me->output_stream = NULL;
200 	}
201 
202 	/* Should we delete the debug stream? */
203 	if (me->orig_debug_stream) {
204 	    HTTRACE(CORE_TRACE, "Request..... Deleting dangling debug stream\n");
205 	    (*me->orig_debug_stream->isa->_free)(me->orig_debug_stream);
206 	    me->orig_debug_stream = NULL;
207 	    HTNoFreeStream_delete(me->debug_stream);
208 	    me->debug_stream = NULL;
209 	}
210 
211 	/* Clean up the error stack */
212 	if (me->error_stack) HTError_deleteAll(me->error_stack);
213 
214 	/* Before and After Filters */
215 	if (me->afters) HTNetCall_deleteAfterAll(me->afters);
216 	if (me->befores) HTNetCall_deleteBeforeAll(me->befores);
217 
218         /* default PUT name */
219         if (me->default_put_name)
220           HTRequest_deleteDefaultPutName (me);
221 
222 	/* Access Authentication */
223 	HT_FREE(me->realm);
224 	if (me->credentials) HTAssocList_delete(me->credentials);
225 
226 	/* Cache control headers */
227 	if (me->cache_control)
228 	    HTAssocList_delete(me->cache_control);
229 
230 	/* Byte ranges */
231 	if (me->byte_ranges) HTAssocList_delete(me->byte_ranges);
232 
233 	/* Connection headers */
234 	if (me->connection) HTAssocList_delete(me->connection);
235 
236 	/* Connection headers */
237 	if (me->expect) HTAssocList_delete(me->expect);
238 
239 	/* Proxy information */
240 	HT_FREE(me->proxy);
241 
242 	/* Extra header fields */
243 	if (me->extra_headers) HTAssocList_delete(me->extra_headers);
244 
245 	/* HTTP Extension Information */
246 	if (me->optional) HTAssocList_delete(me->optional);
247 	if (me->mandatory) HTAssocList_delete(me->mandatory);
248 
249 	/* Any response object */
250 	if (me->response) HTResponse_delete(me->response);
251 
252 #ifdef HT_EXT
253         if (me->messageBody) HTRequest_deleteMessageBody(me); /* MKP: clear message body*/
254         me->messageBodyFormat = NULL;
255         me->messageBodyLength = -1;
256 #endif
257 
258 	HT_FREE(me);
259     }
260 }
261 
262 /*
263 **	Kill this request
264 */
HTRequest_kill(HTRequest * me)265 PUBLIC BOOL HTRequest_kill(HTRequest * me)
266 {
267     return me ? HTNet_kill(me->net) : NO;
268 }
269 
270 /* --------------------------------------------------------------------------*/
271 /*			Methods on the HTRequest Object			     */
272 /* --------------------------------------------------------------------------*/
273 
274 /*
275 **  Internal request object
276 */
HTRequest_setInternal(HTRequest * me,BOOL mode)277 PUBLIC BOOL HTRequest_setInternal (HTRequest * me, BOOL mode)
278 {
279     if (me) {
280 	me->internal = mode;
281 	return YES;
282     }
283     return NO;
284 }
285 
HTRequest_internal(HTRequest * me)286 PUBLIC BOOL HTRequest_internal (HTRequest * me)
287 {
288     return (me ? me->internal : NO);
289 }
290 
291 /*
292 **  Should we flush immediately?
293 */
HTRequest_setFlush(HTRequest * me,BOOL mode)294 PUBLIC BOOL HTRequest_setFlush (HTRequest * me, BOOL mode)
295 {
296     if (me) {
297 	me->flush = mode;
298 	return YES;
299     }
300     return NO;
301 }
302 
HTRequest_flush(HTRequest * me)303 PUBLIC BOOL HTRequest_flush (HTRequest * me)
304 {
305     return (me ? me->flush : NO);
306 }
307 
308 /*
309 **	Date/time stamp when then request was issued
310 **	This is normally set when generating the request headers.
311 */
HTRequest_date(HTRequest * me)312 PUBLIC time_t HTRequest_date (HTRequest * me)
313 {
314     return me ? me->date : -1;
315 }
316 
HTRequest_setDate(HTRequest * me,time_t date)317 PUBLIC BOOL HTRequest_setDate (HTRequest * me, time_t date)
318 {
319     if (me) {
320 	me->date = date;
321 	return YES;
322     }
323     return NO;
324 }
325 
326 /*
327 **	Method
328 */
HTRequest_setMethod(HTRequest * me,HTMethod method)329 PUBLIC void HTRequest_setMethod (HTRequest * me, HTMethod method)
330 {
331     if (me) me->method = method;
332 }
333 
HTRequest_method(HTRequest * me)334 PUBLIC HTMethod HTRequest_method (HTRequest * me)
335 {
336     return me ? me->method : METHOD_INVALID;
337 }
338 
339 /*
340 **  Priority to be inherited by all HTNet object hanging off this request
341 **  The priority can later be chaned by calling the HTNet object directly
342 */
HTRequest_setPriority(HTRequest * me,HTPriority priority)343 PUBLIC BOOL HTRequest_setPriority (HTRequest * me, HTPriority priority)
344 {
345     if (me) {
346 	me->priority = priority;
347 	return YES;
348     }
349     return NO;
350 }
351 
HTRequest_priority(HTRequest * me)352 PUBLIC HTPriority HTRequest_priority (HTRequest * me)
353 {
354     return (me ? me->priority : HT_PRIORITY_INV);
355 }
356 
357 /*
358 **	User Profile
359 */
HTRequest_setUserProfile(HTRequest * me,HTUserProfile * up)360 PUBLIC BOOL HTRequest_setUserProfile (HTRequest * me, HTUserProfile * up)
361 {
362     if (me) {
363 	me->userprofile = up;
364 	return YES;
365     }
366     return NO;
367 }
368 
HTRequest_userProfile(HTRequest * me)369 PUBLIC HTUserProfile * HTRequest_userProfile (HTRequest * me)
370 {
371     return me ? me->userprofile : NULL;
372 }
373 
374 /*
375 **	Net Object
376 */
HTRequest_setNet(HTRequest * me,HTNet * net)377 PUBLIC BOOL HTRequest_setNet (HTRequest * me, HTNet * net)
378 {
379     if (me) {
380 	me->net = net;
381 	return YES;
382     }
383     return NO;
384 }
385 
HTRequest_net(HTRequest * me)386 PUBLIC HTNet * HTRequest_net (HTRequest * me)
387 {
388     return me ? me->net : NULL;
389 }
390 
391 /*
392 **	Response Object. If the object does not exist then create it at the
393 **	same time it is asked for.
394 */
HTRequest_response(HTRequest * me)395 PUBLIC HTResponse * HTRequest_response (HTRequest * me)
396 {
397     if (me) {
398 	if (!me->response)
399 	    me->response = HTResponse_new();
400 	return me->response;
401     }
402     return NULL;
403 }
404 
HTRequest_setResponse(HTRequest * me,HTResponse * response)405 PUBLIC BOOL HTRequest_setResponse (HTRequest * me, HTResponse * response)
406 {
407     if (me) {
408 	if (me->response) HTResponse_delete(me->response);
409 	me->response = response;
410 	return YES;
411     }
412     return NO;
413 }
414 
415 /*	Error Management
416 **	----------------
417 **	Returns the error stack if a stream is
418 */
HTRequest_error(HTRequest * me)419 PUBLIC HTList * HTRequest_error (HTRequest * me)
420 {
421     return me ? me->error_stack : NULL;
422 }
423 
HTRequest_setError(HTRequest * me,HTList * list)424 PUBLIC void HTRequest_setError (HTRequest * me, HTList * list)
425 {
426     if (me) me->error_stack = list;
427 }
428 
429 /* begin _GM_ */
430 /* Note: libwww bug ID: GM11 */
HTRequest_deleteAllErrors(HTRequest * request)431 PUBLIC void HTRequest_deleteAllErrors (HTRequest * request)
432 {
433     HTError_deleteAll(request->error_stack);
434     HTRequest_setError(request, NULL);
435 }
436 /* end _GM_ */
437 
HTRequest_addError(HTRequest * me,HTSeverity severity,BOOL ignore,int element,void * par,unsigned int length,char * where)438 PUBLIC BOOL HTRequest_addError (HTRequest * 	me,
439 				HTSeverity	severity,
440 				BOOL		ignore,
441 				int		element,
442 				void *		par,
443 				unsigned int	length,
444 				char *		where)
445 {
446     if (me) {
447 	if (!me->error_stack) me->error_stack = HTList_new();
448 	return HTError_add(me->error_stack, severity, ignore, element,
449 			   par, length, where);
450     }
451     return NO;
452 }
453 
HTRequest_addSystemError(HTRequest * me,HTSeverity severity,int errornumber,BOOL ignore,char * syscall)454 PUBLIC BOOL HTRequest_addSystemError (HTRequest * 	me,
455 				      HTSeverity 	severity,
456 				      int		errornumber,
457 				      BOOL		ignore,
458 				      char *		syscall)
459 {
460     if (me) {
461 	if (!me->error_stack) me->error_stack = HTList_new();
462 	return HTError_addSystem(me->error_stack, severity, errornumber,
463 				 ignore, syscall);
464     }
465     return NO;
466 }
467 
468 /*
469 **  Set max number of automatic reload. Default is HT_MAX_RELOADS
470 */
HTRequest_setMaxRetry(int newmax)471 PUBLIC BOOL HTRequest_setMaxRetry (int newmax)
472 {
473     if (newmax > 0) {
474 	HTMaxRetry = newmax;
475 	return YES;
476     }
477     return NO;
478 }
479 
HTRequest_maxRetry(void)480 PUBLIC int HTRequest_maxRetry (void)
481 {
482     return HTMaxRetry;
483 }
484 
HTRequest_retrys(HTRequest * me)485 PUBLIC int HTRequest_retrys (HTRequest * me)
486 {
487     return me ? me->retrys : 0;
488 }
489 
HTRequest_addRetry(HTRequest * me)490 PUBLIC BOOL HTRequest_addRetry (HTRequest * me)
491 {
492     return (me && me->retrys++);
493 }
494 
HTRequest_AAretrys(HTRequest * me)495 PUBLIC int HTRequest_AAretrys (HTRequest * me)
496 {
497     return me ? me->AAretrys : 0;
498 }
499 
HTRequest_addAARetry(HTRequest * me)500 PUBLIC BOOL HTRequest_addAARetry (HTRequest * me)
501 {
502     return (me && me->AAretrys++);
503 }
504 
505 /*
506 **	Should we try again?
507 **	--------------------
508 **	Returns YES if we are to retry the load, NO otherwise. We check
509 **	this so that we don't go into an infinte loop
510 */
HTRequest_doRetry(HTRequest * me)511 PUBLIC BOOL HTRequest_doRetry (HTRequest * me)
512 {
513     return (me && me->retrys < HTMaxRetry-1);
514 }
515 
516 /*
517 **	Socket mode: preemptive or non-preemptive (blocking or non-blocking)
518 */
HTRequest_setPreemptive(HTRequest * me,BOOL mode)519 PUBLIC void HTRequest_setPreemptive (HTRequest * me, BOOL mode)
520 {
521     if (me) me->preemptive = mode;
522 }
523 
HTRequest_preemptive(HTRequest * me)524 PUBLIC BOOL HTRequest_preemptive (HTRequest * me)
525 {
526     return me ? me->preemptive : NO;
527 }
528 
529 /*
530 **	Should we use content negotiation?
531 */
HTRequest_setNegotiation(HTRequest * me,BOOL mode)532 PUBLIC void HTRequest_setNegotiation (HTRequest * me, BOOL mode)
533 {
534     if (me) me->ContentNegotiation = mode;
535 }
536 
HTRequest_negotiation(HTRequest * me)537 PUBLIC BOOL HTRequest_negotiation (HTRequest * me)
538 {
539     return me ? me->ContentNegotiation : NO;
540 }
541 
542 /*
543 **  Use preconditions when doing a PUT or a POST. These are the
544 **  if-* header fields that can be used to avoid version conflicts
545 **  etc.
546 */
HTRequest_setPreconditions(HTRequest * me,HTPreconditions mode)547 PUBLIC void HTRequest_setPreconditions (HTRequest * me, HTPreconditions mode)
548 {
549     if (me) me->preconditions = mode;
550 }
551 
HTRequest_preconditions(HTRequest * me)552 PUBLIC HTPreconditions HTRequest_preconditions (HTRequest * me)
553 {
554     return me ? me->preconditions : NO;
555 }
556 
557 /*
558 **	Set General Headers
559 */
HTRequest_setGnHd(HTRequest * me,HTGnHd gnhd)560 PUBLIC void HTRequest_setGnHd (HTRequest * me, HTGnHd gnhd)
561 {
562     if (me) me->GenMask = gnhd;
563 }
564 
HTRequest_addGnHd(HTRequest * me,HTGnHd gnhd)565 PUBLIC void HTRequest_addGnHd (HTRequest * me, HTGnHd gnhd)
566 {
567     if (me) me->GenMask |= gnhd;
568 }
569 
HTRequest_gnHd(HTRequest * me)570 PUBLIC HTGnHd HTRequest_gnHd (HTRequest * me)
571 {
572     return me ? me->GenMask : 0;
573 }
574 
575 /*
576 **	Set Request Headers
577 */
HTRequest_setRqHd(HTRequest * me,HTRqHd rqhd)578 PUBLIC void HTRequest_setRqHd (HTRequest * me, HTRqHd rqhd)
579 {
580     if (me) me->RequestMask = rqhd;
581 }
582 
HTRequest_addRqHd(HTRequest * me,HTRqHd rqhd)583 PUBLIC void HTRequest_addRqHd (HTRequest * me, HTRqHd rqhd)
584 {
585     if (me) me->RequestMask |= rqhd;
586 }
587 
HTRequest_rqHd(HTRequest * me)588 PUBLIC HTRqHd HTRequest_rqHd (HTRequest * me)
589 {
590     return me ? me->RequestMask : 0;
591 }
592 
593 /*
594 **	Set Response Headers
595 */
HTRequest_setRsHd(HTRequest * me,HTRsHd rshd)596 PUBLIC void HTRequest_setRsHd (HTRequest * me, HTRsHd rshd)
597 {
598     if (me) me->ResponseMask = rshd;
599 }
600 
HTRequest_addRsHd(HTRequest * me,HTRsHd rshd)601 PUBLIC void HTRequest_addRsHd (HTRequest * me, HTRsHd rshd)
602 {
603     if (me) me->ResponseMask |= rshd;
604 }
605 
HTRequest_rsHd(HTRequest * me)606 PUBLIC HTRsHd HTRequest_rsHd (HTRequest * me)
607 {
608     return me ? me->ResponseMask : 0;
609 }
610 
611 /*
612 **	Set Entity Headers (for the object)
613 */
HTRequest_setEnHd(HTRequest * me,HTEnHd enhd)614 PUBLIC void HTRequest_setEnHd (HTRequest * me, HTEnHd enhd)
615 {
616     if (me) me->EntityMask = enhd;
617 }
618 
HTRequest_addEnHd(HTRequest * me,HTEnHd enhd)619 PUBLIC void HTRequest_addEnHd (HTRequest * me, HTEnHd enhd)
620 {
621     if (me) me->EntityMask |= enhd;
622 }
623 
HTRequest_enHd(HTRequest * me)624 PUBLIC HTEnHd HTRequest_enHd (HTRequest * me)
625 {
626     return me ? me->EntityMask : 0;
627 }
628 
629 /*
630 **	Extra Header Generators. list can be NULL
631 */
HTRequest_setGenerator(HTRequest * me,HTList * generator,BOOL override)632 PUBLIC void HTRequest_setGenerator (HTRequest * me, HTList *generator,
633 				    BOOL override)
634 {
635     if (me) {
636 	me->generators = generator;
637 	me->gens_local = override;
638     }
639 }
640 
HTRequest_generator(HTRequest * me,BOOL * override)641 PUBLIC HTList * HTRequest_generator (HTRequest * me, BOOL *override)
642 {
643     if (me) {
644 	*override = me->gens_local;
645 	return me->generators;
646     }
647     return NULL;
648 }
649 
650 /*
651 **	Extra Header Parsers. list can be NULL
652 */
HTRequest_setMIMEParseSet(HTRequest * me,HTMIMEParseSet * parseSet,BOOL local)653 PUBLIC void HTRequest_setMIMEParseSet (HTRequest * me,
654 				       HTMIMEParseSet * parseSet, BOOL local)
655 {
656     if (me) {
657         me->parseSet = parseSet;
658 	me->pars_local = local;
659     }
660 }
661 
HTRequest_MIMEParseSet(HTRequest * me,BOOL * pLocal)662 PUBLIC HTMIMEParseSet * HTRequest_MIMEParseSet (HTRequest * me, BOOL * pLocal)
663 {
664     if (me) {
665         if (pLocal) *pLocal = me->pars_local;
666 	return me->parseSet;
667     }
668     return NULL;
669 }
670 
671 /*
672 **	Accept Format Types
673 **	list can be NULL
674 */
HTRequest_setConversion(HTRequest * me,HTList * type,BOOL override)675 PUBLIC void HTRequest_setConversion (HTRequest * me, HTList *type,
676 				     BOOL override)
677 {
678     if (me) {
679 	me->conversions = type;
680 	me->conv_local = override;
681     }
682 }
683 
HTRequest_conversion(HTRequest * me)684 PUBLIC HTList * HTRequest_conversion (HTRequest * me)
685 {
686     return me ? me->conversions : NULL;
687 }
688 
689 /*
690 **	Accept Encoding
691 **	list can be NULL
692 */
HTRequest_setEncoding(HTRequest * me,HTList * enc,BOOL override)693 PUBLIC void HTRequest_setEncoding (HTRequest * me, HTList *enc,
694 				   BOOL override)
695 {
696     if (me) {
697 	me->encodings = enc;
698 	me->enc_local = override;
699     }
700 }
701 
HTRequest_encoding(HTRequest * me)702 PUBLIC HTList * HTRequest_encoding (HTRequest * me)
703 {
704     return me ? me->encodings : NULL;
705 }
706 
707 /*
708 **	Accept Transfer Encoding
709 **	list can be NULL
710 */
HTRequest_setTransfer(HTRequest * me,HTList * te,BOOL override)711 PUBLIC void HTRequest_setTransfer (HTRequest * me,
712 				   HTList * te, BOOL override)
713 {
714     if (me) {
715 	me->tes = te;
716 	me->te_local = override;
717     }
718 }
719 
HTRequest_transfer(HTRequest * me)720 PUBLIC HTList * HTRequest_transfer (HTRequest * me)
721 {
722     return me ? me->tes : NULL;
723 }
724 
725 /*
726 **	Accept Language
727 **	list can be NULL
728 */
HTRequest_setLanguage(HTRequest * me,HTList * lang,BOOL override)729 PUBLIC void HTRequest_setLanguage (HTRequest * me, HTList *lang,
730 				   BOOL override)
731 {
732     if (me) {
733 	me->languages = lang;
734 	me->lang_local = override;
735     }
736 }
737 
HTRequest_language(HTRequest * me)738 PUBLIC HTList * HTRequest_language (HTRequest * me)
739 {
740     return me ? me->languages : NULL;
741 }
742 
743 /*
744 **	Accept Charset
745 **	list can be NULL
746 */
HTRequest_setCharset(HTRequest * me,HTList * charset,BOOL override)747 PUBLIC void HTRequest_setCharset (HTRequest * me, HTList *charset,
748 				  BOOL override)
749 {
750     if (me) {
751 	me->charsets = charset;
752 	me->char_local = override;
753     }
754 }
755 
HTRequest_charset(HTRequest * me)756 PUBLIC HTList * HTRequest_charset (HTRequest * me)
757 {
758     return me ? me->charsets : NULL;
759 }
760 
761 /*
762 **	Are we using the full URL in the request or not?
763 */
HTRequest_setFullURI(HTRequest * me,BOOL mode)764 PUBLIC void HTRequest_setFullURI (HTRequest * me, BOOL mode)
765 {
766     if (me) me->full_uri = mode;
767 }
768 
HTRequest_fullURI(HTRequest * me)769 PUBLIC BOOL HTRequest_fullURI (HTRequest * me)
770 {
771     return me ? me->full_uri : NO;
772 }
773 
774 /*
775 **	Are we using a proxy or not and in that case, which one?
776 */
HTRequest_setProxy(HTRequest * me,const char * proxy)777 PUBLIC BOOL HTRequest_setProxy (HTRequest * me, const char * proxy)
778 {
779     if (me && proxy) {
780 	StrAllocCopy(me->proxy, proxy);
781 	return YES;
782     }
783     return NO;
784 }
785 
HTRequest_proxy(HTRequest * me)786 PUBLIC char * HTRequest_proxy (HTRequest * me)
787 {
788     return me ? me->proxy : NULL;
789 }
790 
HTRequest_deleteProxy(HTRequest * me)791 PUBLIC BOOL HTRequest_deleteProxy (HTRequest * me)
792 {
793     if (me) {
794 	HT_FREE(me->proxy);
795 	return YES;
796     }
797     return NO;
798 }
799 
800 /*
801 **	Reload Mode
802 */
HTRequest_setReloadMode(HTRequest * me,HTReload mode)803 PUBLIC void HTRequest_setReloadMode (HTRequest * me, HTReload mode)
804 {
805     if (me) me->reload = mode;
806 }
807 
HTRequest_reloadMode(HTRequest * me)808 PUBLIC HTReload HTRequest_reloadMode (HTRequest * me)
809 {
810     return me ? me->reload : HT_CACHE_OK;
811 }
812 
813 /*      Default name to use when publishing to a "/" URL
814 **      ----------------------------
815 */
HTRequest_defaultPutName(HTRequest * me)816 PUBLIC char * HTRequest_defaultPutName (HTRequest * me)
817 {
818     if (me)
819       return (me->default_put_name);
820     return NULL;
821 }
822 
823 
HTRequest_setDefaultPutName(HTRequest * me,char * name)824 PUBLIC BOOL HTRequest_setDefaultPutName (HTRequest * me, char * name)
825 {
826     if (me && name) {
827       if (me->default_put_name)
828         HTRequest_deleteDefaultPutName (me);
829       StrAllocCopy (me->default_put_name, name);
830       return YES;
831     }
832     return NO;
833 }
834 
HTRequest_deleteDefaultPutName(HTRequest * me)835 PUBLIC BOOL HTRequest_deleteDefaultPutName (HTRequest * me)
836 {
837     if (me && me->default_put_name) {
838       HT_FREE (me->default_put_name);
839       me->default_put_name = NULL;
840       return YES;
841     }
842     return NO;
843 }
844 
845 
846 /*
847 **	Cache control directives. The cache control can be initiated by both
848 **	the server and the client which is the reason for keeping two lists
849 */
HTRequest_addCacheControl(HTRequest * me,char * token,char * value)850 PUBLIC BOOL HTRequest_addCacheControl (HTRequest * me,
851 				       char * token, char * value)
852 {
853     if (me) {
854 	if (!me->cache_control) me->cache_control = HTAssocList_new();
855 	return HTAssocList_replaceObject(me->cache_control, token, value);
856     }
857     return NO;
858 }
859 
HTRequest_deleteCacheControl(HTRequest * me)860 PUBLIC BOOL HTRequest_deleteCacheControl (HTRequest * me)
861 {
862     if (me && me->cache_control) {
863 	HTAssocList_delete(me->cache_control);
864 	me->cache_control = NULL;
865 	return YES;
866     }
867     return NO;
868 }
869 
HTRequest_cacheControl(HTRequest * me)870 PUBLIC HTAssocList * HTRequest_cacheControl (HTRequest * me)
871 {
872     return (me ? me->cache_control : NULL);
873 }
874 
875 /*
876 **  Byte ranges
877 */
HTRequest_deleteRange(HTRequest * me)878 PUBLIC BOOL HTRequest_deleteRange (HTRequest * me)
879 {
880     if (me && me->byte_ranges) {
881 	HTAssocList_delete(me->byte_ranges);
882 	me->byte_ranges = NULL;
883 	return YES;
884     }
885     return NO;
886 }
887 
HTRequest_addRange(HTRequest * me,char * unit,char * range)888 PUBLIC BOOL HTRequest_addRange (HTRequest * me, char * unit, char * range)
889 {
890     if (me) {
891 	if (!me->byte_ranges) {
892 	    me->byte_ranges = HTAssocList_new();
893 	    HTRequest_addRqHd(me, HT_C_RANGE);
894 	}
895 	return HTAssocList_replaceObject(me->byte_ranges, unit, range);
896     }
897     return NO;
898 }
899 
HTRequest_range(HTRequest * me)900 PUBLIC HTAssocList * HTRequest_range (HTRequest * me)
901 {
902     return (me ? me->byte_ranges : NULL);
903 }
904 
905 /*
906 **	Connection directives. The connection directives can be initiated by
907 **	both the server and the client which is the reason for keeping two
908 **	lists
909 */
HTRequest_addConnection(HTRequest * me,char * token,char * value)910 PUBLIC BOOL HTRequest_addConnection (HTRequest * me,
911 				     char * token, char * value)
912 {
913     if (me) {
914 	if (!me->connection) me->connection = HTAssocList_new();
915 	return HTAssocList_replaceObject(me->connection, token, value);
916     }
917     return NO;
918 }
919 
HTRequest_deleteConnection(HTRequest * me)920 PUBLIC BOOL HTRequest_deleteConnection (HTRequest * me)
921 {
922     if (me && me->connection) {
923 	HTAssocList_delete(me->connection);
924 	me->connection = NULL;
925 	return YES;
926     }
927     return NO;
928 }
929 
HTRequest_connection(HTRequest * me)930 PUBLIC HTAssocList * HTRequest_connection (HTRequest * me)
931 {
932     return (me ? me->connection : NULL);
933 }
934 
935 /*
936 **	Expect directives.
937 */
HTRequest_addExpect(HTRequest * me,char * token,char * value)938 PUBLIC BOOL HTRequest_addExpect (HTRequest * me,
939 				 char * token, char * value)
940 {
941     if (me) {
942 	if (!me->expect) me->expect = HTAssocList_new();
943 	return HTAssocList_replaceObject(me->expect, token, value);
944     }
945     return NO;
946 }
947 
HTRequest_deleteExpect(HTRequest * me)948 PUBLIC BOOL HTRequest_deleteExpect (HTRequest * me)
949 {
950     if (me && me->expect) {
951 	HTAssocList_delete(me->expect);
952 	me->expect = NULL;
953 	return YES;
954     }
955     return NO;
956 }
957 
HTRequest_expect(HTRequest * me)958 PUBLIC HTAssocList * HTRequest_expect (HTRequest * me)
959 {
960     return (me ? me->expect : NULL);
961 }
962 
963 /*
964 **  Access Authentication Credentials
965 */
HTRequest_deleteCredentialsAll(HTRequest * me)966 PUBLIC BOOL HTRequest_deleteCredentialsAll (HTRequest * me)
967 {
968     if (me && me->credentials) {
969 	HTAssocList_delete(me->credentials);
970 	me->credentials = NULL;
971 	return YES;
972     }
973     return NO;
974 }
975 
HTRequest_addCredentials(HTRequest * me,char * token,char * value)976 PUBLIC BOOL HTRequest_addCredentials (HTRequest * me,
977 				    char * token, char * value)
978 {
979     if (me) {
980 	if (!me->credentials) me->credentials = HTAssocList_new();
981 	return HTAssocList_addObject(me->credentials, token, value);
982     }
983     return NO;
984 }
985 
HTRequest_credentials(HTRequest * me)986 PUBLIC HTAssocList * HTRequest_credentials (HTRequest * me)
987 {
988     return (me ? me->credentials : NULL);
989 }
990 
991 /*
992 **  Access Authentication Realms
993 */
HTRequest_setRealm(HTRequest * me,char * realm)994 PUBLIC BOOL HTRequest_setRealm (HTRequest * me, char * realm)
995 {
996     if (me && realm && realm != me->realm) {
997 	StrAllocCopy(me->realm, realm);
998 	return YES;
999     }
1000     return NO;
1001 }
1002 
HTRequest_realm(HTRequest * me)1003 PUBLIC const char * HTRequest_realm (HTRequest * me)
1004 {
1005     return (me ? me->realm : NULL);
1006 }
1007 
HTRequest_deleteRealm(HTRequest * me)1008 PUBLIC BOOL HTRequest_deleteRealm (HTRequest * me)
1009 {
1010     if (me) {
1011 	HT_FREE(me->realm);
1012 	return YES;
1013     }
1014     return NO;
1015 }
1016 
1017 /*
1018 **  New header fields as association list
1019 */
HTRequest_addExtraHeader(HTRequest * me,char * token,char * value)1020 PUBLIC BOOL HTRequest_addExtraHeader (HTRequest * me,
1021 				      char * token, char * value)
1022 {
1023     if (me && token) {
1024 	if (!me->extra_headers) me->extra_headers = HTAssocList_new();
1025 	return HTAssocList_addObject(me->extra_headers, token, value);
1026     }
1027     return NO;
1028 }
1029 
HTRequest_extraHeader(HTRequest * me)1030 PUBLIC HTAssocList * HTRequest_extraHeader (HTRequest * me)
1031 {
1032     return (me ? me->extra_headers : NULL);
1033 }
1034 
HTRequest_deleteExtraHeaderAll(HTRequest * me)1035 PUBLIC BOOL HTRequest_deleteExtraHeaderAll (HTRequest * me)
1036 {
1037     if (me && me->extra_headers) {
1038 	HTAssocList_delete(me->extra_headers);
1039 	me->extra_headers = NULL;
1040 	return YES;
1041     }
1042     return NO;
1043 }
1044 
1045 /*
1046 **  HTTP Extension Framework
1047 */
HTRequest_addOptional(HTRequest * me,char * token,char * value)1048 PUBLIC BOOL HTRequest_addOptional (HTRequest * me,
1049 				   char * token, char * value)
1050 {
1051     if (me) {
1052 	if (!me->optional) me->optional = HTAssocList_new();
1053 	return HTAssocList_addObject(me->optional, token,value);
1054     }
1055     return NO;
1056 }
1057 
HTRequest_optional(HTRequest * me)1058 PUBLIC HTAssocList * HTRequest_optional (HTRequest * me)
1059 {
1060     return (me ? me->optional : NULL);
1061 }
1062 
HTRequest_deleteOptionalAll(HTRequest * me)1063 PUBLIC BOOL HTRequest_deleteOptionalAll (HTRequest * me)
1064 {
1065     if (me && me->optional) {
1066 	HTAssocList_delete(me->optional);
1067 	me->optional = NULL;
1068 	return YES;
1069     }
1070     return NO;
1071 }
1072 
HTRequest_addMandatory(HTRequest * me,char * token,char * value)1073 PUBLIC BOOL HTRequest_addMandatory (HTRequest * me,
1074 				    char * token, char * value)
1075 {
1076     if (me) {
1077 	if (!me->mandatory) me->mandatory = HTAssocList_new();
1078 	return HTAssocList_addObject(me->mandatory, token,value);
1079     }
1080     return NO;
1081 }
1082 
HTRequest_mandatory(HTRequest * me)1083 PUBLIC HTAssocList * HTRequest_mandatory (HTRequest * me)
1084 {
1085     return (me ? me->mandatory : NULL);
1086 }
1087 
HTRequest_deleteMandatoryAll(HTRequest * me)1088 PUBLIC BOOL HTRequest_deleteMandatoryAll (HTRequest * me)
1089 {
1090     if (me && me->mandatory) {
1091 	HTAssocList_delete(me->mandatory);
1092 	me->mandatory = NULL;
1093 	return YES;
1094     }
1095     return NO;
1096 }
1097 
1098 /*
1099 **	Anchor
1100 */
HTRequest_setAnchor(HTRequest * me,HTAnchor * anchor)1101 PUBLIC void HTRequest_setAnchor (HTRequest * me, HTAnchor *anchor)
1102 {
1103     if (me) {
1104 	me->anchor = HTAnchor_parent(anchor);
1105 	me->childAnchor = ((HTAnchor *) me->anchor != anchor) ?
1106 	    (HTChildAnchor *) anchor : NULL;
1107     }
1108 }
1109 
HTRequest_anchor(HTRequest * me)1110 PUBLIC HTParentAnchor * HTRequest_anchor (HTRequest * me)
1111 {
1112     return me ? me->anchor : NULL;
1113 }
1114 
HTRequest_childAnchor(HTRequest * me)1115 PUBLIC HTChildAnchor * HTRequest_childAnchor (HTRequest * me)
1116 {
1117     return me ? me->childAnchor : NULL;
1118 }
1119 
1120 /*
1121 **	Parent anchor for Referer field
1122 */
HTRequest_setParent(HTRequest * me,HTParentAnchor * parent)1123 PUBLIC void HTRequest_setParent (HTRequest * me, HTParentAnchor *parent)
1124 {
1125     if (me) me->parentAnchor = parent;
1126 }
1127 
HTRequest_parent(HTRequest * me)1128 PUBLIC HTParentAnchor * HTRequest_parent (HTRequest * me)
1129 {
1130     return me ? me->parentAnchor : NULL;
1131 }
1132 
1133 /*
1134 **	Output stream
1135 */
HTRequest_setOutputStream(HTRequest * me,HTStream * output)1136 PUBLIC void HTRequest_setOutputStream (HTRequest * me, HTStream *output)
1137 {
1138     if (me) {
1139 	if (output) {
1140 	    me->output_stream = HTNoFreeStream_new(output);
1141 	    me->orig_output_stream = output;
1142 	} else {
1143 	    me->output_stream = output;
1144 	}
1145     }
1146 }
1147 
HTRequest_outputStream(HTRequest * me)1148 PUBLIC HTStream *HTRequest_outputStream (HTRequest * me)
1149 {
1150     return me ? me->output_stream : NULL;
1151 }
1152 
1153 /*
1154 **	Output format
1155 */
HTRequest_setOutputFormat(HTRequest * me,HTFormat format)1156 PUBLIC void HTRequest_setOutputFormat (HTRequest * me, HTFormat format)
1157 {
1158     if (me) me->output_format = format;
1159 }
1160 
HTRequest_outputFormat(HTRequest * me)1161 PUBLIC HTFormat HTRequest_outputFormat (HTRequest * me)
1162 {
1163     return me ? me->output_format : NULL;
1164 }
1165 
1166 /*
1167 **	Debug stream
1168 */
HTRequest_setDebugStream(HTRequest * me,HTStream * debug)1169 PUBLIC void HTRequest_setDebugStream (HTRequest * me, HTStream *debug)
1170 {
1171 	if (debug) {
1172 	    me->debug_stream = HTNoFreeStream_new(debug);
1173 	    me->orig_debug_stream = debug;
1174 	} else {
1175 	    me->debug_stream = debug;
1176 	}
1177 }
1178 
HTRequest_debugStream(HTRequest * me)1179 PUBLIC HTStream *HTRequest_debugStream (HTRequest * me)
1180 {
1181     return me ? me->debug_stream : NULL;
1182 }
1183 
1184 /*
1185 **	Debug Format
1186 */
HTRequest_setDebugFormat(HTRequest * me,HTFormat format)1187 PUBLIC void HTRequest_setDebugFormat (HTRequest * me, HTFormat format)
1188 {
1189     if (me) me->debug_format = format;
1190 }
1191 
HTRequest_debugFormat(HTRequest * me)1192 PUBLIC HTFormat HTRequest_debugFormat (HTRequest * me)
1193 {
1194     return me ? me->debug_format : NULL;
1195 }
1196 
1197 /*
1198 **	Input stream
1199 */
HTRequest_setInputStream(HTRequest * me,HTStream * input)1200 PUBLIC void HTRequest_setInputStream (HTRequest * me, HTStream *input)
1201 {
1202     if (me) me->input_stream = input;
1203 }
1204 
HTRequest_inputStream(HTRequest * me)1205 PUBLIC HTStream *HTRequest_inputStream (HTRequest * me)
1206 {
1207     return me ? me->input_stream : NULL;
1208 }
1209 
1210 /*
1211 **	Net before and after callbacks
1212 */
HTRequest_addBefore(HTRequest * me,HTNetBefore * filter,const char * tmplate,void * param,HTFilterOrder order,BOOL override)1213 PUBLIC BOOL HTRequest_addBefore (HTRequest * me, HTNetBefore * filter,
1214 				 const char * tmplate, void * param,
1215 				 HTFilterOrder order, BOOL override)
1216 {
1217     if (me) {
1218 	me->befores_local = override;
1219 	if (filter) {
1220 	    if (!me->befores) me->befores = HTList_new();
1221 	    return HTNetCall_addBefore(me->befores, filter,
1222 				       tmplate, param, order);
1223 	}
1224 	return YES;			/* It's OK to register a NULL filter */
1225     }
1226     return NO;
1227 }
1228 
HTRequest_deleteBefore(HTRequest * me,HTNetBefore * filter)1229 PUBLIC BOOL HTRequest_deleteBefore (HTRequest * me, HTNetBefore * filter)
1230 {
1231     if (me && me->befores)
1232 	return HTNetCall_deleteBefore(me->befores, filter);
1233     return NO;
1234 }
1235 
HTRequest_deleteBeforeAll(HTRequest * me)1236 PUBLIC BOOL HTRequest_deleteBeforeAll (HTRequest * me)
1237 {
1238     if (me && me->befores) {
1239 	HTNetCall_deleteBeforeAll(me->befores);
1240 	me->befores = NULL;
1241 	me->befores_local = NO;
1242 	return YES;
1243     }
1244     return NO;
1245 }
1246 
HTRequest_before(HTRequest * me,BOOL * override)1247 PUBLIC HTList * HTRequest_before (HTRequest * me, BOOL *override)
1248 {
1249     if (me) {
1250 	*override = me->befores_local;
1251 	return me->befores;
1252     }
1253     return NULL;
1254 }
1255 
HTRequest_addAfter(HTRequest * me,HTNetAfter * filter,const char * tmplate,void * param,int status,HTFilterOrder order,BOOL override)1256 PUBLIC BOOL HTRequest_addAfter (HTRequest * me, HTNetAfter * filter,
1257 				const char * tmplate, void * param,
1258 				int status, HTFilterOrder order,
1259 				BOOL override)
1260 {
1261     if (me) {
1262 	me->afters_local = override;
1263 	if (filter) {
1264 	    if (!me->afters) me->afters = HTList_new();
1265 	    return HTNetCall_addAfter(me->afters, filter,
1266 				      tmplate, param, status, order);
1267 	}
1268 	return YES;			/* It's OK to register a NULL filter */
1269     }
1270     return NO;
1271 }
1272 
HTRequest_deleteAfter(HTRequest * me,HTNetAfter * filter)1273 PUBLIC BOOL HTRequest_deleteAfter (HTRequest * me, HTNetAfter * filter)
1274 {
1275     return (me && me->afters) ?
1276 	HTNetCall_deleteAfter(me->afters, filter) : NO;
1277 }
1278 
HTRequest_deleteAfterStatus(HTRequest * me,int status)1279 PUBLIC BOOL HTRequest_deleteAfterStatus (HTRequest * me, int status)
1280 {
1281     return (me && me->afters) ?
1282 	HTNetCall_deleteAfterStatus(me->afters, status) : NO;
1283 }
1284 
HTRequest_deleteAfterAll(HTRequest * me)1285 PUBLIC BOOL HTRequest_deleteAfterAll (HTRequest * me)
1286 {
1287     if (me && me->afters) {
1288 	HTNetCall_deleteAfterAll(me->afters);
1289 	me->afters = NULL;
1290 	me->afters_local = NO;
1291 	return YES;
1292     }
1293     return NO;
1294 }
1295 
HTRequest_after(HTRequest * me,BOOL * override)1296 PUBLIC HTList * HTRequest_after (HTRequest * me, BOOL *override)
1297 {
1298     if (me) {
1299 	*override = me->afters_local;
1300 	return me->afters;
1301     }
1302     return NULL;
1303 }
1304 
1305 /*
1306 **	Call back function for context swapping
1307 */
HTRequest_setCallback(HTRequest * me,HTRequestCallback * cbf)1308 PUBLIC void HTRequest_setCallback (HTRequest * me, HTRequestCallback *cbf)
1309 {
1310     if (me) me->callback = cbf;
1311 }
1312 
HTRequest_callback(HTRequest * me)1313 PUBLIC HTRequestCallback *HTRequest_callback (HTRequest * me)
1314 {
1315     return me ? me->callback : NULL;
1316 }
1317 
1318 /*
1319 **	Context pointer to be used in context call back function
1320 */
HTRequest_setContext(HTRequest * me,void * context)1321 PUBLIC void HTRequest_setContext (HTRequest * me, void *context)
1322 {
1323     if (me) me->context = context;
1324 }
1325 
HTRequest_context(HTRequest * me)1326 PUBLIC void *HTRequest_context (HTRequest * me)
1327 {
1328     return me ? me->context : NULL;
1329 }
1330 
1331 /*
1332 **	Has output stream been connected to the channel? If not then we
1333 **	must free it explicitly when deleting the request object
1334 */
HTRequest_setOutputConnected(HTRequest * me,BOOL mode)1335 PUBLIC void HTRequest_setOutputConnected (HTRequest * me, BOOL mode)
1336 {
1337     if (me) me->connected = mode;
1338 }
1339 
HTRequest_outputConnected(HTRequest * me)1340 PUBLIC BOOL HTRequest_outputConnected (HTRequest * me)
1341 {
1342     return me ? me->connected : NO;
1343 }
1344 
1345 /*
1346 **	Bytes read in this request
1347 */
HTRequest_bodyRead(HTRequest * me)1348 PUBLIC long HTRequest_bodyRead(HTRequest * me)
1349 {
1350     return me ? HTNet_bytesRead(me->net) - HTNet_headerBytesRead(me->net) : -1;
1351 }
1352 
1353 /*
1354 **	Bytes written in this request
1355 */
HTRequest_bodyWritten(HTRequest * me)1356 PUBLIC long HTRequest_bodyWritten(HTRequest * me)
1357 {
1358     return me ? HTNet_bytesWritten(me->net) - HTNet_headerBytesWritten(me->net) : -1;
1359 }
1360 
1361 /*
1362 **	Total Bytes read in this request
1363 */
HTRequest_bytesRead(HTRequest * me)1364 PUBLIC long HTRequest_bytesRead (HTRequest * me)
1365 {
1366     return me ? HTNet_bytesRead(me->net) : -1;
1367 }
1368 
1369 /*
1370 **	Bytes written in this request
1371 */
HTRequest_bytesWritten(HTRequest * me)1372 PUBLIC long HTRequest_bytesWritten (HTRequest * me)
1373 {
1374     return me ? HTNet_bytesWritten(me->net) : -1;
1375 }
1376 
1377 /*
1378 **	Handle the max forward header value
1379 */
HTRequest_setMaxForwards(HTRequest * me,int maxforwards)1380 PUBLIC BOOL HTRequest_setMaxForwards (HTRequest * me, int maxforwards)
1381 {
1382     if (me && maxforwards >= 0) {
1383 	me->max_forwards = maxforwards;
1384 	HTRequest_addRqHd(me, HT_C_MAX_FORWARDS);	       /* Turn it on */
1385 	return YES;
1386     }
1387     return NO;
1388 }
1389 
HTRequest_maxForwards(HTRequest * me)1390 PUBLIC int HTRequest_maxForwards (HTRequest * me)
1391 {
1392     return me ? me->max_forwards : -1;
1393 }
1394 
1395 /*
1396 **  Source request
1397 */
HTRequest_setSource(HTRequest * me,HTRequest * source)1398 PUBLIC BOOL HTRequest_setSource (HTRequest * me, HTRequest * source)
1399 {
1400     if (me) {
1401 	me->source = source;
1402 	return YES;
1403     }
1404     return NO;
1405 }
1406 
HTRequest_source(HTRequest * me)1407 PUBLIC HTRequest * HTRequest_source (HTRequest * me)
1408 {
1409     return (me ? me->source : NULL);
1410 }
1411 
HTRequest_isPostWeb(HTRequest * me)1412 PUBLIC BOOL HTRequest_isPostWeb (HTRequest * me)
1413 {
1414     return (me ? me->source != NULL: NO);
1415 }
1416 
1417 /*
1418 **	POST Call back function for sending data to the destination
1419 */
HTRequest_setPostCallback(HTRequest * me,HTPostCallback * cbf)1420 PUBLIC void HTRequest_setPostCallback (HTRequest * me, HTPostCallback *cbf)
1421 {
1422     if (me) me->PostCallback = cbf;
1423 }
1424 
HTRequest_postCallback(HTRequest * me)1425 PUBLIC HTPostCallback * HTRequest_postCallback (HTRequest * me)
1426 {
1427     return me ? me->PostCallback : NULL;
1428 }
1429 
1430 /*
1431 **	Entity Anchor
1432 */
HTRequest_setEntityAnchor(HTRequest * me,HTParentAnchor * anchor)1433 PUBLIC BOOL HTRequest_setEntityAnchor (HTRequest * me,
1434 				       HTParentAnchor * anchor)
1435 {
1436     if (me) {
1437 	me->source_anchor = anchor;
1438 	return YES;
1439     }
1440     return NO;
1441 }
1442 
HTRequest_entityAnchor(HTRequest * me)1443 PUBLIC HTParentAnchor * HTRequest_entityAnchor (HTRequest * me)
1444 {
1445     return me ? me->source_anchor ? me->source_anchor :
1446 	me->anchor : NULL;
1447 }
1448 
1449 /* ------------------------------------------------------------------------- */
1450 /*				POST WEB METHODS	      	 	     */
1451 /* ------------------------------------------------------------------------- */
1452 
1453 /*
1454 **  Add a destination request to this source request structure so that we
1455 **  build the internal request representation of the POST web
1456 **  Returns YES if OK, else NO
1457 */
HTRequest_addDestination(HTRequest * src,HTRequest * dest)1458 PUBLIC BOOL HTRequest_addDestination (HTRequest * src, HTRequest * dest)
1459 {
1460     if (src && dest) {
1461 	dest->source = src->source = src;
1462 	if (!src->mainDestination) {
1463 	    src->mainDestination = dest;
1464 	    src->destRequests = 1;
1465 	    HTTRACE(CORE_TRACE, "POSTWeb..... Adding dest %p to src %p\n" _
1466 			 dest _ src);
1467 	    return YES;
1468 	} else {
1469 	    if (!src->destinations) src->destinations = HTList_new();
1470 	    if (HTList_addObject(src->destinations, (void *) dest)==YES) {
1471 		src->destRequests++;
1472 		HTTRACE(CORE_TRACE, "POSTWeb..... Adding dest %p to src %p\n" _
1473 			     dest _ src);
1474 		return YES;
1475 	    }
1476 	}
1477     }
1478     return NO;
1479 }
1480 
1481 /*
1482 **  Remove a destination request from this source request structure
1483 **  Remember only to delete the internal request objects as the other
1484 **  comes from the application!
1485 **  Returns YES if OK, else NO
1486 */
HTRequest_removeDestination(HTRequest * dest)1487 PUBLIC BOOL HTRequest_removeDestination (HTRequest * dest)
1488 {
1489     BOOL found=NO;
1490     if (dest && dest->source) {
1491 	HTRequest *src = dest->source;
1492 	if (src->mainDestination == dest) {
1493 	    dest->source = NULL;
1494 	    src->mainDestination = NULL;
1495 	    src->destRequests--;
1496 	    found = YES;
1497 	} else if (src->destinations) {
1498 	    if (HTList_removeObject(src->destinations, (void *) dest)) {
1499 		src->destRequests--;
1500 		found = YES;
1501 	    }
1502 	}
1503 	if (found) {
1504 	    if (dest->internal) HTRequest_delete(dest);
1505 	    HTTRACE(CORE_TRACE, "POSTWeb..... Deleting dest %p from src %p\n" _
1506 			 dest _ src);
1507 	}
1508 	if (src->destRequests <= 0) {
1509 	    HTTRACE(CORE_TRACE, "POSTWeb..... terminated\n");
1510 	    if (src->internal) HTRequest_delete(src);
1511 	}
1512     }
1513     return found;
1514 }
1515 
1516 /*
1517 **  Check to see whether all destinations are ready. If so then enable the
1518 **  source as ready for reading.
1519 **  Returns YES if all dests are ready, NO otherwise
1520 */
HTRequest_destinationsReady(HTRequest * me)1521 PUBLIC BOOL HTRequest_destinationsReady (HTRequest * me)
1522 {
1523     HTRequest * source = me ? me->source : NULL;
1524     if (source) {
1525 	if (source->destStreams == source->destRequests) {
1526 	    HTNet * net = source->net;
1527 	    HTTRACE(CORE_TRACE, "POSTWeb..... All destinations are ready!\n");
1528 	    if (net)			      /* Might already have finished */
1529 		HTEvent_register(HTNet_socket(net), HTEvent_READ, &net->event);
1530 	    return YES;
1531 	}
1532     }
1533     return NO;
1534 }
1535 
1536 /*
1537 **  Find the source request object and make the link between the
1538 **  source output stream and the destination input stream. There can be
1539 **  a conversion between the two streams!
1540 **  Returns YES if link is made, NO otherwise
1541 */
HTRequest_linkDestination(HTRequest * dest)1542 PUBLIC BOOL HTRequest_linkDestination (HTRequest *dest)
1543 {
1544     if (dest && dest->input_stream && dest->source && dest!=dest->source) {
1545 	HTRequest *source = dest->source;
1546 	HTStream *pipe = HTStreamStack(source->output_format,
1547 				       dest->input_format,
1548 				       dest->input_stream,
1549 				       dest, YES);
1550 
1551 	/* Check if we are the only one - else spawn off T streams */
1552 	/* @@@ We don't do this yet @@@ */
1553 
1554 	/* Now set up output stream of the source */
1555 	if (source->output_stream)
1556 	    (*source->output_stream->isa->_free)(source->output_stream);
1557 	source->output_stream = pipe ? pipe : dest->input_stream;
1558 
1559 	HTTRACE(CORE_TRACE, "POSTWeb..... Linking dest %p to src %p\n" _
1560 		     dest _ source);
1561 	if (++source->destStreams == source->destRequests) {
1562 	    HTNet *net = source->net;
1563 	    HTTRACE(CORE_TRACE, "POSTWeb..... All destinations ready!\n");
1564 	    if (net)			      /* Might already have finished */
1565 		HTEvent_register(HTNet_socket(net), HTEvent_READ, &net->event);
1566 	    return YES;
1567 	}
1568     }
1569     return NO;
1570 }
1571 
1572 /*
1573 **  Remove a feed stream to a destination request from this source
1574 **  request structure. When all feeds are removed the request tree is
1575 **  ready to take down and the operation can be terminated.
1576 **  Returns YES if removed, else NO
1577 */
HTRequest_unlinkDestination(HTRequest * dest)1578 PUBLIC BOOL HTRequest_unlinkDestination (HTRequest *dest)
1579 {
1580     BOOL found = NO;
1581     if (dest && dest->source && dest != dest->source) {
1582 	HTRequest *src = dest->source;
1583 	if (src->mainDestination == dest) {
1584 	    src->output_stream = NULL;
1585 	    if (dest->input_stream)
1586 		(*dest->input_stream->isa->_free)(dest->input_stream);
1587 	    found = YES;
1588 	} else if (src->destinations) {
1589 
1590 	    /* LOOK THROUGH THE LIST AND FIND THE RIGHT ONE */
1591 
1592 	}
1593 	if (found) {
1594 	    src->destStreams--;
1595 	    HTTRACE(CORE_TRACE, "POSTWeb..... Unlinking dest %p from src %p\n" _
1596 			 dest _ src);
1597 	    return YES;
1598 	}
1599     }
1600     return NO;
1601 }
1602 
1603 /*
1604 **  Removes all request structures in this PostWeb.
1605 */
HTRequest_removePostWeb(HTRequest * me)1606 PUBLIC BOOL HTRequest_removePostWeb (HTRequest *me)
1607 {
1608     if (me && me->source) {
1609 	HTRequest *source = me->source;
1610 
1611 	/* Kill main destination */
1612 	if (source->mainDestination)
1613 	    HTRequest_removeDestination(source->mainDestination);
1614 
1615 	/* Kill all other destinations */
1616 	if (source->destinations) {
1617 	    HTList *cur = source->destinations;
1618 	    HTRequest *pres;
1619 	    while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
1620 		HTRequest_removeDestination(pres);
1621 	}
1622 
1623 	/* Remove source request */
1624 	HTRequest_removeDestination(source);
1625 	return YES;
1626     }
1627     return NO;
1628 }
1629 
1630 /*
1631 **  Kills all threads in a POST WEB connected to this request but
1632 **  NOT this request itself. We also keep the request structures.
1633 **  Some requests might be preemptive, for example a SMTP request (when
1634 **  that has been implemented). However, this will be handled internally
1635 **  in the load function.
1636 */
HTRequest_killPostWeb(HTRequest * me)1637 PUBLIC BOOL HTRequest_killPostWeb (HTRequest *me)
1638 {
1639     if (me && me->source) {
1640 	HTRequest *source = me->source;
1641 	HTTRACE(CORE_TRACE, "POSTWeb..... Killing\n");
1642 
1643 	/*
1644 	** Kill source. The stream tree is now freed so we have to build
1645 	** that again. This is done in HTRequest_linkDestination()
1646 	*/
1647 	if (me != source) {
1648 	    HTNet_kill(source->net);
1649 	    source->output_stream = NULL;
1650 	}
1651 
1652 	/* Kill all other destinations */
1653 	if (source->destinations) {
1654 	    HTList *cur = source->destinations;
1655 	    HTRequest *pres;
1656 	    while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
1657 		if (me != pres) HTNet_kill(pres->net);
1658 	}
1659 
1660 	/* Kill main destination */
1661 	if (source->mainDestination && me != source->mainDestination)
1662 	    HTNet_kill(source->mainDestination->net);
1663 	return YES;
1664     }
1665     return NO;
1666 }
1667 
HTRequest_forceFlush(HTRequest * request)1668 PUBLIC int HTRequest_forceFlush (HTRequest * request)
1669 {
1670     HTHost * host = HTNet_host(request->net);
1671     if (host == NULL) return HT_ERROR;
1672     return HTHost_forceFlush(host);
1673 }
1674 
1675 /* --------------------------------------------------------------------------*/
1676 /*				Document Loader 			     */
1677 /* --------------------------------------------------------------------------*/
1678 
1679 /*	Request a resource
1680 **	------------------
1681 **	This is an internal routine, which has an address AND a matching
1682 **	anchor.  (The public routines are called with one OR the other.)
1683 **	Returns:
1684 **		YES	if request has been registered (success)
1685 **		NO	an error occured
1686 */
HTLoad(HTRequest * me,BOOL recursive)1687 PUBLIC BOOL HTLoad (HTRequest * me, BOOL recursive)
1688 {
1689     if (!me || !me->anchor) {
1690         HTTRACE(CORE_TRACE, "Load Start.. Bad argument\n");
1691         return NO;
1692     }
1693 
1694     /* Make sure that we don't carry over any old physical address */
1695     if (!recursive) HTAnchor_clearPhysical(me->anchor);
1696 
1697     /* Set the default method if not already done */
1698     if (me->method == METHOD_INVALID) me->method = METHOD_GET;
1699 
1700     /* Should we keep the error stack or not? */
1701     if (!recursive && me->error_stack) {
1702 	HTError_deleteAll(me->error_stack);
1703 	me->error_stack = NULL;
1704     }
1705 
1706     /* Delete any old Response Object */
1707     if (me->response) {
1708 	HTResponse_delete(me->response);
1709 	me->response = NULL;
1710     }
1711 
1712     /*
1713     **  We set the start point of handling a request to here.
1714     **  This time will be used by the cache
1715     */
1716     HTRequest_setDate(me, time(NULL));
1717 
1718     /* Now start the Net Manager */
1719     return HTNet_newClient(me);
1720 }
1721 
HTServe(HTRequest * me,BOOL recursive)1722 PUBLIC BOOL HTServe (HTRequest * me, BOOL recursive)
1723 {
1724     if (!me || !me->anchor) {
1725         HTTRACE(CORE_TRACE, "Serve Start. Bad argument\n");
1726         return NO;
1727     }
1728 
1729     /* Make sure that we don't carry over any old physical address */
1730     if (!recursive) HTAnchor_clearPhysical(me->anchor);
1731 
1732     /* Should we keep the error stack or not? */
1733     if (!recursive && me->error_stack) {
1734 	HTError_deleteAll(me->error_stack);
1735 	me->error_stack = NULL;
1736     }
1737 
1738     /* Delete any old Response Object */
1739     if (me->response) {
1740 	HTResponse_delete(me->response);
1741 	me->response = NULL;
1742     }
1743 
1744     /* Now start the Net Manager */
1745     return HTNet_newServer(me);
1746 }
1747 
1748 
1749 
1750 /* --------------------------------------------------------------------------*/
1751 /*                              Message Body                                 */
1752 /* --------------------------------------------------------------------------*/
1753 
1754 /*
1755 ** This function sets the request's message body
1756 */
HTRequest_setMessageBody(HTRequest * request,const char * body)1757 PUBLIC BOOL HTRequest_setMessageBody (HTRequest * request, const char * body) {
1758 #ifdef HT_EXT
1759 
1760     if (request && body && *body){
1761         StrAllocCopy (request->messageBody,body);
1762         return YES;
1763     }
1764 #endif /* HT_EXT */
1765     return NO;
1766 }
1767 
1768 /*
1769 ** This function deletes the message body, freeing the string and
1770 ** setting it to NULL.
1771 */
HTRequest_deleteMessageBody(HTRequest * request)1772 PUBLIC BOOL HTRequest_deleteMessageBody (HTRequest * request) {
1773 #ifdef HT_EXT
1774     if (request && request->messageBody) {
1775         HT_FREE (request->messageBody);
1776         request->messageBody = NULL;
1777         return YES;
1778     }
1779 #endif /* HT_EXT */
1780     return NO;
1781 }
1782 
1783 /*
1784 ** This function creates a copy of the message body
1785 */
HTRequest_messageBody(HTRequest * request)1786 PUBLIC char * HTRequest_messageBody (HTRequest * request) {
1787     char * bodycopy = NULL;
1788 
1789 #ifdef HT_EXT
1790     if (request && request->messageBody && *(request->messageBody))
1791         StrAllocCopy(bodycopy,request->messageBody);
1792 #endif /* HT_EXT */
1793 
1794     return bodycopy;
1795 }
1796 
1797 
1798 /*
1799 ** This function sets the length of the body. This length will be
1800 ** used to set Content-Length header.
1801 ** Note: length should be greater than 0, and the Content-Length
1802 ** header will be created only if there is a message Body.
1803 */
HTRequest_setMessageBodyLength(HTRequest * request,long int length)1804 PUBLIC BOOL HTRequest_setMessageBodyLength (HTRequest * request, long int length) {
1805 #ifdef HT_EXT
1806     if (request && length > 0) {
1807         request->messageBodyLength = length;
1808         return YES;
1809     }
1810 #endif /* HT_EXT */
1811 
1812     return NO;
1813 }
1814 
1815 
1816 /*
1817 ** This function returns the message body length,
1818 ** or -1 if it is not set.
1819 */
HTRequest_messageBodyLength(HTRequest * request)1820 PUBLIC long int HTRequest_messageBodyLength (HTRequest * request) {
1821 #ifdef HT_EXT
1822     return (request && (request->messageBody && request->messageBodyLength))?
1823                         request->messageBodyLength:-1;
1824 #else
1825     return -1;
1826 #endif
1827 }
1828 
1829 
1830 /*
1831 ** This function sets the format of the message body to be used
1832 ** in the Content-Type header.
1833 ** Note: the Content-Type header will be created only if there is a
1834 ** message body set.
1835 */
HTRequest_setMessageBodyFormat(HTRequest * request,HTFormat format)1836 PUBLIC BOOL HTRequest_setMessageBodyFormat (HTRequest * request, HTFormat format) {
1837 
1838 #ifdef HT_EXT
1839     if (request && format) {
1840         request->messageBodyFormat = format;
1841         return YES;
1842     }
1843 #endif /*HT_EXT*/
1844     return NO;
1845 }
1846 
1847 
1848 /*
1849 ** This function returns the format of the message body, or
1850 ** NULL if it is not set.
1851 */
HTRequest_messageBodyFormat(HTRequest * request)1852 PUBLIC HTFormat HTRequest_messageBodyFormat (HTRequest * request) {
1853 #ifdef HT_EXT
1854     if (request && request->messageBodyFormat)
1855         return request->messageBodyFormat;
1856     else
1857 #endif /*HT_EXT*/
1858 	return NULL;
1859 }
1860 
1861