static SoupBuffer *
webkit_soup_directory_input_stream_parse_info (WebKitSoupDirectoryInputStream * stream,
					       GFileInfo * info)
{
	SoupBuffer *buffer;
	GString *string;
	const char *s;
	char *escaped, *path, *xml_string;

	if (!g_file_info_get_name (info))
		return NULL;

	s = g_file_info_get_display_name (info);
	if (!s) {
		s = g_file_info_get_name (info);
		/* FIXME: convert somehow? */
		if (!g_utf8_validate (s, -1, NULL))
			return NULL;
	}
	string = g_string_new ("<tr>");

	xml_string = g_markup_escape_text (s, -1);
	escaped = g_uri_escape_string (g_file_info_get_name (info), NULL, FALSE);
	path = g_strconcat (stream->uri, "/", escaped, NULL);
	g_free (escaped);
	g_string_append_printf (string, "<td><a href=\"%s\">%s</a></td>", path, xml_string);
	g_free (path);
	g_free (xml_string);
	g_string_append (string, "</tr>");

	buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len);
	g_string_free (string, FALSE);

	return buffer;
}
Esempio n. 2
0
/**
 * soup_buffer_copy:
 * @buffer: a #SoupBuffer
 *
 * Makes a copy of @buffer. In reality, #SoupBuffer is a refcounted
 * type, and calling soup_buffer_copy() will normally just increment
 * the refcount on @buffer and return it. However, if @buffer was
 * created with #SOUP_MEMORY_TEMPORARY memory, then soup_buffer_copy()
 * will actually return a copy of it, so that the data in the copy
 * will remain valid after the temporary buffer is freed.
 *
 * Return value: the new (or newly-reffed) buffer
 **/
SoupBuffer *
soup_buffer_copy (SoupBuffer *buffer)
{
	SoupBufferPrivate *priv = (SoupBufferPrivate *)buffer;

	/* For non-TEMPORARY buffers, this is just a ref */
	if (priv->use != SOUP_MEMORY_TEMPORARY) {
		priv->refcount++;
		return buffer;
	}

	/* For TEMPORARY buffers, we need to do a real copy the first
	 * time, and then after that, we just keep returning the copy.
	 * We store the copy in priv->owner, which is technically
	 * backwards, but it saves us from having to keep an extra
	 * pointer in SoupBufferPrivate.
	 */

	if (!priv->owner) {
		priv->owner = soup_buffer_new (SOUP_MEMORY_COPY,
					       buffer->data,
					       buffer->length);
		priv->owner_dnotify = (GDestroyNotify)soup_buffer_free;
	}
	return soup_buffer_copy (priv->owner);
}
static void
do_large_chunk_test (SoupSession *session, SoupURI *base_uri)
{
	SoupMessage *msg;
	char *buf_data;
	int i;
	LargeChunkData lcd;

	debug_printf (1, "PUT w/ large chunk\n");

	msg = soup_message_new_from_uri ("PUT", base_uri);

	buf_data = g_malloc0 (LARGE_CHUNK_SIZE);
	for (i = 0; i < LARGE_CHUNK_SIZE; i++)
		buf_data[i] = i & 0xFF;
	lcd.buf = soup_buffer_new (SOUP_MEMORY_TAKE, buf_data, LARGE_CHUNK_SIZE);
	lcd.offset = 0;
	soup_message_body_append_buffer (msg->request_body, lcd.buf);
	soup_message_body_set_accumulate (msg->request_body, FALSE);

	g_signal_connect (msg, "wrote_body_data",
			  G_CALLBACK (large_wrote_body_data), &lcd);
	soup_session_send_message (session, msg);

	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
		debug_printf (1, "  message failed: %d %s\n",
			      msg->status_code, msg->reason_phrase);
		errors++;
	}

	soup_buffer_free (lcd.buf);
	g_object_unref (msg);
}
static gssize
read_internal (GInputStream  *stream,
	       void          *buffer,
	       gsize          count,
	       gboolean       blocking,
	       GCancellable  *cancellable,
	       GError       **error)
{
	SoupCacheInputStream *istream = SOUP_CACHE_INPUT_STREAM (stream);
	SoupCacheInputStreamPrivate *priv = istream->priv;
	GInputStream *base_stream;
	gssize nread;

	base_stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream));
	nread = g_pollable_stream_read (base_stream, buffer, count, blocking,
					cancellable, error);

	if (G_UNLIKELY (nread == -1 || priv->read_finished))
		return nread;

	if (nread == 0) {
		priv->read_finished = TRUE;

		if (priv->current_writing_buffer == NULL && priv->output_stream)
			notify_and_clear (istream, NULL);
	} else {
		SoupBuffer *soup_buffer = soup_buffer_new (SOUP_MEMORY_COPY, buffer, nread);
		g_queue_push_tail (priv->buffer_queue, soup_buffer);

		if (priv->current_writing_buffer == NULL && priv->output_stream)
			soup_cache_input_stream_write_next_buffer (istream);
	}

	return nread;
}
static SoupBuffer *
webkit_soup_directory_input_stream_read_next_file (WebKitSoupDirectoryInputStream  *stream,
						   GCancellable              *cancellable,
						   GError                   **error)
{
	GFileInfo *info;
	SoupBuffer *buffer;
	GError *err = NULL;

	do {
		info = g_file_enumerator_next_file (stream->enumerator, cancellable, &err);
		if (info == NULL) {
			if (err) {
				g_propagate_error (error, err);
				return NULL;
			} else if (!stream->done) {
				stream->done = TRUE;
				return soup_buffer_new (SOUP_MEMORY_STATIC,
							EXIT_STRING,
							sizeof (EXIT_STRING));
			} else {
				return NULL;
			}
		}

		buffer = webkit_soup_directory_input_stream_parse_info (stream, info);
	} while (buffer == NULL);

	return buffer;
}
Esempio n. 6
0
/**
 * soup_message_body_flatten:
 * @body: a #SoupMessageBody
 *
 * Fills in @body's data field with a buffer containing all of the
 * data in @body (plus an additional '\0' byte not counted by @body's
 * length field).
 *
 * Return value: a #SoupBuffer containing the same data as @body.
 * (You must free this buffer if you do not want it.)
 **/
SoupBuffer *
soup_message_body_flatten (SoupMessageBody *body)
{
	SoupMessageBodyPrivate *priv = (SoupMessageBodyPrivate *)body;
	char *buf, *ptr;
	GSList *iter;
	SoupBuffer *chunk;

	g_return_val_if_fail (priv->accumulate == TRUE, NULL);

	if (!priv->flattened) {
#if GLIB_SIZEOF_SIZE_T < 8
		g_return_val_if_fail (body->length < G_MAXSIZE, NULL);
#endif

		buf = ptr = g_malloc (body->length + 1);
		for (iter = priv->chunks; iter; iter = iter->next) {
			chunk = iter->data;
			memcpy (ptr, chunk->data, chunk->length);
			ptr += chunk->length;
		}
		*ptr = '\0';

		priv->flattened = soup_buffer_new (SOUP_MEMORY_TAKE,
						   buf, body->length);
		body->data = priv->flattened->data;
	}

	return soup_buffer_copy (priv->flattened);
}
static void
webkit_soup_directory_input_stream_init (WebKitSoupDirectoryInputStream *stream)
{
	stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC,
					  INIT_STRING,
					  sizeof (INIT_STRING));
}
Esempio n. 8
0
/*
 *  * Read from g_input_stream until we get 0 bytes read.  Then process
 *   * using the value of stream_type.  Finally try and read another multipart.
 *    */
static void
read_cb (GObject *source, GAsyncResult *async_result, gpointer user_data)
{
    //g_print ("read_cb: Enter\n");
    GInputStream *in = G_INPUT_STREAM (source);
    MultiPartData *multipart_data = (MultiPartData *) user_data;
    SoupMultipartInputStream *multipart = SOUP_MULTIPART_INPUT_STREAM (multipart_data->multipart);
    gssize bytes_read;

    bytes_read = g_input_stream_read_finish (in, async_result, &multipart_data->error);

    /* Read 0 bytes - try to start reading another part. */
    if (bytes_read <= 0) {
        g_input_stream_close_async (in,
                                    G_PRIORITY_DEFAULT,
                                    multipart_data->cancellable,
                                    close_cb,
                                    user_data);
        if (multipart_data->callback) {
            SoupBuffer *soup_buffer;
            //g_print ("callback\n");
            soup_buffer = soup_buffer_new(SOUP_MEMORY_TEMPORARY,
                                (guchar *) multipart_data->buffer->str,
                                multipart_data->buffer->len);
            multipart_data->callback (multipart_data->method,
                                      multipart_data->path,
                                      multipart_data->cancellable,
                                      multipart_data->error,
                                      multipart_data->headers,
                                      soup_buffer,
                                      multipart_data->user_data);
            soup_buffer_free(soup_buffer);
        }
        g_string_free (multipart_data->buffer, TRUE);
        if (multipart_data->error) {
            g_input_stream_close_async (G_INPUT_STREAM (multipart),
                                        G_PRIORITY_DEFAULT,
                                        multipart_data->cancellable,
                                        close_base_cb,
                                        user_data);
            return;
        }
        soup_multipart_input_stream_next_part_async (multipart_data->multipart,
                                                     G_PRIORITY_DEFAULT,
                                                     multipart_data->cancellable,
                                                     next_part_cb,
                                                     user_data);
        return;
    }
    multipart_data->buffer = g_string_append_len (multipart_data->buffer, buffer, bytes_read);
    g_input_stream_read_async (in,
                               buffer,
                               READ_BUFFER_SIZE,
                               G_PRIORITY_DEFAULT,
                               multipart_data->cancellable,
                               read_cb,
                               user_data);
    //g_print ("read_cb: Exit\n");
}
static SoupBuffer *
error_chunk_allocator (SoupMessage *msg, gsize max_len, gpointer user_data)
{
	/* This should never be called, because there is no response body. */
	debug_printf (1, "  error_chunk_allocator called!\n");
	errors++;
	return soup_buffer_new (SOUP_MEMORY_TAKE, g_malloc (100), 100);
}
Esempio n. 10
0
/**
 * soup_message_body_append:
 * @body: a #SoupMessageBody
 * @use: how to use @data
 * @data: (array length=length) (element-type guint8): data to append
 * @length: length of @data
 *
 * Appends @length bytes from @data to @body according to @use.
 **/
void
soup_message_body_append (SoupMessageBody *body, SoupMemoryUse use,
			  gconstpointer data, gsize length)
{
	if (length > 0)
		append_buffer (body, soup_buffer_new (use, data, length));
	else if (use == SOUP_MEMORY_TAKE)
		g_free ((gpointer)data);
}
Esempio n. 11
0
/* Attempts to write @len bytes from @data. See the note at
 * read_metadata() for an explanation of the return value.
 */
static gboolean
write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
{
	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
	SoupMessageIOData *io = priv->io_data;
	SoupSocketIOStatus status;
	gsize nwrote;
	GError *error = NULL;
	SoupBuffer *chunk;
	const char *start;

	while (len > io->written) {
		status = soup_socket_write (io->sock,
					    data + io->written,
					    len - io->written,
					    &nwrote, NULL, &error);
		switch (status) {
		case SOUP_SOCKET_EOF:
		case SOUP_SOCKET_ERROR:
			io_error (io->sock, msg, error);
			return FALSE;

		case SOUP_SOCKET_WOULD_BLOCK:
			return FALSE;

		case SOUP_SOCKET_OK:
			start = data + io->written;
			io->written += nwrote;

			if (body) {
				if (io->write_length)
					io->write_length -= nwrote;

				chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
							 start, nwrote);
				SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
				soup_message_wrote_body_data (msg, chunk);
				soup_buffer_free (chunk);
				SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
			}
			break;
		}
	}

	io->written = 0;
	return TRUE;
}
static gssize
read_and_sniff (GInputStream *stream, gboolean blocking,
		GCancellable *cancellable, GError **error)
{
	SoupContentSnifferStreamPrivate *priv = SOUP_CONTENT_SNIFFER_STREAM (stream)->priv;
	gssize nread;
	GError *my_error = NULL;
	SoupBuffer *buf;

	do {
		nread = g_pollable_stream_read (G_FILTER_INPUT_STREAM (stream)->base_stream,
						priv->buffer + priv->buffer_nread,
						priv->buffer_size - priv->buffer_nread,
						blocking, cancellable, &my_error);
		if (nread <= 0)
			break;
		priv->buffer_nread += nread;
	} while (priv->buffer_nread < priv->buffer_size);

	/* If we got EAGAIN or cancellation before filling the buffer,
	 * just return that right away. Likewise if we got any other
	 * error without ever reading any data. Otherwise, save the
	 * error to return after we're done sniffing.
	 */
	if (my_error) {
		if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
		    g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
		    priv->buffer_nread == 0) {
			g_propagate_error (error, my_error);
			return -1;
		} else
			priv->error = my_error;
	}

	/* Sniff, then return the data */
	buf = soup_buffer_new (SOUP_MEMORY_TEMPORARY, priv->buffer, priv->buffer_nread);
	priv->sniffed_type =
		soup_content_sniffer_sniff (priv->sniffer, priv->msg, buf,
					    &priv->sniffed_params);
	soup_buffer_free (buf);
	priv->sniffing = FALSE;

	return priv->buffer_nread;
}	
Esempio n. 13
0
static void
do_md5_test_libsoup (const char *uri, const char *contents,
                     gsize length, const char *md5)
{
    SoupMultipart *multipart;
    SoupBuffer *buffer;
    SoupMessage *msg;
    SoupSession *session;

    debug_printf (1, "  via libsoup: ");

    multipart = soup_multipart_new (SOUP_FORM_MIME_TYPE_MULTIPART);
    buffer = soup_buffer_new (SOUP_MEMORY_COPY, contents, length);
    soup_multipart_append_form_file (multipart, "file",
                                     MD5_TEST_FILE_BASENAME,
                                     MD5_TEST_FILE_MIME_TYPE,
                                     buffer);
    soup_buffer_free (buffer);
    soup_multipart_append_form_string (multipart, "fmt", "text");

    msg = soup_form_request_new_from_multipart (uri, multipart);
    soup_multipart_free (multipart);

    session = soup_test_session_new (SOUP_TYPE_SESSION_ASYNC, NULL);
    soup_session_send_message (session, msg);

    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
        debug_printf (1, "ERROR: Unexpected status %d %s\n",
                      msg->status_code, msg->reason_phrase);
        errors++;
    } else if (strcmp (msg->response_body->data, md5) != 0) {
        debug_printf (1, "ERROR: Incorrect response: expected '%s' got '%s'\n",
                      md5, msg->response_body->data);
        errors++;
    } else
        debug_printf (1, "OK!\n");

    g_object_unref (msg);
    soup_test_session_abort_unref (session);
}
Esempio n. 14
0
static gboolean
send_chunks (gpointer user_data)
{
  SoupMessage *msg = SOUP_MESSAGE (user_data);
  char *s;
  SoupBuffer *buf;

  s = g_strdup_printf ("%d %d %d %d\n",
                       server_count, server_count,
                       server_count, server_count);
  buf = soup_buffer_new (SOUP_MEMORY_TAKE, s, strlen (s));

  soup_message_body_append_buffer (msg->response_body, buf);
  soup_server_unpause_message (server, msg);

  if (++server_count == NUM_CHUNKS)
  {
    soup_message_body_complete (msg->response_body);
    return FALSE;
  } else {
    return TRUE;
  }
}
Esempio n. 15
0
/* Reads as much message body data as is available on io->sock (but no
 * further than the end of the current message body or chunk). On a
 * successful read, emits "got_chunk" (possibly multiple times), and
 * (unless told not to) appends the chunk to io->read_body.
 *
 * See the note at read_metadata() for an explanation of the return
 * value.
 */
static gboolean
read_body_chunk (SoupMessage *msg)
{
	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
	SoupMessageIOData *io = priv->io_data;
	SoupSocketIOStatus status;
	guchar *stack_buf = NULL;
	gsize len;
	gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
	gsize nread;
	GError *error = NULL;
	SoupBuffer *buffer;

	if (!io_handle_sniffing (msg, FALSE))
		return FALSE;

	while (read_to_eof || io->read_length > 0) {
		if (priv->chunk_allocator) {
			buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
			if (!buffer) {
				soup_message_io_pause (msg);
				return FALSE;
			}
		} else {
			if (!stack_buf)
				stack_buf = alloca (RESPONSE_BLOCK_SIZE);
			buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
						  stack_buf,
						  RESPONSE_BLOCK_SIZE);
		}

		if (read_to_eof)
			len = buffer->length;
		else
			len = MIN (buffer->length, io->read_length);

		status = soup_socket_read (io->sock,
					   (guchar *)buffer->data, len,
					   &nread, NULL, &error);

		if (status == SOUP_SOCKET_OK && nread) {
			buffer->length = nread;
			io->read_length -= nread;

			buffer = content_decode (msg, buffer);
			if (!buffer)
				continue;

			soup_message_body_got_chunk (io->read_body, buffer);

			if (io->need_content_sniffed) {
				soup_message_body_append_buffer (io->sniff_data, buffer);
				soup_buffer_free (buffer);
				io->need_got_chunk = TRUE;
				if (!io_handle_sniffing (msg, FALSE))
					return FALSE;
				continue;
			}

			SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
			soup_message_got_chunk (msg, buffer);
			soup_buffer_free (buffer);
			SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
			continue;
		}

		soup_buffer_free (buffer);
		switch (status) {
		case SOUP_SOCKET_OK:
			break;

		case SOUP_SOCKET_EOF:
			if (read_to_eof)
				return TRUE;
			/* else fall through */

		case SOUP_SOCKET_ERROR:
			io_error (io->sock, msg, error);
			return FALSE;

		case SOUP_SOCKET_WOULD_BLOCK:
			return FALSE;
		}
	}

	return TRUE;
}
Esempio n. 16
0
/* Attempts to push forward the reading side of @msg's I/O. Returns
 * %TRUE if it manages to make some progress, and it is likely that
 * further progress can be made. Returns %FALSE if it has reached a
 * stopping point of some sort (need input from the application,
 * socket not readable, read is complete, etc).
 */
static gboolean
io_read (SoupMessage *msg, gboolean blocking,
	 GCancellable *cancellable, GError **error)
{
	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
	SoupMessageIOData *io = priv->io_data;
	guchar *stack_buf = NULL;
	gssize nread;
	SoupBuffer *buffer;
	guint status;

	switch (io->read_state) {
	case SOUP_MESSAGE_IO_STATE_HEADERS:
		if (!read_headers (msg, blocking, cancellable, error))
			return FALSE;

		status = io->parse_headers_cb (msg, (char *)io->read_header_buf->data,
					       io->read_header_buf->len,
					       &io->read_encoding,
					       io->header_data, error);
		g_byte_array_set_size (io->read_header_buf, 0);

		if (status != SOUP_STATUS_OK) {
			/* Either we couldn't parse the headers, or they
			 * indicated something that would mean we wouldn't
			 * be able to parse the body. (Eg, unknown
			 * Transfer-Encoding.). Skip the rest of the
			 * reading, and make sure the connection gets
			 * closed when we're done.
			 */
			soup_message_set_status (msg, status);
			soup_message_headers_append (msg->request_headers,
						     "Connection", "close");
			io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
			break;
		}

		if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
		    SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
			if (msg->status_code == SOUP_STATUS_CONTINUE &&
			    io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
				/* Pause the reader, unpause the writer */
				io->read_state =
					SOUP_MESSAGE_IO_STATE_BLOCKING;
				io->write_state =
					SOUP_MESSAGE_IO_STATE_BODY_START;
			} else {
				/* Just stay in HEADERS */
				io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
			}

			/* Informational responses have no bodies, so
			 * bail out here rather than parsing encoding, etc
			 */
			soup_message_got_informational (msg);

			/* If this was "101 Switching Protocols", then
			 * the session may have stolen the connection...
			 */
			if (io != priv->io_data)
				return FALSE;

			soup_message_cleanup_response (msg);
			break;
		} else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
			   soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
			/* We must return a status code and response
			 * headers to the client; either an error to
			 * be set by a got-headers handler below, or
			 * else %SOUP_STATUS_CONTINUE otherwise.
			 */
			io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
			io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
		} else {
			io->read_state = SOUP_MESSAGE_IO_STATE_BODY_START;

			/* If the client was waiting for a Continue
			 * but got something else, then it's done
			 * writing.
			 */
			if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
			    io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
				io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
		}

		if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
			SoupMessageHeaders *hdrs =
				(io->mode == SOUP_MESSAGE_IO_CLIENT) ?
				msg->response_headers : msg->request_headers;
			io->read_length = soup_message_headers_get_content_length (hdrs);

			if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
			    !soup_message_is_keepalive (msg)) {
				/* Some servers suck and send
				 * incorrect Content-Length values, so
				 * allow EOF termination in this case
				 * (iff the message is too short) too.
				 */
				io->read_encoding = SOUP_ENCODING_EOF;
			}
		} else
			io->read_length = -1;

		soup_message_got_headers (msg);
		break;


	case SOUP_MESSAGE_IO_STATE_BODY_START:
		if (!io->body_istream) {
			GInputStream *body_istream = soup_body_input_stream_new (G_INPUT_STREAM (io->istream),
										 io->read_encoding,
										 io->read_length);

			/* TODO: server-side messages do not have a io->item. This means
			 * that we cannot use content processors for them right now.
			 */
			if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
				io->body_istream = soup_message_setup_body_istream (body_istream, msg,
										    io->item->session,
										    SOUP_STAGE_MESSAGE_BODY);
				g_object_unref (body_istream);
			} else {
				io->body_istream = body_istream;
			}
		}

		if (priv->sniffer) {
			SoupContentSnifferStream *sniffer_stream = SOUP_CONTENT_SNIFFER_STREAM (io->body_istream);
			const char *content_type;
			GHashTable *params;

			if (!soup_content_sniffer_stream_is_ready (sniffer_stream, blocking,
								   cancellable, error))
				return FALSE;

			content_type = soup_content_sniffer_stream_sniff (sniffer_stream, &params);
			soup_message_content_sniffed (msg, content_type, params);
		}

		io->read_state = SOUP_MESSAGE_IO_STATE_BODY;
		break;


	case SOUP_MESSAGE_IO_STATE_BODY:
		if (priv->chunk_allocator) {
			buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
			if (!buffer) {
				g_return_val_if_fail (!io->item || !io->item->new_api, FALSE);
				soup_message_io_pause (msg);
				return FALSE;
			}
		} else {
			if (!stack_buf)
				stack_buf = alloca (RESPONSE_BLOCK_SIZE);
			buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
						  stack_buf,
						  RESPONSE_BLOCK_SIZE);
		}

		nread = g_pollable_stream_read (io->body_istream,
						(guchar *)buffer->data,
						buffer->length,
						blocking,
						cancellable, error);
		if (nread > 0) {
			buffer->length = nread;
			soup_message_body_got_chunk (io->read_body, buffer);
			soup_message_got_chunk (msg, buffer);
			soup_buffer_free (buffer);
			break;
		}

		soup_buffer_free (buffer);
		if (nread == -1)
			return FALSE;

		/* else nread == 0 */
		io->read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE;
		break;


	case SOUP_MESSAGE_IO_STATE_BODY_DONE:
		io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
		soup_message_got_body (msg);
		break;


	case SOUP_MESSAGE_IO_STATE_FINISHING:
		io->read_state = SOUP_MESSAGE_IO_STATE_DONE;

		if (io->mode == SOUP_MESSAGE_IO_SERVER)
			io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
		break;


	default:
		g_return_val_if_reached (FALSE);
	}

	return TRUE;
}
Esempio n. 17
0
static void
upload_photo_file_buffer_ready_cb (void     **buffer,
				   gsize      count,
				   GError    *error,
				   gpointer   user_data)
{
	FacebookService *self = user_data;
	GthFileData     *file_data;
	SoupMultipart   *multipart;
	char            *uri;
	SoupBuffer      *body;
	SoupMessage     *msg;

	if (error != NULL) {
		upload_photos_done (self, error);
		return;
	}

	file_data = self->priv->post_photos->current->data;
	multipart = soup_multipart_new ("multipart/form-data");

	/* the metadata part */

	{
		GHashTable *data_set;
		char       *title;
		char       *description;
		GList      *keys;
		GList      *scan;

		data_set = g_hash_table_new (g_str_hash, g_str_equal);

		g_hash_table_insert (data_set, "method", "facebook.photos.upload");

		title = gth_file_data_get_attribute_as_string (file_data, "general::title");
		description = gth_file_data_get_attribute_as_string (file_data, "general::description");
		if (description != NULL)
			g_hash_table_insert (data_set, "caption", description);
		else if (title != NULL)
			g_hash_table_insert (data_set, "caption", title);

		if (self->priv->post_photos->album != NULL)
			g_hash_table_insert (data_set, "aid", self->priv->post_photos->album->id);

		facebook_connection_add_api_sig (self->priv->conn, data_set);

		keys = g_hash_table_get_keys (data_set);
		for (scan = keys; scan; scan = scan->next) {
			char *key = scan->data;
			soup_multipart_append_form_string (multipart, key, g_hash_table_lookup (data_set, key));
		}

		g_list_free (keys);
		g_hash_table_unref (data_set);
	}

	/* the file part */

	uri = g_file_get_uri (file_data->file);
	body = soup_buffer_new (SOUP_MEMORY_TEMPORARY, *buffer, count);
	soup_multipart_append_form_file (multipart,
					 NULL,
					 _g_uri_get_basename (uri),
					 gth_file_data_get_mime_type (file_data),
					 body);

	soup_buffer_free (body);
	g_free (uri);

	/* send the file */

	{
		char *details;

		/* Translators: %s is a filename */
		details = g_strdup_printf (_("Uploading '%s'"), g_file_info_get_display_name (file_data->info));
		gth_task_progress (GTH_TASK (self->priv->conn),
				   NULL, details,
				   FALSE,
				   (double) (self->priv->post_photos->uploaded_size + (g_file_info_get_size (file_data->info) / 2.0)) / self->priv->post_photos->total_size);

		g_free (details);
	}

	msg = soup_form_request_new_from_multipart (FACEBOOK_HTTPS_REST_SERVER, multipart);
	facebook_connection_send_message (self->priv->conn,
					  msg,
					  self->priv->post_photos->cancellable,
					  self->priv->post_photos->callback,
					  self->priv->post_photos->user_data,
					  facebook_service_upload_photos,
					  upload_photo_ready_cb,
					  self);

	soup_multipart_free (multipart);
}
Esempio n. 18
0
static void
post_photo_file_buffer_ready_cb (void     **buffer,
				 gsize      count,
				 GError    *error,
				 gpointer   user_data)
{
	PicasaWebService   *self = user_data;
	OAuthAccount       *account;
	GthFileData        *file_data;
	SoupMultipart      *multipart;
	const char         *filename;
	char               *value;
	GObject            *metadata;
	DomDocument        *doc;
	DomElement         *entry;
	char               *entry_buffer;
	gsize               entry_len;
	SoupMessageHeaders *headers;
	SoupBuffer         *body;
	void               *resized_buffer;
	gsize               resized_count;
	char               *url;
	SoupMessage        *msg;

	if (error != NULL) {
		post_photos_done (self, error);
		return;
	}

	account = web_service_get_current_account (WEB_SERVICE (self));
	file_data = self->priv->post_photos->current->data;
	multipart = soup_multipart_new ("multipart/related");

	/* the metadata part */

	doc = dom_document_new ();
	entry = dom_document_create_element (doc, "entry",
					     "xmlns", "http://www.w3.org/2005/Atom",
					     "xmlns:gphoto", "http://schemas.google.com/photos/2007",
					     "xmlns:media", "http://search.yahoo.com/mrss/",
					     NULL);

	filename = g_file_info_get_display_name (file_data->info);
	dom_element_append_child (entry,
				  dom_document_create_element_with_text (doc, filename, "title", NULL));

	value = gth_file_data_get_attribute_as_string (file_data, "general::description");
	if (value == NULL)
		value = gth_file_data_get_attribute_as_string (file_data, "general::title");
	dom_element_append_child (entry,
				  dom_document_create_element_with_text (doc, value, "summary", NULL));

	value = gth_file_data_get_attribute_as_string (file_data, "general::location");
	if (value != NULL)
		dom_element_append_child (entry,
					  dom_document_create_element_with_text (doc, value, "gphoto:location", NULL));

	metadata = g_file_info_get_attribute_object (file_data->info, "general::tags");
	if (metadata != NULL)
		value = gth_string_list_join (GTH_STRING_LIST (gth_metadata_get_string_list (GTH_METADATA (metadata))), ", ");
	if (value != NULL) {
		DomElement *group;

		group = dom_document_create_element (doc, "media:group", NULL);
		dom_element_append_child (group,
					  dom_document_create_element_with_text (doc, value, "media:keywords", NULL));
		dom_element_append_child (entry, group);

		g_free (value);
	}

	dom_element_append_child (entry,
				  dom_document_create_element (doc, "category",
							       "scheme", "http://schemas.google.com/g/2005#kind",
							       "term", "http://schemas.google.com/photos/2007#photo",
							       NULL));
	dom_element_append_child (DOM_ELEMENT (doc), entry);
	entry_buffer = dom_document_dump (doc, &entry_len);

	headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST);
	soup_message_headers_append (headers, "Content-Type", "application/atom+xml");
	body = soup_buffer_new (SOUP_MEMORY_TAKE, entry_buffer, entry_len);
	soup_multipart_append_part (multipart, headers, body);

	soup_buffer_free (body);
	soup_message_headers_free (headers);
	g_object_unref (doc);

	/* the file part */

	if (_g_buffer_resize_image (*buffer,
				    count,
				    file_data,
				    self->priv->post_photos->max_width,
				    self->priv->post_photos->max_height,
				    &resized_buffer,
				    &resized_count,
				    self->priv->post_photos->cancellable,
				    &error))
	{
		body = soup_buffer_new (SOUP_MEMORY_TAKE, resized_buffer, resized_count);
	}
	else if (error == NULL) {
		body = soup_buffer_new (SOUP_MEMORY_TEMPORARY, *buffer, count);
	}
	else {
		soup_multipart_free (multipart);
		post_photos_done (self, error);
		return;
	}

	soup_multipart_append_form_file (multipart,
					 "file",
					 NULL,
					 gth_file_data_get_mime_type (file_data),
					 body);

	soup_buffer_free (body);

	/* send the file */

	self->priv->post_photos->wrote_body_data_size = 0;
	url = g_strconcat ("https://picasaweb.google.com/data/feed/api/user/",
			   account->id,
			   "/albumid/",
			   self->priv->post_photos->album->id,
			   NULL);
	msg = soup_form_request_new_from_multipart (url, multipart);
	g_signal_connect (msg,
			  "wrote-body-data",
			  (GCallback) upload_photo_wrote_body_data_cb,
			  self);

	_picasa_web_service_add_headers (self, msg);
	_web_service_send_message (WEB_SERVICE (self),
				   msg,
				   self->priv->post_photos->cancellable,
				   self->priv->post_photos->callback,
				   self->priv->post_photos->user_data,
				   picasa_web_service_post_photos,
				   post_photo_ready_cb,
				   self);

	g_free (url);
	soup_multipart_free (multipart);
}
Esempio n. 19
0
/**
 * soup_buffer_new_take: (rename-to soup_buffer_new)
 * @data: (array length=length) (transfer full): data
 * @length: length of @data
 *
 * Creates a new #SoupBuffer containing @length bytes from @data.
 *
 * This function is exactly equivalent to soup_buffer_new() with
 * %SOUP_MEMORY_TAKE as first argument; it exists mainly for
 * convenience and simplifying language bindings.
 *
 * Return value: the new #SoupBuffer.
 *
 * Since: 2.32
 **/
SoupBuffer *
soup_buffer_new_take (guchar *data, gsize length)
{
	return soup_buffer_new (SOUP_MEMORY_TAKE, data, length);
}
Esempio n. 20
0
/**
 * soup_message_body_complete:
 * @body: a #SoupMessageBody
 *
 * Tags @body as being complete; Call this when using chunked encoding
 * after you have appended the last chunk.
 **/
void
soup_message_body_complete (SoupMessageBody *body)
{
	append_buffer (body, soup_buffer_new (SOUP_MEMORY_STATIC, NULL, 0));
}