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