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