initialize encoding to SOUP_TRANSFER_CONTENT_LENGTH rather than
[platform/upstream/libsoup.git] / libsoup / soup-message.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-message.c: HTTP request/response
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "soup-auth.h"
12 #include "soup-marshal.h"
13 #include "soup-message.h"
14 #include "soup-message-private.h"
15 #include "soup-misc.h"
16 #include "soup-server-message.h"
17 #include "soup-uri.h"
18
19 G_DEFINE_TYPE (SoupMessage, soup_message, G_TYPE_OBJECT)
20
21 enum {
22         WROTE_INFORMATIONAL,
23         WROTE_HEADERS,
24         WROTE_CHUNK,
25         WROTE_BODY,
26
27         GOT_INFORMATIONAL,
28         GOT_HEADERS,
29         GOT_CHUNK,
30         GOT_BODY,
31
32         RESTARTED,
33         FINISHED,
34
35         LAST_SIGNAL
36 };
37
38 static guint signals[LAST_SIGNAL] = { 0 };
39
40 static void wrote_body (SoupMessage *req);
41 static void got_headers (SoupMessage *req);
42 static void got_chunk (SoupMessage *req);
43 static void got_body (SoupMessage *req);
44 static void restarted (SoupMessage *req);
45 static void finished (SoupMessage *req);
46 static void free_chunks (SoupMessage *msg);
47
48 static void
49 soup_message_init (SoupMessage *msg)
50 {
51         msg->status  = SOUP_MESSAGE_STATUS_IDLE;
52
53         msg->request_headers = g_hash_table_new (soup_str_case_hash,
54                                                  soup_str_case_equal);
55
56         msg->response_headers = g_hash_table_new (soup_str_case_hash,
57                                                   soup_str_case_equal);
58
59         SOUP_MESSAGE_GET_PRIVATE (msg)->http_version = SOUP_HTTP_1_1;
60 }
61
62 static void
63 finalize (GObject *object)
64 {
65         SoupMessage *msg = SOUP_MESSAGE (object);
66         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
67
68         soup_message_io_stop (msg);
69
70         if (priv->uri)
71                 soup_uri_free (priv->uri);
72
73         if (msg->request.owner == SOUP_BUFFER_SYSTEM_OWNED)
74                 g_free (msg->request.body);
75         if (msg->response.owner == SOUP_BUFFER_SYSTEM_OWNED)
76                 g_free (msg->response.body);
77         free_chunks (msg);
78
79         soup_message_clear_headers (msg->request_headers);
80         g_hash_table_destroy (msg->request_headers);
81
82         soup_message_clear_headers (msg->response_headers);
83         g_hash_table_destroy (msg->response_headers);
84
85         g_slist_foreach (priv->content_handlers, (GFunc) g_free, NULL);
86         g_slist_free (priv->content_handlers);
87
88         g_free ((char *) msg->reason_phrase);
89
90         G_OBJECT_CLASS (soup_message_parent_class)->finalize (object);
91 }
92
93 static void
94 soup_message_class_init (SoupMessageClass *message_class)
95 {
96         GObjectClass *object_class = G_OBJECT_CLASS (message_class);
97
98         g_type_class_add_private (message_class, sizeof (SoupMessagePrivate));
99
100         /* virtual method definition */
101         message_class->wrote_body   = wrote_body;
102         message_class->got_headers  = got_headers;
103         message_class->got_chunk    = got_chunk;
104         message_class->got_body     = got_body;
105         message_class->restarted    = restarted;
106         message_class->finished     = finished;
107
108         /* virtual method override */
109         object_class->finalize = finalize;
110
111         /* signals */
112
113         /**
114          * SoupMessage::wrote-informational:
115          * @msg: the message
116          *
117          * Emitted immediately after writing a 1xx (Informational)
118          * response for a message.
119          **/
120         signals[WROTE_INFORMATIONAL] =
121                 g_signal_new ("wrote_informational",
122                               G_OBJECT_CLASS_TYPE (object_class),
123                               G_SIGNAL_RUN_FIRST,
124                               G_STRUCT_OFFSET (SoupMessageClass, wrote_informational),
125                               NULL, NULL,
126                               soup_marshal_NONE__NONE,
127                               G_TYPE_NONE, 0);
128
129         /**
130          * SoupMessage::wrote-headers:
131          * @msg: the message
132          *
133          * Emitted immediately after writing the headers for a message.
134          **/
135         signals[WROTE_HEADERS] =
136                 g_signal_new ("wrote_headers",
137                               G_OBJECT_CLASS_TYPE (object_class),
138                               G_SIGNAL_RUN_FIRST,
139                               G_STRUCT_OFFSET (SoupMessageClass, wrote_headers),
140                               NULL, NULL,
141                               soup_marshal_NONE__NONE,
142                               G_TYPE_NONE, 0);
143
144         /**
145          * SoupMessage::wrote-chunk:
146          * @msg: the message
147          *
148          * Emitted immediately after writing a body chunk for a message.
149          * (This is
150          **/
151         signals[WROTE_CHUNK] =
152                 g_signal_new ("wrote_chunk",
153                               G_OBJECT_CLASS_TYPE (object_class),
154                               G_SIGNAL_RUN_FIRST,
155                               G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk),
156                               NULL, NULL,
157                               soup_marshal_NONE__NONE,
158                               G_TYPE_NONE, 0);
159
160         /**
161          * SoupMessage::wrote-body:
162          * @msg: the message
163          *
164          * Emitted immediately after writing the complete body for a message.
165          **/
166         signals[WROTE_BODY] =
167                 g_signal_new ("wrote_body",
168                               G_OBJECT_CLASS_TYPE (object_class),
169                               G_SIGNAL_RUN_FIRST,
170                               G_STRUCT_OFFSET (SoupMessageClass, wrote_body),
171                               NULL, NULL,
172                               soup_marshal_NONE__NONE,
173                               G_TYPE_NONE, 0);
174
175         /**
176          * SoupMessage::got-informational:
177          * @msg: the message
178          *
179          * Emitted after receiving a 1xx (Informational) response for
180          * a message.
181          **/
182         signals[GOT_INFORMATIONAL] =
183                 g_signal_new ("got_informational",
184                               G_OBJECT_CLASS_TYPE (object_class),
185                               G_SIGNAL_RUN_FIRST,
186                               G_STRUCT_OFFSET (SoupMessageClass, got_informational),
187                               NULL, NULL,
188                               soup_marshal_NONE__NONE,
189                               G_TYPE_NONE, 0);
190
191         /**
192          * SoupMessage::got-headers:
193          * @msg: the message
194          *
195          * Emitted after receiving all message headers for a message.
196          **/
197         signals[GOT_HEADERS] =
198                 g_signal_new ("got_headers",
199                               G_OBJECT_CLASS_TYPE (object_class),
200                               G_SIGNAL_RUN_FIRST,
201                               G_STRUCT_OFFSET (SoupMessageClass, got_headers),
202                               NULL, NULL,
203                               soup_marshal_NONE__NONE,
204                               G_TYPE_NONE, 0);
205
206         /**
207          * SoupMessage::got-chunk:
208          * @msg: the message
209          *
210          * Emitted after receiving a chunk of a message body. Note
211          * that "chunk" in this context means any subpiece of the
212          * body, not necessarily the specific HTTP 1.1 chunks sent by
213          * the other side.
214          **/
215         signals[GOT_CHUNK] =
216                 g_signal_new ("got_chunk",
217                               G_OBJECT_CLASS_TYPE (object_class),
218                               G_SIGNAL_RUN_FIRST,
219                               G_STRUCT_OFFSET (SoupMessageClass, got_chunk),
220                               NULL, NULL,
221                               soup_marshal_NONE__NONE,
222                               G_TYPE_NONE, 0);
223
224         /**
225          * SoupMessage::got-body:
226          * @msg: the message
227          *
228          * Emitted after receiving the complete message body.
229          **/
230         signals[GOT_BODY] =
231                 g_signal_new ("got_body",
232                               G_OBJECT_CLASS_TYPE (object_class),
233                               G_SIGNAL_RUN_FIRST,
234                               G_STRUCT_OFFSET (SoupMessageClass, got_body),
235                               NULL, NULL,
236                               soup_marshal_NONE__NONE,
237                               G_TYPE_NONE, 0);
238
239         /**
240          * SoupMessage::restarted:
241          * @msg: the message
242          *
243          * Emitted when a message is about to be re-queued.
244          **/
245         signals[RESTARTED] =
246                 g_signal_new ("restarted",
247                               G_OBJECT_CLASS_TYPE (object_class),
248                               G_SIGNAL_RUN_FIRST,
249                               G_STRUCT_OFFSET (SoupMessageClass, restarted),
250                               NULL, NULL,
251                               soup_marshal_NONE__NONE,
252                               G_TYPE_NONE, 0);
253
254         /**
255          * SoupMessage::finished:
256          * @msg: the message
257          *
258          * Emitted when all HTTP processing is finished for a message.
259          * (After #read-body for client-side code, or after
260          * #wrote-body for server-side code.)
261          **/
262         signals[FINISHED] =
263                 g_signal_new ("finished",
264                               G_OBJECT_CLASS_TYPE (object_class),
265                               G_SIGNAL_RUN_FIRST,
266                               G_STRUCT_OFFSET (SoupMessageClass, finished),
267                               NULL, NULL,
268                               soup_marshal_NONE__NONE,
269                               G_TYPE_NONE, 0);
270 }
271
272
273 /**
274  * soup_message_new:
275  * @method: the HTTP method for the created request
276  * @uri_string: the destination endpoint (as a string)
277  * 
278  * Creates a new empty #SoupMessage, which will connect to @uri
279  *
280  * Return value: the new #SoupMessage (or %NULL if @uri could not
281  * be parsed).
282  */
283 SoupMessage *
284 soup_message_new (const char *method, const char *uri_string)
285 {
286         SoupMessage *msg;
287         SoupUri *uri;
288
289         uri = soup_uri_new (uri_string);
290         if (!uri)
291                 return NULL;
292
293         if (!uri->host) {
294                 soup_uri_free (uri);
295                 return NULL;
296         }
297
298         msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
299         msg->method = method ? method : SOUP_METHOD_GET;
300         SOUP_MESSAGE_GET_PRIVATE (msg)->uri = uri;
301
302         return msg;
303 }
304
305 /**
306  * soup_message_new_from_uri:
307  * @method: the HTTP method for the created request
308  * @uri: the destination endpoint (as a #SoupUri)
309  * 
310  * Creates a new empty #SoupMessage, which will connect to @uri
311  *
312  * Return value: the new #SoupMessage
313  */
314 SoupMessage *
315 soup_message_new_from_uri (const char *method, const SoupUri *uri)
316 {
317         SoupMessage *msg;
318
319         msg = g_object_new (SOUP_TYPE_MESSAGE, NULL);
320         msg->method = method ? method : SOUP_METHOD_GET;
321         SOUP_MESSAGE_GET_PRIVATE (msg)->uri = soup_uri_copy (uri);
322
323         return msg;
324 }
325
326 /**
327  * soup_message_set_request:
328  * @msg: the message
329  * @content_type: MIME Content-Type of the body
330  * @req_owner: the #SoupOwnership of the passed data buffer.
331  * @req_body: a data buffer containing the body of the message request.
332  * @req_length: the byte length of @req_body.
333  * 
334  * Convenience function to set the request body of a #SoupMessage
335  */
336 void
337 soup_message_set_request (SoupMessage   *msg,
338                           const char    *content_type,
339                           SoupOwnership  req_owner,
340                           char          *req_body,
341                           gulong         req_length)
342 {
343         g_return_if_fail (SOUP_IS_MESSAGE (msg));
344         g_return_if_fail (content_type != NULL);
345         g_return_if_fail (req_body != NULL || req_length == 0);
346
347         soup_message_add_header (msg->request_headers,
348                                  "Content-Type", content_type);
349         msg->request.owner = req_owner;
350         msg->request.body = req_body;
351         msg->request.length = req_length;
352 }
353
354 /**
355  * soup_message_set_response:
356  * @msg: the message
357  * @content_type: MIME Content-Type of the body
358  * @resp_owner: the #SoupOwnership of the passed data buffer.
359  * @resp_body: a data buffer containing the body of the message response.
360  * @resp_length: the byte length of @resp_body.
361  * 
362  * Convenience function to set the response body of a #SoupMessage
363  */
364 void
365 soup_message_set_response (SoupMessage   *msg,
366                            const char    *content_type,
367                            SoupOwnership  resp_owner,
368                            char          *resp_body,
369                            gulong         resp_length)
370 {
371         g_return_if_fail (SOUP_IS_MESSAGE (msg));
372         g_return_if_fail (content_type != NULL);
373         g_return_if_fail (resp_body != NULL || resp_length == 0);
374
375         soup_message_add_header (msg->response_headers,
376                                  "Content-Type", content_type);
377         msg->response.owner = resp_owner;
378         msg->response.body = resp_body;
379         msg->response.length = resp_length;
380 }
381
382 /**
383  * soup_message_wrote_informational:
384  * @msg: a #SoupMessage
385  *
386  * Emits the %wrote_informational signal, indicating that the IO layer
387  * finished writing an informational (1xx) response for @msg.
388  **/
389 void
390 soup_message_wrote_informational (SoupMessage *msg)
391 {
392         g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0);
393 }
394
395 /**
396  * soup_message_wrote_headers:
397  * @msg: a #SoupMessage
398  *
399  * Emits the %wrote_headers signal, indicating that the IO layer
400  * finished writing the (non-informational) headers for @msg.
401  **/
402 void
403 soup_message_wrote_headers (SoupMessage *msg)
404 {
405         g_signal_emit (msg, signals[WROTE_HEADERS], 0);
406 }
407
408 /**
409  * soup_message_wrote_chunk:
410  * @msg: a #SoupMessage
411  *
412  * Emits the %wrote_chunk signal, indicating that the IO layer
413  * finished writing a chunk of @msg's body.
414  **/
415 void
416 soup_message_wrote_chunk (SoupMessage *msg)
417 {
418         g_signal_emit (msg, signals[WROTE_CHUNK], 0);
419 }
420
421 static void
422 wrote_body (SoupMessage *req)
423 {
424         g_object_ref (req);
425         soup_message_run_handlers (req, SOUP_HANDLER_POST_REQUEST);
426         g_object_unref (req);
427 }
428
429 /**
430  * soup_message_wrote_body:
431  * @msg: a #SoupMessage
432  *
433  * Emits the %wrote_body signal, indicating that the IO layer finished
434  * writing the body for @msg.
435  **/
436 void
437 soup_message_wrote_body (SoupMessage *msg)
438 {
439         g_signal_emit (msg, signals[WROTE_BODY], 0);
440 }
441
442 /**
443  * soup_message_got_informational:
444  * @msg: a #SoupMessage
445  *
446  * Emits the %got_informational signal, indicating that the IO layer
447  * read a complete informational (1xx) response for @msg.
448  **/
449 void
450 soup_message_got_informational (SoupMessage *msg)
451 {
452         g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0);
453 }
454
455 static void
456 got_headers (SoupMessage *req)
457 {
458         g_object_ref (req);
459         soup_message_run_handlers (req, SOUP_HANDLER_PRE_BODY);
460         if (SOUP_MESSAGE_IS_STARTING (req))
461                 g_signal_stop_emission (req, signals[GOT_HEADERS], 0);
462         g_object_unref (req);
463 }
464
465 /**
466  * soup_message_got_headers:
467  * @msg: a #SoupMessage
468  *
469  * Emits the %got_headers signal, indicating that the IO layer
470  * finished reading the (non-informational) headers for @msg.
471  **/
472 void
473 soup_message_got_headers (SoupMessage *msg)
474 {
475         g_signal_emit (msg, signals[GOT_HEADERS], 0);
476 }
477
478 static void
479 got_chunk (SoupMessage *req)
480 {
481         g_object_ref (req);
482         soup_message_run_handlers (req, SOUP_HANDLER_BODY_CHUNK);
483         if (SOUP_MESSAGE_IS_STARTING (req))
484                 g_signal_stop_emission (req, signals[GOT_CHUNK], 0);
485         g_object_unref (req);
486 }
487
488 /**
489  * soup_message_got_chunk:
490  * @msg: a #SoupMessage
491  *
492  * Emits the %got_chunk signal, indicating that the IO layer finished
493  * reading a chunk of @msg's body.
494  **/
495 void
496 soup_message_got_chunk (SoupMessage *msg)
497 {
498         g_signal_emit (msg, signals[GOT_CHUNK], 0);
499 }
500
501 static void
502 got_body (SoupMessage *req)
503 {
504         g_object_ref (req);
505         soup_message_run_handlers (req, SOUP_HANDLER_POST_BODY);
506         if (SOUP_MESSAGE_IS_STARTING (req))
507                 g_signal_stop_emission (req, signals[GOT_BODY], 0);
508         g_object_unref (req);
509 }
510
511 /**
512  * soup_message_got_body:
513  * @msg: a #SoupMessage
514  *
515  * Emits the %got_body signal, indicating that the IO layer finished
516  * reading the body for @msg.
517  **/
518 void
519 soup_message_got_body (SoupMessage *msg)
520 {
521         g_signal_emit (msg, signals[GOT_BODY], 0);
522 }
523
524 static void
525 restarted (SoupMessage *req)
526 {
527         soup_message_io_stop (req);
528 }
529
530 /**
531  * soup_message_restarted:
532  * @msg: a #SoupMessage
533  *
534  * Emits the %restarted signal, indicating that @msg should be
535  * requeued.
536  **/
537 void
538 soup_message_restarted (SoupMessage *msg)
539 {
540         g_signal_emit (msg, signals[RESTARTED], 0);
541 }
542
543 static void
544 finished (SoupMessage *req)
545 {
546         soup_message_io_stop (req);
547         req->status = SOUP_MESSAGE_STATUS_FINISHED;
548 }
549
550 /**
551  * soup_message_finished:
552  * @msg: a #SoupMessage
553  *
554  * Emits the %finished signal, indicating that @msg has been completely
555  * processed.
556  **/
557 void
558 soup_message_finished (SoupMessage *msg)
559 {
560         g_signal_emit (msg, signals[FINISHED], 0);
561 }
562
563 static gboolean
564 free_header_list (gpointer name, gpointer vals, gpointer user_data)
565 {
566         g_free (name);
567         g_slist_foreach (vals, (GFunc) g_free, NULL);
568         g_slist_free (vals);
569
570         return TRUE;
571 }
572
573 /**
574  * soup_message_clear_headers:
575  * @hash: a header table (the %request_headers or %response_headers
576  * field of a #SoupMessage)
577  *
578  * Clears @hash.
579  **/
580 void
581 soup_message_clear_headers (GHashTable *hash)
582 {
583         g_return_if_fail (hash != NULL);
584
585         g_hash_table_foreach_remove (hash, free_header_list, NULL);
586 }
587
588 /**
589  * soup_message_remove_header:
590  * @hash: a header table (the %request_headers or %response_headers
591  * field of a #SoupMessage)
592  * @name: the header name to remove
593  *
594  * Removes @name from @hash. If there are multiple values for @name,
595  * they are all removed.
596  **/
597 void
598 soup_message_remove_header (GHashTable *hash, const char *name)
599 {
600         gpointer old_key, old_vals;
601
602         g_return_if_fail (hash != NULL);
603         g_return_if_fail (name != NULL || name[0] != '\0');
604
605         if (g_hash_table_lookup_extended (hash, name, &old_key, &old_vals)) {
606                 g_hash_table_remove (hash, name);
607                 free_header_list (old_key, old_vals, NULL);
608         }
609 }
610
611 /**
612  * soup_message_add_header:
613  * @hash: a header table (the %request_headers or %response_headers
614  * field of a #SoupMessage)
615  * @name: the header name to add
616  * @value: the value of the new header
617  *
618  * Adds a header with name @name and value @value to @hash. If there
619  * was already a header with name @name, this one does not replace it,
620  * it is merely added to it.
621  **/
622 void
623 soup_message_add_header (GHashTable *hash, const char *name, const char *value)
624 {
625         GSList *old_value;
626
627         g_return_if_fail (hash != NULL);
628         g_return_if_fail (name != NULL || name [0] != '\0');
629         g_return_if_fail (value != NULL);
630
631         old_value = g_hash_table_lookup (hash, name);
632
633         if (old_value)
634                 g_slist_append (old_value, g_strdup (value));
635         else {
636                 g_hash_table_insert (hash, g_strdup (name),
637                                      g_slist_append (NULL, g_strdup (value)));
638         }
639 }
640
641 /**
642  * soup_message_get_header:
643  * @hash: a header table (the %request_headers or %response_headers
644  * field of a #SoupMessage)
645  * @name: header name.
646  * 
647  * Finds the first header in @hash with name @name.
648  * 
649  * Return value: the header's value or %NULL if not found.
650  **/
651 const char *
652 soup_message_get_header (GHashTable *hash, const char *name)
653 {
654         GSList *vals;
655
656         g_return_val_if_fail (hash != NULL, NULL);
657         g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
658
659         vals = g_hash_table_lookup (hash, name);
660         if (vals)
661                 return vals->data;
662
663         return NULL;
664 }
665
666 /**
667  * soup_message_get_header_list:
668  * @hash: a header table (the %request_headers or %response_headers
669  * field of a #SoupMessage)
670  * @name: header name.
671  * 
672  * Finds all headers in @hash with name @name.
673  * 
674  * Return value: a (possibly empty) list of values of headers with
675  * name @name. The caller should not modify or free this list.
676  **/
677 const GSList *
678 soup_message_get_header_list (GHashTable *hash, const char *name)
679 {
680         g_return_val_if_fail (hash != NULL, NULL);
681         g_return_val_if_fail (name != NULL || name [0] != '\0', NULL);
682
683         return g_hash_table_lookup (hash, name);
684 }
685
686 typedef struct {
687         GHFunc   func;
688         gpointer user_data;
689 } SoupMessageForeachHeaderData;
690
691 static void
692 foreach_value_in_list (gpointer name, gpointer value, gpointer user_data)
693 {
694         GSList *vals = value;
695         SoupMessageForeachHeaderData *data = user_data;
696
697         while (vals) {
698                 (*data->func) (name, vals->data, data->user_data);
699                 vals = vals->next;
700         }
701 }
702
703 /**
704  * soup_message_foreach_header:
705  * @hash: a header table (the %request_headers or %response_headers
706  * field of a #SoupMessage)
707  * @func: callback function to run for each header
708  * @user_data: data to pass to @func
709  * 
710  * Calls @func once for each header value in @hash. (If there are
711  * headers will multiple values, @func will be called once on each
712  * value.)
713  **/
714 void
715 soup_message_foreach_header (GHashTable *hash, GHFunc func, gpointer user_data)
716 {
717         SoupMessageForeachHeaderData data;
718
719         g_return_if_fail (hash != NULL);
720         g_return_if_fail (func != NULL);
721
722         data.func = func;
723         data.user_data = user_data;
724         g_hash_table_foreach (hash, foreach_value_in_list, &data);
725 }
726
727 /**
728  * soup_message_cleanup_response:
729  * @req: a #SoupMessage
730  *
731  * Cleans up all response data on @req, so that the request can be sent
732  * again and receive a new response. (Eg, as a result of a redirect or
733  * authorization request.)
734  **/
735 void
736 soup_message_cleanup_response (SoupMessage *req)
737 {
738         if (req->response.owner == SOUP_BUFFER_SYSTEM_OWNED)
739                 g_free (req->response.body);
740
741         req->response.owner = 0;
742         req->response.body = NULL;
743         req->response.length = 0;
744
745         free_chunks (req);
746
747         soup_message_clear_headers (req->response_headers);
748
749         req->status_code = SOUP_STATUS_NONE;
750         if (req->reason_phrase) {
751                 g_free ((char *) req->reason_phrase);
752                 req->reason_phrase = NULL;
753         }
754 }
755
756 /**
757  * soup_message_set_flags:
758  * @msg: a #SoupMessage
759  * @flags: a set of #SoupMessageFlags values
760  *
761  * Sets the specified flags on @msg.
762  **/
763 void
764 soup_message_set_flags (SoupMessage *msg, guint flags)
765 {
766         g_return_if_fail (SOUP_IS_MESSAGE (msg));
767
768         SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags = flags;
769 }
770
771 /**
772  * soup_message_get_flags:
773  * @msg: a #SoupMessage
774  *
775  * Gets the flags on @msg
776  *
777  * Return value: the flags
778  **/
779 guint
780 soup_message_get_flags (SoupMessage *msg)
781 {
782         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
783
784         return SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags;
785 }
786
787 /**
788  * soup_message_set_http_version:
789  * @msg: a #SoupMessage
790  * @version: the HTTP version
791  *
792  * Sets the HTTP version on @msg. The default version is
793  * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain
794  * functionality from being used.
795  **/
796 void
797 soup_message_set_http_version (SoupMessage *msg, SoupHttpVersion version)
798 {
799         g_return_if_fail (SOUP_IS_MESSAGE (msg));
800
801         SOUP_MESSAGE_GET_PRIVATE (msg)->http_version = version;
802 }
803
804 /**
805  * soup_message_get_http_version:
806  * @msg: a #SoupMessage
807  *
808  * Gets the HTTP version of @msg. This is the minimum of the
809  * version from the request and the version from the response.
810  *
811  * Return value: the HTTP version
812  **/
813 SoupHttpVersion
814 soup_message_get_http_version (SoupMessage *msg)
815 {
816         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_HTTP_1_0);
817
818         return SOUP_MESSAGE_GET_PRIVATE (msg)->http_version;
819 }
820
821 /**
822  * soup_message_is_keepalive:
823  * @msg: a #SoupMessage
824  *
825  * Determines whether or not @msg's connection can be kept alive for
826  * further requests after processing @msg.
827  *
828  * Return value: %TRUE or %FALSE.
829  **/
830 gboolean
831 soup_message_is_keepalive (SoupMessage *msg)
832 {
833         const char *c_conn, *s_conn;
834
835         c_conn = soup_message_get_header (msg->request_headers, "Connection");
836         s_conn = soup_message_get_header (msg->response_headers, "Connection");
837
838         if (msg->status_code == SOUP_STATUS_OK &&
839             soup_method_get_id (msg->method) == SOUP_METHOD_ID_CONNECT)
840                 return TRUE;
841
842         if (SOUP_MESSAGE_GET_PRIVATE (msg)->http_version == SOUP_HTTP_1_0) {
843                 /* Only persistent if the client requested keepalive
844                  * and the server agreed.
845                  */
846
847                 if (!c_conn || !s_conn)
848                         return FALSE;
849                 if (g_ascii_strcasecmp (c_conn, "Keep-Alive") != 0 ||
850                     g_ascii_strcasecmp (s_conn, "Keep-Alive") != 0)
851                         return FALSE;
852
853                 return TRUE;
854         } else {
855                 /* Normally persistent unless either side requested otherwise */
856                 if (c_conn && g_ascii_strcasecmp (c_conn, "close") == 0)
857                         return FALSE;
858                 if (s_conn && g_ascii_strcasecmp (s_conn, "close") == 0)
859                         return FALSE;
860
861                 /* But not if the server sent a terminate-by-EOF response */
862                 if (soup_message_get_response_encoding (msg, NULL) == SOUP_TRANSFER_EOF)
863                         return FALSE;
864
865                 return TRUE;
866         }
867 }
868
869 /**
870  * soup_message_set_uri:
871  * @msg: a #SoupMessage
872  * @uri: the new #SoupUri
873  *
874  * Changes the URI that @msg is directed to (generally as a result
875  * of a redirect).
876  **/
877 void
878 soup_message_set_uri (SoupMessage *msg, const SoupUri *uri)
879 {
880         SoupMessagePrivate *priv;
881
882         g_return_if_fail (SOUP_IS_MESSAGE (msg));
883         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
884
885         if (priv->uri && uri) {
886                 if (strcmp (priv->uri->host, uri->host) != 0)
887                         soup_message_io_stop (msg);
888         } else if (!uri)
889                 soup_message_io_stop (msg);
890
891         if (priv->uri)
892                 soup_uri_free (priv->uri);
893         priv->uri = soup_uri_copy (uri);
894 }
895
896 /**
897  * soup_message_get_uri:
898  * @msg: a #SoupMessage
899  *
900  * Gets @msg's URI
901  *
902  * Return value: the URI @msg is targeted for.
903  **/
904 const SoupUri *
905 soup_message_get_uri (SoupMessage *msg)
906 {
907         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
908
909         return SOUP_MESSAGE_GET_PRIVATE (msg)->uri;
910 }
911
912 /**
913  * soup_message_get_request_encoding:
914  * @msg: a #SoupMessage
915  * @content_length: a pointer to store the Content-Length in (or
916  * %NULL).
917  *
918  * Gets @msg's request encoding. For an outgoing (client) request,
919  * this is only valid after the message has been fully set up (from
920  * the library's perspective, that means not until the message has
921  * been queued). For an incoming (server) request, this is valid after
922  * the request headers have been read and @msg->request_headers filled
923  * in.
924  *
925  * Return value: the request encoding (which cannot be
926  * %SOUP_TRANSFER_UNKNOWN or %SOUP_TRANSFER_EOF). If it is
927  * %SOUP_TRANSFER_CONTENT_LENGTH, *@content_length will be set to the
928  * request body's length.
929  **/
930 SoupTransferEncoding
931 soup_message_get_request_encoding  (SoupMessage *msg, guint *content_length)
932 {
933         if (SOUP_IS_SERVER_MESSAGE (msg)) {
934                 const char *enc, *len;
935
936                 enc = soup_message_get_header (msg->request_headers,
937                                                "Transfer-Encoding");
938                 len = soup_message_get_header (msg->request_headers,
939                                                "Content-Length");
940                 if (enc) {
941                         if (g_ascii_strcasecmp (enc, "chunked") == 0)
942                                 return SOUP_TRANSFER_CHUNKED;
943                         else
944                                 return SOUP_TRANSFER_UNKNOWN;
945                 } else if (len) {
946                         int lval = atoi (len);
947
948                         if (lval < 0)
949                                 return SOUP_TRANSFER_UNKNOWN;
950                         else {
951                                 if (content_length)
952                                         *content_length = lval;
953                                 return SOUP_TRANSFER_CONTENT_LENGTH;
954                         }
955                 } else
956                         return SOUP_TRANSFER_NONE;
957         } else {
958                 if (msg->request.length) {
959                         if (content_length)
960                                 *content_length = msg->request.length;
961                         return SOUP_TRANSFER_CONTENT_LENGTH;
962                 } else
963                         return SOUP_TRANSFER_NONE;
964         }
965 }
966
967 /**
968  * soup_message_get_response_encoding:
969  * @msg: a #SoupMessage
970  * @content_length: a pointer to store the Content-Length in (or
971  * %NULL).
972  *
973  * Gets @msg's response encoding. For an outgoing (client) request,
974  * this is only valid after the response headers have been read and
975  * @msg->response_headers filled in. For an incoming (server) request,
976  * this is valid after the server handler has run.
977  *
978  * Note that the returned value is the encoding actually used on the
979  * wire; this will not agree with the response headers in some cases
980  * (eg, a HEAD response may have a Content-Length header, but will
981  * still be considered %SOUP_TRANSFER_NONE by this function).
982  *
983  * Return value: the response encoding (which will not be
984  * %SOUP_TRANSFER_UNKNOWN). If it is %SOUP_TRANSFER_CONTENT_LENGTH,
985  * *@content_length will be set to the response body's length.
986  **/
987 SoupTransferEncoding
988 soup_message_get_response_encoding (SoupMessage *msg, guint *content_length)
989 {
990         SoupMethodId method = soup_method_get_id (msg->method);
991
992         /* FIXME: should CONNECT really be here? Where does it say that? */
993         if (method == SOUP_METHOD_ID_HEAD ||
994             method == SOUP_METHOD_ID_CONNECT ||
995             msg->status_code  == SOUP_STATUS_NO_CONTENT ||
996             msg->status_code  == SOUP_STATUS_NOT_MODIFIED ||
997             SOUP_STATUS_IS_INFORMATIONAL (msg->status_code))
998                 return SOUP_TRANSFER_NONE;
999
1000         if (SOUP_IS_SERVER_MESSAGE (msg)) {
1001                 SoupTransferEncoding enc =
1002                         soup_server_message_get_encoding ((SoupServerMessage *)msg);
1003                 if (enc == SOUP_TRANSFER_UNKNOWN)
1004                         enc = SOUP_TRANSFER_CONTENT_LENGTH;
1005                 if (enc == SOUP_TRANSFER_CONTENT_LENGTH && content_length)
1006                         *content_length = msg->response.length;
1007                 return enc;
1008         } else {
1009                 const char *enc, *len;
1010
1011                 enc = soup_message_get_header (msg->response_headers,
1012                                                "Transfer-Encoding");
1013                 len = soup_message_get_header (msg->response_headers,
1014                                                "Content-Length");
1015                 if (enc) {
1016                         if (g_ascii_strcasecmp (enc, "chunked") == 0)
1017                                 return SOUP_TRANSFER_CHUNKED;
1018                         else
1019                                 return SOUP_TRANSFER_UNKNOWN;
1020                 } else if (len) {
1021                         int lval = atoi (len);
1022
1023                         if (lval < 0)
1024                                 return SOUP_TRANSFER_UNKNOWN;
1025                         else {
1026                                 if (content_length)
1027                                         *content_length = lval;
1028                                 return SOUP_TRANSFER_CONTENT_LENGTH;
1029                         }
1030                 } else
1031                         return SOUP_TRANSFER_EOF;
1032         }
1033 }
1034
1035 /**
1036  * soup_message_set_status:
1037  * @msg: a #SoupMessage
1038  * @status_code: an HTTP status code
1039  *
1040  * Sets @msg's status code to @status_code. If @status_code is a
1041  * known value, it will also set @msg's reason_phrase.
1042  **/
1043 void
1044 soup_message_set_status (SoupMessage *msg, guint status_code)
1045 {
1046         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1047         g_return_if_fail (status_code != 0);
1048
1049         g_free ((char *) msg->reason_phrase);
1050
1051         msg->status_code = status_code;
1052         msg->reason_phrase = g_strdup (soup_status_get_phrase (status_code));
1053 }
1054
1055 /**
1056  * soup_message_set_status_full:
1057  * @msg: a #SoupMessage
1058  * @status_code: an HTTP status code
1059  * @reason_phrase: a description of the status
1060  *
1061  * Sets @msg's status code and reason phrase.
1062  **/
1063 void
1064 soup_message_set_status_full (SoupMessage *msg,
1065                               guint        status_code,
1066                               const char  *reason_phrase)
1067 {
1068         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1069         g_return_if_fail (status_code != 0);
1070         g_return_if_fail (reason_phrase != NULL);
1071
1072         g_free ((char *) msg->reason_phrase);
1073
1074         msg->status_code = status_code;
1075         msg->reason_phrase = g_strdup (reason_phrase);
1076 }
1077
1078
1079 /**
1080  * soup_message_add_chunk:
1081  * @msg: a #SoupMessage
1082  * @owner: the ownership of @body
1083  * @body: body data
1084  * @length: length of @body
1085  *
1086  * Adds a chunk of response data to @body. (Note that currently
1087  * there is no way to send a request using chunked encoding.)
1088  **/
1089 void
1090 soup_message_add_chunk (SoupMessage   *msg,
1091                         SoupOwnership  owner,
1092                         const char    *body,
1093                         guint          length)
1094 {
1095         SoupMessagePrivate *priv;
1096         SoupDataBuffer *chunk;
1097
1098         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1099         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1100         g_return_if_fail (body != NULL || length == 0);
1101
1102         chunk = g_new0 (SoupDataBuffer, 1);
1103         if (owner == SOUP_BUFFER_USER_OWNED) {
1104                 chunk->owner = SOUP_BUFFER_SYSTEM_OWNED;
1105                 chunk->body = g_memdup (body, length);
1106         } else {
1107                 chunk->owner = owner;
1108                 chunk->body = (char *)body;
1109         }
1110         chunk->length = length;
1111
1112         if (priv->chunks) {
1113                 g_slist_append (priv->last_chunk, chunk);
1114                 priv->last_chunk = priv->last_chunk->next;
1115         } else {
1116                 priv->chunks = priv->last_chunk =
1117                         g_slist_append (NULL, chunk);
1118         }
1119 }
1120
1121 /**
1122  * soup_message_add_final_chunk:
1123  * @msg: a #SoupMessage
1124  *
1125  * Adds a final, empty chunk of response data to @body. This must
1126  * be called after adding the last real chunk, to indicate that
1127  * there is no more data.
1128  **/
1129 void
1130 soup_message_add_final_chunk (SoupMessage *msg)
1131 {
1132         soup_message_add_chunk (msg, SOUP_BUFFER_STATIC, NULL, 0);
1133 }
1134
1135 /**
1136  * soup_message_pop_chunk:
1137  * @msg: a #SoupMessage
1138  *
1139  * Pops a chunk of response data from @msg's chunk list. The caller
1140  * must free @chunk itself, and must handle the data in @chunk
1141  * according to its %ownership.
1142  *
1143  * Return value: the chunk, or %NULL if there are no chunks left.
1144  **/
1145 SoupDataBuffer *
1146 soup_message_pop_chunk (SoupMessage *msg)
1147 {
1148         SoupMessagePrivate *priv;
1149         SoupDataBuffer *chunk;
1150
1151         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1152         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1153
1154         if (!priv->chunks)
1155                 return NULL;
1156
1157         chunk = priv->chunks->data;
1158         priv->chunks = g_slist_remove (priv->chunks, chunk);
1159         if (!priv->chunks)
1160                 priv->last_chunk = NULL;
1161
1162         return chunk;
1163 }
1164
1165 static void
1166 free_chunks (SoupMessage *msg)
1167 {
1168         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1169         SoupDataBuffer *chunk;
1170         GSList *ch;
1171
1172         for (ch = priv->chunks; ch; ch = ch->next) {
1173                 chunk = ch->data;
1174
1175                 if (chunk->owner == SOUP_BUFFER_SYSTEM_OWNED)
1176                         g_free (chunk->body);
1177                 g_free (chunk);
1178         }
1179
1180         g_slist_free (priv->chunks);
1181         priv->chunks = priv->last_chunk = NULL;
1182 }