[capi-http] Implemented the http authentication & http credential apis 06/67806/8
authorpradeep kumar B <b.pradeep@samsung.com>
Thu, 28 Apr 2016 09:45:22 +0000 (15:15 +0530)
committerpradeep kumar B <b.pradeep@samsung.com>
Mon, 23 May 2016 10:17:01 +0000 (15:47 +0530)
Change-Id: I7d76504f5909b4354dbe1bc8410f0755458f3eda
Signed-off-by: pradeep kumar B <b.pradeep@samsung.com>
include/http.h
include/http_private.h
src/http_common.c
src/http_response.c
src/http_session.c
src/http_transaction.c
test/http_test.c

index a4a4318..10158c0 100644 (file)
@@ -177,6 +177,21 @@ typedef enum {
 } http_status_code_e;
 
 /**
+ * @brief Enumeration for the http authentication schemes.
+ * @since_tizen 3.0
+ */
+typedef enum {
+       HTTP_AUTH_NONE = 0,             /**< No authentication type */
+       HTTP_AUTH_PROXY_BASIC = 1,      /**< The authentication type is Proxy Basic Authentication */
+       HTTP_AUTH_PROXY_MD5 = 2,        /**< The authentication type is Proxy Digest Authentication */
+       HTTP_AUTH_WWW_BASIC = 3,        /**< The authentication Type is HTTP Basic Authentication */
+       HTTP_AUTH_WWW_MD5 = 4,          /**< The authentication type is HTTP Digest Authentication */
+       HTTP_AUTH_PROXY_NTLM = 5,       /**< The authentication type is Proxy NTLM Authentication */
+       HTTP_AUTH_WWW_NTLM = 7,         /**< The authentication type is NTLM Authentication */
+       HTTP_AUTH_WWW_NEGOTIATE = 8     /**< The authentication type is Negotiate Authentication */
+} http_auth_scheme_e;
+
+/**
  * @brief Called when the http header is received.
  * @since_tizen 3.0
  * @param[in]  http_transaction The http transaction handle
@@ -379,7 +394,7 @@ int http_session_get_active_transaction_count(http_session_h http_session, int *
  */
 int http_session_get_max_transaction_count(http_session_h http_session, int *transaction_count);
 
-/*
+/**
  * @brief Destroys all transaction.
  * @since_tizen 3.0
  * @remarks All http_transactions should be set to NULL after using it
@@ -431,7 +446,7 @@ int http_transaction_submit(http_transaction_h http_transaction);
  */
 int http_transaction_destroy(http_transaction_h http_transaction);
 
-/*
+/**
  * @brief Registers callback called when receive header.
  * @since_tizen 3.0
  * @param[in]  http_transaction  The http transaction handle
@@ -445,7 +460,7 @@ int http_transaction_destroy(http_transaction_h http_transaction);
  */
 int http_transaction_set_received_header_cb(http_transaction_h http_transaction, http_transaction_header_cb header_cb, void* user_data);
 
-/*
+/**
  * @brief Registers callback called when receive body.
  * @since_tizen 3.0
  * @param[in]  http_transaction  The http transaction handle
@@ -459,7 +474,7 @@ int http_transaction_set_received_header_cb(http_transaction_h http_transaction,
  */
 int http_transaction_set_received_body_cb(http_transaction_h http_transaction, http_transaction_body_cb body_cb, void* user_data);
 
-/*
+/**
  * @brief Registers callback called when write data.
  * @since_tizen 3.0
  * @param[in]  http_transaction  The http transaction handle
@@ -473,7 +488,7 @@ int http_transaction_set_received_body_cb(http_transaction_h http_transaction, h
  */
 int http_transaction_set_uploaded_cb(http_transaction_h http_transaction, http_transaction_write_cb write_cb, void* user_data);
 
-/*
+/**
  * @brief Registers callback called when transaction is completed.
  * @since_tizen 3.0
  * @param[in]  http_transaction  The http transaction handle
@@ -487,11 +502,11 @@ int http_transaction_set_uploaded_cb(http_transaction_h http_transaction, http_t
  */
 int http_transaction_set_completed_cb(http_transaction_h http_transaction, http_transaction_completed_cb completed_cb, void* user_data);
 
-/*
+/**
  * @brief Registers callback called when transaction is aborted.
  * @since_tizen 3.0
  * @param[in]  http_transaction  The http transaction handle
- * @param[in]  header_cb                The callback function to be called
+ * @param[in]  aborted_cb               The callback function to be called
  * @param[in]  user_data                The user data passed to the callback function
  * @return 0 on success, otherwise negative error value
  * @retval  #HTTP_ERROR_NONE  Successful
@@ -501,7 +516,6 @@ int http_transaction_set_completed_cb(http_transaction_h http_transaction, http_
  */
 int http_transaction_set_aborted_cb(http_transaction_h http_http_transaction, http_transaction_aborted_cb aborted_cb, void* user_data);
 
-
 /**
  * @brief Registers the progress callbacks.
  * @details Registers callback that is called when data is uploaded/downloaded.
@@ -684,6 +698,92 @@ int http_transaction_header_remove_field(http_transaction_h http_transaction, co
 int http_transaction_header_get_field_value(http_transaction_h http_transaction, const char *field_name, char **field_value);
 
 /**
+ * @brief Opens Http transaction with authentication information.
+ * @since_tizen 3.0
+ * @remarks The @a http_transaction should be released using http_transaction_destroy().
+ * @param[in]  http_transaction                The http transaction handle
+ * @param[out] http_auth_transaction The http transaction handle
+ * @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_OUT_OF_MEMORY  Out of memory
+ * @retval  #HTTP_ERROR_NOT_SUPPORTED  Not Supported
+ */
+int http_open_authentication(http_transaction_h http_transaction, http_transaction_h *http_auth_transaction);
+
+/**
+ * @brief Sets an HTTP crendentials.
+ * @details Set an HTTP authentication scheme such as username and password.
+ * @since_tizen 3.0
+ * @param[in]  http_transaction  The http transaction handle
+ * @param[in]  user_name                The http user name
+ * @param[in]  password                         The http password
+ * @return 0 on success, otherwise negative error value
+ * @retval  #HTTP_ERROR_NONE  Successful
+ * @retval  #HTTP_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #HTTP_ERROR_NOT_SUPPORTED  Not Supported
+ */
+int http_transaction_set_credentials(http_transaction_h http_transaction, const char *user_name, const char *password);
+
+/**
+ * @brief Gets the username & password for the http credential.
+ * @since_tizen 3.0
+ * @remarks The @a user_name & password should be freed using free().
+ * @param[in]  http_transaction  The http transaction handle
+ * @param[out]  user_name               The http credential user name
+ * @param[out] password         The http credential password
+ * @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_OUT_OF_MEMORY  Out of memory
+ * @retval  #HTTP_ERROR_NOT_SUPPORTED  Not Supported
+ */
+int http_transaction_get_credentials(http_transaction_h http_transaction, char **user_name, char **password);
+
+/**
+ * @brief Sets an HTTP authentication scheme.
+ * @details Set an HTTP authentication scheme such as BASIC, MD5, NTLM and etc.
+ * @since_tizen 3.0
+ * @param[in]  http_transaction  The http transaction handle
+ * @param[in]  auth_scheme                      The http authentication scheme
+ * @return 0 on success, otherwise negative error value
+ * @retval  #HTTP_ERROR_NONE  Successful
+ * @retval  #HTTP_ERROR_INVALID_PARAMETER  Invalid parameter
+ * @retval  #HTTP_ERROR_NOT_SUPPORTED  Not Supported
+ */
+int http_transaction_set_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e auth_scheme);
+
+/**
+ * @brief Gets the Http authentication scheme.
+ * @since_tizen 3.0
+ * @param[in]  http_transaction  The http transaction handle
+ * @param[out] auth_scheme      The http auth scheme value
+ * @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_get_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e *auth_scheme);
+
+/**
+ * @brief Gets the Http authentication realm.
+ * @since_tizen 3.0
+ * @remarks The @a realm should be freed using free().
+ * @param[in]  http_transaction  The http transaction handle
+ * @param[out] realm    The http realm value
+ * @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_OUT_OF_MEMORY  Out of memory
+ * @retval  #HTTP_ERROR_NOT_SUPPORTED  Not Supported
+ */
+int http_transaction_get_realm(http_transaction_h http_transaction, char **realm);
+
+/**
  * @}
  */
 
@@ -837,7 +937,7 @@ int http_transaction_request_get_cookie(http_transaction_h http_transaction, con
 /**
  * @brief Writes the request message body.
  * @details This function writes the request message body in the internal queue. \n
- *                     The written queue for request body is uploaded after invoking http_transaction_submit() 
+ *                     The written queue for request body is uploaded after invoking http_transaction_submit()
  * @since_tizen 3.0
  * @param[in]  http_transaction The http transaction handle
  * @param[in]  body                    The message body data
index f0e26fa..7b8b43b 100644 (file)
@@ -89,9 +89,24 @@ static const int _HTTP_DEFAULT_HEADER_SIZE = 1024;
 static const int _MAX_HTTP_TRANSACTIONS_PER_SESSION_NORMAL = 1;
 static const int _MAX_HTTP_TRANSACTIONS_PER_SESSION_PIPE = 5;
 
+
+#define _HTTP_PROXY_AUTHENTICATE_HEADER_NAME "Proxy-Authenticate"
+#define _HTTP_WWW_AUTHENTICATE_HEADER_NAME "WWW-Authenticate"
+#define _HTTP_CONTENT_LENGTH_HEADER_NAME "Content-Length"
+
+typedef enum {
+       _CURL_HTTP_AUTH_NONE = 0,                       //none
+       _CURL_HTTP_AUTH_BASIC = 1,                      // The constant for basic authentication
+       _CURL_HTTP_AUTH_DIGEST = 2,                     // The constant for digest authentication
+       _CURL_HTTP_AUTH_GSSNEGOTIATE = 4,       // The constant for gss-negotiate authentication
+       _CURL_HTTP_AUTH_NTLM = 8                        // The constant for ntlm authentication
+} curl_http_auth_scheme_e;
+
 typedef struct {
        struct curl_slist *header_list;
        GHashTable *hash_table;
+       gchar *rsp_header;
+       gint rsp_header_len;
 } __http_header_h;
 
 typedef struct {
@@ -131,12 +146,22 @@ typedef struct {
        gchar *ca_path;
        gchar error[CURL_ERROR_SIZE];
 
+       /*Authentication Info*/
+       bool auth_required;
+       bool proxy_auth_type;
+       http_auth_scheme_e auth_scheme;
+       gchar* realm;
+       /*Credential Info*/
+       gchar* user_name;
+       gchar* password;
+
        int socket_fd;
        /*Transaction Callbacks and User data*/
        http_transaction_progress_cb progress_cb;
        void* progress_user_data;
        http_transaction_header_cb header_cb;
        void* header_user_data;
+       bool header_event;
        http_transaction_body_cb body_cb;
        void* body_user_data;
        http_transaction_write_cb write_cb;
@@ -174,13 +199,16 @@ gchar* _get_proxy();
 struct curl_slist* _get_header_list(http_transaction_h http_transaction);
 
 int _get_request_body_size(http_transaction_h http_transaction, int *body_size);
-int _read_request_body(http_transaction_h http_transaction, char **body);
-void __parse_response_header(char *buffer, size_t written, gpointer user_data);
+int _read_request_body(http_transaction_h http_transaction, gchar **body);
+void __parse_response_header(gchar *buffer, size_t written, gpointer user_data);
 int _generate_session_id(void);
 int _generate_transaction_id(void);
 void _add_transaction_to_list(http_transaction_h http_transaction);
 void _remove_transaction_from_list(http_transaction_h http_transaction);
 void _remove_transaction_list(void);
+curl_http_auth_scheme_e _get_http_curl_auth_scheme(http_auth_scheme_e auth_scheme);
+http_auth_scheme_e _get_http_auth_scheme(bool proxy_auth, curl_http_auth_scheme_e curl_auth_scheme);
+gchar* parse_values(const gchar* string, int from_index, int to_index);
 
 #ifdef __cplusplus
  }
index d363473..e8e044e 100644 (file)
@@ -106,9 +106,83 @@ gchar* _get_http_method(http_method_e method)
        return http_method;
 }
 
+http_auth_scheme_e _get_http_auth_scheme(bool proxy_auth, curl_http_auth_scheme_e curl_auth_scheme)
+{
+       http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
+       if (proxy_auth) {
+               switch (curl_auth_scheme) {
+               case _CURL_HTTP_AUTH_NONE:
+                       auth_scheme = HTTP_AUTH_NONE;
+                       break;
+               case _CURL_HTTP_AUTH_BASIC:
+                       auth_scheme = HTTP_AUTH_PROXY_BASIC;
+                       break;
+               case _CURL_HTTP_AUTH_DIGEST:
+                       auth_scheme = HTTP_AUTH_PROXY_MD5;
+                       break;
+               case _CURL_HTTP_AUTH_NTLM:
+                       auth_scheme = HTTP_AUTH_PROXY_NTLM;
+                       break;
+               default:
+                       auth_scheme = HTTP_AUTH_NONE;
+                       break;
+               }
+       } else {
+               switch (curl_auth_scheme) {
+               case _CURL_HTTP_AUTH_NONE:
+                       auth_scheme = HTTP_AUTH_NONE;
+                       break;
+               case _CURL_HTTP_AUTH_BASIC:
+                       auth_scheme = HTTP_AUTH_WWW_BASIC;
+                       break;
+               case _CURL_HTTP_AUTH_DIGEST:
+                       auth_scheme = HTTP_AUTH_WWW_MD5;
+                       break;
+               case _CURL_HTTP_AUTH_NTLM:
+                       auth_scheme = HTTP_AUTH_WWW_NTLM;
+                       break;
+               case _CURL_HTTP_AUTH_GSSNEGOTIATE:
+                       auth_scheme = HTTP_AUTH_WWW_NEGOTIATE;
+                       break;
+               default:
+                       auth_scheme = HTTP_AUTH_NONE;
+                       break;
+               }
+       }
+
+       return auth_scheme;
+}
+
+curl_http_auth_scheme_e _get_http_curl_auth_scheme(http_auth_scheme_e auth_scheme)
+{
+       curl_http_auth_scheme_e curl_auth_scheme = _CURL_HTTP_AUTH_NONE;
+       switch (auth_scheme) {
+       case HTTP_AUTH_PROXY_BASIC:
+       case HTTP_AUTH_WWW_BASIC:
+               curl_auth_scheme = _CURL_HTTP_AUTH_BASIC;
+               break;
+       case HTTP_AUTH_PROXY_MD5:
+       case HTTP_AUTH_WWW_MD5:
+               curl_auth_scheme = _CURL_HTTP_AUTH_DIGEST;
+               break;
+       case HTTP_AUTH_PROXY_NTLM:
+       case HTTP_AUTH_WWW_NTLM:
+               curl_auth_scheme = _CURL_HTTP_AUTH_NTLM;
+               break;
+       case HTTP_AUTH_WWW_NEGOTIATE:
+               curl_auth_scheme = _CURL_HTTP_AUTH_GSSNEGOTIATE;
+               break;
+       default:
+               curl_auth_scheme = _CURL_HTTP_AUTH_NONE;
+               break;
+       }
+
+       return curl_auth_scheme;
+}
+
 void print_curl_multi_errorCode(CURLMcode code)
 {
-       const char* message = NULL;
+       const gchar* message = NULL;
        switch (code) {
        case CURLM_CALL_MULTI_PERFORM:
                message = "CURLM_CALL_MULTI_PERFORM";
@@ -142,6 +216,20 @@ void print_curl_multi_errorCode(CURLMcode code)
        DBG("CURLMcode(%d): %s", code, message);
 }
 
+gchar* parse_values(const gchar* string, int from_index, int to_index)
+{
+       gchar* str = NULL;
+       int cur_index = to_index - from_index;
+
+       str = (gchar*) malloc(cur_index + 1);
+       memset(str, '\0', cur_index + 1);
+
+       strncpy(str, (string + from_index), cur_index);
+       str[cur_index] = '\0';
+
+       return str;
+}
+
 gchar* _get_proxy()
 {
        connection_h connection = NULL;
index 03e9558..29671ef 100644 (file)
@@ -19,7 +19,7 @@
 #include "http.h"
 #include "http_private.h"
 
-static int __convert_status_code(char *status_code)
+static int __convert_status_code(gchar *status_code)
 {
        int i = 0;
        int converted_digit = 0;
@@ -33,14 +33,14 @@ static int __convert_status_code(char *status_code)
        return converted_status_code;
 }
 
-void __parse_response_header(char *buffer, size_t written, gpointer user_data)
+void __parse_response_header(gchar *buffer, size_t written, gpointer user_data)
 {
        __http_transaction_h* transaction = (__http_transaction_h *)user_data;
        __http_response_h*response = (__http_response_h *)transaction->response;
 
-       char status_code[HTTP_STATUS_CODE_SIZE] = {0, };
-       char* start = NULL;
-       char* end = NULL;
+       gchar status_code[HTTP_STATUS_CODE_SIZE] = {0, };
+       gchar* start = NULL;
+       gchar* end = NULL;
 
        if (strncmp(buffer, "HTTP/", HTTP_PREFIX_SIZE) == 0) {
                if (strncmp(buffer + HTTP_PREFIX_SIZE, "1.0", HTTP_VERSION_SIZE) == 0)
@@ -60,7 +60,26 @@ void __parse_response_header(char *buffer, size_t written, gpointer user_data)
                response->status_code = __convert_status_code(status_code);
                response->status_text = g_strndup(start, end - start);
 
-               DBG("[Seonah] reason_pharse: %s", response->status_text);
+               DBG("reason_pharse: %s", response->status_text);
+       } else {
+               gchar *field_name = NULL;
+               gchar *field_value = NULL;
+               gchar *curpos = NULL;
+               int pos = 0, len = 0;
+
+               len = strlen(buffer);
+               curpos = strchr(buffer, ':');
+               if (curpos == NULL)
+                       return;
+
+               pos = curpos - buffer + 1;
+
+               field_name = parse_values(buffer, 0, pos - 1);
+               field_value = parse_values(buffer, pos + 1, len);
+
+               http_transaction_header_add_field(transaction, field_name, field_value);
+               free(field_name);
+               free(field_value);
        }
 }
 
index 6b0e2b3..dcd6692 100644 (file)
@@ -41,8 +41,33 @@ void _check_curl_multi_status(gpointer user_data)
 
                        switch (curl_code) {
                        case CURLE_OK:
-                               if (transaction->completed_cb)
+
+                               if (transaction->completed_cb) {
+                                       long http_auth = _CURL_HTTP_AUTH_NONE;
+                                       long proxy_auth = _CURL_HTTP_AUTH_NONE;
+                                       http_status_code_e status = 0;
+                                       bool auth_req = FALSE;
+                                       bool proxy = FALSE;
+
+                                       http_transaction_response_get_status_code(transaction, &status);
+                                       DBG("Status(%d)\n", status);
+
+                                       if (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED) {
+
+                                               transaction->auth_required = auth_req = TRUE;
+
+                                               curl_easy_getinfo(transaction->easy_handle, CURLINFO_HTTPAUTH_AVAIL, &http_auth);
+                                               curl_easy_getinfo(transaction->easy_handle, CURLINFO_PROXYAUTH_AVAIL, &proxy_auth);
+
+                                               if (proxy_auth != _CURL_HTTP_AUTH_NONE)
+                                                       proxy = TRUE;
+
+                                               http_auth_scheme_e auth_scheme = _get_http_auth_scheme(proxy, http_auth);
+                                               http_transaction_set_http_auth_scheme(transaction, auth_scheme);
+                                       }
                                        transaction->completed_cb(transaction, transaction->completed_user_data);
+                               }
+
                                break;
                        case CURLE_COULDNT_RESOLVE_HOST:
                                if (transaction->aborted_cb)
@@ -64,9 +89,8 @@ void _check_curl_multi_status(gpointer user_data)
                                break;
                        }
 
-                       if (session->multi_handle != NULL && curl_easy != NULL) {
+                       if (session->multi_handle != NULL && curl_easy != NULL)
                                curl_multi_remove_handle(session->multi_handle, curl_easy);
-                       }
                }
                message = curl_multi_info_read(session->multi_handle, &count);
        }
@@ -197,7 +221,7 @@ int __handle_socket_cb(CURL *curl_easy, curl_socket_t fd, int action, void *user
 
        static const char *actionstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE"};
 
-       DBG("__handle_socket_cb: fd=%d easy_handle=%p action=%s ", fd, curl_easy, actionstr[action]);
+       DBG("__handle_socket_cb: fd=%d easy_handle=%p action=%s", fd, curl_easy, actionstr[action]);
        if (action == CURL_POLL_REMOVE) {
                DBG("CURL_POLL_REMOVE\n");
                _remove_socket_info(sock_info);
index 2639459..b1962bd 100644 (file)
@@ -50,28 +50,49 @@ curl_socket_t __handle_opensocket_cb(void *client_fd, curlsocktype purpose, stru
        return fd;
 }
 
-size_t __handle_header_cb(char *buffer, size_t size, size_t nmemb, gpointer user_data)
+size_t __handle_header_cb(gchar *buffer, size_t size, size_t nmemb, gpointer user_data)
 {
        __http_transaction_h *transaction = (__http_transaction_h *)user_data;
+       __http_header_h *header = transaction->header;
+
+       gchar *temp_header = NULL;
        size_t written = size * nmemb;
+       size_t new_len = header->rsp_header_len + written;
+
+       temp_header = header->rsp_header;
+       header->rsp_header = realloc(header->rsp_header, new_len + 1);
+       if (header->rsp_header == NULL) {
+               free(temp_header);
+               ERR("realloc() failed\n");
+               return -1;
+       }
+
+       memcpy(header->rsp_header + header->rsp_header_len, buffer, written);
+       header->rsp_header[new_len] = '\0';
+       header->rsp_header_len = new_len;
 
        __parse_response_header(buffer, written, user_data);
-       transaction->header_cb(transaction, buffer, written, transaction->header_user_data);
 
        return written;
 }
 
-size_t __handle_body_cb(char *ptr, size_t size, size_t nmemb, gpointer user_data)
+size_t __handle_body_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
 {
        __http_transaction_h *transaction = (__http_transaction_h *)user_data;
+       __http_header_h *header = transaction->header;
        size_t written = size * nmemb;
 
+       if (!transaction->header_event) {
+               transaction->header_event = TRUE;
+               transaction->header_cb(transaction, header->rsp_header, header->rsp_header_len, transaction->header_user_data);
+       }
+
        transaction->body_cb(transaction, ptr, size, nmemb, transaction->body_user_data);
 
        return written;
 }
 
-size_t __handle_write_cb(char *ptr, size_t size, size_t nmemb, gpointer user_data)
+size_t __handle_write_cb(gchar *ptr, size_t size, size_t nmemb, gpointer user_data)
 {
        __http_transaction_h *transaction = (__http_transaction_h *)user_data;
        __http_request_h *request = transaction->request;
@@ -90,7 +111,7 @@ size_t __handle_write_cb(char *ptr, size_t size, size_t nmemb, gpointer user_dat
        return body_size;
 }
 
-size_t __http_debug_received(CURL* easy_handle, curl_infotype type, char* byte, size_t size, void *user_data)
+size_t __http_debug_received(CURL* easy_handle, curl_infotype type, gchar* byte, size_t size, void *user_data)
 {
        char log_buffer[_HTTP_DEFAULT_HEADER_SIZE];
        int log_size = 0;
@@ -118,6 +139,42 @@ size_t __http_debug_received(CURL* easy_handle, curl_infotype type, char* byte,
        return 0;
 }
 
+int http_transaction_set_authentication_info(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_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
+
+       http_transaction_get_http_auth_scheme(transaction, &auth_scheme);
+
+       switch (auth_scheme) {
+       case HTTP_AUTH_PROXY_BASIC:
+       case HTTP_AUTH_PROXY_MD5:
+       case HTTP_AUTH_PROXY_NTLM:
+               http_transaction_header_get_field_value(transaction, _HTTP_PROXY_AUTHENTICATE_HEADER_NAME, &transaction->realm);
+
+               transaction->proxy_auth_type = TRUE;
+               break;
+
+       case HTTP_AUTH_WWW_BASIC:
+       case HTTP_AUTH_WWW_MD5:
+       case HTTP_AUTH_WWW_NEGOTIATE:
+       case HTTP_AUTH_WWW_NTLM:
+               http_transaction_header_get_field_value(transaction, _HTTP_WWW_AUTHENTICATE_HEADER_NAME, &transaction->realm);
+
+               transaction->proxy_auth_type = FALSE;
+               break;
+
+       default:
+               break;
+       }
+
+       return HTTP_ERROR_NONE;
+}
+
 int _transaction_submit(gpointer user_data)
 {
        __http_transaction_h *transaction = (__http_transaction_h *)user_data;
@@ -131,8 +188,10 @@ int _transaction_submit(gpointer user_data)
        gboolean write_event = FALSE;
        gint body_size = 0;
        gint content_len = 0;
+       http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
 
-       transaction->easy_handle = curl_easy_init();
+       if (!transaction->easy_handle)
+               transaction->easy_handle = curl_easy_init();
 
        if (request->http_version == HTTP_VERSION_1_0)
                curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
@@ -198,6 +257,36 @@ int _transaction_submit(gpointer user_data)
                DBG("Disabled Auto-Redirection\n");
        }
 
+       /* Authentication */
+       if (transaction->auth_required) {
+
+               curl_http_auth_scheme_e curl_auth_scheme;
+               gchar *user_name = NULL;
+               gchar *password = NULL;
+               gchar *credentials = NULL;
+
+               http_transaction_get_credentials(transaction, &user_name, &password);
+               credentials = (gchar *)malloc(sizeof(gchar) * (strlen(user_name) + 1 + strlen(password) + 1));
+               sprintf(credentials, "%s:%s", (gchar*)user_name, (gchar*)password);
+               free(user_name);
+               free(password);
+
+               http_transaction_get_http_auth_scheme(transaction, &auth_scheme);
+
+               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);
+
+               } else {
+                       curl_easy_setopt(transaction->easy_handle, CURLOPT_HTTPAUTH, curl_auth_scheme);
+                       curl_easy_setopt(transaction->easy_handle, CURLOPT_USERPWD, credentials);
+               }
+               free(credentials);
+       }
+
        curl_easy_setopt(transaction->easy_handle, CURLOPT_HEADERFUNCTION, __handle_header_cb);
        curl_easy_setopt(transaction->easy_handle, CURLOPT_HEADERDATA, transaction);
 
@@ -300,6 +389,13 @@ API int http_session_open_transaction(http_session_h http_session, http_method_e
        transaction->ca_path = g_strdup(HTTP_DEFAULT_CA_PATH);
        transaction->error[0] = '\0';
 
+       transaction->auth_required = FALSE;
+       transaction->realm = NULL;
+       transaction->user_name = NULL;
+       transaction->password = NULL;
+       transaction->proxy_auth_type = FALSE;
+       transaction->auth_scheme = HTTP_AUTH_NONE;
+
        transaction->header_cb = NULL;
        transaction->body_cb = NULL;
        transaction->write_cb = NULL;
@@ -329,6 +425,11 @@ API int http_session_open_transaction(http_session_h http_session, http_method_e
                return HTTP_ERROR_OUT_OF_MEMORY;
        }
 
+       transaction->header->rsp_header_len = 0;
+       transaction->header->rsp_header = malloc(transaction->header->rsp_header_len + 1);
+       transaction->header->rsp_header[0] = '\0';
+       transaction->header_event = FALSE;
+
        transaction->request->host_uri = NULL;
        transaction->request->method = _get_http_method(method);
        transaction->request->encoding = NULL;
@@ -409,6 +510,25 @@ API int http_transaction_destroy(http_transaction_h http_transaction)
                }
                transaction->error[0] = '\0';
 
+               if (transaction->user_name) {
+                       free(transaction->user_name);
+                       transaction->user_name = NULL;
+               }
+
+               if (transaction->password) {
+                       free(transaction->password);
+                       transaction->password = NULL;
+               }
+
+               if (transaction->realm) {
+                       free(transaction->realm);
+                       transaction->realm = NULL;
+               }
+
+               transaction->auth_required = FALSE;
+               transaction->proxy_auth_type = FALSE;
+               transaction->auth_scheme = HTTP_AUTH_NONE;
+
                transaction->header_cb = NULL;
                transaction->body_cb = NULL;
                transaction->write_cb = NULL;
@@ -461,10 +581,18 @@ API int http_transaction_destroy(http_transaction_h http_transaction)
                        }
 
                        if (header->hash_table != NULL) {
+
+                               g_hash_table_remove_all(header->hash_table);
+
                                g_hash_table_destroy(header->hash_table);
                                header->hash_table = NULL;
                        }
 
+                       if (header->rsp_header != NULL) {
+                               free(header->rsp_header);
+                               header->rsp_header = NULL;
+                               header->rsp_header_len = 0;
+                       }
                        free(header);
                }
 
@@ -778,3 +906,199 @@ API int http_session_destroy_all_transactions(http_session_h http_session)
        return HTTP_ERROR_NONE;
 }
 
+API int http_transaction_set_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e auth_scheme)
+{
+       _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(http_transaction) is NULL\n");
+
+       __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+
+       transaction->auth_scheme = auth_scheme;
+
+       return HTTP_ERROR_NONE;
+}
+
+API int http_transaction_get_http_auth_scheme(http_transaction_h http_transaction, http_auth_scheme_e *auth_scheme)
+{
+       _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(http_transaction) is NULL\n");
+       _retvm_if(auth_scheme == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(auth_scheme) is NULL\n");
+
+       __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+
+       *auth_scheme =  transaction->auth_scheme;
+
+       return HTTP_ERROR_NONE;
+}
+
+API int http_transaction_get_realm(http_transaction_h http_transaction, char **realm)
+{
+       _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(http_transaction) is NULL\n");
+       _retvm_if(realm == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(realm) is NULL\n");
+
+       __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+
+       *realm = g_strdup(transaction->realm);
+       if (*realm == NULL) {
+               ERR("strdup is failed\n");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+
+       return HTTP_ERROR_NONE;
+}
+
+API int http_transaction_set_credentials(http_transaction_h http_transaction, const char *user_name, const char *password)
+{
+       _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(http_transaction) is NULL\n");
+       _retvm_if(user_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(user_name) is NULL\n");
+       _retvm_if(password == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(password) is NULL\n");
+
+       __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+
+       transaction->user_name = g_strdup(user_name);
+       transaction->password = g_strdup(password);
+
+       return HTTP_ERROR_NONE;
+}
+
+API int http_transaction_get_credentials(http_transaction_h http_transaction, char **user_name, char **password)
+{
+       _retvm_if(http_transaction == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(http_transaction) is NULL\n");
+       _retvm_if(user_name == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(user_name) is NULL\n");
+       _retvm_if(password == NULL, HTTP_ERROR_INVALID_PARAMETER,
+                       "parameter(password) is NULL\n");
+
+       __http_transaction_h *transaction = (__http_transaction_h *)http_transaction;
+
+       *user_name = g_strdup(transaction->user_name);
+       if (*user_name == NULL) {
+               ERR("strdup is failed\n");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+
+       *password = g_strdup(transaction->password);
+       if (*password == NULL) {
+               ERR("strdup is failed\n");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+       return HTTP_ERROR_NONE;
+}
+
+API int http_open_authentication(http_transaction_h http_transaction, http_transaction_h *http_auth_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_transaction_h *auth_transaction = NULL;
+
+       auth_transaction = (__http_transaction_h *)malloc(sizeof(__http_transaction_h));
+       if (auth_transaction == NULL) {
+               ERR("Fail to allocate transaction memory!!");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+
+       auth_transaction->easy_handle = NULL;
+       auth_transaction->interface_name = NULL;
+       auth_transaction->ca_path = NULL;
+       auth_transaction->error[0] = '\0';
+
+       if (transaction->interface_name)
+               auth_transaction->interface_name = g_strdup(transaction->interface_name);
+       auth_transaction->timeout = 0;
+       auth_transaction->verify_peer = transaction->verify_peer;
+       if (transaction->ca_path)
+               auth_transaction->ca_path = g_strdup(transaction->ca_path);
+
+       auth_transaction->auth_required = transaction->auth_required;
+       auth_transaction->realm = NULL;
+       auth_transaction->user_name = NULL;
+       auth_transaction->password = NULL;
+       auth_transaction->proxy_auth_type = FALSE;
+       auth_transaction->auth_scheme = transaction->auth_scheme;
+       auth_transaction->write_event = FALSE;
+
+       auth_transaction->header_cb = NULL;
+       auth_transaction->header_user_data = NULL;
+       auth_transaction->body_cb = NULL;
+       auth_transaction->body_user_data = NULL;
+       auth_transaction->write_cb = NULL;
+       auth_transaction->write_user_data = NULL;
+       auth_transaction->completed_cb = NULL;
+       auth_transaction->completed_user_data = NULL;
+       auth_transaction->aborted_cb = NULL;
+       auth_transaction->progress_cb = NULL;
+       auth_transaction->progress_user_data = NULL;
+
+       auth_transaction->session = transaction->session;
+       auth_transaction->session->active_transaction_count = transaction->session->active_transaction_count;
+       auth_transaction->session_id = transaction->session_id;
+
+       auth_transaction->request = (__http_request_h *)malloc(sizeof(__http_request_h));
+       if (auth_transaction->request == NULL) {
+               free(auth_transaction->interface_name);
+               free(auth_transaction->ca_path);
+               free(auth_transaction);
+               ERR("Fail to allocate request memory!!");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+
+       auth_transaction->request->host_uri = NULL;
+       auth_transaction->request->method = NULL;
+
+       auth_transaction->response = (__http_response_h *)malloc(sizeof(__http_response_h));
+       if (auth_transaction->response == NULL) {
+               free(auth_transaction->interface_name);
+               free(auth_transaction->ca_path);
+               free(auth_transaction->request);
+               free(auth_transaction);
+               ERR("Fail to allocate response memory!!");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+
+       auth_transaction->header = (__http_header_h *)malloc(sizeof(__http_header_h));
+       if (auth_transaction->header == NULL) {
+               free(auth_transaction->interface_name);
+               free(auth_transaction->ca_path);
+               free(auth_transaction->request);
+               free(auth_transaction->response);
+               free(auth_transaction);
+               ERR("Fail to allocate header memory!!");
+               return HTTP_ERROR_OUT_OF_MEMORY;
+       }
+
+       auth_transaction->header->rsp_header_len = 0;
+       auth_transaction->header->rsp_header = malloc(auth_transaction->header->rsp_header_len + 1);
+       auth_transaction->header->rsp_header[0] = '\0';
+       auth_transaction->header_event = FALSE;
+
+       if (transaction->request->host_uri)
+               auth_transaction->request->host_uri = g_strdup(transaction->request->host_uri);
+       if (transaction->request->method)
+               auth_transaction->request->method = g_strdup(transaction->request->method);
+       auth_transaction->request->encoding = NULL;
+       auth_transaction->request->cookie = NULL;
+       auth_transaction->request->http_version = HTTP_VERSION_1_1;
+       auth_transaction->request->body_queue = g_queue_new();
+       auth_transaction->request->tot_size = 0;
+
+       auth_transaction->header->header_list = NULL;
+       auth_transaction->header->hash_table = NULL;
+
+       auth_transaction->thread = NULL;
+
+       *http_auth_transaction = (http_transaction_h)auth_transaction;
+       _add_transaction_to_list(auth_transaction);
+
+       http_transaction_set_authentication_info((http_transaction_h)auth_transaction);
+
+       return HTTP_ERROR_NONE;
+}
index 32e1d27..a6b5927 100644 (file)
@@ -31,6 +31,7 @@ FILE* fp1 = NULL;
 FILE* fp2 = NULL;
 
 http_session_h session = NULL;
+void _register_callbacks(http_transaction_h transaction);
 
 void __transaction_header_cb(http_transaction_h transaction, char *header, size_t header_len, void *user_data)
 {
@@ -57,12 +58,31 @@ void __transaction_completed_cb(http_transaction_h transaction, void *user_data)
        http_status_code_e status = 0;
        int ret;
        char *uri = NULL;
+       char id[16] = {0, };
+       char pw[16] = {0, };
 
        ret = http_transaction_request_get_uri(transaction, &uri);
        ret = http_transaction_response_get_status_code(transaction, &status);
+       DBG("%s - status(%d)\n", uri, status);
+       if (status == HTTP_STATUS_UNAUTHORIZED) {
+               DBG("Authentication Required\n");
+               http_transaction_h http_auth_transaction;
+               http_auth_scheme_e auth_scheme = HTTP_AUTH_NONE;
+
+               http_open_authentication(transaction, &http_auth_transaction);
+               http_transaction_get_http_auth_scheme(http_auth_transaction, &auth_scheme);
+
+               printf("User ID: ");
+               ret = scanf("%15s", id);
+               printf("Password: ");
+               ret = scanf("%15s", pw);
+
+               http_transaction_set_credentials(http_auth_transaction, id, pw);
+               _register_callbacks(http_auth_transaction);
+               http_transaction_submit(http_auth_transaction);
+       }
 
        http_transaction_header_remove_field(transaction, "Content-Length");
-       DBG("%s - status(%d)\n", uri, status);
        ret = http_transaction_destroy(transaction);
        if (ret == HTTP_ERROR_NONE) DBG("Success to close transaction\n");
        else DBG("Fail to close transaction\n");
@@ -225,6 +245,40 @@ int test_simple_post(void)
        return 1;
 }
 
+int test_simple_authentication_get(void)
+{
+       int ret;
+       http_transaction_h transaction = NULL;
+       http_method_e method;
+       char uri[1024];
+
+       ret = http_session_open_transaction(session, HTTP_METHOD_GET, &transaction);
+       if (ret != 0) {
+               ERR("Fail to open transaction", ret);
+               return 0;
+       }
+
+       printf("Input uri for transaction: ");
+       ret = scanf("%1023s", uri);
+
+       http_transaction_request_get_method(transaction, &method);
+       ret = http_transaction_request_set_uri(transaction, uri);
+       if (ret != 0) {
+               ERR("Fail to set URI", ret);
+               return 0;
+       }
+
+       _register_callbacks(transaction);
+       ret = http_transaction_submit(transaction);
+
+       if (ret != 0) {
+               ERR("Fail to submit transaction", ret);
+               return 0;
+       }
+
+       return 1;
+}
+
 gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
 {
        int rv;
@@ -247,7 +301,8 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
                printf("5       - Simple GET\n");
                printf("6       - Multiple GET\n");
                printf("7       - Simple POST\n");
-               printf("8       - \n");
+               printf("8       - Simple Authentication GET\n");
+               printf("9       - \n");
                printf("0       - Exit \n");
                printf("ENTER  - Show options menu.......\n");
        }
@@ -274,6 +329,9 @@ gboolean test_thread(GIOChannel *source, GIOCondition condition, gpointer data)
        case '7':
                rv = test_simple_post();
                break;
+       case '8':
+               rv = test_simple_authentication_get();
+               break;
        }
 
        if (rv == 1)