1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-message-body.c: SoupMessage request/response bodies
5 * Copyright (C) 2000-2003, Ximian, Inc.
10 #include "soup-message-body.h"
13 * SECTION:soup-message-body
14 * @short_description: HTTP message body
15 * @see_also: #SoupMessage
17 * #SoupMessageBody represents the request or response body of a
20 * In addition to #SoupMessageBody, libsoup also defines a "smaller"
21 * data buffer type, #SoupBuffer, which is primarily used as a
22 * component of #SoupMessageBody. In particular, when using chunked
23 * encoding to transmit or receive a message, each chunk is
24 * represented as a #SoupBuffer.
29 * @SOUP_MEMORY_STATIC: The memory is statically allocated and
30 * constant; libsoup can use the passed-in buffer directly and not
31 * need to worry about it being modified or freed.
32 * @SOUP_MEMORY_TAKE: The caller has allocated the memory for the
33 * #SoupBuffer's use; libsoup will assume ownership of it and free it
34 * (with g_free()) when it is done with it.
35 * @SOUP_MEMORY_COPY: The passed-in data belongs to the caller; the
36 * #SoupBuffer will copy it into new memory, leaving the caller free
37 * to reuse the original memory.
38 * @SOUP_MEMORY_TEMPORARY: The passed-in data belongs to the caller,
39 * but will remain valid for the lifetime of the #SoupBuffer. The
40 * difference between this and @SOUP_MEMORY_STATIC is that if you copy
41 * a @SOUP_MEMORY_TEMPORARY buffer, it will make a copy of the memory
42 * as well, rather than reusing the original memory.
44 * Describes how #SoupBuffer should use the data passed in by the
47 * See also soup_buffer_new_with_owner(), which allows to you create a
48 * buffer containing data which is owned by another object.
51 /* Internal SoupMemoryUse values */
53 SOUP_MEMORY_SUBBUFFER = SOUP_MEMORY_TEMPORARY + 1,
59 * @data: (type gpointer): the data
60 * @length: length of @data
62 * A data buffer, generally used to represent a chunk of a
65 * @data is a #char because that's generally convenient; in some
66 * situations you may need to cast it to #guchar or another type.
75 GDestroyNotify owner_dnotify;
80 * @use: how @data is to be used by the buffer
82 * @length: length of @data
84 * Creates a new #SoupBuffer containing @length bytes from @data.
86 * Return value: the new #SoupBuffer.
89 soup_buffer_new (SoupMemoryUse use, gconstpointer data, gsize length)
91 SoupBufferPrivate *priv = g_slice_new0 (SoupBufferPrivate);
93 if (use == SOUP_MEMORY_COPY) {
94 data = g_memdup (data, length);
95 use = SOUP_MEMORY_TAKE;
98 priv->buffer.data = data;
99 priv->buffer.length = length;
103 if (use == SOUP_MEMORY_TAKE) {
104 priv->owner = (gpointer)data;
105 priv->owner_dnotify = g_free;
108 return (SoupBuffer *)priv;
112 * soup_buffer_new_take:
113 * @data: (array length=length) (transfer full): data
114 * @length: length of @data
116 * Creates a new #SoupBuffer containing @length bytes from @data.
118 * This function is exactly equivalent to soup_buffer_new() with
119 * %SOUP_MEMORY_TAKE as first argument; it exists mainly for
120 * convenience and simplifying language bindings.
122 * Return value: the new #SoupBuffer.
125 * Rename to: soup_buffer_new
128 soup_buffer_new_take (guchar *data, gsize length)
130 return soup_buffer_new (SOUP_MEMORY_TAKE, data, length);
134 * soup_buffer_new_subbuffer:
135 * @parent: the parent #SoupBuffer
136 * @offset: offset within @parent to start at
137 * @length: number of bytes to copy from @parent
139 * Creates a new #SoupBuffer containing @length bytes "copied" from
140 * @parent starting at @offset. (Normally this will not actually copy
141 * any data, but will instead simply reference the same data as
144 * Return value: the new #SoupBuffer.
147 soup_buffer_new_subbuffer (SoupBuffer *parent, gsize offset, gsize length)
149 SoupBufferPrivate *priv;
151 /* Normally this is just a ref, but if @parent is TEMPORARY,
152 * it will do an actual copy.
154 parent = soup_buffer_copy (parent);
156 priv = g_slice_new0 (SoupBufferPrivate);
157 priv->buffer.data = parent->data + offset;
158 priv->buffer.length = length;
159 priv->use = SOUP_MEMORY_SUBBUFFER;
160 priv->owner = parent;
161 priv->owner_dnotify = (GDestroyNotify)soup_buffer_free;
164 return (SoupBuffer *)priv;
168 * soup_buffer_new_with_owner:
170 * @length: length of @data
171 * @owner: pointer to an object that owns @data
172 * @owner_dnotify: (allow-none): a function to free/unref @owner when
173 * the buffer is freed
175 * Creates a new #SoupBuffer containing @length bytes from @data. When
176 * the #SoupBuffer is freed, it will call @owner_dnotify, passing
177 * @owner to it. You must ensure that @data will remain valid until
178 * @owner_dnotify is called.
180 * For example, you could use this to create a buffer containing data
181 * returned from libxml without needing to do an extra copy:
183 * <informalexample><programlisting>
184 * xmlDocDumpMemory (doc, &xmlbody, &len);
185 * return soup_buffer_new_with_owner (xmlbody, len, xmlbody,
186 * (GDestroyNotify)xmlFree);
187 * </programlisting></informalexample>
189 * In this example, @data and @owner are the same, but in other cases
190 * they would be different (eg, @owner would be a object, and @data
191 * would be a pointer to one of the object's fields).
193 * Return value: the new #SoupBuffer.
196 soup_buffer_new_with_owner (gconstpointer data, gsize length,
197 gpointer owner, GDestroyNotify owner_dnotify)
199 SoupBufferPrivate *priv = g_slice_new0 (SoupBufferPrivate);
201 priv->buffer.data = data;
202 priv->buffer.length = length;
203 priv->use = SOUP_MEMORY_OWNED;
205 priv->owner_dnotify = owner_dnotify;
208 return (SoupBuffer *)priv;
212 * soup_buffer_get_owner:
213 * @buffer: a #SoupBuffer created with soup_buffer_new_with_owner()
215 * Gets the "owner" object for a buffer created with
216 * soup_buffer_new_with_owner().
218 * Return value: (transfer none): the owner pointer
221 soup_buffer_get_owner (SoupBuffer *buffer)
223 SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;
225 g_return_val_if_fail ((int)priv->use == (int)SOUP_MEMORY_OWNED, NULL);
230 * soup_buffer_get_data:
231 * @buffer: a #SoupBuffer
232 * @data: (out) (array length=length) (transfer none): the pointer
233 * to the buffer data is stored here
234 * @length: (out): the length of the buffer data is stored here
236 * This function exists for use by language bindings, because it's not
237 * currently possible to get the right effect by annotating the fields
243 soup_buffer_get_data (SoupBuffer *buffer,
247 *data = (const guint8 *)buffer->data;
248 *length = buffer->length;
253 * @buffer: a #SoupBuffer
255 * Makes a copy of @buffer. In reality, #SoupBuffer is a refcounted
256 * type, and calling soup_buffer_copy() will normally just increment
257 * the refcount on @buffer and return it. However, if @buffer was
258 * created with #SOUP_MEMORY_TEMPORARY memory, then soup_buffer_copy()
259 * will actually return a copy of it, so that the data in the copy
260 * will remain valid after the temporary buffer is freed.
262 * Return value: the new (or newly-reffed) buffer
265 soup_buffer_copy (SoupBuffer *buffer)
267 SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;
269 /* For non-TEMPORARY buffers, this is just a ref */
270 if (priv->use != SOUP_MEMORY_TEMPORARY) {
275 /* For TEMPORARY buffers, we need to do a real copy the first
276 * time, and then after that, we just keep returning the copy.
277 * We store the copy in priv->owner, which is technically
278 * backwards, but it saves us from having to keep an extra
279 * pointer in SoupBufferPrivate.
283 priv->owner = soup_buffer_new (SOUP_MEMORY_COPY,
286 priv->owner_dnotify = (GDestroyNotify)soup_buffer_free;
288 return soup_buffer_copy (priv->owner);
293 * @buffer: a #SoupBuffer
295 * Frees @buffer. (In reality, as described in the documentation for
296 * soup_buffer_copy(), this is actually an "unref" operation, and may
297 * or may not actually free @buffer.)
300 soup_buffer_free (SoupBuffer *buffer)
302 SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;
304 if (!--priv->refcount) {
305 if (priv->owner_dnotify)
306 priv->owner_dnotify (priv->owner);
307 g_slice_free (SoupBufferPrivate, priv);
312 soup_buffer_get_type (void)
314 static volatile gsize type_volatile = 0;
316 if (g_once_init_enter (&type_volatile)) {
317 GType type = g_boxed_type_register_static (
318 g_intern_static_string ("SoupBuffer"),
319 (GBoxedCopyFunc) soup_buffer_copy,
320 (GBoxedFreeFunc) soup_buffer_free);
321 g_once_init_leave (&type_volatile, type);
323 return type_volatile;
330 * @length: length of @data
332 * A #SoupMessage request or response body.
334 * Note that while @length always reflects the full length of the
335 * message body, @data is normally %NULL, and will only be filled in
336 * after soup_message_body_flatten() is called. For client-side
337 * messages, this automatically happens for the response body after it
338 * has been fully read, unless you set the
339 * %SOUP_MESSAGE_OVERWRITE_CHUNKS flags. Likewise, for server-side
340 * messages, the request body is automatically filled in after being
343 * As an added bonus, when @data is filled in, it is always terminated
344 * with a '\0' byte (which is not reflected in @length).
348 SoupMessageBody body;
349 GSList *chunks, *last;
350 SoupBuffer *flattened;
354 } SoupMessageBodyPrivate;
357 * soup_message_body_new:
359 * Creates a new #SoupMessageBody. #SoupMessage uses this internally; you
360 * will not normally need to call it yourself.
362 * Return value: a new #SoupMessageBody.
365 soup_message_body_new (void)
367 SoupMessageBodyPrivate *priv;
369 priv = g_slice_new0 (SoupMessageBodyPrivate);
370 priv->accumulate = TRUE;
373 return (SoupMessageBody *)priv;
377 * soup_message_body_set_accumulate:
378 * @body: a #SoupMessageBody
379 * @accumulate: whether or not to accumulate body chunks in @body
381 * Sets or clears the accumulate flag on @body. (The default value is
382 * %TRUE.) If set to %FALSE, @body's %data field will not be filled in
383 * after the body is fully sent/received, and the chunks that make up
384 * @body may be discarded when they are no longer needed.
386 * In particular, if you set this flag to %FALSE on an "incoming"
387 * message body (that is, the %response_body of a client-side message,
388 * or %request_body of a server-side message), this will cause each
389 * chunk of the body to be discarded after its corresponding
390 * #SoupMessage::got_chunk signal is emitted. (This is equivalent to
391 * setting the deprecated %SOUP_MESSAGE_OVERWRITE_CHUNKS flag on the
394 * If you set this flag to %FALSE on the %response_body of a
395 * server-side message, it will cause each chunk of the body to be
396 * discarded after its corresponding #SoupMessage::wrote_chunk signal
399 * If you set the flag to %FALSE on the %request_body of a client-side
400 * message, it will block the accumulation of chunks into @body's
401 * %data field, but it will not normally cause the chunks to be
402 * discarded after being written like in the server-side
403 * %response_body case, because the request body needs to be kept
404 * around in case the request needs to be sent a second time due to
405 * redirection or authentication. However, if you set the
406 * %SOUP_MESSAGE_CAN_REBUILD flag on the message, then the chunks will
407 * be discarded, and you will be responsible for recreating the
408 * request body after the #SoupMessage::restarted signal is emitted.
413 soup_message_body_set_accumulate (SoupMessageBody *body,
416 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
418 priv->accumulate = accumulate;
422 * soup_message_body_get_accumulate:
423 * @body: a #SoupMessageBody
425 * Gets the accumulate flag on @body; see
426 * soup_message_body_set_accumulate() for details.
428 * Return value: the accumulate flag for @body.
433 soup_message_body_get_accumulate (SoupMessageBody *body)
435 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
437 return priv->accumulate;
441 append_buffer (SoupMessageBody *body, SoupBuffer *buffer)
443 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
446 priv->last = g_slist_append (priv->last, buffer);
447 priv->last = priv->last->next;
449 priv->chunks = priv->last = g_slist_append (NULL, buffer);
451 if (priv->flattened) {
452 soup_buffer_free (priv->flattened);
453 priv->flattened = NULL;
456 body->length += buffer->length;
460 * soup_message_body_append:
461 * @body: a #SoupMessageBody
462 * @use: how to use @data
463 * @data: (array length=length) (element-type guint8): data to append
464 * @length: length of @data
466 * Appends @length bytes from @data to @body according to @use.
469 soup_message_body_append (SoupMessageBody *body, SoupMemoryUse use,
470 gconstpointer data, gsize length)
473 append_buffer (body, soup_buffer_new (use, data, length));
474 else if (use == SOUP_MEMORY_TAKE)
475 g_free ((gpointer)data);
479 * soup_message_body_append_take:
480 * @body: a #SoupMessageBody
481 * @data: (array length=length) (transfer full): data to append
482 * @length: length of @data
484 * Appends @length bytes from @data to @body.
486 * This function is exactly equivalent to soup_message_body_apppend()
487 * with %SOUP_MEMORY_TAKE as second argument; it exists mainly for
488 * convenience and simplifying language bindings.
491 * Rename to: soup_message_body_append
494 soup_message_body_append_take (SoupMessageBody *body,
495 guchar *data, gsize length)
497 soup_message_body_append(body, SOUP_MEMORY_TAKE, data, length);
501 * soup_message_body_append_buffer:
502 * @body: a #SoupMessageBody
503 * @buffer: a #SoupBuffer
505 * Appends the data from @buffer to @body. (#SoupMessageBody uses
506 * #SoupBuffers internally, so this is normally a constant-time
507 * operation that doesn't actually require copying the data in
511 soup_message_body_append_buffer (SoupMessageBody *body, SoupBuffer *buffer)
513 g_return_if_fail (buffer->length > 0);
514 append_buffer (body, soup_buffer_copy (buffer));
518 * soup_message_body_truncate:
519 * @body: a #SoupMessageBody
521 * Deletes all of the data in @body.
524 soup_message_body_truncate (SoupMessageBody *body)
526 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
529 for (iter = priv->chunks; iter; iter = iter->next)
530 soup_buffer_free (iter->data);
531 g_slist_free (priv->chunks);
532 priv->chunks = priv->last = NULL;
533 priv->base_offset = 0;
535 if (priv->flattened) {
536 soup_buffer_free (priv->flattened);
537 priv->flattened = NULL;
544 * soup_message_body_complete:
545 * @body: a #SoupMessageBody
547 * Tags @body as being complete; Call this when using chunked encoding
548 * after you have appended the last chunk.
551 soup_message_body_complete (SoupMessageBody *body)
553 append_buffer (body, soup_buffer_new (SOUP_MEMORY_STATIC, NULL, 0));
557 * soup_message_body_flatten:
558 * @body: a #SoupMessageBody
560 * Fills in @body's data field with a buffer containing all of the
561 * data in @body (plus an additional '\0' byte not counted by @body's
564 * Return value: a #SoupBuffer containing the same data as @body.
565 * (You must free this buffer if you do not want it.)
568 soup_message_body_flatten (SoupMessageBody *body)
570 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
575 g_return_val_if_fail (priv->accumulate == TRUE, NULL);
577 if (!priv->flattened) {
578 #if GLIB_SIZEOF_SIZE_T < 8
579 g_return_val_if_fail (body->length < G_MAXSIZE, NULL);
582 buf = ptr = g_malloc (body->length + 1);
583 for (iter = priv->chunks; iter; iter = iter->next) {
585 memcpy (ptr, chunk->data, chunk->length);
586 ptr += chunk->length;
590 priv->flattened = soup_buffer_new (SOUP_MEMORY_TAKE,
592 body->data = priv->flattened->data;
595 return soup_buffer_copy (priv->flattened);
599 * soup_message_body_get_chunk:
600 * @body: a #SoupMessageBody
603 * Gets a #SoupBuffer containing data from @body starting at @offset.
604 * The size of the returned chunk is unspecified. You can iterate
605 * through the entire body by first calling
606 * soup_message_body_get_chunk() with an offset of 0, and then on each
607 * successive call, increment the offset by the length of the
608 * previously-returned chunk.
610 * If @offset is greater than or equal to the total length of @body,
611 * then the return value depends on whether or not
612 * soup_message_body_complete() has been called or not; if it has,
613 * then soup_message_body_get_chunk() will return a 0-length chunk
614 * (indicating the end of @body). If it has not, then
615 * soup_message_body_get_chunk() will return %NULL (indicating that
616 * @body may still potentially have more data, but that data is not
617 * currently available).
619 * Return value: a #SoupBuffer, or %NULL.
622 soup_message_body_get_chunk (SoupMessageBody *body, goffset offset)
624 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
626 SoupBuffer *chunk = NULL;
628 offset -= priv->base_offset;
629 for (iter = priv->chunks; iter; iter = iter->next) {
632 if (offset < chunk->length || offset == 0)
635 offset -= chunk->length;
642 return soup_buffer_copy (chunk);
644 return soup_buffer_new_subbuffer (chunk, offset,
645 chunk->length - offset);
650 * soup_message_body_got_chunk:
651 * @body: a #SoupMessageBody
652 * @chunk: a #SoupBuffer received from the network
654 * Handles the #SoupMessageBody part of receiving a chunk of data from
655 * the network. Normally this means appending @chunk to @body, exactly
656 * as with soup_message_body_append_buffer(), but if you have set
657 * @body's accumulate flag to %FALSE, then that will not happen.
659 * This is a low-level method which you should not normally need to
665 soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk)
667 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
669 if (!priv->accumulate)
672 soup_message_body_append_buffer (body, chunk);
676 * soup_message_body_wrote_chunk:
677 * @body: a #SoupMessageBody
678 * @chunk: a #SoupBuffer returned from soup_message_body_get_chunk()
680 * Handles the #SoupMessageBody part of writing a chunk of data to the
681 * network. Normally this is a no-op, but if you have set @body's
682 * accumulate flag to %FALSE, then this will cause @chunk to be
683 * discarded to free up memory.
685 * This is a low-level method which you should not need to use, and
686 * there are further restrictions on its proper use which are not
692 soup_message_body_wrote_chunk (SoupMessageBody *body, SoupBuffer *chunk)
694 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
697 if (priv->accumulate)
700 chunk2 = priv->chunks->data;
701 g_return_if_fail (chunk->length == chunk2->length);
702 g_return_if_fail (chunk == chunk2 || ((SoupBufferPrivate *)chunk2)->use == SOUP_MEMORY_TEMPORARY);
704 priv->chunks = g_slist_remove (priv->chunks, chunk2);
708 priv->base_offset += chunk2->length;
709 soup_buffer_free (chunk2);
712 static SoupMessageBody *
713 soup_message_body_copy (SoupMessageBody *body)
715 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
722 * soup_message_body_free:
723 * @body: a #SoupMessageBody
725 * Frees @body. You will not normally need to use this, as
726 * #SoupMessage frees its associated message bodies automatically.
729 soup_message_body_free (SoupMessageBody *body)
731 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
733 if (--priv->ref_count == 0) {
734 soup_message_body_truncate (body);
735 g_slice_free (SoupMessageBodyPrivate, priv);
740 soup_message_body_get_type (void)
742 static volatile gsize type_volatile = 0;
744 if (g_once_init_enter (&type_volatile)) {
745 GType type = g_boxed_type_register_static (
746 g_intern_static_string ("SoupMessageBody"),
747 (GBoxedCopyFunc) soup_message_body_copy,
748 (GBoxedFreeFunc) soup_message_body_free);
749 g_once_init_leave (&type_volatile, type);
751 return type_volatile;