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