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"
14 * SECTION:soup-message-body
15 * @short_description: HTTP message body
16 * @see_also: #SoupMessage
18 * #SoupMessageBody represents the request or response body of a
21 * In addition to #SoupMessageBody, libsoup also defines a "smaller"
22 * data buffer type, #SoupBuffer, which is primarily used as a
23 * component of #SoupMessageBody. In particular, when using chunked
24 * encoding to transmit or receive a message, each chunk is
25 * represented as a #SoupBuffer.
30 * @SOUP_MEMORY_STATIC: The memory is statically allocated and
31 * constant; libsoup can use the passed-in buffer directly and not
32 * need to worry about it being modified or freed.
33 * @SOUP_MEMORY_TAKE: The caller has allocated the memory for the
34 * #SoupBuffer's use; libsoup will assume ownership of it and free it
35 * (with g_free()) when it is done with it.
36 * @SOUP_MEMORY_COPY: The passed-in data belongs to the caller; the
37 * #SoupBuffer will copy it into new memory, leaving the caller free
38 * to reuse the original memory.
39 * @SOUP_MEMORY_TEMPORARY: The passed-in data belongs to the caller,
40 * but will remain valid for the lifetime of the #SoupBuffer. The
41 * difference between this and @SOUP_MEMORY_STATIC is that if you copy
42 * a @SOUP_MEMORY_TEMPORARY buffer, it will make a copy of the memory
43 * as well, rather than reusing the original memory.
45 * Describes how #SoupBuffer should use the data passed in by the
48 * See also soup_buffer_new_with_owner(), which allows to you create a
49 * buffer containing data which is owned by another object.
52 /* Internal SoupMemoryUse values */
54 SOUP_MEMORY_SUBBUFFER = SOUP_MEMORY_TEMPORARY + 1,
60 * @data: (type gpointer): the data
61 * @length: length of @data
63 * A data buffer, generally used to represent a chunk of a
66 * @data is a #char because that's generally convenient; in some
67 * situations you may need to cast it to #guchar or another type.
76 GDestroyNotify owner_dnotify;
81 * @use: how @data is to be used by the buffer
83 * @length: length of @data
85 * Creates a new #SoupBuffer containing @length bytes from @data.
87 * Return value: the new #SoupBuffer.
90 soup_buffer_new (SoupMemoryUse use, gconstpointer data, gsize length)
92 SoupBufferPrivate *priv = g_slice_new0 (SoupBufferPrivate);
94 if (use == SOUP_MEMORY_COPY) {
95 data = g_memdup (data, length);
96 use = SOUP_MEMORY_TAKE;
99 priv->buffer.data = data;
100 priv->buffer.length = length;
104 if (use == SOUP_MEMORY_TAKE) {
105 priv->owner = (gpointer)data;
106 priv->owner_dnotify = g_free;
109 return (SoupBuffer *)priv;
113 * soup_buffer_new_take:
114 * @data: (array length=length) (transfer full): data
115 * @length: length of @data
117 * Creates a new #SoupBuffer containing @length bytes from @data.
119 * This function is exactly equivalent to soup_buffer_new() with
120 * %SOUP_MEMORY_TAKE as first argument; it exists mainly for
121 * convenience and simplifying language bindings.
123 * Return value: the new #SoupBuffer.
125 * Rename to: soup_buffer_new
129 soup_buffer_new_take (guchar *data, gsize length)
131 return soup_buffer_new (SOUP_MEMORY_TAKE, data, length);
135 * soup_buffer_new_subbuffer:
136 * @parent: the parent #SoupBuffer
137 * @offset: offset within @parent to start at
138 * @length: number of bytes to copy from @parent
140 * Creates a new #SoupBuffer containing @length bytes "copied" from
141 * @parent starting at @offset. (Normally this will not actually copy
142 * any data, but will instead simply reference the same data as
145 * Return value: the new #SoupBuffer.
148 soup_buffer_new_subbuffer (SoupBuffer *parent, gsize offset, gsize length)
150 SoupBufferPrivate *priv;
152 /* Normally this is just a ref, but if @parent is TEMPORARY,
153 * it will do an actual copy.
155 parent = soup_buffer_copy (parent);
157 priv = g_slice_new0 (SoupBufferPrivate);
158 priv->buffer.data = parent->data + offset;
159 priv->buffer.length = length;
160 priv->use = SOUP_MEMORY_SUBBUFFER;
161 priv->owner = parent;
162 priv->owner_dnotify = (GDestroyNotify)soup_buffer_free;
165 return (SoupBuffer *)priv;
169 * soup_buffer_new_with_owner:
171 * @length: length of @data
172 * @owner: pointer to an object that owns @data
173 * @owner_dnotify: (allow-none): a function to free/unref @owner when
174 * the buffer is freed
176 * Creates a new #SoupBuffer containing @length bytes from @data. When
177 * the #SoupBuffer is freed, it will call @owner_dnotify, passing
178 * @owner to it. You must ensure that @data will remain valid until
179 * @owner_dnotify is called.
181 * For example, you could use this to create a buffer containing data
182 * returned from libxml without needing to do an extra copy:
184 * <informalexample><programlisting>
185 * xmlDocDumpMemory (doc, &xmlbody, &len);
186 * return soup_buffer_new_with_owner (xmlbody, len, xmlbody,
187 * (GDestroyNotify)xmlFree);
188 * </programlisting></informalexample>
190 * In this example, @data and @owner are the same, but in other cases
191 * they would be different (eg, @owner would be a object, and @data
192 * would be a pointer to one of the object's fields).
194 * Return value: the new #SoupBuffer.
197 soup_buffer_new_with_owner (gconstpointer data, gsize length,
198 gpointer owner, GDestroyNotify owner_dnotify)
200 SoupBufferPrivate *priv = g_slice_new0 (SoupBufferPrivate);
202 priv->buffer.data = data;
203 priv->buffer.length = length;
204 priv->use = SOUP_MEMORY_OWNED;
206 priv->owner_dnotify = owner_dnotify;
209 return (SoupBuffer *)priv;
213 * soup_buffer_get_owner:
214 * @buffer: a #SoupBuffer created with soup_buffer_new_with_owner()
216 * Gets the "owner" object for a buffer created with
217 * soup_buffer_new_with_owner().
219 * Return value: (transfer none): the owner pointer
222 soup_buffer_get_owner (SoupBuffer *buffer)
224 SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;
226 g_return_val_if_fail ((int)priv->use == (int)SOUP_MEMORY_OWNED, NULL);
231 * soup_buffer_get_data:
232 * @buffer: a #SoupBuffer
233 * @data: (out) (array length=length) (transfer none): the pointer
234 * to the buffer data is stored here
235 * @length: (out): the length of the buffer data is stored here
237 * This function exists for use by language bindings, because it's not
238 * currently possible to get the right effect by annotating the fields
244 soup_buffer_get_data (SoupBuffer *buffer,
248 *data = (const guint8 *)buffer->data;
249 *length = buffer->length;
254 * @buffer: a #SoupBuffer
256 * Makes a copy of @buffer. In reality, #SoupBuffer is a refcounted
257 * type, and calling soup_buffer_copy() will normally just increment
258 * the refcount on @buffer and return it. However, if @buffer was
259 * created with #SOUP_MEMORY_TEMPORARY memory, then soup_buffer_copy()
260 * will actually return a copy of it, so that the data in the copy
261 * will remain valid after the temporary buffer is freed.
263 * Return value: the new (or newly-reffed) buffer
266 soup_buffer_copy (SoupBuffer *buffer)
268 SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;
270 /* For non-TEMPORARY buffers, this is just a ref */
271 if (priv->use != SOUP_MEMORY_TEMPORARY) {
276 /* For TEMPORARY buffers, we need to do a real copy the first
277 * time, and then after that, we just keep returning the copy.
278 * We store the copy in priv->owner, which is technically
279 * backwards, but it saves us from having to keep an extra
280 * pointer in SoupBufferPrivate.
284 priv->owner = soup_buffer_new (SOUP_MEMORY_COPY,
287 priv->owner_dnotify = (GDestroyNotify)soup_buffer_free;
289 return soup_buffer_copy (priv->owner);
294 * @buffer: a #SoupBuffer
296 * Frees @buffer. (In reality, as described in the documentation for
297 * soup_buffer_copy(), this is actually an "unref" operation, and may
298 * or may not actually free @buffer.)
301 soup_buffer_free (SoupBuffer *buffer)
303 SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;
305 if (!--priv->refcount) {
306 if (priv->owner_dnotify)
307 priv->owner_dnotify (priv->owner);
308 g_slice_free (SoupBufferPrivate, priv);
313 * soup_buffer_get_as_bytes:
314 * @buffer: a #SoupBuffer
316 * Creates a #GBytes pointing to the same memory as @buffer. The
317 * #GBytes will hold a reference on @buffer to ensure that it is not
318 * freed while the #GBytes is still valid.
320 * Returns: (transfer full): a new #GBytes which has the same content
321 * as the #SoupBuffer.
326 soup_buffer_get_as_bytes (SoupBuffer *buffer)
330 copy = soup_buffer_copy (buffer);
331 return g_bytes_new_with_free_func (copy->data, copy->length,
332 (GDestroyNotify)soup_buffer_free,
336 G_DEFINE_BOXED_TYPE (SoupBuffer, soup_buffer, soup_buffer_copy, soup_buffer_free)
342 * @length: length of @data
344 * A #SoupMessage request or response body.
346 * Note that while @length always reflects the full length of the
347 * message body, @data is normally %NULL, and will only be filled in
348 * after soup_message_body_flatten() is called. For client-side
349 * messages, this automatically happens for the response body after it
350 * has been fully read, unless you set the
351 * %SOUP_MESSAGE_OVERWRITE_CHUNKS flags. Likewise, for server-side
352 * messages, the request body is automatically filled in after being
355 * As an added bonus, when @data is filled in, it is always terminated
356 * with a '\0' byte (which is not reflected in @length).
360 SoupMessageBody body;
361 GSList *chunks, *last;
362 SoupBuffer *flattened;
366 } SoupMessageBodyPrivate;
369 * soup_message_body_new:
371 * Creates a new #SoupMessageBody. #SoupMessage uses this internally; you
372 * will not normally need to call it yourself.
374 * Return value: a new #SoupMessageBody.
377 soup_message_body_new (void)
379 SoupMessageBodyPrivate *priv;
381 priv = g_slice_new0 (SoupMessageBodyPrivate);
382 priv->accumulate = TRUE;
385 return (SoupMessageBody *)priv;
389 * soup_message_body_set_accumulate:
390 * @body: a #SoupMessageBody
391 * @accumulate: whether or not to accumulate body chunks in @body
393 * Sets or clears the accumulate flag on @body. (The default value is
394 * %TRUE.) If set to %FALSE, @body's %data field will not be filled in
395 * after the body is fully sent/received, and the chunks that make up
396 * @body may be discarded when they are no longer needed.
398 * In particular, if you set this flag to %FALSE on an "incoming"
399 * message body (that is, the #SoupMessage:response_body of a
400 * client-side message, or #SoupMessage:request_body of a server-side
401 * message), this will cause each chunk of the body to be discarded
402 * after its corresponding #SoupMessage::got_chunk signal is emitted.
403 * (This is equivalent to setting the deprecated
404 * %SOUP_MESSAGE_OVERWRITE_CHUNKS flag on the message.)
406 * If you set this flag to %FALSE on the #SoupMessage:response_body of
407 * a server-side message, it will cause each chunk of the body to be
408 * discarded after its corresponding #SoupMessage::wrote_chunk signal
411 * If you set the flag to %FALSE on the #SoupMessage:request_body of a
412 * client-side message, it will block the accumulation of chunks into
413 * @body's %data field, but it will not normally cause the chunks to
414 * be discarded after being written like in the server-side
415 * #SoupMessage:response_body case, because the request body needs to
416 * be kept around in case the request needs to be sent a second time
417 * due to redirection or authentication. However, if you set the
418 * %SOUP_MESSAGE_CAN_REBUILD flag on the message, then the chunks will
419 * be discarded, and you will be responsible for recreating the
420 * request body after the #SoupMessage::restarted signal is emitted.
425 soup_message_body_set_accumulate (SoupMessageBody *body,
428 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
430 priv->accumulate = accumulate;
434 * soup_message_body_get_accumulate:
435 * @body: a #SoupMessageBody
437 * Gets the accumulate flag on @body; see
438 * soup_message_body_set_accumulate() for details.
440 * Return value: the accumulate flag for @body.
445 soup_message_body_get_accumulate (SoupMessageBody *body)
447 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
449 return priv->accumulate;
453 append_buffer (SoupMessageBody *body, SoupBuffer *buffer)
455 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
458 priv->last = g_slist_append (priv->last, buffer);
459 priv->last = priv->last->next;
461 priv->chunks = priv->last = g_slist_append (NULL, buffer);
463 if (priv->flattened) {
464 soup_buffer_free (priv->flattened);
465 priv->flattened = NULL;
468 body->length += buffer->length;
472 * soup_message_body_append:
473 * @body: a #SoupMessageBody
474 * @use: how to use @data
475 * @data: (array length=length) (element-type guint8): data to append
476 * @length: length of @data
478 * Appends @length bytes from @data to @body according to @use.
481 soup_message_body_append (SoupMessageBody *body, SoupMemoryUse use,
482 gconstpointer data, gsize length)
485 append_buffer (body, soup_buffer_new (use, data, length));
486 else if (use == SOUP_MEMORY_TAKE)
487 g_free ((gpointer)data);
491 * soup_message_body_append_take:
492 * @body: a #SoupMessageBody
493 * @data: (array length=length) (transfer full): data to append
494 * @length: length of @data
496 * Appends @length bytes from @data to @body.
498 * This function is exactly equivalent to soup_message_body_append()
499 * with %SOUP_MEMORY_TAKE as second argument; it exists mainly for
500 * convenience and simplifying language bindings.
502 * Rename to: soup_message_body_append
506 soup_message_body_append_take (SoupMessageBody *body,
507 guchar *data, gsize length)
509 soup_message_body_append(body, SOUP_MEMORY_TAKE, data, length);
513 * soup_message_body_append_buffer:
514 * @body: a #SoupMessageBody
515 * @buffer: a #SoupBuffer
517 * Appends the data from @buffer to @body. (#SoupMessageBody uses
518 * #SoupBuffers internally, so this is normally a constant-time
519 * operation that doesn't actually require copying the data in
523 soup_message_body_append_buffer (SoupMessageBody *body, SoupBuffer *buffer)
525 g_return_if_fail (buffer->length > 0);
526 append_buffer (body, soup_buffer_copy (buffer));
530 * soup_message_body_truncate:
531 * @body: a #SoupMessageBody
533 * Deletes all of the data in @body.
536 soup_message_body_truncate (SoupMessageBody *body)
538 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
540 g_slist_free_full (priv->chunks, (GDestroyNotify)soup_buffer_free);
541 priv->chunks = priv->last = NULL;
542 priv->base_offset = 0;
544 if (priv->flattened) {
545 soup_buffer_free (priv->flattened);
546 priv->flattened = NULL;
553 * soup_message_body_complete:
554 * @body: a #SoupMessageBody
556 * Tags @body as being complete; Call this when using chunked encoding
557 * after you have appended the last chunk.
560 soup_message_body_complete (SoupMessageBody *body)
562 append_buffer (body, soup_buffer_new (SOUP_MEMORY_STATIC, NULL, 0));
566 * soup_message_body_flatten:
567 * @body: a #SoupMessageBody
569 * Fills in @body's data field with a buffer containing all of the
570 * data in @body (plus an additional '\0' byte not counted by @body's
573 * Return value: a #SoupBuffer containing the same data as @body.
574 * (You must free this buffer if you do not want it.)
577 soup_message_body_flatten (SoupMessageBody *body)
579 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
584 g_return_val_if_fail (priv->accumulate == TRUE, NULL);
586 if (!priv->flattened) {
587 #if GLIB_SIZEOF_SIZE_T < 8
588 g_return_val_if_fail (body->length < G_MAXSIZE, NULL);
591 buf = ptr = g_malloc (body->length + 1);
592 for (iter = priv->chunks; iter; iter = iter->next) {
594 memcpy (ptr, chunk->data, chunk->length);
595 ptr += chunk->length;
599 priv->flattened = soup_buffer_new (SOUP_MEMORY_TAKE,
601 body->data = priv->flattened->data;
604 return soup_buffer_copy (priv->flattened);
608 * soup_message_body_get_chunk:
609 * @body: a #SoupMessageBody
612 * Gets a #SoupBuffer containing data from @body starting at @offset.
613 * The size of the returned chunk is unspecified. You can iterate
614 * through the entire body by first calling
615 * soup_message_body_get_chunk() with an offset of 0, and then on each
616 * successive call, increment the offset by the length of the
617 * previously-returned chunk.
619 * If @offset is greater than or equal to the total length of @body,
620 * then the return value depends on whether or not
621 * soup_message_body_complete() has been called or not; if it has,
622 * then soup_message_body_get_chunk() will return a 0-length chunk
623 * (indicating the end of @body). If it has not, then
624 * soup_message_body_get_chunk() will return %NULL (indicating that
625 * @body may still potentially have more data, but that data is not
626 * currently available).
628 * Return value: a #SoupBuffer, or %NULL.
631 soup_message_body_get_chunk (SoupMessageBody *body, goffset offset)
633 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
635 SoupBuffer *chunk = NULL;
637 offset -= priv->base_offset;
638 for (iter = priv->chunks; iter; iter = iter->next) {
641 if (offset < chunk->length || offset == 0)
644 offset -= chunk->length;
651 return soup_buffer_copy (chunk);
653 return soup_buffer_new_subbuffer (chunk, offset,
654 chunk->length - offset);
659 * soup_message_body_got_chunk:
660 * @body: a #SoupMessageBody
661 * @chunk: a #SoupBuffer received from the network
663 * Handles the #SoupMessageBody part of receiving a chunk of data from
664 * the network. Normally this means appending @chunk to @body, exactly
665 * as with soup_message_body_append_buffer(), but if you have set
666 * @body's accumulate flag to %FALSE, then that will not happen.
668 * This is a low-level method which you should not normally need to
674 soup_message_body_got_chunk (SoupMessageBody *body, SoupBuffer *chunk)
676 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
678 if (!priv->accumulate)
681 soup_message_body_append_buffer (body, chunk);
685 * soup_message_body_wrote_chunk:
686 * @body: a #SoupMessageBody
687 * @chunk: a #SoupBuffer returned from soup_message_body_get_chunk()
689 * Handles the #SoupMessageBody part of writing a chunk of data to the
690 * network. Normally this is a no-op, but if you have set @body's
691 * accumulate flag to %FALSE, then this will cause @chunk to be
692 * discarded to free up memory.
694 * This is a low-level method which you should not need to use, and
695 * there are further restrictions on its proper use which are not
701 soup_message_body_wrote_chunk (SoupMessageBody *body, SoupBuffer *chunk)
703 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
706 if (priv->accumulate)
709 chunk2 = priv->chunks->data;
710 g_return_if_fail (chunk->length == chunk2->length);
711 g_return_if_fail (chunk == chunk2 || ((SoupBufferPrivate *)chunk2)->use == SOUP_MEMORY_TEMPORARY);
713 priv->chunks = g_slist_remove (priv->chunks, chunk2);
717 priv->base_offset += chunk2->length;
718 soup_buffer_free (chunk2);
721 static SoupMessageBody *
722 soup_message_body_copy (SoupMessageBody *body)
724 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
731 * soup_message_body_free:
732 * @body: a #SoupMessageBody
734 * Frees @body. You will not normally need to use this, as
735 * #SoupMessage frees its associated message bodies automatically.
738 soup_message_body_free (SoupMessageBody *body)
740 SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
742 if (--priv->ref_count == 0) {
743 soup_message_body_truncate (body);
744 g_slice_free (SoupMessageBodyPrivate, priv);
748 G_DEFINE_BOXED_TYPE (SoupMessageBody, soup_message_body, soup_message_body_copy, soup_message_body_free)