/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; { /* * Curl calculates the content-length automatically. * This commented section is not only unnecessary, * it interferes with authentication. * * NTLM, for example, will send an empty request * first (no body) to get the auth challenge * before resending with actual content. */ /*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 */