Reapplying patch to disable attempts to use gtk-doc
[profile/ivi/libsoup2.4.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-address.h"
12 #include "soup-auth.h"
13 #include "soup-connection.h"
14 #include "soup-enum-types.h"
15 #include "soup-marshal.h"
16 #include "soup-message.h"
17 #include "soup-message-private.h"
18 #include "soup-misc.h"
19 #include "soup-socket.h"
20 #include "soup-uri.h"
21
22 /**
23  * SECTION:soup-message
24  * @short_description: An HTTP request and response.
25  * @see_also: #SoupMessageHeaders, #SoupMessageBody
26  *
27  * A #SoupMessage represents an HTTP message that is being sent or
28  * received.
29  *
30  * For client-side usage, you would create a #SoupMessage with
31  * soup_message_new() or soup_message_new_from_uri(), set up its
32  * fields appropriate, and send it via a #SoupSession.
33  *
34  * For server-side usage, #SoupServer will create #SoupMessage<!--
35  * -->s automatically for incoming requests, which your application
36  * will receive via handlers.
37  *
38  * Note that libsoup's terminology here does not quite match the HTTP
39  * specification: in RFC 2616, an "HTTP-message" is
40  * <emphasis>either</emphasis> a Request, <emphasis>or</emphasis> a
41  * Response. In libsoup, a #SoupMessage combines both the request and
42  * the response.
43  **/
44
45 /**
46  * SoupMessage:
47  * @method: the HTTP method
48  * @status_code: the HTTP status code
49  * @reason_phrase: the status phrase associated with @status_code
50  * @request_body: the request body
51  * @request_headers: the request headers
52  * @response_body: the response body
53  * @response_headers: the response headers
54  *
55  * Represents an HTTP message being sent or received.
56  *
57  * @status_code will normally be a #SoupKnownStatusCode, eg,
58  * %SOUP_STATUS_OK, though of course it might actually be an unknown
59  * status code. @reason_phrase is the actual text returned from the
60  * server, which may or may not correspond to the "standard"
61  * description of @status_code. At any rate, it is almost certainly
62  * not localized, and not very descriptive even if it is in the user's
63  * language; you should not use @reason_phrase in user-visible
64  * messages. Rather, you should look at @status_code, and determine an
65  * end-user-appropriate message based on that and on what you were
66  * trying to do.
67  *
68  * As described in the #SoupMessageBody documentation, the
69  * @request_body and @response_body <literal>data</literal> fields
70  * will not necessarily be filled in at all times. When they are
71  * filled in, they will be terminated with a '\0' byte (which is not
72  * included in the <literal>length</literal>), so you can use them as
73  * ordinary C strings (assuming that you know that the body doesn't
74  * have any other '\0' bytes).
75  *
76  * For a client-side #SoupMessage, @request_body's %data is usually
77  * filled in right before libsoup writes the request to the network,
78  * but you should not count on this; use soup_message_body_flatten()
79  * if you want to ensure that %data is filled in. @response_body's
80  * %data will be filled in before #SoupMessage::finished is emitted.
81  *
82  * For a server-side #SoupMessage, @request_body's %data will be
83  * filled in before #SoupMessage::got_body is emitted.
84  *
85  * To prevent the %data field from being filled in at all (eg, if you
86  * are handling the data from a #SoupMessage::got_chunk, and so don't
87  * need to see it all at the end), call
88  * soup_message_body_set_accumulate() on @response_body or
89  * @request_body as appropriate, passing %FALSE.
90  **/
91
92 G_DEFINE_TYPE (SoupMessage, soup_message, G_TYPE_OBJECT)
93
94 enum {
95         WROTE_INFORMATIONAL,
96         WROTE_HEADERS,
97         WROTE_CHUNK,
98         WROTE_BODY_DATA,
99         WROTE_BODY,
100
101         GOT_INFORMATIONAL,
102         GOT_HEADERS,
103         GOT_CHUNK,
104         GOT_BODY,
105         CONTENT_SNIFFED,
106
107         RESTARTED,
108         FINISHED,
109
110         NETWORK_EVENT,
111
112         LAST_SIGNAL
113 };
114
115 static guint signals[LAST_SIGNAL] = { 0 };
116
117 enum {
118         PROP_0,
119
120         PROP_METHOD,
121         PROP_URI,
122         PROP_HTTP_VERSION,
123         PROP_FLAGS,
124         PROP_SERVER_SIDE,
125         PROP_STATUS_CODE,
126         PROP_REASON_PHRASE,
127         PROP_FIRST_PARTY,
128         PROP_REQUEST_BODY,
129         PROP_REQUEST_HEADERS,
130         PROP_RESPONSE_BODY,
131         PROP_RESPONSE_HEADERS,
132         PROP_TLS_CERTIFICATE,
133         PROP_TLS_ERRORS,
134
135         LAST_PROP
136 };
137
138 static void got_body (SoupMessage *req);
139
140 static void set_property (GObject *object, guint prop_id,
141                           const GValue *value, GParamSpec *pspec);
142 static void get_property (GObject *object, guint prop_id,
143                           GValue *value, GParamSpec *pspec);
144
145 static void
146 soup_message_init (SoupMessage *msg)
147 {
148         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
149
150         priv->http_version = priv->orig_http_version = SOUP_HTTP_1_1;
151
152         msg->request_body = soup_message_body_new ();
153         msg->request_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST);
154         msg->response_body = soup_message_body_new ();
155         msg->response_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
156 }
157
158 static void
159 finalize (GObject *object)
160 {
161         SoupMessage *msg = SOUP_MESSAGE (object);
162         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
163
164         soup_message_io_cleanup (msg);
165         if (priv->chunk_allocator_dnotify)
166                 priv->chunk_allocator_dnotify (priv->chunk_allocator_data);
167
168         if (priv->uri)
169                 soup_uri_free (priv->uri);
170         if (priv->first_party)
171                 soup_uri_free (priv->first_party);
172         if (priv->addr)
173                 g_object_unref (priv->addr);
174
175         if (priv->auth)
176                 g_object_unref (priv->auth);
177         if (priv->proxy_auth)
178                 g_object_unref (priv->proxy_auth);
179
180         g_slist_free (priv->disabled_features);
181
182         while (priv->decoders) {
183                 g_object_unref (priv->decoders->data);
184                 priv->decoders = g_slist_delete_link (priv->decoders, priv->decoders);
185         }
186
187         if (priv->tls_certificate)
188                 g_object_unref (priv->tls_certificate);
189
190         soup_message_body_free (msg->request_body);
191         soup_message_headers_free (msg->request_headers);
192         soup_message_body_free (msg->response_body);
193         soup_message_headers_free (msg->response_headers);
194
195         g_free (msg->reason_phrase);
196
197         G_OBJECT_CLASS (soup_message_parent_class)->finalize (object);
198 }
199
200 static void
201 soup_message_class_init (SoupMessageClass *message_class)
202 {
203         GObjectClass *object_class = G_OBJECT_CLASS (message_class);
204
205         g_type_class_add_private (message_class, sizeof (SoupMessagePrivate));
206
207         /* virtual method definition */
208         message_class->got_body = got_body;
209
210         /* virtual method override */
211         object_class->finalize = finalize;
212         object_class->set_property = set_property;
213         object_class->get_property = get_property;
214
215         /* signals */
216
217         /**
218          * SoupMessage::wrote-informational:
219          * @msg: the message
220          *
221          * Emitted immediately after writing a 1xx (Informational)
222          * response for a (server-side) message.
223          **/
224         signals[WROTE_INFORMATIONAL] =
225                 g_signal_new ("wrote_informational",
226                               G_OBJECT_CLASS_TYPE (object_class),
227                               G_SIGNAL_RUN_FIRST,
228                               G_STRUCT_OFFSET (SoupMessageClass, wrote_informational),
229                               NULL, NULL,
230                               _soup_marshal_NONE__NONE,
231                               G_TYPE_NONE, 0);
232
233         /**
234          * SoupMessage::wrote-headers:
235          * @msg: the message
236          *
237          * Emitted immediately after writing the headers for a
238          * message. (For a client-side message, this is after writing
239          * the request headers; for a server-side message, it is after
240          * writing the response headers.)
241          **/
242         signals[WROTE_HEADERS] =
243                 g_signal_new ("wrote_headers",
244                               G_OBJECT_CLASS_TYPE (object_class),
245                               G_SIGNAL_RUN_FIRST,
246                               G_STRUCT_OFFSET (SoupMessageClass, wrote_headers),
247                               NULL, NULL,
248                               _soup_marshal_NONE__NONE,
249                               G_TYPE_NONE, 0);
250
251         /**
252          * SoupMessage::wrote-chunk:
253          * @msg: the message
254          *
255          * Emitted immediately after writing a body chunk for a message.
256          *
257          * Note that this signal is not parallel to
258          * #SoupMessage::got_chunk; it is emitted only when a complete
259          * chunk (added with soup_message_body_append() or
260          * soup_message_body_append_buffer()) has been written. To get
261          * more useful continuous progress information, use
262          * #SoupMessage::wrote_body_data.
263          **/
264         signals[WROTE_CHUNK] =
265                 g_signal_new ("wrote_chunk",
266                               G_OBJECT_CLASS_TYPE (object_class),
267                               G_SIGNAL_RUN_FIRST,
268                               G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk),
269                               NULL, NULL,
270                               _soup_marshal_NONE__NONE,
271                               G_TYPE_NONE, 0);
272
273         /**
274          * SoupMessage::wrote-body-data:
275          * @msg: the message
276          * @chunk: the data written
277          *
278          * Emitted immediately after writing a portion of the message
279          * body to the network.
280          *
281          * Unlike #SoupMessage::wrote_chunk, this is emitted after
282          * every successful write() call, not only after finishing a
283          * complete "chunk".
284          *
285          * Since: 2.4.1
286          **/
287         signals[WROTE_BODY_DATA] =
288                 g_signal_new ("wrote_body_data",
289                               G_OBJECT_CLASS_TYPE (object_class),
290                               G_SIGNAL_RUN_FIRST,
291                               0, /* FIXME after next ABI break */
292                               NULL, NULL,
293                               _soup_marshal_NONE__BOXED,
294                               G_TYPE_NONE, 1,
295                               SOUP_TYPE_BUFFER);
296
297         /**
298          * SoupMessage::wrote-body:
299          * @msg: the message
300          *
301          * Emitted immediately after writing the complete body for a
302          * message. (For a client-side message, this means that
303          * libsoup is done writing and is now waiting for the response
304          * from the server. For a server-side message, this means that
305          * libsoup has finished writing the response and is nearly
306          * done with the message.)
307          **/
308         signals[WROTE_BODY] =
309                 g_signal_new ("wrote_body",
310                               G_OBJECT_CLASS_TYPE (object_class),
311                               G_SIGNAL_RUN_FIRST,
312                               G_STRUCT_OFFSET (SoupMessageClass, wrote_body),
313                               NULL, NULL,
314                               _soup_marshal_NONE__NONE,
315                               G_TYPE_NONE, 0);
316
317         /**
318          * SoupMessage::got-informational:
319          * @msg: the message
320          *
321          * Emitted after receiving a 1xx (Informational) response for
322          * a (client-side) message. The response_headers will be
323          * filled in with the headers associated with the
324          * informational response; however, those header values will
325          * be erased after this signal is done.
326          *
327          * If you cancel or requeue @msg while processing this signal,
328          * then the current HTTP I/O will be stopped after this signal
329          * emission finished, and @msg's connection will be closed.
330          **/
331         signals[GOT_INFORMATIONAL] =
332                 g_signal_new ("got_informational",
333                               G_OBJECT_CLASS_TYPE (object_class),
334                               G_SIGNAL_RUN_FIRST,
335                               G_STRUCT_OFFSET (SoupMessageClass, got_informational),
336                               NULL, NULL,
337                               _soup_marshal_NONE__NONE,
338                               G_TYPE_NONE, 0);
339
340         /**
341          * SoupMessage::got-headers:
342          * @msg: the message
343          *
344          * Emitted after receiving all message headers for a message.
345          * (For a client-side message, this is after receiving the
346          * Status-Line and response headers; for a server-side
347          * message, it is after receiving the Request-Line and request
348          * headers.)
349          *
350          * See also soup_message_add_header_handler() and
351          * soup_message_add_status_code_handler(), which can be used
352          * to connect to a subset of emissions of this signal.
353          *
354          * If you cancel or requeue @msg while processing this signal,
355          * then the current HTTP I/O will be stopped after this signal
356          * emission finished, and @msg's connection will be closed.
357          * (If you need to requeue a message--eg, after handling
358          * authentication or redirection--it is usually better to
359          * requeue it from a #SoupMessage::got_body handler rather
360          * than a #SoupMessage::got_headers handler, so that the
361          * existing HTTP connection can be reused.)
362          **/
363         signals[GOT_HEADERS] =
364                 g_signal_new ("got_headers",
365                               G_OBJECT_CLASS_TYPE (object_class),
366                               G_SIGNAL_RUN_FIRST,
367                               G_STRUCT_OFFSET (SoupMessageClass, got_headers),
368                               NULL, NULL,
369                               _soup_marshal_NONE__NONE,
370                               G_TYPE_NONE, 0);
371
372         /**
373          * SoupMessage::got-chunk:
374          * @msg: the message
375          * @chunk: the just-read chunk
376          *
377          * Emitted after receiving a chunk of a message body. Note
378          * that "chunk" in this context means any subpiece of the
379          * body, not necessarily the specific HTTP 1.1 chunks sent by
380          * the other side.
381          *
382          * If you cancel or requeue @msg while processing this signal,
383          * then the current HTTP I/O will be stopped after this signal
384          * emission finished, and @msg's connection will be closed.
385          **/
386         signals[GOT_CHUNK] =
387                 g_signal_new ("got_chunk",
388                               G_OBJECT_CLASS_TYPE (object_class),
389                               G_SIGNAL_RUN_FIRST,
390                               G_STRUCT_OFFSET (SoupMessageClass, got_chunk),
391                               NULL, NULL,
392                               _soup_marshal_NONE__BOXED,
393                               G_TYPE_NONE, 1,
394                               /* Use %G_SIGNAL_TYPE_STATIC_SCOPE so that
395                                * the %SOUP_MEMORY_TEMPORARY buffers used
396                                * by soup-message-io.c when emitting this
397                                * signal don't get forcibly copied by
398                                * g_signal_emit().
399                                */
400                               SOUP_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
401
402         /**
403          * SoupMessage::got-body:
404          * @msg: the message
405          *
406          * Emitted after receiving the complete message body. (For a
407          * server-side message, this means it has received the request
408          * body. For a client-side message, this means it has received
409          * the response body and is nearly done with the message.)
410          *
411          * See also soup_message_add_header_handler() and
412          * soup_message_add_status_code_handler(), which can be used
413          * to connect to a subset of emissions of this signal.
414          **/
415         signals[GOT_BODY] =
416                 g_signal_new ("got_body",
417                               G_OBJECT_CLASS_TYPE (object_class),
418                               G_SIGNAL_RUN_FIRST,
419                               G_STRUCT_OFFSET (SoupMessageClass, got_body),
420                               NULL, NULL,
421                               _soup_marshal_NONE__NONE,
422                               G_TYPE_NONE, 0);
423
424         /**
425          * SoupMessage::content-sniffed:
426          * @msg: the message
427          * @type: the content type that we got from sniffing
428          * @params: (element-type utf8 utf8): a #GHashTable with the parameters
429          *
430          * This signal is emitted after #SoupMessage::got-headers, and
431          * before the first #SoupMessage::got-chunk. If content
432          * sniffing is disabled, or no content sniffing will be
433          * performed, due to the sniffer deciding to trust the
434          * Content-Type sent by the server, this signal is emitted
435          * immediately after #SoupMessage::got-headers, and @type is
436          * %NULL.
437          *
438          * If the #SoupContentSniffer feature is enabled, and the
439          * sniffer decided to perform sniffing, the first
440          * #SoupMessage::got-chunk emission may be delayed, so that the
441          * sniffer has enough data to correctly sniff the content. It
442          * notified the library user that the content has been
443          * sniffed, and allows it to change the header contents in the
444          * message, if desired.
445          *
446          * After this signal is emitted, the data that was spooled so
447          * that sniffing could be done is delivered on the first
448          * emission of #SoupMessage::got-chunk.
449          *
450          * Since: 2.27.3
451          **/
452         signals[CONTENT_SNIFFED] =
453                 g_signal_new ("content_sniffed",
454                               G_OBJECT_CLASS_TYPE (object_class),
455                               G_SIGNAL_RUN_FIRST,
456                               0,
457                               NULL, NULL,
458                               _soup_marshal_NONE__STRING_BOXED,
459                               G_TYPE_NONE, 2,
460                               G_TYPE_STRING,
461                               G_TYPE_HASH_TABLE);
462
463         /**
464          * SoupMessage::restarted:
465          * @msg: the message
466          *
467          * Emitted when a request that was already sent once is now
468          * being sent again (eg, because the first attempt received a
469          * redirection response, or because we needed to use
470          * authentication).
471          **/
472         signals[RESTARTED] =
473                 g_signal_new ("restarted",
474                               G_OBJECT_CLASS_TYPE (object_class),
475                               G_SIGNAL_RUN_FIRST,
476                               G_STRUCT_OFFSET (SoupMessageClass, restarted),
477                               NULL, NULL,
478                               _soup_marshal_NONE__NONE,
479                               G_TYPE_NONE, 0);
480
481         /**
482          * SoupMessage::finished:
483          * @msg: the message
484          *
485          * Emitted when all HTTP processing is finished for a message.
486          * (After #SoupMessage::got_body for client-side messages, or
487          * after #SoupMessage::wrote_body for server-side messages.)
488          **/
489         signals[FINISHED] =
490                 g_signal_new ("finished",
491                               G_OBJECT_CLASS_TYPE (object_class),
492                               G_SIGNAL_RUN_FIRST,
493                               G_STRUCT_OFFSET (SoupMessageClass, finished),
494                               NULL, NULL,
495                               _soup_marshal_NONE__NONE,
496                               G_TYPE_NONE, 0);
497
498         /**
499          * SoupMessage::network-event:
500          * @msg: the message
501          * @event: the network event
502          * @connection: the current state of the network connection
503          *
504          * Emitted to indicate that some network-related event
505          * related to @msg has occurred. This essentially proxies the
506          * #GSocketClient::event signal, but only for events that
507          * occur while @msg "owns" the connection; if @msg is sent on
508          * an existing persistent connection, then this signal will
509          * not be emitted. (If you want to force the message to be
510          * sent on a new connection, set the
511          * %SOUP_MESSAGE_NEW_CONNECTION flag on it.)
512          *
513          * See #GSocketClient::event for more information on what
514          * the different values of @event correspond to, and what
515          * @connection will be in each case.
516          *
517          * Since: 2.38
518          **/
519         signals[NETWORK_EVENT] =
520                 g_signal_new ("network_event",
521                               G_OBJECT_CLASS_TYPE (object_class),
522                               G_SIGNAL_RUN_FIRST,
523                               0,
524                               NULL, NULL,
525                               NULL,
526                               G_TYPE_NONE, 2,
527                               G_TYPE_SOCKET_CLIENT_EVENT,
528                               G_TYPE_IO_STREAM);
529
530         /* properties */
531         /**
532          * SOUP_MESSAGE_METHOD:
533          *
534          * Alias for the #SoupMessage:method property. (The message's
535          * HTTP method.)
536          **/
537         g_object_class_install_property (
538                 object_class, PROP_METHOD,
539                 g_param_spec_string (SOUP_MESSAGE_METHOD,
540                                      "Method",
541                                      "The message's HTTP method",
542                                      SOUP_METHOD_GET,
543                                      G_PARAM_READWRITE));
544         /**
545          * SOUP_MESSAGE_URI:
546          *
547          * Alias for the #SoupMessage:uri property. (The message's
548          * #SoupURI.)
549          **/
550         g_object_class_install_property (
551                 object_class, PROP_URI,
552                 g_param_spec_boxed (SOUP_MESSAGE_URI,
553                                     "URI",
554                                     "The message's Request-URI",
555                                     SOUP_TYPE_URI,
556                                     G_PARAM_READWRITE));
557         /**
558          * SOUP_MESSAGE_HTTP_VERSION:
559          *
560          * Alias for the #SoupMessage:http-version property. (The
561          * message's #SoupHTTPVersion.)
562          **/
563         g_object_class_install_property (
564                 object_class, PROP_HTTP_VERSION,
565                 g_param_spec_enum (SOUP_MESSAGE_HTTP_VERSION,
566                                    "HTTP Version",
567                                    "The HTTP protocol version to use",
568                                    SOUP_TYPE_HTTP_VERSION,
569                                    SOUP_HTTP_1_1,
570                                    G_PARAM_READWRITE));
571         /**
572          * SOUP_MESSAGE_FLAGS:
573          *
574          * Alias for the #SoupMessage:flags property. (The message's
575          * #SoupMessageFlags.)
576          **/
577         g_object_class_install_property (
578                 object_class, PROP_FLAGS,
579                 g_param_spec_flags (SOUP_MESSAGE_FLAGS,
580                                     "Flags",
581                                     "Various message options",
582                                     SOUP_TYPE_MESSAGE_FLAGS,
583                                     0,
584                                     G_PARAM_READWRITE));
585         /**
586          * SOUP_MESSAGE_SERVER_SIDE:
587          *
588          * Alias for the #SoupMessage:server-side property. (%TRUE if
589          * the message was created by #SoupServer.)
590          **/
591         g_object_class_install_property (
592                 object_class, PROP_SERVER_SIDE,
593                 g_param_spec_boolean (SOUP_MESSAGE_SERVER_SIDE,
594                                       "Server-side",
595                                       "Whether or not the message is server-side rather than client-side",
596                                       FALSE,
597                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
598         /**
599          * SOUP_MESSAGE_STATUS_CODE:
600          *
601          * Alias for the #SoupMessage:status-code property. (The
602          * message's HTTP response status code.)
603          **/
604         g_object_class_install_property (
605                 object_class, PROP_STATUS_CODE,
606                 g_param_spec_uint (SOUP_MESSAGE_STATUS_CODE,
607                                    "Status code",
608                                    "The HTTP response status code",
609                                    0, 599, 0,
610                                    G_PARAM_READWRITE));
611         /**
612          * SOUP_MESSAGE_REASON_PHRASE:
613          *
614          * Alias for the #SoupMessage:reason-phrase property. (The
615          * message's HTTP response reason phrase.)
616          **/
617         g_object_class_install_property (
618                 object_class, PROP_REASON_PHRASE,
619                 g_param_spec_string (SOUP_MESSAGE_REASON_PHRASE,
620                                      "Reason phrase",
621                                      "The HTTP response reason phrase",
622                                      NULL,
623                                      G_PARAM_READWRITE));
624         /**
625          * SOUP_MESSAGE_FIRST_PARTY:
626          *
627          * Alias for the #SoupMessage:first-party property. (The
628          * #SoupURI loaded in the application when the message was
629          * queued.)
630          *
631          * Since: 2.30
632          **/
633         /**
634          * SoupMessage:first-party:
635          *
636          * The #SoupURI loaded in the application when the message was
637          * queued.
638          *
639          * Since: 2.30
640          */
641         g_object_class_install_property (
642                 object_class, PROP_FIRST_PARTY,
643                 g_param_spec_boxed (SOUP_MESSAGE_FIRST_PARTY,
644                                     "First party",
645                                     "The URI loaded in the application when the message was requested.",
646                                     SOUP_TYPE_URI,
647                                     G_PARAM_READWRITE));
648         /**
649          * SOUP_MESSAGE_REQUEST_BODY:
650          *
651          * Alias for the #SoupMessage:request-body property. (The
652          * message's HTTP request body.)
653          **/
654         g_object_class_install_property (
655                 object_class, PROP_REQUEST_BODY,
656                 g_param_spec_boxed (SOUP_MESSAGE_REQUEST_BODY,
657                                     "Request Body",
658                                     "The HTTP request content",
659                                     SOUP_TYPE_MESSAGE_BODY,
660                                     G_PARAM_READABLE));
661         /**
662          * SOUP_MESSAGE_REQUEST_HEADERS:
663          *
664          * Alias for the #SoupMessage:request-headers property. (The
665          * message's HTTP request headers.)
666          **/
667         g_object_class_install_property (
668                 object_class, PROP_REQUEST_HEADERS,
669                 g_param_spec_boxed (SOUP_MESSAGE_REQUEST_HEADERS,
670                                     "Request Headers",
671                                     "The HTTP request headers",
672                                     SOUP_TYPE_MESSAGE_HEADERS,
673                                     G_PARAM_READABLE));
674         /**
675          * SOUP_MESSAGE_RESPONSE_BODY:
676          *
677          * Alias for the #SoupMessage:response-body property. (The
678          * message's HTTP response body.)
679          **/
680         g_object_class_install_property (
681                 object_class, PROP_RESPONSE_BODY,
682                 g_param_spec_boxed (SOUP_MESSAGE_RESPONSE_BODY,
683                                     "Response Body",
684                                     "The HTTP response content",
685                                     SOUP_TYPE_MESSAGE_BODY,
686                                     G_PARAM_READABLE));
687         /**
688          * SOUP_MESSAGE_RESPONSE_HEADERS:
689          *
690          * Alias for the #SoupMessage:response-headers property. (The
691          * message's HTTP response headers.)
692          **/
693         g_object_class_install_property (
694                 object_class, PROP_RESPONSE_HEADERS,
695                 g_param_spec_boxed (SOUP_MESSAGE_RESPONSE_HEADERS,
696                                     "Response Headers",
697                                      "The HTTP response headers",
698                                     SOUP_TYPE_MESSAGE_HEADERS,
699                                     G_PARAM_READABLE));
700         /**
701          * SOUP_MESSAGE_TLS_CERTIFICATE:
702          *
703          * Alias for the #SoupMessage:tls-certificate property. (The
704          * TLS certificate associated with the message, if any.)
705          *
706          * Since: 2.34
707          **/
708         /**
709          * SoupMessage:tls-certificate:
710          *
711          * The #GTlsCertificate associated with the message
712          *
713          * Since: 2.34
714          */      
715         g_object_class_install_property (
716                 object_class, PROP_TLS_CERTIFICATE,
717                 g_param_spec_object (SOUP_MESSAGE_TLS_CERTIFICATE,
718                                      "TLS Certificate",
719                                      "The TLS certificate associated with the message",
720                                      G_TYPE_TLS_CERTIFICATE,
721                                      G_PARAM_READWRITE));
722         /**
723          * SOUP_MESSAGE_TLS_ERRORS:
724          *
725          * Alias for the #SoupMessage:tls-errors property. (The
726          * verification errors on #SoupMessage:tls-certificate.)
727          *
728          * Since: 2.34
729          **/
730         /**
731          * SoupMessage:tls-errors:
732          *
733          * The verification errors on #SoupMessage:tls-certificate
734          *
735          * Since: 2.34
736          */      
737         g_object_class_install_property (
738                 object_class, PROP_TLS_ERRORS,
739                 g_param_spec_flags (SOUP_MESSAGE_TLS_ERRORS,
740                                     "TLS Errors",
741                                     "The verification errors on the message's TLS certificate",
742                                     G_TYPE_TLS_CERTIFICATE_FLAGS, 0,
743                                     G_PARAM_READWRITE));
744 }
745
746 static void
747 set_property (GObject *object, guint prop_id,
748               const GValue *value, GParamSpec *pspec)
749 {
750         SoupMessage *msg = SOUP_MESSAGE (object);
751         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
752
753         switch (prop_id) {
754         case PROP_METHOD:
755                 msg->method = g_intern_string (g_value_get_string (value));
756                 break;
757         case PROP_URI:
758                 soup_message_set_uri (msg, g_value_get_boxed (value));
759                 break;
760         case PROP_HTTP_VERSION:
761                 soup_message_set_http_version (msg, g_value_get_enum (value));
762                 break;
763         case PROP_FLAGS:
764                 soup_message_set_flags (msg, g_value_get_flags (value));
765                 break;
766         case PROP_SERVER_SIDE:
767                 priv->server_side = g_value_get_boolean (value);
768                 if (priv->server_side) {
769                         soup_message_headers_set_encoding (msg->response_headers,
770                                                            SOUP_ENCODING_CONTENT_LENGTH);
771                 }
772                 break;
773         case PROP_STATUS_CODE:
774                 soup_message_set_status (msg, g_value_get_uint (value));
775                 break;
776         case PROP_REASON_PHRASE:
777                 soup_message_set_status_full (msg, msg->status_code,
778                                               g_value_get_string (value));
779                 break;
780         case PROP_FIRST_PARTY:
781                 soup_message_set_first_party (msg, g_value_get_boxed (value));
782                 break;
783         case PROP_TLS_CERTIFICATE:
784                 if (priv->tls_certificate)
785                         g_object_unref (priv->tls_certificate);
786                 priv->tls_certificate = g_value_dup_object (value);
787                 if (priv->tls_errors)
788                         priv->msg_flags &= ~SOUP_MESSAGE_CERTIFICATE_TRUSTED;
789                 else if (priv->tls_certificate)
790                         priv->msg_flags |= SOUP_MESSAGE_CERTIFICATE_TRUSTED;
791                 break;
792         case PROP_TLS_ERRORS:
793                 priv->tls_errors = g_value_get_flags (value);
794                 if (priv->tls_errors)
795                         priv->msg_flags &= ~SOUP_MESSAGE_CERTIFICATE_TRUSTED;
796                 else if (priv->tls_certificate)
797                         priv->msg_flags |= SOUP_MESSAGE_CERTIFICATE_TRUSTED;
798                 break;
799         default:
800                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
801                 break;
802         }
803 }
804
805 static void
806 get_property (GObject *object, guint prop_id,
807               GValue *value, GParamSpec *pspec)
808 {
809         SoupMessage *msg = SOUP_MESSAGE (object);
810         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
811
812         switch (prop_id) {
813         case PROP_METHOD:
814                 g_value_set_string (value, msg->method);
815                 break;
816         case PROP_URI:
817                 g_value_set_boxed (value, priv->uri);
818                 break;
819         case PROP_HTTP_VERSION:
820                 g_value_set_enum (value, priv->http_version);
821                 break;
822         case PROP_FLAGS:
823                 g_value_set_flags (value, priv->msg_flags);
824                 break;
825         case PROP_SERVER_SIDE:
826                 g_value_set_boolean (value, priv->server_side);
827                 break;
828         case PROP_STATUS_CODE:
829                 g_value_set_uint (value, msg->status_code);
830                 break;
831         case PROP_REASON_PHRASE:
832                 g_value_set_string (value, msg->reason_phrase);
833                 break;
834         case PROP_FIRST_PARTY:
835                 g_value_set_boxed (value, priv->first_party);
836                 break;
837         case PROP_REQUEST_BODY:
838                 g_value_set_boxed (value, msg->request_body);
839                 break;
840         case PROP_REQUEST_HEADERS:
841                 g_value_set_boxed (value, msg->request_headers);
842                 break;
843         case PROP_RESPONSE_BODY:
844                 g_value_set_boxed (value, msg->response_body);
845                 break;
846         case PROP_RESPONSE_HEADERS:
847                 g_value_set_boxed (value, msg->response_headers);
848                 break;
849         case PROP_TLS_CERTIFICATE:
850                 g_value_set_object (value, priv->tls_certificate);
851                 break;
852         case PROP_TLS_ERRORS:
853                 g_value_set_flags (value, priv->tls_errors);
854                 break;
855         default:
856                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
857                 break;
858         }
859 }
860
861
862 /**
863  * soup_message_new:
864  * @method: the HTTP method for the created request
865  * @uri_string: the destination endpoint (as a string)
866  * 
867  * Creates a new empty #SoupMessage, which will connect to @uri
868  *
869  * Return value: the new #SoupMessage (or %NULL if @uri could not
870  * be parsed).
871  */
872 SoupMessage *
873 soup_message_new (const char *method, const char *uri_string)
874 {
875         SoupMessage *msg;
876         SoupURI *uri;
877
878         g_return_val_if_fail (method != NULL, NULL);
879         g_return_val_if_fail (uri_string != NULL, NULL);
880
881         uri = soup_uri_new (uri_string);
882         if (!uri)
883                 return NULL;
884         if (!uri->host) {
885                 soup_uri_free (uri);
886                 return NULL;
887         }
888
889         msg = soup_message_new_from_uri (method, uri);
890         soup_uri_free (uri);
891         return msg;
892 }
893
894 /**
895  * soup_message_new_from_uri:
896  * @method: the HTTP method for the created request
897  * @uri: the destination endpoint (as a #SoupURI)
898  * 
899  * Creates a new empty #SoupMessage, which will connect to @uri
900  *
901  * Return value: the new #SoupMessage
902  */
903 SoupMessage *
904 soup_message_new_from_uri (const char *method, SoupURI *uri)
905 {
906         return g_object_new (SOUP_TYPE_MESSAGE,
907                              SOUP_MESSAGE_METHOD, method,
908                              SOUP_MESSAGE_URI, uri,
909                              NULL);
910 }
911
912 /**
913  * soup_message_set_request:
914  * @msg: the message
915  * @content_type: MIME Content-Type of the body
916  * @req_use: a #SoupMemoryUse describing how to handle @req_body
917  * @req_body: a data buffer containing the body of the message request.
918  * @req_length: the byte length of @req_body.
919  * 
920  * Convenience function to set the request body of a #SoupMessage. If
921  * @content_type is %NULL, the request body must be empty as well.
922  */
923 void
924 soup_message_set_request (SoupMessage    *msg,
925                           const char     *content_type,
926                           SoupMemoryUse   req_use,
927                           const char     *req_body,
928                           gsize           req_length)
929 {
930         g_return_if_fail (SOUP_IS_MESSAGE (msg));
931         g_return_if_fail (content_type != NULL || req_length == 0);
932
933         if (content_type) {
934                 soup_message_headers_replace (msg->request_headers,
935                                               "Content-Type", content_type);
936                 soup_message_body_append (msg->request_body, req_use,
937                                           req_body, req_length);
938         } else {
939                 soup_message_headers_remove (msg->request_headers,
940                                              "Content-Type");
941                 soup_message_body_truncate (msg->request_body);
942         }
943 }
944
945 /**
946  * soup_message_set_response:
947  * @msg: the message
948  * @content_type: (allow-none): MIME Content-Type of the body
949  * @resp_use: a #SoupMemoryUse describing how to handle @resp_body
950  * @resp_body: (array length=resp_length) (element-type guint8): a data buffer
951  * containing the body of the message response.
952  * @resp_length: the byte length of @resp_body.
953  * 
954  * Convenience function to set the response body of a #SoupMessage. If
955  * @content_type is %NULL, the response body must be empty as well.
956  */
957 void
958 soup_message_set_response (SoupMessage    *msg,
959                            const char     *content_type,
960                            SoupMemoryUse   resp_use,
961                            const char     *resp_body,
962                            gsize           resp_length)
963 {
964         g_return_if_fail (SOUP_IS_MESSAGE (msg));
965         g_return_if_fail (content_type != NULL || resp_length == 0);
966
967         if (content_type) {
968                 soup_message_headers_replace (msg->response_headers,
969                                               "Content-Type", content_type);
970                 soup_message_body_append (msg->response_body, resp_use,
971                                           resp_body, resp_length);
972         } else {
973                 soup_message_headers_remove (msg->response_headers,
974                                              "Content-Type");
975                 soup_message_body_truncate (msg->response_body);
976         }
977 }
978
979 /**
980  * soup_message_wrote_informational:
981  * @msg: a #SoupMessage
982  *
983  * Emits the %wrote_informational signal, indicating that the IO layer
984  * finished writing an informational (1xx) response for @msg.
985  **/
986 void
987 soup_message_wrote_informational (SoupMessage *msg)
988 {
989         g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0);
990 }
991
992 /**
993  * soup_message_wrote_headers:
994  * @msg: a #SoupMessage
995  *
996  * Emits the %wrote_headers signal, indicating that the IO layer
997  * finished writing the (non-informational) headers for @msg.
998  **/
999 void
1000 soup_message_wrote_headers (SoupMessage *msg)
1001 {
1002         g_signal_emit (msg, signals[WROTE_HEADERS], 0);
1003 }
1004
1005 /**
1006  * soup_message_wrote_chunk:
1007  * @msg: a #SoupMessage
1008  *
1009  * Emits the %wrote_chunk signal, indicating that the IO layer
1010  * finished writing a chunk of @msg's body.
1011  **/
1012 void
1013 soup_message_wrote_chunk (SoupMessage *msg)
1014 {
1015         g_signal_emit (msg, signals[WROTE_CHUNK], 0);
1016 }
1017
1018 /**
1019  * soup_message_wrote_body_data:
1020  * @msg: a #SoupMessage
1021  * @chunk: the data written
1022  *
1023  * Emits the %wrote_body_data signal, indicating that the IO layer
1024  * finished writing a portion of @msg's body.
1025  **/
1026 void
1027 soup_message_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk)
1028 {
1029         g_signal_emit (msg, signals[WROTE_BODY_DATA], 0, chunk);
1030 }
1031
1032 /**
1033  * soup_message_wrote_body:
1034  * @msg: a #SoupMessage
1035  *
1036  * Emits the %wrote_body signal, indicating that the IO layer finished
1037  * writing the body for @msg.
1038  **/
1039 void
1040 soup_message_wrote_body (SoupMessage *msg)
1041 {
1042         g_signal_emit (msg, signals[WROTE_BODY], 0);
1043 }
1044
1045 /**
1046  * soup_message_got_informational:
1047  * @msg: a #SoupMessage
1048  *
1049  * Emits the #SoupMessage::got_informational signal, indicating that
1050  * the IO layer read a complete informational (1xx) response for @msg.
1051  **/
1052 void
1053 soup_message_got_informational (SoupMessage *msg)
1054 {
1055         g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0);
1056 }
1057
1058 /**
1059  * soup_message_got_headers:
1060  * @msg: a #SoupMessage
1061  *
1062  * Emits the #SoupMessage::got_headers signal, indicating that the IO
1063  * layer finished reading the (non-informational) headers for @msg.
1064  **/
1065 void
1066 soup_message_got_headers (SoupMessage *msg)
1067 {
1068         g_signal_emit (msg, signals[GOT_HEADERS], 0);
1069 }
1070
1071 /**
1072  * soup_message_got_chunk:
1073  * @msg: a #SoupMessage
1074  * @chunk: the newly-read chunk
1075  *
1076  * Emits the #SoupMessage::got_chunk signal, indicating that the IO
1077  * layer finished reading a chunk of @msg's body.
1078  **/
1079 void
1080 soup_message_got_chunk (SoupMessage *msg, SoupBuffer *chunk)
1081 {
1082         g_signal_emit (msg, signals[GOT_CHUNK], 0, chunk);
1083 }
1084
1085 static void
1086 got_body (SoupMessage *req)
1087 {
1088         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
1089         SoupMessageBody *body;
1090
1091         body = priv->server_side ? req->request_body : req->response_body;
1092         if (soup_message_body_get_accumulate (body)) {
1093                 SoupBuffer *buffer;
1094
1095                 buffer = soup_message_body_flatten (body);
1096                 soup_buffer_free (buffer);
1097         }
1098 }
1099
1100 /**
1101  * soup_message_got_body:
1102  * @msg: a #SoupMessage
1103  *
1104  * Emits the #SoupMessage::got_body signal, indicating that the IO
1105  * layer finished reading the body for @msg.
1106  **/
1107 void
1108 soup_message_got_body (SoupMessage *msg)
1109 {
1110         g_signal_emit (msg, signals[GOT_BODY], 0);
1111 }
1112
1113 /**
1114  * soup_message_content_sniffed:
1115  * @msg: a #SoupMessage
1116  * @content_type: a string with the sniffed content type
1117  * @params: a #GHashTable with the parameters
1118  *
1119  * Emits the %content_sniffed signal, indicating that the IO layer
1120  * finished sniffing the content type for @msg. If content sniffing
1121  * will not be performed, due to the sniffer deciding to trust the
1122  * Content-Type sent by the server, this signal is emitted immediately
1123  * after #SoupMessage::got_headers, with %NULL as @content_type.
1124  **/
1125 void
1126 soup_message_content_sniffed (SoupMessage *msg, const char *content_type, GHashTable *params)
1127 {
1128         g_signal_emit (msg, signals[CONTENT_SNIFFED], 0, content_type, params);
1129 }
1130
1131 /**
1132  * soup_message_restarted:
1133  * @msg: a #SoupMessage
1134  *
1135  * Emits the %restarted signal, indicating that @msg should be
1136  * requeued.
1137  **/
1138 void
1139 soup_message_restarted (SoupMessage *msg)
1140 {
1141         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1142
1143         if (priv->msg_flags & SOUP_MESSAGE_CAN_REBUILD)
1144                 soup_message_body_truncate (msg->request_body);
1145
1146         g_signal_emit (msg, signals[RESTARTED], 0);
1147 }
1148
1149 /**
1150  * soup_message_finished:
1151  * @msg: a #SoupMessage
1152  *
1153  * Emits the %finished signal, indicating that @msg has been completely
1154  * processed.
1155  **/
1156 void
1157 soup_message_finished (SoupMessage *msg)
1158 {
1159         g_signal_emit (msg, signals[FINISHED], 0);
1160 }
1161
1162 void
1163 soup_message_network_event (SoupMessage         *msg,
1164                             GSocketClientEvent   event,
1165                             GIOStream           *connection)
1166 {
1167         g_signal_emit (msg, signals[NETWORK_EVENT], 0,
1168                        event, connection);
1169 }
1170
1171 static void
1172 header_handler_free (gpointer header_name, GClosure *closure)
1173 {
1174         g_free (header_name);
1175 }
1176
1177 static void
1178 header_handler_metamarshal (GClosure *closure, GValue *return_value,
1179                             guint n_param_values, const GValue *param_values,
1180                             gpointer invocation_hint, gpointer marshal_data)
1181 {
1182         SoupMessage *msg = g_value_get_object (&param_values[0]);
1183         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1184         const char *header_name = marshal_data;
1185         SoupMessageHeaders *hdrs;
1186
1187 #ifdef FIXME
1188         if (priv->io_status != SOUP_MESSAGE_IO_STATUS_RUNNING)
1189                 return;
1190 #endif
1191
1192         hdrs = priv->server_side ? msg->request_headers : msg->response_headers;
1193         if (soup_message_headers_get_one (hdrs, header_name)) {
1194                 closure->marshal (closure, return_value, n_param_values,
1195                                   param_values, invocation_hint,
1196                                   ((GCClosure *)closure)->callback);
1197         }
1198 }
1199
1200 /**
1201  * soup_message_add_header_handler: (skip)
1202  * @msg: a #SoupMessage
1203  * @signal: signal to connect the handler to.
1204  * @header: HTTP response header to match against
1205  * @callback: the header handler
1206  * @user_data: data to pass to @handler_cb
1207  *
1208  * Adds a signal handler to @msg for @signal, as with
1209  * g_signal_connect(), but with two differences: the @callback will
1210  * only be run if @msg has a header named @header, and it will only be
1211  * run if no earlier handler cancelled or requeued the message.
1212  *
1213  * If @signal is one of the "got" signals (eg, "got_headers"), or
1214  * "finished" or "restarted", then @header is matched against the
1215  * incoming message headers (that is, the #request_headers for a
1216  * client #SoupMessage, or the #response_headers for a server
1217  * #SoupMessage). If @signal is one of the "wrote" signals, then
1218  * @header is matched against the outgoing message headers.
1219  *
1220  * Return value: the handler ID from g_signal_connect()
1221  **/
1222 guint
1223 soup_message_add_header_handler (SoupMessage *msg,
1224                                  const char  *signal,
1225                                  const char  *header,
1226                                  GCallback    callback,
1227                                  gpointer     user_data)
1228 {
1229         GClosure *closure;
1230         char *header_name;
1231
1232         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
1233         g_return_val_if_fail (signal != NULL, 0);
1234         g_return_val_if_fail (header != NULL, 0);
1235         g_return_val_if_fail (callback != NULL, 0);
1236
1237         closure = g_cclosure_new (callback, user_data, NULL);
1238
1239         header_name = g_strdup (header);
1240         g_closure_set_meta_marshal (closure, header_name,
1241                                     header_handler_metamarshal);
1242         g_closure_add_finalize_notifier (closure, header_name,
1243                                          header_handler_free);
1244
1245         return g_signal_connect_closure (msg, signal, closure, FALSE);
1246 }
1247
1248 static void
1249 status_handler_metamarshal (GClosure *closure, GValue *return_value,
1250                             guint n_param_values, const GValue *param_values,
1251                             gpointer invocation_hint, gpointer marshal_data)
1252 {
1253         SoupMessage *msg = g_value_get_object (&param_values[0]);
1254         guint status = GPOINTER_TO_UINT (marshal_data);
1255
1256 #ifdef FIXME
1257         if (priv->io_status != SOUP_MESSAGE_IO_STATUS_RUNNING)
1258                 return;
1259 #endif
1260
1261         if (msg->status_code == status) {
1262                 closure->marshal (closure, return_value, n_param_values,
1263                                   param_values, invocation_hint,
1264                                   ((GCClosure *)closure)->callback);
1265         }
1266 }
1267
1268 /**
1269  * soup_message_add_status_code_handler: (skip)
1270  * @msg: a #SoupMessage
1271  * @signal: signal to connect the handler to.
1272  * @status_code: status code to match against
1273  * @callback: the header handler
1274  * @user_data: data to pass to @handler_cb
1275  *
1276  * Adds a signal handler to @msg for @signal, as with
1277  * g_signal_connect() but with two differences: the @callback will
1278  * only be run if @msg has the status @status_code, and it will only
1279  * be run if no earlier handler cancelled or requeued the message.
1280  *
1281  * @signal must be a signal that will be emitted after @msg's status
1282  * is set. For a client #SoupMessage, this means it can't be a "wrote"
1283  * signal. For a server #SoupMessage, this means it can't be a "got"
1284  * signal.
1285  *
1286  * Return value: the handler ID from g_signal_connect()
1287  **/
1288 guint
1289 soup_message_add_status_code_handler (SoupMessage *msg,
1290                                       const char  *signal,
1291                                       guint        status_code,
1292                                       GCallback    callback,
1293                                       gpointer     user_data)
1294 {
1295         GClosure *closure;
1296
1297         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
1298         g_return_val_if_fail (signal != NULL, 0);
1299         g_return_val_if_fail (callback != NULL, 0);
1300
1301         closure = g_cclosure_new (callback, user_data, NULL);
1302         g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (status_code),
1303                                     status_handler_metamarshal);
1304
1305         return g_signal_connect_closure (msg, signal, closure, FALSE);
1306 }
1307
1308
1309 /**
1310  * soup_message_set_auth:
1311  * @msg: a #SoupMessage
1312  * @auth: a #SoupAuth, or %NULL
1313  *
1314  * Sets @msg to authenticate to its destination using @auth, which
1315  * must have already been fully authenticated. If @auth is %NULL, @msg
1316  * will not authenticate to its destination.
1317  **/
1318 void
1319 soup_message_set_auth (SoupMessage *msg, SoupAuth *auth)
1320 {
1321         SoupMessagePrivate *priv;
1322         char *token;
1323
1324         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1325         g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth));
1326         g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth));
1327
1328         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1329
1330         if (priv->auth) {
1331                 g_object_unref (priv->auth);
1332                 soup_message_headers_remove (msg->request_headers,
1333                                              "Authorization");
1334         }
1335         priv->auth = auth;
1336         if (!priv->auth)
1337                 return;
1338
1339         g_object_ref (priv->auth);
1340         token = soup_auth_get_authorization (auth, msg);
1341         soup_message_headers_replace (msg->request_headers,
1342                                       "Authorization", token);
1343         g_free (token);
1344 }
1345
1346 /**
1347  * soup_message_get_auth:
1348  * @msg: a #SoupMessage
1349  *
1350  * Gets the #SoupAuth used by @msg for authentication.
1351  *
1352  * Return value: (transfer none): the #SoupAuth used by @msg for
1353  * authentication, or %NULL if @msg is unauthenticated.
1354  **/
1355 SoupAuth *
1356 soup_message_get_auth (SoupMessage *msg)
1357 {
1358         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1359
1360         return SOUP_MESSAGE_GET_PRIVATE (msg)->auth;
1361 }
1362
1363 /**
1364  * soup_message_set_proxy_auth:
1365  * @msg: a #SoupMessage
1366  * @auth: a #SoupAuth, or %NULL
1367  *
1368  * Sets @msg to authenticate to its proxy using @auth, which must have
1369  * already been fully authenticated. If @auth is %NULL, @msg will not
1370  * authenticate to its proxy.
1371  **/
1372 void
1373 soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth)
1374 {
1375         SoupMessagePrivate *priv;
1376         char *token;
1377
1378         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1379         g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth));
1380         g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth));
1381
1382         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1383
1384         if (priv->proxy_auth) {
1385                 g_object_unref (priv->proxy_auth);
1386                 soup_message_headers_remove (msg->request_headers,
1387                                              "Proxy-Authorization");
1388         }
1389         priv->proxy_auth = auth;
1390         if (!priv->proxy_auth)
1391                 return;
1392
1393         g_object_ref (priv->proxy_auth);
1394         token = soup_auth_get_authorization (auth, msg);
1395         soup_message_headers_replace (msg->request_headers,
1396                                       "Proxy-Authorization", token);
1397         g_free (token);
1398 }
1399
1400 /**
1401  * soup_message_get_proxy_auth:
1402  * @msg: a #SoupMessage
1403  *
1404  * Gets the #SoupAuth used by @msg for authentication to its proxy..
1405  *
1406  * Return value: the #SoupAuth used by @msg for authentication to its
1407  * proxy, or %NULL if @msg isn't authenticated to its proxy.
1408  **/
1409 SoupAuth *
1410 soup_message_get_proxy_auth (SoupMessage *msg)
1411 {
1412         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1413
1414         return SOUP_MESSAGE_GET_PRIVATE (msg)->proxy_auth;
1415 }
1416
1417 /**
1418  * soup_message_cleanup_response:
1419  * @req: a #SoupMessage
1420  *
1421  * Cleans up all response data on @req, so that the request can be sent
1422  * again and receive a new response. (Eg, as a result of a redirect or
1423  * authorization request.)
1424  **/
1425 void
1426 soup_message_cleanup_response (SoupMessage *req)
1427 {
1428         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
1429
1430         soup_message_body_truncate (req->response_body);
1431         soup_message_headers_clear (req->response_headers);
1432         if (priv->server_side) {
1433                 soup_message_headers_set_encoding (req->response_headers,
1434                                                    SOUP_ENCODING_CONTENT_LENGTH);
1435         }
1436
1437         while (priv->decoders) {
1438                 g_object_unref (priv->decoders->data);
1439                 priv->decoders = g_slist_delete_link (priv->decoders, priv->decoders);
1440         }
1441         priv->msg_flags &= ~SOUP_MESSAGE_CONTENT_DECODED;
1442
1443         req->status_code = SOUP_STATUS_NONE;
1444         if (req->reason_phrase) {
1445                 g_free (req->reason_phrase);
1446                 req->reason_phrase = NULL;
1447         }
1448         priv->http_version = priv->orig_http_version;
1449
1450         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE);
1451         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE);
1452         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_HTTP_VERSION);
1453         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_FLAGS);
1454         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_TLS_CERTIFICATE);
1455         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_TLS_ERRORS);
1456 }
1457
1458 /**
1459  * SoupMessageFlags:
1460  * @SOUP_MESSAGE_NO_REDIRECT: The session should not follow redirect
1461  *   (3xx) responses received by this message.
1462  * @SOUP_MESSAGE_CAN_REBUILD: The caller will rebuild the request
1463  *   body if the message is restarted; see
1464  *   soup_message_body_set_accumulate() for more details.
1465  * @SOUP_MESSAGE_OVERWRITE_CHUNKS: Deprecated: equivalent to calling
1466  *   soup_message_body_set_accumulate() on the incoming message body
1467  *   (ie, #SoupMessage:response_body for a client-side request),
1468  *   passing %FALSE.
1469  * @SOUP_MESSAGE_CONTENT_DECODED: Set by #SoupContentDecoder to
1470  *   indicate that it has removed the Content-Encoding on a message (and
1471  *   so headers such as Content-Length may no longer accurately describe
1472  *   the body).
1473  * @SOUP_MESSAGE_CERTIFICATE_TRUSTED: if set after an https response
1474  *   has been received, indicates that the server's SSL certificate is
1475  *   trusted according to the session's CA.
1476  * @SOUP_MESSAGE_NEW_CONNECTION: The message should be sent on a
1477  *   newly-created connection, not reusing an existing persistent
1478  *   connection. Note that messages with non-idempotent
1479  *   #SoupMessage:method<!-- -->s behave this way by default.
1480  *
1481  * Various flags that can be set on a #SoupMessage to alter its
1482  * behavior.
1483  **/
1484
1485 /**
1486  * soup_message_set_flags:
1487  * @msg: a #SoupMessage
1488  * @flags: a set of #SoupMessageFlags values
1489  *
1490  * Sets the specified flags on @msg.
1491  **/
1492 void
1493 soup_message_set_flags (SoupMessage *msg, SoupMessageFlags flags)
1494 {
1495         SoupMessagePrivate *priv;
1496
1497         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1498         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1499
1500         if ((priv->msg_flags ^ flags) & SOUP_MESSAGE_OVERWRITE_CHUNKS) {
1501                 soup_message_body_set_accumulate (
1502                         priv->server_side ? msg->request_body : msg->response_body,
1503                         !(flags & SOUP_MESSAGE_OVERWRITE_CHUNKS));
1504         }
1505
1506         priv->msg_flags = flags;
1507         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FLAGS);
1508 }
1509
1510 /**
1511  * soup_message_get_flags:
1512  * @msg: a #SoupMessage
1513  *
1514  * Gets the flags on @msg
1515  *
1516  * Return value: the flags
1517  **/
1518 SoupMessageFlags
1519 soup_message_get_flags (SoupMessage *msg)
1520 {
1521         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
1522
1523         return SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags;
1524 }
1525
1526 /**
1527  * SoupHTTPVersion:
1528  * @SOUP_HTTP_1_0: HTTP 1.0 (RFC 1945)
1529  * @SOUP_HTTP_1_1: HTTP 1.1 (RFC 2616)
1530  *
1531  * Indicates the HTTP protocol version being used.
1532  **/
1533
1534 /**
1535  * soup_message_set_http_version:
1536  * @msg: a #SoupMessage
1537  * @version: the HTTP version
1538  *
1539  * Sets the HTTP version on @msg. The default version is
1540  * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain
1541  * functionality from being used.
1542  **/
1543 void
1544 soup_message_set_http_version (SoupMessage *msg, SoupHTTPVersion version)
1545 {
1546         SoupMessagePrivate *priv;
1547
1548         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1549         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1550
1551         priv->http_version = version;
1552         if (msg->status_code == SOUP_STATUS_NONE)
1553                 priv->orig_http_version = version;
1554         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION);
1555 }
1556
1557 /**
1558  * soup_message_get_http_version:
1559  * @msg: a #SoupMessage
1560  *
1561  * Gets the HTTP version of @msg. This is the minimum of the
1562  * version from the request and the version from the response.
1563  *
1564  * Return value: the HTTP version
1565  **/
1566 SoupHTTPVersion
1567 soup_message_get_http_version (SoupMessage *msg)
1568 {
1569         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_HTTP_1_0);
1570
1571         return SOUP_MESSAGE_GET_PRIVATE (msg)->http_version;
1572 }
1573
1574 /**
1575  * soup_message_is_keepalive:
1576  * @msg: a #SoupMessage
1577  *
1578  * Determines whether or not @msg's connection can be kept alive for
1579  * further requests after processing @msg, based on the HTTP version,
1580  * Connection header, etc.
1581  *
1582  * Return value: %TRUE or %FALSE.
1583  **/
1584 gboolean
1585 soup_message_is_keepalive (SoupMessage *msg)
1586 {
1587         const char *c_conn, *s_conn;
1588
1589         c_conn = soup_message_headers_get_list (msg->request_headers,
1590                                                 "Connection");
1591         s_conn = soup_message_headers_get_list (msg->response_headers,
1592                                                 "Connection");
1593
1594         if (msg->status_code == SOUP_STATUS_OK &&
1595             msg->method == SOUP_METHOD_CONNECT)
1596                 return TRUE;
1597
1598         /* Not persistent if the server sent a terminate-by-EOF response */
1599         if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_EOF)
1600                 return FALSE;
1601
1602         if (SOUP_MESSAGE_GET_PRIVATE (msg)->http_version == SOUP_HTTP_1_0) {
1603                 /* In theory, HTTP/1.0 connections are only persistent
1604                  * if the client requests it, and the server agrees.
1605                  * But some servers do keep-alive even if the client
1606                  * doesn't request it. So ignore c_conn.
1607                  */
1608
1609                 if (!s_conn || !soup_header_contains (s_conn, "Keep-Alive"))
1610                         return FALSE;
1611         } else {
1612                 /* Normally persistent unless either side requested otherwise */
1613                 if (c_conn && soup_header_contains (c_conn, "close"))
1614                         return FALSE;
1615                 if (s_conn && soup_header_contains (s_conn, "close"))
1616                         return FALSE;
1617
1618                 return TRUE;
1619         }
1620
1621         return TRUE;
1622 }
1623
1624 /**
1625  * soup_message_set_uri:
1626  * @msg: a #SoupMessage
1627  * @uri: the new #SoupURI
1628  *
1629  * Sets @msg's URI to @uri. If @msg has already been sent and you want
1630  * to re-send it with the new URI, you need to call
1631  * soup_session_requeue_message().
1632  **/
1633 void
1634 soup_message_set_uri (SoupMessage *msg, SoupURI *uri)
1635 {
1636         SoupMessagePrivate *priv;
1637
1638         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1639         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1640
1641         if (priv->uri)
1642                 soup_uri_free (priv->uri);
1643         if (priv->addr) {
1644                 g_object_unref (priv->addr);
1645                 priv->addr = NULL;
1646         }
1647         priv->uri = soup_uri_copy (uri);
1648
1649         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_URI);
1650 }
1651
1652 /**
1653  * soup_message_get_uri:
1654  * @msg: a #SoupMessage
1655  *
1656  * Gets @msg's URI
1657  *
1658  * Return value: (transfer none): the URI @msg is targeted for.
1659  **/
1660 SoupURI *
1661 soup_message_get_uri (SoupMessage *msg)
1662 {
1663         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1664
1665         return SOUP_MESSAGE_GET_PRIVATE (msg)->uri;
1666 }
1667
1668 /**
1669  * soup_message_get_address:
1670  * @msg: a #SoupMessage
1671  *
1672  * Gets the address @msg's URI points to. After first setting the
1673  * URI on a message, this will be unresolved, although the message's
1674  * session will resolve it before sending the message.
1675  *
1676  * Return value: (transfer none): the address @msg's URI points to
1677  *
1678  * Since: 2.26
1679  **/
1680 SoupAddress *
1681 soup_message_get_address (SoupMessage *msg)
1682 {
1683         SoupMessagePrivate *priv;
1684
1685         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1686
1687         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1688         if (!priv->addr) {
1689                 priv->addr = soup_address_new (priv->uri->host,
1690                                                priv->uri->port);
1691         }
1692         return priv->addr;
1693 }
1694
1695 /**
1696  * soup_message_set_status:
1697  * @msg: a #SoupMessage
1698  * @status_code: an HTTP status code
1699  *
1700  * Sets @msg's status code to @status_code. If @status_code is a
1701  * known value, it will also set @msg's reason_phrase.
1702  **/
1703 void
1704 soup_message_set_status (SoupMessage *msg, guint status_code)
1705 {
1706         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1707         g_return_if_fail (status_code != 0);
1708
1709         g_free (msg->reason_phrase);
1710
1711         msg->status_code = status_code;
1712         msg->reason_phrase = g_strdup (soup_status_get_phrase (status_code));
1713         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE);
1714         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE);
1715 }
1716
1717 /**
1718  * soup_message_set_status_full:
1719  * @msg: a #SoupMessage
1720  * @status_code: an HTTP status code
1721  * @reason_phrase: a description of the status
1722  *
1723  * Sets @msg's status code and reason phrase.
1724  **/
1725 void
1726 soup_message_set_status_full (SoupMessage *msg,
1727                               guint        status_code,
1728                               const char  *reason_phrase)
1729 {
1730         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1731         g_return_if_fail (status_code != 0);
1732         g_return_if_fail (reason_phrase != NULL);
1733
1734         g_free (msg->reason_phrase);
1735
1736         msg->status_code = status_code;
1737         msg->reason_phrase = g_strdup (reason_phrase);
1738         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE);
1739         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE);
1740 }
1741
1742 /**
1743  * SoupChunkAllocator:
1744  * @msg: the #SoupMessage the chunk is being allocated for
1745  * @max_len: the maximum length that will be read, or 0.
1746  * @user_data: the data passed to soup_message_set_chunk_allocator()
1747  *
1748  * The prototype for a chunk allocation callback. This should allocate
1749  * a new #SoupBuffer and return it for the I/O layer to read message
1750  * body data off the network into.
1751  *
1752  * If @max_len is non-0, it indicates the maximum number of bytes that
1753  * could be read, based on what is known about the message size. Note
1754  * that this might be a very large number, and you should not simply
1755  * try to allocate that many bytes blindly. If @max_len is 0, that
1756  * means that libsoup does not know how many bytes remain to be read,
1757  * and the allocator should return a buffer of a size that it finds
1758  * convenient.
1759  *
1760  * If the allocator returns %NULL, the message will be paused. It is
1761  * up to the application to make sure that it gets unpaused when it
1762  * becomes possible to allocate a new buffer.
1763  *
1764  * Return value: the new buffer (or %NULL)
1765  **/
1766
1767 /**
1768  * soup_message_set_chunk_allocator:
1769  * @msg: a #SoupMessage
1770  * @allocator: the chunk allocator callback
1771  * @user_data: data to pass to @allocator
1772  * @destroy_notify: destroy notifier to free @user_data when @msg is
1773  * destroyed
1774  *
1775  * Sets an alternate chunk-allocation function to use when reading
1776  * @msg's body. Every time data is available to read, libsoup will
1777  * call @allocator, which should return a #SoupBuffer. (See
1778  * #SoupChunkAllocator for additional details.) Libsoup will then read
1779  * data from the network into that buffer, and update the buffer's
1780  * <literal>length</literal> to indicate how much data it read.
1781  *
1782  * Generally, a custom chunk allocator would be used in conjunction
1783  * with soup_message_body_set_accumulate() %FALSE and
1784  * #SoupMessage::got_chunk, as part of a strategy to avoid unnecessary
1785  * copying of data. However, you cannot assume that every call to the
1786  * allocator will be followed by a call to your
1787  * #SoupMessage::got_chunk handler; if an I/O error occurs, then the
1788  * buffer will be unreffed without ever having been used. If your
1789  * buffer-allocation strategy requires special cleanup, use
1790  * soup_buffer_new_with_owner() rather than doing the cleanup from the
1791  * #SoupMessage::got_chunk handler.
1792  *
1793  * The other thing to remember when using non-accumulating message
1794  * bodies is that the buffer passed to the #SoupMessage::got_chunk
1795  * handler will be unreffed after the handler returns, just as it
1796  * would be in the non-custom-allocated case. If you want to hand the
1797  * chunk data off to some other part of your program to use later,
1798  * you'll need to ref the #SoupBuffer (or its owner, in the
1799  * soup_buffer_new_with_owner() case) to ensure that the data remains
1800  * valid.
1801  **/
1802 void
1803 soup_message_set_chunk_allocator (SoupMessage *msg,
1804                                   SoupChunkAllocator allocator,
1805                                   gpointer user_data,
1806                                   GDestroyNotify destroy_notify)
1807 {
1808         SoupMessagePrivate *priv;
1809
1810         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1811
1812         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1813
1814         if (priv->chunk_allocator_dnotify)
1815                 priv->chunk_allocator_dnotify (priv->chunk_allocator_data);
1816
1817         priv->chunk_allocator         = allocator;
1818         priv->chunk_allocator_data    = user_data;
1819         priv->chunk_allocator_dnotify = destroy_notify;
1820 }
1821
1822 /**
1823  * soup_message_disable_feature:
1824  * @msg: a #SoupMessage
1825  * @feature_type: the #GType of a #SoupSessionFeature
1826  *
1827  * This disables the actions of #SoupSessionFeature<!-- -->s with the
1828  * given @feature_type (or a subclass of that type) on @msg, so that
1829  * @msg is processed as though the feature(s) hadn't been added to the
1830  * session. Eg, passing #SOUP_TYPE_PROXY_URI_RESOLVER for @feature_type
1831  * will disable proxy handling and cause @msg to be sent directly to
1832  * the indicated origin server, regardless of system proxy
1833  * configuration.
1834  *
1835  * You must call this before queueing @msg on a session; calling it on
1836  * a message that has already been queued is undefined. In particular,
1837  * you cannot call this on a message that is being requeued after a
1838  * redirect or authentication.
1839  *
1840  * Since: 2.28
1841  **/
1842 void
1843 soup_message_disable_feature (SoupMessage *msg, GType feature_type)
1844 {
1845         SoupMessagePrivate *priv;
1846
1847         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1848
1849         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1850
1851         priv->disabled_features = g_slist_prepend (priv->disabled_features,
1852                                                    GSIZE_TO_POINTER (feature_type));
1853 }
1854
1855 gboolean
1856 soup_message_disables_feature (SoupMessage *msg, gpointer feature)
1857 {
1858         SoupMessagePrivate *priv;
1859         GSList *f;
1860
1861         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE);
1862
1863         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1864
1865         for (f = priv->disabled_features; f; f = f->next) {
1866                 if (G_TYPE_CHECK_INSTANCE_TYPE (feature, (GType) GPOINTER_TO_SIZE (f->data)))
1867                         return TRUE;
1868         }
1869         return FALSE;
1870 }
1871
1872 /**
1873  * soup_message_get_first_party:
1874  * @msg: a #SoupMessage
1875  *
1876  * Gets @msg's first-party #SoupURI
1877  * 
1878  * Returns: (transfer none): the @msg's first party #SoupURI
1879  * 
1880  * Since: 2.30
1881  **/
1882 SoupURI *
1883 soup_message_get_first_party (SoupMessage *msg)
1884 {
1885         SoupMessagePrivate *priv;
1886
1887         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1888
1889         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1890         return priv->first_party;
1891 }
1892
1893 /**
1894  * soup_message_set_first_party:
1895  * @msg: a #SoupMessage
1896  * @first_party: the #SoupURI for the @msg's first party
1897  * 
1898  * Sets @first_party as the main document #SoupURI for @msg. For
1899  * details of when and how this is used refer to the documentation for
1900  * #SoupCookieJarAcceptPolicy.
1901  *
1902  * Since: 2.30
1903  **/
1904 void
1905 soup_message_set_first_party (SoupMessage *msg,
1906                               SoupURI     *first_party)
1907 {
1908         SoupMessagePrivate *priv;
1909
1910         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1911         g_return_if_fail (first_party != NULL);
1912
1913         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1914
1915         if (priv->first_party) {
1916                 if (soup_uri_equal (priv->first_party, first_party))
1917                         return;
1918
1919                 soup_uri_free (priv->first_party);
1920         }
1921
1922         priv->first_party = soup_uri_copy (first_party);
1923         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FIRST_PARTY);
1924 }
1925
1926 void
1927 soup_message_set_https_status (SoupMessage *msg, SoupConnection *conn)
1928 {
1929         SoupSocket *sock;
1930
1931         sock = conn ? soup_connection_get_socket (conn) : NULL;
1932         if (sock && soup_socket_is_ssl (sock)) {
1933                 GTlsCertificate *certificate;
1934                 GTlsCertificateFlags errors;
1935
1936                 g_object_get (sock,
1937                               SOUP_SOCKET_TLS_CERTIFICATE, &certificate,
1938                               SOUP_SOCKET_TLS_ERRORS, &errors,
1939                               NULL);
1940                 g_object_set (msg,
1941                               SOUP_MESSAGE_TLS_CERTIFICATE, certificate,
1942                               SOUP_MESSAGE_TLS_ERRORS, errors,
1943                               NULL);
1944                 if (certificate)
1945                         g_object_unref (certificate);
1946         } else {
1947                 g_object_set (msg,
1948                               SOUP_MESSAGE_TLS_CERTIFICATE, NULL,
1949                               SOUP_MESSAGE_TLS_ERRORS, 0,
1950                               NULL);
1951         }
1952 }
1953
1954 /**
1955  * soup_message_get_https_status:
1956  * @msg: a #SoupMessage
1957  * @certificate: (out) (transfer none): @msg's TLS certificate
1958  * @errors: (out): the verification status of @certificate
1959  *
1960  * If @msg is using https, this retrieves the #GTlsCertificate
1961  * associated with its connection, and the #GTlsCertificateFlags showing
1962  * what problems, if any, have been found with that certificate.
1963  *
1964  * Return value: %TRUE if @msg uses https, %FALSE if not
1965  *
1966  * Since: 2.34
1967  */
1968 gboolean
1969 soup_message_get_https_status (SoupMessage           *msg,
1970                                GTlsCertificate      **certificate,
1971                                GTlsCertificateFlags  *errors)
1972 {
1973         SoupMessagePrivate *priv;
1974
1975         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), FALSE);
1976
1977         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1978
1979         if (certificate)
1980                 *certificate = priv->tls_certificate;
1981         if (errors)
1982                 *errors = priv->tls_errors;
1983         return priv->tls_certificate != NULL;
1984 }
1985
1986 /**
1987  * soup_message_set_redirect:
1988  * @msg: a #SoupMessage
1989  * @status_code: a 3xx status code
1990  * @redirect_uri: the URI to redirect @msg to
1991  *
1992  * Sets @msg's status_code to @status_code and adds a Location header
1993  * pointing to @redirect_uri. Use this from a #SoupServer when you
1994  * want to redirect the client to another URI.
1995  *
1996  * @redirect_uri can be a relative URI, in which case it is
1997  * interpreted relative to @msg's current URI. In particular, if
1998  * @redirect_uri is just a path, it will replace the path
1999  * <emphasis>and query</emphasis> of @msg's URI.
2000  *
2001  * Since: 2.38
2002  */
2003 void
2004 soup_message_set_redirect (SoupMessage *msg, guint status_code,
2005                            const char *redirect_uri)
2006 {
2007         SoupURI *location;
2008         char *location_str;
2009
2010         location = soup_uri_new_with_base (soup_message_get_uri (msg), redirect_uri);
2011         g_return_if_fail (location != NULL);
2012
2013         soup_message_set_status (msg, status_code);
2014         location_str = soup_uri_to_string (location, FALSE);
2015         soup_message_headers_replace (msg->response_headers, "Location",
2016                                       location_str);
2017         g_free (location_str);
2018         soup_uri_free (location);
2019 }