/** * soup_form_decode_multipart: * @msg: a #SoupMessage containing a "multipart/form-data" request body * @file_control_name: the name of the HTML file upload control, or %NULL * @filename: (out): return location for the name of the uploaded file * @content_type: (out): return location for the MIME type of the uploaded file * @file: (out): return location for the uploaded file data * * Decodes the "multipart/form-data" request in @msg; this is a * convenience method for the case when you have a single file upload * control in a form. (Or when you don't have any file upload * controls, but are still using "multipart/form-data" anyway.) Pass * the name of the file upload control in @file_control_name, and * soup_form_decode_multipart() will extract the uploaded file data * into @filename, @content_type, and @file. All of the other form * control data will be returned (as strings, as with * soup_form_decode()) in the returned #GHashTable. * * You may pass %NULL for @filename and/or @content_type if you do not * care about those fields. soup_form_decode_multipart() may also * return %NULL in those fields if the client did not provide that * information. You must free the returned filename and content-type * with g_free(), and the returned file data with soup_buffer_free(). * * If you have a form with more than one file upload control, you will * need to decode it manually, using soup_multipart_new_from_message() * and soup_multipart_get_part(). * * Return value: (element-type utf8 utf8) (transfer full): a hash * table containing the name/value pairs (other than * @file_control_name) from @msg, which you can free with * g_hash_table_destroy(). On error, it will return %NULL. * * Since: 2.26 **/ GHashTable * soup_form_decode_multipart (SoupMessage *msg, const char *file_control_name, char **filename, char **content_type, SoupBuffer **file) { SoupMultipart *multipart; GHashTable *form_data_set, *params; SoupMessageHeaders *part_headers; SoupBuffer *part_body; char *disposition, *name; int i; multipart = soup_multipart_new_from_message (msg->request_headers, msg->request_body); if (!multipart) return NULL; if (filename) *filename = NULL; if (content_type) *content_type = NULL; *file = NULL; form_data_set = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); for (i = 0; i < soup_multipart_get_length (multipart); i++) { soup_multipart_get_part (multipart, i, &part_headers, &part_body); if (!soup_message_headers_get_content_disposition ( part_headers, &disposition, ¶ms)) continue; name = g_hash_table_lookup (params, "name"); if (g_ascii_strcasecmp (disposition, "form-data") != 0 || !name) { g_free (disposition); g_hash_table_destroy (params); continue; } if (!strcmp (name, file_control_name)) { if (filename) *filename = g_strdup (g_hash_table_lookup (params, "filename")); if (content_type) *content_type = g_strdup (soup_message_headers_get_content_type (part_headers, NULL)); if (file) *file = soup_buffer_copy (part_body); } else { g_hash_table_insert (form_data_set, g_strdup (name), g_strndup (part_body->data, part_body->length)); } g_free (disposition); g_hash_table_destroy (params); } soup_multipart_free (multipart); return form_data_set; }
static void file_info_from_message (SoupMessage *msg, GFileInfo *info, GFileAttributeMatcher *matcher) { const char *text; GHashTable *params; char *basename; char *ed_name; basename = ed_name = NULL; /* prefer the filename from the Content-Disposition (rfc2183) header if one if present. See bug 551298. */ if (soup_message_headers_get_content_disposition (msg->response_headers, NULL, ¶ms)) { const char *name = g_hash_table_lookup (params, "filename"); if (name) basename = g_strdup (name); g_hash_table_destroy (params); } if (basename == NULL) { const SoupURI *uri; uri = soup_message_get_uri (msg); basename = http_uri_get_basename (uri->path); } g_debug ("basename:%s\n", basename); /* read http/1.1 rfc, until then we copy the local files * behaviour */ if (basename != NULL && (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) || g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME))) ed_name = gvfs_file_info_populate_names_as_local (info, basename); g_free (basename); g_free (ed_name); if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_CONTENT_LENGTH) { goffset start, end, length; gboolean ret; ret = soup_message_headers_get_content_range (msg->response_headers, &start, &end, &length); if (ret && length != -1) { g_file_info_set_size (info, length); } else if (!ret) { length = soup_message_headers_get_content_length (msg->response_headers); g_file_info_set_size (info, length); } } g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR); text = soup_message_headers_get_content_type (msg->response_headers, NULL); if (text) { GIcon *icon; g_file_info_set_content_type (info, text); g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, text); icon = g_content_type_get_icon (text); g_file_info_set_icon (info, icon); g_object_unref (icon); icon = g_content_type_get_symbolic_icon (text); g_file_info_set_symbolic_icon (info, icon); g_object_unref (icon); } text = soup_message_headers_get_one (msg->response_headers, "Last-Modified"); if (text) { SoupDate *sd; GTimeVal tv; sd = soup_date_new_from_string(text); if (sd) { soup_date_to_timeval (sd, &tv); g_file_info_set_modification_time (info, &tv); soup_date_free (sd); } } text = soup_message_headers_get_one (msg->response_headers, "ETag"); if (text) { g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE, text); } }