* @retval #HTTP_ERROR_INVALID_OPERATION Invalid operation
* @retval #HTTP_ERROR_NOT_SUPPORTED Not Supported
*/
-int http_transaction_set_ready_to_write(http_transaction_h http_transaction, bool read_to_write);
+int http_transaction_set_ready_to_write(http_transaction_h http_transaction, bool ready_to_write);
/**
* @brief Sets the interface name.
--- /dev/null
+/**
+ * @brief Enumeration for the http multipart types.
+ * @since_tizen 3.0
+ */
+typedef enum {
+ HTTP_MULTIPART_CONTENTS,
+ HTTP_MULTIPART_FILE,
+} http_formdata_type_e;
+
+/**
+ * @brief Sets file path for uploading a file.
+ * @since_tizen 3.0
+ * @remarks It is used with #HTTP_METHOD_PUT
+ * @param[in] http_transaction The http transaction handle
+ * @param[in] file_path The path for file
+ * @return 0 on success, otherwise negative error value
+ * @retval #HTTP_ERROR_NONE Successful
+ * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #HTTP_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #HTTP_ERROR_NOT_SUPPORTED Not Supported
+ */
+int http_transaction_request_set_upload_file(http_transaction_h http_transaction, const char *file_path);
+
+/**
+ * @brief Adds the multipart/form-data.
+ * @since_tizen 3.0
+ * @remarks It is used with #HTTP_METHOD_POST
+ * @param[in] http_transaction The http transaction handle
+ * @param[in] multipart_type The type of form-data
+ * @param[in] part_name The name of part
+ * @param[in] value The value of part \n
+ * It will be file path or content value
+ * @param[in] content_type The content type of value (e.g text/html, image/jpeg, etc) \n
+ * It will be #NULL
+ * @return 0 on success, otherwise negative error value
+ * @retval #HTTP_ERROR_NONE Successful
+ * @retval #HTTP_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #HTTP_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #HTTP_ERROR_NOT_SUPPORTED Not Supported
+ */
+int http_transaction_request_add_multipart(http_transaction_h http_transaction,
+ http_formdata_type_e multipart_type, const char *part_name, const char *value, const char *content_type);
gchar *cookie;
GQueue* body_queue;
gint tot_size;
+ struct curl_httppost *formpost;
+ struct curl_httppost *lastptr;
+ gchar *upload_file;
+ FILE *fp;
+ curl_off_t upload_size;
http_version_e http_version;
} __http_request_h;
gchar *interface_name;
int timeout;
int write_event;
+ bool upload_event;
bool verify_peer;
gchar *ca_path;
gchar error[CURL_ERROR_SIZE];
int _get_request_body_size(http_transaction_h http_transaction, int *body_size);
int _read_request_body(http_transaction_h http_transaction, gchar **body);
+curl_off_t _get_upload_file_size(http_transaction_h http_transaction);
void __parse_response_header(gchar *buffer, size_t written, gpointer user_data);
int _generate_session_id(void);
void _add_transaction_to_list(http_transaction_h http_transaction);
int _set_authentication_info(http_transaction_h http_transaction);
gchar* parse_values(const gchar* string, int from_index, int to_index);
+FILE* _get_upload_file(http_transaction_h http_transaction);
+void _open_upload_file(http_transaction_h http_transaction);
+void _close_upload_file(__http_transaction_h *http_transaction);
+
#ifdef __cplusplus
}
#endif
* limitations under the License.
*/
+#include <sys/stat.h>
+
#include "http.h"
+#include "http_internal.h"
#include "http_private.h"
+static void _add_multipart_data(http_transaction_h http_transaction,
+ const char *part_name, const char *value,
+ const char *content_type, http_formdata_type_e type);
+
API int http_transaction_request_set_method(http_transaction_h http_transaction, http_method_e method)
{
_retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
return HTTP_ERROR_NONE;
}
+API int http_transaction_request_set_upload_file(http_transaction_h http_transaction, const char *file_path)
+{
+ _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
+ "http isn't initialized");
+ _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+ "parameter(http_transaction) is NULL\n");
+ _retvm_if(file_path == NULL, HTTP_ERROR_INVALID_PARAMETER,
+ "parameter(file_path) is NULL\n");
+
+ __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+ __http_request_h *request = transaction->request;
+
+ request->upload_file = strdup(file_path);
+
+ return HTTP_ERROR_NONE;
+}
+
+API int http_transaction_request_add_multipart(http_transaction_h http_transaction,
+ http_formdata_type_e formdata_type,
+ const char *part_name, const char *path,
+ const char *content_type)
+{
+ _retvm_if(_http_is_init() == false, HTTP_ERROR_INVALID_OPERATION,
+ "http isn't initialized");
+ _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+ "parameter(http_transaction) is NULL\n");
+ _retvm_if(part_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
+ "parameter(part_name) is NULL\n");
+ _retvm_if(path == NULL, HTTP_ERROR_INVALID_PARAMETER,
+ "parameter(path) is NULL\n");
+
+ _add_multipart_data(http_transaction, part_name, path, content_type, formdata_type);
+
+ return HTTP_ERROR_NONE;
+}
+
int _get_request_body_size(http_transaction_h http_transaction, int *body_size)
{
_retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
return HTTP_ERROR_NONE;
}
+void _open_upload_file(http_transaction_h http_transaction)
+{
+ __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+ __http_request_h *request = transaction->request;
+ struct stat file_info;
+
+ stat(request->upload_file, &file_info);
+ request->fp = fopen(request->upload_file, "rb");
+ request->upload_size = (curl_off_t)file_info.st_size;
+}
+
+void _close_upload_file(__http_transaction_h *transaction)
+{
+ __http_request_h *request = transaction->request;
+
+ if (request->fp) {
+ fclose(request->fp);
+ request->fp = NULL;
+ }
+}
+
+FILE* _get_upload_file(http_transaction_h http_transaction)
+{
+ __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+ __http_request_h *request = transaction->request;
+
+ return request->fp;
+}
+
+curl_off_t _get_upload_file_size(http_transaction_h http_transaction)
+{
+ _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+ "parameter(http_transaction) is NULL\n");
+
+ __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+ __http_request_h *request = transaction->request;
+
+ return request->upload_size;
+}
+
//LCOV_EXCL_START
int _read_request_body(http_transaction_h http_transaction, char **body)
{
for (index = 0; index < len; index++) {
ptr = (gchar*)g_queue_pop_head(request->body_queue);
+ if (!ptr) {
+ DBG("body_queue is empty\n");
+ break;
+ }
+
body_size = strlen(ptr);
new_len = curr_len + body_size;
return HTTP_ERROR_NONE;
}
+
+static void _add_multipart_data(http_transaction_h http_transaction,
+ const char *part_name, const char *value,
+ const char *content_type, http_formdata_type_e type)
+{
+ __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+ __http_request_h *request = transaction->request;
+ CURLformoption option = CURLFORM_COPYCONTENTS;
+
+ if (type == HTTP_MULTIPART_CONTENTS)
+ option = CURLFORM_COPYCONTENTS;
+ else if (type == HTTP_MULTIPART_FILE)
+ option = CURLFORM_FILE;
+
+ if (content_type) {
+ curl_formadd(&(request->formpost),
+ &(request->lastptr),
+ CURLFORM_COPYNAME, part_name,
+ option, value,
+ CURLFORM_CONTENTTYPE, content_type,
+ CURLFORM_END);
+ } else {
+ curl_formadd(&(request->formpost),
+ &(request->lastptr),
+ CURLFORM_COPYNAME, part_name,
+ option, value,
+ CURLFORM_END);
+ }
+}
//LCOV_EXCL_STOP
curl_easy_getinfo(curl_easy, CURLINFO_PRIVATE, &transaction);
curl_easy_getinfo(curl_easy, CURLINFO_EFFECTIVE_URL, &url);
+ if (transaction->upload_event)
+ _close_upload_file(transaction);
+
DBG("Completed -%s: result(%d)\n", url, curl_code);
switch (curl_code) {
case CURLE_OK:
-
if (transaction->completed_cb) {
long http_auth = _CURL_HTTP_AUTH_NONE;
long proxy_auth = _CURL_HTTP_AUTH_NONE;
transaction->aborted_cb(transaction, HTTP_ERROR_OPERATION_TIMEDOUT, transaction->aborted_user_data);
break;
default:
+ if (transaction->aborted_cb)
+ transaction->aborted_cb(transaction, HTTP_ERROR_OPERATION_FAILED, transaction->aborted_user_data);
break;
}
return body_size;
}
+
+size_t __handle_upload_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
+{
+ __http_transaction_h *transaction = (__http_transaction_h *)user_data;
+ size_t recommended_size;
+ curl_off_t nread;
+ FILE *fp = _get_upload_file(transaction);
+
+ recommended_size = fread(ptr, size, nmemb, fp);
+ nread = (curl_off_t)recommended_size;
+ DBG("Read %" CURL_FORMAT_CURL_OFF_T " bytes from file", nread);
+
+ if (transaction->write_cb)
+ transaction->write_cb(transaction, recommended_size, transaction->write_user_data);
+
+ return recommended_size;
+}
//LCOV_EXCL_STOP
size_t __http_debug_received(CURL *easy_handle, curl_infotype type, gchar *byte, size_t size, void *user_data)
curl_auth_scheme = _get_http_curl_auth_scheme(auth_scheme);
if (transaction->proxy_auth_type) {
-
curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXYAUTH, curl_auth_scheme);
curl_easy_setopt(transaction->easy_handle, CURLOPT_PROXYUSERPWD, credentials);
_get_request_body_size(transaction, &body_size);
+
+ /* Setup for POST method */
if (transaction->write_event) {
if (content_len > 0 && content_len <= body_size)
write_event = FALSE;
DBG("The write_event is %d.\n", write_event);
}
- if ((_get_method(request->method) == HTTP_METHOD_POST) && !write_event) {
+ if ((_get_method(request->method) == HTTP_METHOD_POST) && !write_event && !request->formpost) {
gchar *body = NULL;
_read_request_body(transaction, &body);
curl_easy_setopt(transaction->easy_handle, CURLOPT_READDATA, transaction);
}
+ /* Mulipart POST */
+ if (request->formpost)
+ curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPPOST, request->formpost);
+
+ /* Setup for PUT method */
+ if (transaction->upload_event) {
+ _open_upload_file(transaction);
+ curl_easy_setopt(transaction->easy_handle, CURLOPT_UPLOAD, 1L);
+ curl_easy_setopt(transaction->easy_handle, CURLOPT_READFUNCTION, __handle_upload_cb);
+ curl_easy_setopt(transaction->easy_handle, CURLOPT_READDATA, transaction);
+ curl_easy_setopt(transaction->easy_handle, CURLOPT_INFILESIZE_LARGE, _get_upload_file_size(transaction));
+ }
+
curl_easy_setopt(transaction->easy_handle, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(transaction->easy_handle, CURLOPT_PROGRESSFUNCTION, __progress_cb);
curl_easy_setopt(transaction->easy_handle, CURLOPT_PROGRESSDATA, transaction);
transaction->request->host_uri = NULL;
transaction->request->method = _get_http_method(method);
+ if (method == HTTP_METHOD_PUT)
+ transaction->upload_event = TRUE;
+ else
+ transaction->upload_event = FALSE;
+
transaction->request->encoding = NULL;
transaction->request->cookie = NULL;
transaction->request->http_version = HTTP_VERSION_1_1;
transaction->request->body_queue = g_queue_new();
transaction->request->tot_size = 0;
+ transaction->request->upload_size = 0;
+ transaction->request->upload_file = NULL;
+ transaction->request->fp = NULL;
+ transaction->request->formpost = NULL;
+ transaction->request->lastptr = NULL;
transaction->response->status_text = NULL;
if (request->body_queue != NULL)
g_queue_free(request->body_queue);
+ if (request->formpost) {
+ curl_formfree(request->formpost);
+ request->formpost = NULL;
+ }
+
+ if (request->upload_file != NULL) {
+ free(request->upload_file);
+ request->upload_file = NULL;
+ }
+
free(request);
}
#include <gio/gio.h>
#include "http.h"
+#include "http_internal.h"
#define ERR(x, y) printf("[ERR] %s(%d)\n", x, y)
#define PRG(x, y) printf("[PRG] %s(%p)\n", x, y)
{
PRG("transaction_body_cb", transaction);
int written = size * nmemb;
- DBG("Received: %d\n", written);
+ DBG("Received length: %d\n", written);
+ DBG("Received body: %s\n", body);
}
void __transaction_write_cb(http_transaction_h transaction, int recommended_chunk_size, void *user_data)
return 1;
}
+int test_multipart_post(void)
+{
+ int ret;
+ http_transaction_h transaction;
+ char *file_path = "/home/test.txt";
+ char *file_name = "test.txt";
+
+ ret = http_session_open_transaction(session, HTTP_METHOD_POST, &transaction);
+ if (ret != 0) {
+ ERR("Fail to open transaction", ret);
+ return 0;
+ }
+ ret = http_transaction_request_set_uri(transaction, "http://posttestserver.com/post.php");
+ if (ret != 0) {
+ ERR("Fail to set URI", ret);
+ return 0;
+ }
+
+ ret = http_transaction_request_add_multipart(transaction, HTTP_MULTIPART_FILE,
+ "sendfile", file_path, NULL);
+
+ ret = http_transaction_request_add_multipart(transaction, HTTP_MULTIPART_CONTENTS,
+ "filename", file_name, NULL);
+
+ http_transaction_set_received_header_cb(transaction, __transaction_header_cb, NULL);
+ http_transaction_set_received_body_cb(transaction, __transaction_body_cb, NULL);
+ http_transaction_set_completed_cb(transaction, __transaction_completed_cb, NULL);
+ http_transaction_set_aborted_cb(transaction, __transaction_aborted_cb, NULL);
+ http_transaction_set_progress_cb(transaction, __transaction_progress_cb, NULL);
+
+ http_transaction_submit(transaction);
+
+ return 1;
+}
+
+int test_put(void)
+{
+ http_transaction_h transaction;
+ const char *file_path = "/home/test.txt";
+ int ret = 0;
+
+ ret = http_session_open_transaction(session, HTTP_METHOD_PUT, &transaction);
+ if (ret != 0) {
+ ERR("Fail to open transaction", ret);
+ return 0;
+ }
+
+ ret = http_transaction_request_set_uri(transaction, "http://posttestserver.com/post.php");
+ if (ret != 0) {
+ ERR("Fail to set URI", ret);
+ return 0;
+ }
+
+ ret = http_transaction_request_set_upload_file(transaction, file_path);
+ if (ret != 0) {
+ ERR("Fail to set file path", ret);
+ return 0;
+ }
+
+ _register_callbacks(transaction);
+ ret = http_transaction_submit(transaction);
+ if (ret != 0) {
+ ERR("Fail to submit transaction", ret);
+ return 0;
+ }
+
+ return 1;
+}
+
int test_simple_authentication_get(void)
{
int ret;
_register_callbacks(transaction);
ret = http_transaction_submit(transaction);
-
if (ret != 0) {
ERR("Fail to submit transaction", ret);
return 0;
printf("5 - Simple GET\n");
printf("6 - Multiple GET\n");
printf("7 - Simple POST\n");
- printf("8 - Simple Authentication GET\n");
- printf("9 - \n");
+ printf("8 - Multipart POST\n");
+ printf("9 - Simple Authentication GET\n");
+ printf("a - Upload file (PUT)\n");
printf("0 - Exit \n");
printf("ENTER - Show options menu.......\n");
}
rv = test_simple_post();
break;
case '8':
+ rv = test_multipart_post();
+ break;
+ case '9':
rv = test_simple_authentication_get();
break;
+ case 'a':
+ rv = test_put();
+ break;
}
if (rv == 1)