summaryrefslogtreecommitdiffstats
path: root/src/core/transport/http/sender/libcurl/axis2_libcurl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/transport/http/sender/libcurl/axis2_libcurl.c')
-rw-r--r--src/core/transport/http/sender/libcurl/axis2_libcurl.c1169
1 files changed, 1169 insertions, 0 deletions
diff --git a/src/core/transport/http/sender/libcurl/axis2_libcurl.c b/src/core/transport/http/sender/libcurl/axis2_libcurl.c
new file mode 100644
index 0000000..834e69b
--- /dev/null
+++ b/src/core/transport/http/sender/libcurl/axis2_libcurl.c
@@ -0,0 +1,1169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef AXIS2_LIBCURL_ENABLED
+
+#include "axis2_libcurl.h"
+#include <axiom_soap.h>
+#include <axutil_string.h>
+#include <axis2_http_transport.h>
+#include <axiom_output.h>
+#include <axis2_op_ctx.h>
+#include <axis2_ctx.h>
+#include <axis2_conf_ctx.h>
+#include <axis2_http_client.h>
+#include <axiom_xml_writer.h>
+#include <axutil_property.h>
+#include <axutil_param.h>
+#include <axutil_types.h>
+#include <axutil_generic_obj.h>
+#include <axis2_const.h>
+#include <axis2_util.h>
+#include <stdlib.h>
+#include <axis2_http_sender.h>
+#include <axis2_http_transport.h>
+#include "libcurl_stream.h"
+
+static int ref = 0;
+
+struct axis2_libcurl
+{
+ axis2_char_t *memory;
+ axutil_array_list_t *alist;
+ unsigned int size;
+ const axutil_env_t *env;
+ char errorbuffer[CURL_ERROR_SIZE];
+ CURL *handler;
+ axis2_bool_t cookies;
+};
+
+static size_t
+axis2_libcurl_write_memory_callback(
+ void *ptr,
+ size_t size,
+ size_t nmemb,
+ void *data);
+
+static size_t
+axis2_libcurl_header_callback(
+ void *ptr,
+ size_t size,
+ size_t nmemb,
+ void *data);
+
+static axis2_char_t *
+axis2_libcurl_get_content_type(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env);
+
+static int
+axis2_libcurl_get_content_length(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env);
+
+static axis2_http_header_t *
+axis2_libcurl_get_first_header(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env,
+ const axis2_char_t * str);
+
+static void
+axis2_libcurl_free_headers(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env);
+
+static axis2_status_t
+axis2_libcurl_set_options(
+ CURL *handler,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx);
+
+axis2_status_t AXIS2_CALL
+axis2_libcurl_send(
+ axis2_libcurl_t *data,
+ axiom_output_t * om_output,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx,
+ axiom_soap_envelope_t * out,
+ const axis2_char_t * str_url,
+ const axis2_char_t * soap_action)
+{
+ struct curl_slist *headers = NULL;
+ axiom_soap_body_t *soap_body;
+ axis2_bool_t is_soap = AXIS2_TRUE;
+ axis2_bool_t send_via_get = AXIS2_FALSE;
+ axis2_bool_t send_via_head = AXIS2_FALSE;
+ axis2_bool_t send_via_put = AXIS2_FALSE;
+ axis2_bool_t send_via_delete = AXIS2_FALSE;
+ axis2_bool_t doing_mtom = AXIS2_FALSE;
+ axiom_node_t *body_node = NULL;
+ axiom_node_t *data_out = NULL;
+ axutil_property_t *method = NULL;
+ axis2_char_t *method_value = NULL;
+ axiom_xml_writer_t *xml_writer = NULL;
+ axis2_char_t *buffer = NULL;
+ unsigned int buffer_size = 0;
+ int content_length = -1;
+ axis2_char_t *content_type = NULL;
+ axis2_char_t *content_len = AXIS2_HTTP_HEADER_CONTENT_LENGTH_;
+ const axis2_char_t *char_set_enc = NULL;
+ axis2_char_t *content = AXIS2_HTTP_HEADER_CONTENT_TYPE_;
+ axis2_char_t *soap_action_header = AXIS2_HTTP_HEADER_SOAP_ACTION_;
+ axutil_stream_t *in_stream;
+ axutil_property_t *trans_in_property;
+ axutil_string_t *char_set_enc_str;
+ axis2_byte_t *output_stream = NULL;
+ int output_stream_size = 0;
+ CURL *handler;
+ axis2_conf_ctx_t *conf_ctx = NULL;
+ axis2_conf_t *conf = NULL;
+ axis2_transport_out_desc_t *trans_desc = NULL;
+ axutil_param_t *write_xml_declaration_param = NULL;
+ axutil_hash_t *transport_attrs = NULL;
+ axis2_bool_t write_xml_declaration = AXIS2_FALSE;
+ axutil_property_t *property;
+ int *response_length = NULL;
+ axis2_http_status_line_t *status_line = NULL;
+ axis2_char_t *status_line_str = NULL;
+ axis2_char_t *tmp_strcat = NULL;
+ int status_code = 0;
+
+ AXIS2_PARAM_CHECK(env->error, data, AXIS2_FAILURE);
+ AXIS2_PARAM_CHECK(env->error, data->handler, AXIS2_FAILURE);
+
+ handler = data->handler;
+ curl_easy_reset(handler);
+ curl_easy_setopt(handler, CURLOPT_ERRORBUFFER, &data->errorbuffer);
+ headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_USER_AGENT_AXIS2C);
+ headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_ACCEPT_);
+ headers = curl_slist_append(headers, AXIS2_HTTP_HEADER_EXPECT_);
+
+ if(AXIS2_FAILURE == axis2_libcurl_set_options(handler, env, msg_ctx))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[axis2libcurl]Setting options in Libcurl failed");
+ return AXIS2_FAILURE;
+ }
+
+ if (AXIS2_TRUE == axis2_msg_ctx_get_doing_rest(msg_ctx, env))
+ {
+ is_soap = AXIS2_FALSE;
+ }
+ else
+ {
+ is_soap = AXIS2_TRUE;
+ }
+
+ if (!is_soap)
+ {
+ soap_body = axiom_soap_envelope_get_body(out, env);
+ if (!soap_body)
+ {
+ AXIS2_HANDLE_ERROR(env,
+ AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL,
+ AXIS2_FAILURE);
+ return AXIS2_FAILURE;
+ }
+
+ body_node = axiom_soap_body_get_base_node(soap_body, env);
+ if (!body_node)
+ {
+ AXIS2_HANDLE_ERROR(env,
+ AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL,
+ AXIS2_FAILURE);
+
+ return AXIS2_FAILURE;
+ }
+ data_out = axiom_node_get_first_element(body_node, env);
+
+ method = (axutil_property_t *) axis2_msg_ctx_get_property(msg_ctx, env,
+ AXIS2_HTTP_METHOD);
+
+ if (method)
+ {
+ method_value =
+ (axis2_char_t *) axutil_property_get_value(method, env);
+ }
+
+ /* The default is POST */
+ if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_GET))
+ {
+ send_via_get = AXIS2_TRUE;
+ }
+ else if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_HEAD))
+ {
+ send_via_head = AXIS2_TRUE;
+ }
+ else if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_PUT))
+ {
+ send_via_put = AXIS2_TRUE;
+ }
+ else if (method_value && 0 == axutil_strcmp(method_value, AXIS2_HTTP_DELETE))
+ {
+ send_via_delete = AXIS2_TRUE;
+ }
+ }
+
+ conf_ctx = axis2_msg_ctx_get_conf_ctx (msg_ctx, env);
+ if (conf_ctx)
+ {
+ conf = axis2_conf_ctx_get_conf (conf_ctx, env);
+ }
+
+ if (conf)
+ {
+ trans_desc = axis2_conf_get_transport_out (conf,
+ env, AXIS2_TRANSPORT_ENUM_HTTP);
+ }
+
+ if (trans_desc)
+ {
+ write_xml_declaration_param =
+ axutil_param_container_get_param
+ (axis2_transport_out_desc_param_container (trans_desc, env), env,
+ AXIS2_XML_DECLARATION);
+ }
+
+ if (write_xml_declaration_param)
+ {
+ transport_attrs =
+ axutil_param_get_attributes (write_xml_declaration_param, env);
+ if (transport_attrs)
+ {
+ axutil_generic_obj_t *obj = NULL;
+ axiom_attribute_t *write_xml_declaration_attr = NULL;
+ axis2_char_t *write_xml_declaration_attr_value = NULL;
+
+ obj = axutil_hash_get (transport_attrs, AXIS2_ADD_XML_DECLARATION,
+ AXIS2_HASH_KEY_STRING);
+ if (obj)
+ {
+ write_xml_declaration_attr = (axiom_attribute_t *)
+ axutil_generic_obj_get_value (obj,
+ env);
+ }
+ if (write_xml_declaration_attr)
+ {
+ write_xml_declaration_attr_value =
+ axiom_attribute_get_value (write_xml_declaration_attr, env);
+ }
+ if (write_xml_declaration_attr_value &&
+ 0 == axutil_strcasecmp (write_xml_declaration_attr_value,
+ AXIS2_VALUE_TRUE))
+ {
+ write_xml_declaration = AXIS2_TRUE;
+ }
+ }
+ }
+
+ if (write_xml_declaration)
+ {
+ axiom_output_write_xml_version_encoding (om_output, env);
+ }
+
+ if (!send_via_get && !send_via_head && !send_via_delete)
+ {
+ xml_writer = axiom_output_get_xml_writer(om_output, env);
+
+ char_set_enc_str = axis2_msg_ctx_get_charset_encoding(msg_ctx, env);
+
+ if (!char_set_enc_str)
+ {
+ char_set_enc = AXIS2_DEFAULT_CHAR_SET_ENCODING;
+ }
+ else
+ {
+ char_set_enc = axutil_string_get_buffer(char_set_enc_str, env);
+ }
+
+ if (!send_via_put && is_soap)
+ {
+ doing_mtom = axis2_msg_ctx_get_doing_mtom(msg_ctx, env);
+
+ axiom_output_set_do_optimize(om_output, env, doing_mtom);
+ axiom_soap_envelope_serialize(out, env, om_output, AXIS2_FALSE);
+ if (AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env))
+ {
+ if (AXIS2_ESC_DOUBLE_QUOTE != *soap_action)
+ {
+ axis2_char_t *tmp_soap_action = NULL;
+ tmp_soap_action =
+ AXIS2_MALLOC(env->allocator,
+ (axutil_strlen(soap_action) +
+ 5) * sizeof(axis2_char_t));
+ sprintf(tmp_soap_action, "\"%s\"", soap_action);
+ tmp_strcat = axutil_stracat(env, soap_action_header,tmp_soap_action);
+ headers = curl_slist_append(headers, tmp_strcat);
+ AXIS2_FREE(env->allocator, tmp_strcat);
+ AXIS2_FREE(env->allocator, tmp_soap_action);
+ }
+ else
+ {
+ tmp_strcat = axutil_stracat(env, soap_action_header, soap_action);
+ headers = curl_slist_append(headers, tmp_strcat );
+ AXIS2_FREE(env->allocator, tmp_strcat);
+ }
+ }
+
+ if (doing_mtom)
+ {
+ /*axiom_output_flush(om_output, env, &output_stream,
+ &output_stream_size);*/
+ axiom_output_flush(om_output, env);
+ content_type =
+ (axis2_char_t *) axiom_output_get_content_type(om_output,
+ env);
+ if (AXIS2_TRUE != axis2_msg_ctx_get_is_soap_11(msg_ctx, env))
+ {
+ if (axutil_strcmp(soap_action, ""))
+ {
+ /* handle SOAP action for SOAP 1.2 case */
+ axis2_char_t *temp_content_type = NULL;
+ temp_content_type = axutil_stracat (env,
+ content_type,
+ AXIS2_CONTENT_TYPE_ACTION);
+ content_type = temp_content_type;
+ temp_content_type = axutil_stracat (env,
+ content_type,
+ soap_action);
+ AXIS2_FREE (env->allocator, content_type);
+ content_type = temp_content_type;
+ temp_content_type =
+ axutil_stracat (env, content_type,
+ AXIS2_ESC_DOUBLE_QUOTE_STR);
+ AXIS2_FREE (env->allocator, content_type);
+ content_type = temp_content_type;
+ }
+ }
+ }
+ else if (AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env))
+ {
+ axis2_char_t *temp_content_type = NULL;
+ content_type =
+ (axis2_char_t *) AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML;
+ content_type = axutil_stracat(env, content_type,
+ AXIS2_CONTENT_TYPE_CHARSET);
+ temp_content_type =
+ axutil_stracat(env, content_type, char_set_enc);
+ AXIS2_FREE(env->allocator, content_type);
+ content_type = temp_content_type;
+ }
+ else
+ {
+ axis2_char_t *temp_content_type = NULL;
+ content_type =
+ (axis2_char_t *) AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP;
+ content_type = axutil_stracat(env, content_type,
+ AXIS2_CONTENT_TYPE_CHARSET);
+ temp_content_type =
+ axutil_stracat(env, content_type, char_set_enc);
+ AXIS2_FREE(env->allocator, content_type);
+ content_type = temp_content_type;
+ if (axutil_strcmp(soap_action, ""))
+ {
+ temp_content_type =
+ axutil_stracat(env, content_type,
+ AXIS2_CONTENT_TYPE_ACTION);
+ AXIS2_FREE(env->allocator, content_type);
+ content_type = temp_content_type;
+ temp_content_type =
+ axutil_stracat(env, content_type, soap_action);
+ AXIS2_FREE(env->allocator, content_type);
+ content_type = temp_content_type;
+ }
+ temp_content_type = axutil_stracat(env, content_type,
+ AXIS2_SEMI_COLON_STR);
+ AXIS2_FREE(env->allocator, content_type);
+ content_type = temp_content_type;
+ }
+ }
+ else if (is_soap)
+ {
+ AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, "Attempt to send SOAP"
+ "message using HTTP PUT failed");
+ return AXIS2_FAILURE;
+ }
+ else
+ {
+ axutil_property_t *content_type_property = NULL;
+ axutil_hash_t *content_type_hash = NULL;
+ axis2_char_t *content_type_value = NULL;
+
+ axiom_node_serialize(data_out, env, om_output);
+ content_type_property =
+ (axutil_property_t *)
+ axis2_msg_ctx_get_property(msg_ctx, env,
+ AXIS2_USER_DEFINED_HTTP_HEADER_CONTENT_TYPE);
+
+ if (content_type_property)
+ {
+ content_type_hash =
+ (axutil_hash_t *)
+ axutil_property_get_value(content_type_property, env);
+
+ if (content_type_hash)
+ {
+ content_type_value =
+ (char *) axutil_hash_get(content_type_hash,
+ AXIS2_HTTP_HEADER_CONTENT_TYPE,
+ AXIS2_HASH_KEY_STRING);
+ }
+ }
+
+ if (content_type_value)
+ {
+ content_type = content_type_value;
+ }
+ else
+ {
+ content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML;
+ }
+
+ }
+
+ buffer = axiom_xml_writer_get_xml(xml_writer, env);
+ if (!doing_mtom)
+ {
+ buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env);
+ }
+ else
+ buffer_size = output_stream_size;
+ {
+ char tmp_buf[10];
+ sprintf(tmp_buf, "%d", buffer_size);
+ tmp_strcat = axutil_stracat(env, content_len, tmp_buf);
+ headers = curl_slist_append(headers, tmp_strcat);
+ AXIS2_FREE(env->allocator, tmp_strcat);
+ tmp_strcat = NULL;
+
+ tmp_strcat = axutil_stracat(env, content, content_type);
+ headers = curl_slist_append(headers, tmp_strcat);
+ AXIS2_FREE(env->allocator, tmp_strcat);
+ tmp_strcat = NULL;
+ }
+
+ if (!doing_mtom)
+ {
+ curl_easy_setopt(handler, CURLOPT_POSTFIELDSIZE, buffer_size);
+ curl_easy_setopt(handler, CURLOPT_POSTFIELDS, buffer);
+ }
+ else
+ {
+ curl_easy_setopt(handler, CURLOPT_POSTFIELDSIZE,
+ output_stream_size);
+ curl_easy_setopt(handler, CURLOPT_POSTFIELDS, output_stream);
+ }
+
+ if (send_via_put)
+ {
+ curl_easy_setopt(handler, CURLOPT_CUSTOMREQUEST, AXIS2_HTTP_PUT);
+ }
+ curl_easy_setopt(handler, CURLOPT_URL, str_url);
+ }
+ else
+ {
+ axis2_char_t *request_param;
+ axis2_char_t *url_encode;
+ request_param =
+ (axis2_char_t *) axis2_http_sender_get_param_string(NULL, env,
+ msg_ctx);
+ url_encode = axutil_strcat(env, str_url, AXIS2_Q_MARK_STR,
+ request_param, NULL);
+ if (send_via_get)
+ {
+ curl_easy_setopt(handler, CURLOPT_HTTPGET, 1);
+ }
+ else if (send_via_head)
+ {
+ curl_easy_setopt(handler, CURLOPT_NOBODY, 1);
+ }
+ else if (send_via_delete)
+ {
+ curl_easy_setopt(handler, CURLOPT_CUSTOMREQUEST, AXIS2_HTTP_DELETE);
+ }
+ curl_easy_setopt(handler, CURLOPT_URL, url_encode);
+ }
+
+ {
+ axis2_bool_t manage_session;
+ manage_session = axis2_msg_ctx_get_manage_session(msg_ctx, env);
+ if (manage_session == AXIS2_TRUE)
+ {
+ if (data->cookies == AXIS2_FALSE)
+ {
+ /* Ensure cookies enabled to manage session */
+ /* Pass empty cookie string to enable cookies */
+ curl_easy_setopt(handler, CURLOPT_COOKIEFILE, " ");
+ data->cookies = AXIS2_TRUE;
+ }
+ }
+ else if (data->cookies == AXIS2_TRUE)
+ {
+ /* Pass special string ALL to reset cookies if any have been enabled. */
+ /* If cookies have ever been enabled, we reset every time as long as
+ manage_session is false, as there is no clear curl option to
+ turn off the cookie engine once enabled. */
+ curl_easy_setopt(handler, CURLOPT_COOKIELIST, AXIS2_ALL);
+ }
+ }
+
+ curl_easy_setopt(handler, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(handler, CURLOPT_WRITEFUNCTION,
+ axis2_libcurl_write_memory_callback);
+ curl_easy_setopt(handler, CURLOPT_WRITEDATA, data);
+
+ curl_easy_setopt (handler, CURLOPT_HEADERFUNCTION, axis2_libcurl_header_callback);
+
+ curl_easy_setopt (handler, CURLOPT_WRITEHEADER, data);
+
+ /* Free response data from previous request */
+ if( data->size )
+ {
+ if (data->memory)
+ {
+ AXIS2_FREE(data->env->allocator, data->memory);
+ }
+ data->size = 0;
+ }
+
+ if (curl_easy_perform(handler))
+ {
+ AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, "%s", &data->errorbuffer);
+ AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR,
+ AXIS2_FAILURE);
+ return AXIS2_FAILURE;
+ }
+
+ in_stream = axutil_stream_create_libcurl(env, data->memory, data->size);
+ trans_in_property = axutil_property_create(env);
+ axutil_property_set_scope(trans_in_property, env, AXIS2_SCOPE_REQUEST);
+ axutil_property_set_free_func(trans_in_property, env,
+ libcurl_stream_free);
+ axutil_property_set_value(trans_in_property, env, in_stream);
+ axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN,
+ trans_in_property);
+
+ if (axutil_array_list_size(data->alist, env) > 0)
+ {
+ status_line_str = axutil_array_list_get(data->alist, env, 0);
+ if (status_line_str)
+ {
+ status_line = axis2_http_status_line_create(env, status_line_str);
+ }
+ }
+
+ if (status_line)
+ {
+ status_code = axis2_http_status_line_get_status_code(status_line, env);
+ }
+
+ axis2_msg_ctx_set_status_code (msg_ctx, env, status_code);
+ AXIS2_FREE(data->env->allocator, content_type);
+ content_type = axis2_libcurl_get_content_type(data, env);
+
+ if (content_type)
+ {
+ if (strstr (content_type, AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED)
+ && strstr (content_type, AXIS2_HTTP_HEADER_ACCEPT_XOP_XML))
+ {
+ axis2_ctx_t *axis_ctx =
+ axis2_op_ctx_get_base (axis2_msg_ctx_get_op_ctx (msg_ctx, env),
+ env);
+ property = axutil_property_create (env);
+ axutil_property_set_scope (property, env, AXIS2_SCOPE_REQUEST);
+ axutil_property_set_value (property,
+ env, axutil_strdup (env, content_type));
+ axis2_ctx_set_property (axis_ctx,
+ env, MTOM_RECIVED_CONTENT_TYPE, property);
+ }
+ }
+
+ content_length = axis2_libcurl_get_content_length(data, env);
+ if (content_length >= 0)
+ {
+ response_length = AXIS2_MALLOC (env->allocator, sizeof (int));
+ memcpy (response_length, &content_length, sizeof (int));
+ property = axutil_property_create (env);
+ axutil_property_set_scope (property, env, AXIS2_SCOPE_REQUEST);
+ axutil_property_set_value (property, env, response_length);
+ axis2_msg_ctx_set_property (msg_ctx, env,
+ AXIS2_HTTP_HEADER_CONTENT_LENGTH, property);
+ }
+
+ curl_slist_free_all (headers);
+ /* release the read http headers. */
+ /* (commenting out the call below is a clever way to force a premature EOF
+ condition in subsequent messages, as they will be read using the content-length
+ of the first message.) */
+ axis2_libcurl_free_headers(data, env);
+ AXIS2_FREE(data->env->allocator, content_type);
+ axis2_http_status_line_free( status_line, env);
+
+ return AXIS2_SUCCESS;
+}
+
+static size_t
+axis2_libcurl_write_memory_callback(
+ void *ptr,
+ size_t size,
+ size_t nmemb,
+ void *data)
+{
+ size_t realsize = size * nmemb;
+ axis2_libcurl_t *curl = (axis2_libcurl_t *) data;
+ axis2_char_t *buffer =
+ (axis2_char_t *) AXIS2_MALLOC(curl->env->allocator,
+ curl->size + realsize + 1);
+ if (buffer)
+ {
+ if (curl->size)
+ {
+ memcpy(&(buffer[0]), curl->memory, curl->size);
+ AXIS2_FREE(curl->env->allocator, curl->memory);
+ }
+
+ memcpy(&(buffer[curl->size]), ptr, realsize);
+ curl->size += (int)realsize;
+ /* We are sure that the difference lies within the int range */
+ buffer[curl->size] = 0;
+ curl->memory = buffer;
+ }
+ return realsize;
+}
+
+static size_t
+axis2_libcurl_header_callback(
+ void *ptr,
+ size_t size,
+ size_t nmemb,
+ void *data)
+{
+ axis2_char_t *memory;
+ size_t realsize = size * nmemb;
+ axis2_libcurl_t *curl = (axis2_libcurl_t *) data;
+ memory = (axis2_char_t *)AXIS2_MALLOC(curl->env->allocator, realsize + 1);
+ if (memory)
+ {
+ memcpy(&(memory[0]), ptr, realsize);
+ memory[realsize] = 0;
+ axutil_array_list_add(curl->alist, curl->env, memory);
+ }
+ return realsize;
+}
+
+axis2_libcurl_t * AXIS2_CALL
+axis2_libcurl_create(
+ const axutil_env_t * env)
+{
+ axis2_libcurl_t *curl = NULL;
+ CURLcode code;
+
+ if (!ref)
+ {
+ /* curl_global_init is not thread-safe so it would be better
+ to do this, as well as the test and increment of ref, under
+ mutex if one is available, or as part of an
+ axis2_initialize() if a global initialize is created.
+ Otherwise the client application should perform the the
+ curl_global_init itself in a thread-safe fashion.
+ */
+ code = curl_global_init(CURL_GLOBAL_ALL);
+ if (code)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "libcurl curl_global_init failed, error: %d", code);
+ return NULL;
+ }
+ ref++;
+ }
+
+ curl =
+ (axis2_libcurl_t *) AXIS2_MALLOC(env->allocator,
+ sizeof(axis2_libcurl_t));
+ if (curl)
+ {
+ curl->memory = 0;
+ curl->size = 0;
+ curl->alist = axutil_array_list_create(env, 15);
+ curl->env = env;
+ curl->handler = curl_easy_init();
+ curl->cookies = AXIS2_FALSE;
+ if ((!curl->alist) || (!curl->handler))
+ {
+ axis2_libcurl_free(curl, env);
+ curl = 0;
+ }
+ }
+ return curl;
+}
+
+void AXIS2_CALL
+axis2_libcurl_free(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env)
+{
+ if (!curl)
+ {
+ return;
+ }
+
+ if (curl->handler)
+ {
+ curl_easy_cleanup (curl->handler);
+ }
+ if (curl->alist)
+ {
+ axis2_libcurl_free_headers(curl, env);
+ axutil_array_list_free(curl->alist, env);
+ curl->alist = NULL;
+ }
+ if (curl->memory)
+ {
+ AXIS2_FREE(env->allocator, curl->memory);
+ }
+
+ AXIS2_FREE(env->allocator, curl);
+}
+
+static void
+axis2_libcurl_free_headers(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env)
+{
+ int count = 0;
+ axutil_array_list_t *header_group = curl->alist;
+ if (header_group)
+ {
+ while ((count = axutil_array_list_size(header_group, env)) > 0)
+ {
+ axis2_char_t *header = axutil_array_list_remove(header_group, env, count-1);
+ AXIS2_FREE(env->allocator, header);
+ }
+ }
+}
+
+static axis2_http_header_t *
+axis2_libcurl_get_first_header(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env,
+ const axis2_char_t * str)
+{
+ axis2_http_header_t *tmp_header = NULL;
+ axis2_char_t *tmp_header_str = NULL;
+ axis2_char_t *tmp_name = NULL;
+ int i = 0;
+ int count = 0;
+ axutil_array_list_t *header_group = NULL;
+
+ AXIS2_PARAM_CHECK(env->error, curl, NULL);
+ AXIS2_PARAM_CHECK(env->error, str, NULL);
+
+ header_group = curl->alist;
+ if (!header_group)
+ {
+ return NULL;
+ }
+
+ if (0 == axutil_array_list_size(header_group, env))
+ {
+ return NULL;
+ }
+
+ count = axutil_array_list_size(header_group, env);
+
+ for (i = 0; i < count; i++)
+ {
+ tmp_header_str = (axis2_char_t *) axutil_array_list_get(header_group,
+ env, i);
+ if(!tmp_header_str)
+ {
+ continue;
+ }
+ tmp_header = (axis2_http_header_t *) axis2_http_header_create_by_str(env, tmp_header_str);
+ if(!tmp_header)
+ {
+ continue;
+ }
+
+ tmp_name = axis2_http_header_get_name(tmp_header, env);
+ if (0 == axutil_strcasecmp(str, tmp_name))
+ {
+ return tmp_header;
+ }
+ else
+ {
+ axis2_http_header_free( tmp_header, env );
+ }
+
+ }
+ return NULL;
+}
+
+static int
+axis2_libcurl_get_content_length(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env)
+{
+ axis2_http_header_t *tmp_header;
+ int rtn_value = -1;
+
+ tmp_header = axis2_libcurl_get_first_header
+ (curl, env, AXIS2_HTTP_HEADER_CONTENT_LENGTH);
+ if (tmp_header)
+ {
+ rtn_value = AXIS2_ATOI(axis2_http_header_get_value(tmp_header, env));
+ axis2_http_header_free( tmp_header, env );
+ }
+ return rtn_value;
+}
+
+static axis2_char_t *
+axis2_libcurl_get_content_type(
+ axis2_libcurl_t *curl,
+ const axutil_env_t * env)
+{
+ axis2_http_header_t *tmp_header;
+ axis2_char_t *rtn_value = NULL;
+
+ tmp_header = axis2_libcurl_get_first_header
+ (curl, env, AXIS2_HTTP_HEADER_CONTENT_TYPE);
+ if (tmp_header)
+ {
+ rtn_value = axutil_strdup (env, axis2_http_header_get_value(tmp_header, env) );
+ axis2_http_header_free( tmp_header, env );
+ }
+ else
+ {
+ rtn_value = axutil_strdup (env, AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN);
+ }
+
+ return rtn_value;
+}
+
+/**
+ * axis2_libcurl_set_auth_options maps authentication AXIS2/C options to
+ * libcURL options.
+ *
+ * CURLOPT_USERPWD - char * user:password for authentication
+ * CURLOPT_HTTPAUTH - long bitmask which authentication methods to use
+ */
+static axis2_status_t
+axis2_libcurl_set_auth_options(
+ CURL *handler,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx)
+{
+ axutil_property_t *property = NULL;
+ axis2_char_t *uname = NULL;
+ axis2_char_t *passwd = NULL;
+ axis2_char_t *auth_type = NULL;
+
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_UNAME);
+ if (property)
+ {
+ uname = (axis2_char_t *) axutil_property_get_value(property, env);
+ }
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_PASSWD);
+ if (property)
+ {
+ passwd = (axis2_char_t *) axutil_property_get_value(property, env);
+ }
+ if (uname && passwd)
+ {
+ axis2_char_t buffer[256];
+ strncpy(buffer, uname, 256);
+ strncat(buffer, ":", 256);
+ strncat(buffer, passwd, 256);
+ curl_easy_setopt(handler, CURLOPT_USERPWD, buffer);
+ }
+
+ property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_TYPE);
+
+ if (property)
+ {
+ auth_type = (axis2_char_t *) axutil_property_get_value(property, env);
+ }
+
+ if (auth_type && 0 == axutil_strcmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC))
+ {
+ curl_easy_setopt(handler, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+ }
+ else
+ {
+ /* Uses anonymous connection.*/
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+/**
+ * axis2_libcurl_set_proxy_options maps proxy AXIS2/C options to
+ * libcURL options.
+ *
+ * CURLOPT_PROXY - char * proxy hostname
+ * CURLOPT_PROXYPORT - long proxy listen port
+ * CURLOPT_PROXYUSERPWD - char * user:password to authenticate to proxy
+ *
+ * TODO:
+ * CURLOPT_PROXYTYPE - long enum type of proxy (HTTP, SOCKS)
+ * CURLOPT_PROXYAUTH - long bitmask which authentication methods to use for proxy
+ */
+static axis2_status_t
+axis2_libcurl_set_proxy_options(
+ CURL *handler,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx)
+{
+ axis2_conf_ctx_t *conf_ctx = NULL;
+ axis2_conf_t *conf = NULL;
+ axis2_transport_out_desc_t *trans_desc = NULL;
+ axutil_param_t *proxy_param = NULL;
+ axutil_hash_t *transport_attrs = NULL;
+ axutil_property_t *property = NULL;
+ axis2_char_t *uname = NULL;
+ axis2_char_t *passwd = NULL;
+ axis2_char_t *proxy_host = NULL;
+ axis2_char_t *proxy_port = NULL;
+
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_UNAME);
+ if (property)
+ {
+ uname = (axis2_char_t *) axutil_property_get_value(property, env);
+ }
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_PASSWD);
+ if (property)
+ {
+ passwd = (axis2_char_t *) axutil_property_get_value(property, env);
+ }
+
+ conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env);
+ if (conf_ctx)
+ {
+ conf = axis2_conf_ctx_get_conf(conf_ctx, env);
+ if (conf)
+ {
+ trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP);
+ }
+ }
+ if (trans_desc)
+ {
+ proxy_param = axutil_param_container_get_param(
+ axis2_transport_out_desc_param_container(trans_desc, env), env, AXIS2_HTTP_PROXY_API);
+ if (!proxy_param)
+ {
+ proxy_param = axutil_param_container_get_param(
+ axis2_transport_out_desc_param_container(trans_desc, env), env, AXIS2_HTTP_PROXY);
+ }
+ if (proxy_param)
+ {
+ transport_attrs = axutil_param_get_attributes(proxy_param, env);
+ }
+ }
+
+ if (transport_attrs)
+ {
+ axutil_generic_obj_t *obj = NULL;
+ axiom_attribute_t *attr = NULL;
+
+ if (!uname || !passwd)
+ {
+ obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_USERNAME, AXIS2_HASH_KEY_STRING);
+ if (obj)
+ {
+ attr = (axiom_attribute_t *) axutil_generic_obj_get_value(obj, env);
+ }
+ if (attr)
+ {
+ uname = axiom_attribute_get_value(attr, env);
+ }
+
+ attr = NULL;
+ obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PASSWORD, AXIS2_HASH_KEY_STRING);
+ if (obj)
+ {
+ attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env);
+ }
+ if (attr)
+ {
+ passwd = axiom_attribute_get_value(attr, env);
+ }
+ }
+
+ obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_HOST, AXIS2_HASH_KEY_STRING);
+ if (obj)
+ {
+ attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env);
+ }
+ if (attr)
+ {
+ proxy_host = axiom_attribute_get_value(attr, env);
+ }
+ if (proxy_host)
+ {
+ curl_easy_setopt(handler, CURLOPT_PROXY, proxy_host);
+ }
+
+ attr = NULL;
+ obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PORT, AXIS2_HASH_KEY_STRING);
+ if (obj)
+ {
+ attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env);
+ }
+ if (attr)
+ {
+ proxy_port = axiom_attribute_get_value(attr, env);
+ }
+ if (proxy_port)
+ {
+ curl_easy_setopt(handler, CURLOPT_PROXYPORT, AXIS2_ATOI(proxy_port));
+ }
+ }
+ if (uname && passwd)
+ {
+ axis2_char_t buffer[256];
+ strncpy(buffer, uname, 256);
+ strncat(buffer, ":", 256);
+ strncat(buffer, passwd, 256);
+ curl_easy_setopt(handler, CURLOPT_PROXYUSERPWD, buffer);
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+/**
+ * axis2_libcurl_set_ssl_options maps SSL AXIS2/C options to
+ * libcURL options.
+ *
+ * CURLOPT_SSL_VERIFYHOST - long enum whether to verify the server identity
+ * CURLOPT_SSL_VERIFYPEER - long boolean whether to verify the server certificate
+ */
+static axis2_status_t
+axis2_libcurl_set_ssl_options(
+ CURL *handler,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx)
+{
+ axutil_property_t *property = NULL;
+ axis2_char_t *verify_peer = NULL;
+ axis2_char_t *verify_host = NULL;
+
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_VERIFY_PEER);
+ if (property)
+ {
+ verify_peer = (axis2_char_t *)axutil_property_get_value(property, env);
+ }
+ if (verify_peer)
+ {
+ if (0 == axutil_strcasecmp(verify_peer, AXIS2_VALUE_TRUE))
+ {
+ curl_easy_setopt(handler, CURLOPT_SSL_VERIFYPEER, 1);
+ }
+ else
+ {
+ curl_easy_setopt(handler, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+ }
+
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_VERIFY_HOST);
+ if (property)
+ {
+ verify_host = (axis2_char_t *)axutil_property_get_value(property, env);
+ }
+ if (verify_host)
+ {
+ curl_easy_setopt(handler, CURLOPT_SSL_VERIFYHOST, AXIS2_ATOI(verify_host));
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+/**
+ * axis2_libcurl_set_connection_options maps connection AXIS2/C options to
+ * libcURL options.
+ * CURLOPT_CONNECTTIMEOUT_MS - long connection timeout in milliseconds
+ * CURLOPT_TIMEOUT_MS - long transfer timeout in milliseconds
+ */
+static axis2_status_t
+axis2_libcurl_set_connection_options(
+ CURL *handler,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx)
+{
+ axutil_property_t *property = NULL;
+ long long_property_value = 0;
+
+ /* check if timeout has been set by user using options
+ * with axis2_options_set_timeout_in_milli_seconds
+ */
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_CONNECTION_TIMEOUT);
+ if (property)
+ {
+ axis2_char_t *value = axutil_property_get_value(property, env);
+ if (value)
+ {
+ long_property_value = AXIS2_ATOI(value);
+ curl_easy_setopt(handler, CURLOPT_CONNECTTIMEOUT_MS, long_property_value);
+ }
+ }
+
+ property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_SO_TIMEOUT);
+ if (property)
+ {
+ axis2_char_t *value = axutil_property_get_value(property, env);
+ if (value)
+ {
+ long_property_value = AXIS2_ATOI(value);
+ curl_easy_setopt(handler, CURLOPT_TIMEOUT_MS, long_property_value);
+ }
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+/**
+ * axis2_libcurl_set_options maps the AXIS2/C options to libcURL options.
+ */
+static axis2_status_t
+axis2_libcurl_set_options(
+ CURL *handler,
+ const axutil_env_t * env,
+ axis2_msg_ctx_t * msg_ctx)
+{
+ if (axis2_libcurl_set_auth_options(handler, env, msg_ctx) != AXIS2_SUCCESS)
+ {
+ return AXIS2_FAILURE;
+ }
+
+ if (axis2_libcurl_set_proxy_options(handler, env, msg_ctx) != AXIS2_SUCCESS)
+ {
+ return AXIS2_FAILURE;
+ }
+
+ if (axis2_libcurl_set_ssl_options(handler, env, msg_ctx) != AXIS2_SUCCESS)
+ {
+ return AXIS2_FAILURE;
+ }
+
+ if (axis2_libcurl_set_connection_options(handler, env, msg_ctx) != AXIS2_SUCCESS)
+ {
+ return AXIS2_FAILURE;
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+
+#endif /* AXIS2_LIBCURL_ENABLED */
+