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; }
/** * 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; }
/** * 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)); }
/* * * 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); }
/** * 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); }
/* 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; }
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); }
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; } }
/* 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; }
/* 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, ¶ms); 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; }
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); }
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); }
/** * 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); }
/** * 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)); }