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