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