From 0425aadc78680e53000fd0108b540d6eca048516 Mon Sep 17 00:00:00 2001 From: gmcdonald Date: Sat, 13 Feb 2010 01:32:03 +0000 Subject: Moving axis svn, part of TLP move INFRA-2441 git-svn-id: http://svn.apache.org/repos/asf/axis/axis2/c/core/trunk@909681 13f79535-47bb-0310-9956-ffa450edef68 --- src/core/transport/http/Makefile.am | 1 + src/core/transport/http/common/Makefile.am | 29 + .../transport/http/common/http_accept_record.c | 165 + src/core/transport/http/common/http_header.c | 168 + .../http/common/http_out_transport_info.c | 353 ++ src/core/transport/http/common/http_request_line.c | 227 ++ .../transport/http/common/http_response_writer.c | 176 + .../transport/http/common/http_simple_request.c | 433 +++ .../transport/http/common/http_simple_response.c | 615 ++++ src/core/transport/http/common/http_status_line.c | 267 ++ src/core/transport/http/common/http_worker.c | 2064 +++++++++++ .../transport/http/common/simple_http_svr_conn.c | 504 +++ src/core/transport/http/receiver/Makefile.am | 21 + src/core/transport/http/receiver/http_receiver.c | 508 +++ src/core/transport/http/receiver/http_svr_thread.c | 315 ++ src/core/transport/http/sender/Makefile.am | 51 + src/core/transport/http/sender/http_client.c | 965 +++++ src/core/transport/http/sender/http_sender.c | 3332 +++++++++++++++++ .../transport/http/sender/http_transport_sender.c | 859 +++++ src/core/transport/http/sender/libcurl/Makefile.am | 2 + .../transport/http/sender/libcurl/axis2_libcurl.c | 1169 ++++++ .../transport/http/sender/libcurl/axis2_libcurl.h | 53 + .../transport/http/sender/libcurl/libcurl_stream.c | 192 + .../transport/http/sender/libcurl/libcurl_stream.h | 51 + src/core/transport/http/sender/ssl/Makefile.am | 2 + src/core/transport/http/sender/ssl/ssl_stream.c | 239 ++ src/core/transport/http/sender/ssl/ssl_stream.h | 50 + src/core/transport/http/sender/ssl/ssl_utils.c | 227 ++ src/core/transport/http/sender/ssl/ssl_utils.h | 56 + src/core/transport/http/server/CGI/Makefile.am | 31 + .../transport/http/server/CGI/axis2_cgi_main.c | 280 ++ .../http/server/CGI/axis2_cgi_out_transport_info.c | 160 + .../http/server/CGI/axis2_cgi_out_transport_info.h | 62 + .../transport/http/server/CGI/axis2_cgi_stream.c | 164 + .../transport/http/server/CGI/axis2_cgi_stream.h | 44 + .../transport/http/server/CGI/axis2_cgi_types.h | 34 + src/core/transport/http/server/IIS/README | 61 + .../http/server/IIS/axis2_iis_constants.h | 51 + .../http/server/IIS/axis2_iis_out_transport_info.c | 153 + .../http/server/IIS/axis2_iis_out_transport_info.h | 61 + .../transport/http/server/IIS/axis2_iis_regedit.js | 84 + .../transport/http/server/IIS/axis2_iis_stream.c | 313 ++ .../transport/http/server/IIS/axis2_iis_stream.h | 45 + .../transport/http/server/IIS/axis2_iis_worker.c | 607 +++ .../transport/http/server/IIS/axis2_iis_worker.h | 62 + .../transport/http/server/IIS/axis2_isapi_plugin.c | 476 +++ .../IIS/iis_iaspi_plugin_51/axis2_isapi_51.c | 153 + src/core/transport/http/server/IIS/mod_axis2.def | 7 + src/core/transport/http/server/Makefile.am | 2 + src/core/transport/http/server/apache2/Makefile.am | 40 + .../server/apache2/apache2_out_transport_info.c | 191 + .../transport/http/server/apache2/apache2_stream.c | 292 ++ .../transport/http/server/apache2/apache2_stream.h | 46 + .../transport/http/server/apache2/apache2_worker.c | 1687 +++++++++ .../apache2/axis2_apache2_out_transport_info.h | 61 + .../http/server/apache2/axis2_apache2_worker.h | 78 + src/core/transport/http/server/apache2/mod_axis2.c | 844 +++++ .../http/server/simple_axis2_server/Makefile.am | 30 + .../server/simple_axis2_server/http_server_main.c | 310 ++ src/core/transport/http/util/Makefile.am | 14 + .../transport/http/util/http_transport_utils.c | 3885 ++++++++++++++++++++ 61 files changed, 23422 insertions(+) create mode 100644 src/core/transport/http/Makefile.am create mode 100644 src/core/transport/http/common/Makefile.am create mode 100644 src/core/transport/http/common/http_accept_record.c create mode 100644 src/core/transport/http/common/http_header.c create mode 100644 src/core/transport/http/common/http_out_transport_info.c create mode 100644 src/core/transport/http/common/http_request_line.c create mode 100644 src/core/transport/http/common/http_response_writer.c create mode 100644 src/core/transport/http/common/http_simple_request.c create mode 100644 src/core/transport/http/common/http_simple_response.c create mode 100644 src/core/transport/http/common/http_status_line.c create mode 100644 src/core/transport/http/common/http_worker.c create mode 100644 src/core/transport/http/common/simple_http_svr_conn.c create mode 100644 src/core/transport/http/receiver/Makefile.am create mode 100644 src/core/transport/http/receiver/http_receiver.c create mode 100644 src/core/transport/http/receiver/http_svr_thread.c create mode 100644 src/core/transport/http/sender/Makefile.am create mode 100644 src/core/transport/http/sender/http_client.c create mode 100644 src/core/transport/http/sender/http_sender.c create mode 100644 src/core/transport/http/sender/http_transport_sender.c create mode 100644 src/core/transport/http/sender/libcurl/Makefile.am create mode 100644 src/core/transport/http/sender/libcurl/axis2_libcurl.c create mode 100644 src/core/transport/http/sender/libcurl/axis2_libcurl.h create mode 100644 src/core/transport/http/sender/libcurl/libcurl_stream.c create mode 100644 src/core/transport/http/sender/libcurl/libcurl_stream.h create mode 100644 src/core/transport/http/sender/ssl/Makefile.am create mode 100644 src/core/transport/http/sender/ssl/ssl_stream.c create mode 100644 src/core/transport/http/sender/ssl/ssl_stream.h create mode 100644 src/core/transport/http/sender/ssl/ssl_utils.c create mode 100644 src/core/transport/http/sender/ssl/ssl_utils.h create mode 100644 src/core/transport/http/server/CGI/Makefile.am create mode 100644 src/core/transport/http/server/CGI/axis2_cgi_main.c create mode 100644 src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c create mode 100644 src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h create mode 100644 src/core/transport/http/server/CGI/axis2_cgi_stream.c create mode 100644 src/core/transport/http/server/CGI/axis2_cgi_stream.h create mode 100644 src/core/transport/http/server/CGI/axis2_cgi_types.h create mode 100644 src/core/transport/http/server/IIS/README create mode 100644 src/core/transport/http/server/IIS/axis2_iis_constants.h create mode 100644 src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c create mode 100644 src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h create mode 100644 src/core/transport/http/server/IIS/axis2_iis_regedit.js create mode 100644 src/core/transport/http/server/IIS/axis2_iis_stream.c create mode 100644 src/core/transport/http/server/IIS/axis2_iis_stream.h create mode 100644 src/core/transport/http/server/IIS/axis2_iis_worker.c create mode 100644 src/core/transport/http/server/IIS/axis2_iis_worker.h create mode 100644 src/core/transport/http/server/IIS/axis2_isapi_plugin.c create mode 100644 src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c create mode 100644 src/core/transport/http/server/IIS/mod_axis2.def create mode 100644 src/core/transport/http/server/Makefile.am create mode 100644 src/core/transport/http/server/apache2/Makefile.am create mode 100644 src/core/transport/http/server/apache2/apache2_out_transport_info.c create mode 100644 src/core/transport/http/server/apache2/apache2_stream.c create mode 100644 src/core/transport/http/server/apache2/apache2_stream.h create mode 100644 src/core/transport/http/server/apache2/apache2_worker.c create mode 100644 src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h create mode 100644 src/core/transport/http/server/apache2/axis2_apache2_worker.h create mode 100644 src/core/transport/http/server/apache2/mod_axis2.c create mode 100644 src/core/transport/http/server/simple_axis2_server/Makefile.am create mode 100644 src/core/transport/http/server/simple_axis2_server/http_server_main.c create mode 100644 src/core/transport/http/util/Makefile.am create mode 100644 src/core/transport/http/util/http_transport_utils.c (limited to 'src/core/transport/http') diff --git a/src/core/transport/http/Makefile.am b/src/core/transport/http/Makefile.am new file mode 100644 index 0000000..cc23d78 --- /dev/null +++ b/src/core/transport/http/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = sender receiver server diff --git a/src/core/transport/http/common/Makefile.am b/src/core/transport/http/common/Makefile.am new file mode 100644 index 0000000..8aaa2c6 --- /dev/null +++ b/src/core/transport/http/common/Makefile.am @@ -0,0 +1,29 @@ +lib_LTLIBRARIES = libaxis2_http_common.la + +libaxis2_http_common_la_LIBADD=$(top_builddir)/util/src/libaxutil.la\ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la + +libaxis2_http_common_la_SOURCES = http_header.c\ + http_out_transport_info.c\ + http_request_line.c\ + http_simple_request.c\ + http_simple_response.c\ + http_status_line.c\ + http_accept_record.c\ + http_response_writer.c\ + simple_http_svr_conn.c\ + http_worker.c + + +libaxis2_http_common_la_LDFLAGS = -version-info $(VERSION_NO) + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/transport\ + -I$(top_builddir)/src/core/transport/http \ + -I$(top_builddir)/src/core/description \ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/src/core/deployment \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/common/http_accept_record.c b/src/core/transport/http/common/http_accept_record.c new file mode 100644 index 0000000..25f15b1 --- /dev/null +++ b/src/core/transport/http/common/http_accept_record.c @@ -0,0 +1,165 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +struct axis2_http_accept_record +{ + axis2_char_t *name; + float quality; + int level; + axis2_char_t *record; +}; + +AXIS2_EXTERN axis2_http_accept_record_t *AXIS2_CALL +axis2_http_accept_record_create( + const axutil_env_t * env, + const axis2_char_t * str) +{ + axis2_char_t *tmp_accept_record = NULL; + axis2_char_t *tmp = NULL; + axis2_http_accept_record_t *accept_record = NULL; + float quality = 1.0; + int level = -1; + axis2_char_t *name = NULL; + + AXIS2_PARAM_CHECK(env->error, str, NULL); + + tmp_accept_record = (axis2_char_t *)axutil_strdup(env, str); + if(!tmp_accept_record) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "unable to strdup string %s", str); + return NULL; + } + + accept_record = (axis2_http_accept_record_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_accept_record_t)); + + if(!accept_record) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset((void *)accept_record, 0, sizeof(axis2_http_accept_record_t)); + accept_record->record = axutil_strtrim(env, tmp_accept_record, AXIS2_SPACE_COMMA); + + tmp = strchr(tmp_accept_record, AXIS2_Q); + if(tmp) + { + *tmp = AXIS2_ESC_NULL; + tmp++; + tmp = axutil_strtrim(env, tmp, AXIS2_EQ_N_SEMICOLON); + if(tmp) + { + sscanf(tmp, "%f", &quality); + AXIS2_FREE(env->allocator, tmp); + } + } + + tmp = strstr(tmp_accept_record, AXIS2_LEVEL); + if(tmp) + { + *tmp = AXIS2_ESC_NULL; + tmp++; + tmp = axutil_strtrim(env, tmp, AXIS2_EQ_N_SEMICOLON); + if(tmp) + { + sscanf(tmp, "%d", &level); + AXIS2_FREE(env->allocator, tmp); + } + } + + tmp = axutil_strtrim(env, tmp_accept_record, AXIS2_SPACE_SEMICOLON); + if(tmp) + { + name = tmp; + } + + if(!name || quality > 1.0 || quality < 0.0) + { + axis2_http_accept_record_free(accept_record, env); + return NULL; + } + + accept_record->name = name; + accept_record->quality = quality; + accept_record->level = level; + + AXIS2_FREE(env->allocator, tmp_accept_record); + return accept_record; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_accept_record_free( + axis2_http_accept_record_t * accept_record, + const axutil_env_t * env) +{ + + if(!accept_record) + { + return; + } + + if(accept_record->name) + { + AXIS2_FREE(env->allocator, accept_record->name); + } + if(accept_record->record) + { + AXIS2_FREE(env->allocator, accept_record->record); + } + AXIS2_FREE(env->allocator, accept_record); + return; +} + +AXIS2_EXTERN float AXIS2_CALL +axis2_http_accept_record_get_quality_factor( + const axis2_http_accept_record_t * accept_record, + const axutil_env_t * env) +{ + return accept_record->quality; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_accept_record_get_name( + const axis2_http_accept_record_t * accept_record, + const axutil_env_t * env) +{ + return accept_record->name; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_accept_record_get_level( + const axis2_http_accept_record_t * accept_record, + const axutil_env_t * env) +{ + return accept_record->level; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_accept_record_to_string( + axis2_http_accept_record_t * accept_record, + const axutil_env_t * env) +{ + return accept_record->record; +} diff --git a/src/core/transport/http/common/http_header.c b/src/core/transport/http/common/http_header.c new file mode 100644 index 0000000..3ea2ffc --- /dev/null +++ b/src/core/transport/http/common/http_header.c @@ -0,0 +1,168 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include + +struct axis2_http_header +{ + axis2_char_t *name; + axis2_char_t *value; +}; + +AXIS2_EXTERN axis2_http_header_t *AXIS2_CALL +axis2_http_header_create( + const axutil_env_t * env, + const axis2_char_t * name, + const axis2_char_t * value) +{ + axis2_http_header_t *http_header = NULL; + http_header = (axis2_http_header_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_http_header_t)); + if(!http_header) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)http_header, 0, sizeof(axis2_http_header_t)); + http_header->name = (axis2_char_t *)axutil_strdup(env, name); + http_header->value = (axis2_char_t *)axutil_strdup(env, value); + + return http_header; +} + +/** + * Creates http header object from a string having format "header_name: header_value" + * (e.g. "SOAPAction: urn:hello") + * @param env pointer to environment struct + * @param str pointer to str + */ +AXIS2_EXTERN axis2_http_header_t *AXIS2_CALL +axis2_http_header_create_by_str( + const axutil_env_t * env, + const axis2_char_t * str) +{ + axis2_char_t *tmp_str = NULL; + axis2_char_t *ch = NULL; + axis2_char_t *ch2 = NULL; + axis2_http_header_t *ret = NULL; + int tmp_str_len = 0; + AXIS2_PARAM_CHECK(env->error, str, NULL); + + /* + tmp_str = axutil_strdup(env, str); + if(!tmp_str) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "unable to strdup string, %s", str); + return NULL; + } + */ + /* + * strdup is removed to increase the performance. This method is called from + * axis2_simple_http_svr_conn_read_request and axis2_http_client_recieve_header and both of them + * passes a temporary string. hence we can modify the contents without doing a strdup. + * Above code is commented after 1.6.0 . If no issue is found until 1.8.0, above can be removed + */ + tmp_str = (axis2_char_t *)str; + + /* remove trailing \r\n */ + tmp_str_len = axutil_strlen(tmp_str); + if((tmp_str_len >= 2) && (AXIS2_RETURN == tmp_str[tmp_str_len - 2])) + { + tmp_str[tmp_str_len - 2] = AXIS2_ESC_NULL; + } + + /* get http header */ + ch = strchr((const char *)tmp_str, AXIS2_COLON); + if(!ch) + { + /*AXIS2_FREE(env->allocator, tmp_str);*/ + return NULL; + } + *ch = AXIS2_ESC_NULL; + + /* get http header value */ + ch2 = ++ch; + + /* skip spaces */ + while(AXIS2_SPACE == *ch2) + { + ++ch2; + } + + ret = axis2_http_header_create(env, tmp_str, ch2); + /*AXIS2_FREE(env->allocator, tmp_str);*/ + return ret; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_header_free( + axis2_http_header_t * http_header, + const axutil_env_t * env) +{ + + if(!http_header) + { + return; + } + + if(http_header->name) + { + AXIS2_FREE(env->allocator, http_header->name); + } + if(http_header->value) + { + AXIS2_FREE(env->allocator, http_header->value); + } + + AXIS2_FREE(env->allocator, http_header); + return; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_header_to_external_form( + axis2_http_header_t * http_header, + const axutil_env_t * env) +{ + axis2_ssize_t len = 0; + axis2_char_t *external_form = NULL; + + AXIS2_PARAM_CHECK(env->error, http_header, NULL); + + len = axutil_strlen(http_header->name) + axutil_strlen(http_header->value) + 8; + external_form = (axis2_char_t *)AXIS2_MALLOC(env->allocator, len); + sprintf(external_form, "%s: %s%s", http_header->name, http_header->value, AXIS2_HTTP_CRLF); + return external_form; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_header_get_name( + const axis2_http_header_t * http_header, + const axutil_env_t * env) +{ + return http_header->name; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_header_get_value( + const axis2_http_header_t * http_header, + const axutil_env_t * env) +{ + return http_header->value; +} diff --git a/src/core/transport/http/common/http_out_transport_info.c b/src/core/transport/http/common/http_out_transport_info.c new file mode 100644 index 0000000..b70ee6c --- /dev/null +++ b/src/core/transport/http/common/http_out_transport_info.c @@ -0,0 +1,353 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_http_out_transport_info_t *) \ + (out_transport_info)) + +axis2_status_t AXIS2_CALL +axis2_out_transport_info_impl_set_content_type( + axis2_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_http_out_transport_info_t *http_transport_info = NULL; + http_transport_info = AXIS2_INTF_TO_IMPL(out_transport_info); + return axis2_http_out_transport_info_set_content_type(http_transport_info, env, content_type); +} + +axis2_status_t AXIS2_CALL +axis2_out_transport_info_impl_set_char_encoding( + axis2_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + axis2_http_out_transport_info_t *http_transport_info = NULL; + http_transport_info = AXIS2_INTF_TO_IMPL(out_transport_info); + return axis2_http_out_transport_info_set_char_encoding(http_transport_info, env, encoding); +} + +axis2_status_t AXIS2_CALL +axis2_out_transport_info_impl_set_cookie_header( + axis2_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * set_cookie) +{ + axis2_http_out_transport_info_t *http_transport_info = NULL; + http_transport_info = AXIS2_INTF_TO_IMPL(out_transport_info); + return axis2_http_out_transport_info_set_cookie_header(http_transport_info, env, set_cookie); +} + +axis2_status_t AXIS2_CALL +axis2_out_transport_info_impl_set_session( + axis2_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * session_id, + const axis2_char_t * session_value) +{ + axis2_http_out_transport_info_t *http_transport_info = NULL; + http_transport_info = AXIS2_INTF_TO_IMPL(out_transport_info); + return axis2_http_out_transport_info_set_session(http_transport_info, env, session_id, + session_value); +} + +void AXIS2_CALL +axis2_out_transport_info_impl_free( + axis2_out_transport_info_t * out_transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *http_transport_info = NULL; + http_transport_info = AXIS2_INTF_TO_IMPL(out_transport_info); + axis2_http_out_transport_info_free(http_transport_info, env); + return; +} + +static const axis2_out_transport_info_ops_t ops_var = { + axis2_out_transport_info_impl_set_content_type, + axis2_out_transport_info_impl_set_char_encoding, + axis2_out_transport_info_impl_set_cookie_header, + axis2_out_transport_info_impl_set_session, + axis2_out_transport_info_impl_free }; + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_impl_set_content_type( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_char_t *tmp1 = NULL; + axis2_char_t *tmp2 = NULL; + + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + if(http_out_transport_info->encoding) + { + axis2_char_t *charset_pos = axutil_strcasestr(content_type, AXIS2_CHARSET); + if(!charset_pos) + { + /* if "charset" not found in content_type string */ + tmp1 = axutil_stracat(env, content_type, AXIS2_CONTENT_TYPE_CHARSET); + tmp2 = axutil_stracat(env, tmp1, http_out_transport_info->encoding); + axis2_http_simple_response_set_header(http_out_transport_info-> response, env, + axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, tmp2)); + AXIS2_FREE(env->allocator, tmp1); + AXIS2_FREE(env->allocator, tmp2); + } + else + { + /* "charset" is found in content_type string */ + axis2_http_simple_response_set_header(http_out_transport_info-> response, env, + axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, content_type)); + } + } + else + { + /* no http_out_transport_info->encoding */ + if(http_out_transport_info->response) + { + axis2_http_simple_response_set_header(http_out_transport_info-> response, env, + axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, content_type)); + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_impl_set_char_encoding( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + if(http_out_transport_info->encoding) + { + AXIS2_FREE(env->allocator, http_out_transport_info->encoding); + } + http_out_transport_info->encoding = axutil_strdup(env, encoding); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_impl_set_cookie_header( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * set_cookie) +{ + AXIS2_PARAM_CHECK(env->error, set_cookie, AXIS2_FAILURE); + if(http_out_transport_info->response) + { + axis2_http_simple_response_set_header(http_out_transport_info-> response, env, + axis2_http_header_create(env, AXIS2_HTTP_HEADER_SET_COOKIE, set_cookie)); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_impl_set_session( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * session_id, + const axis2_char_t * session_value) +{ + AXIS2_PARAM_CHECK(env->error, session_id, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, session_value, AXIS2_FAILURE); + if(http_out_transport_info->server) + { + env->set_session_fn((void *) http_out_transport_info->server, session_id, session_value); + } + return AXIS2_SUCCESS; +} +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_impl_free( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env) +{ + + if(!http_out_transport_info) + { + return; + } + + if(http_out_transport_info->response) + { + axis2_http_simple_response_free(http_out_transport_info->response, env); + } + if(http_out_transport_info->encoding) + { + AXIS2_FREE(env->allocator, http_out_transport_info->encoding); + } + AXIS2_FREE(env->allocator, http_out_transport_info); + return; +} + +AXIS2_EXTERN axis2_http_out_transport_info_t *AXIS2_CALL +axis2_http_out_transport_info_create( + const axutil_env_t * env, + axis2_http_simple_response_t * response) +{ + axis2_http_out_transport_info_t *http_out_transport_info = NULL; + + http_out_transport_info = (axis2_http_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_out_transport_info_t)); + + if(!http_out_transport_info) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)http_out_transport_info, 0, sizeof(axis2_http_out_transport_info_t)); + http_out_transport_info->out_transport.ops = &ops_var; + http_out_transport_info->response = response; + http_out_transport_info->encoding = NULL; + http_out_transport_info->set_char_encoding = NULL; + http_out_transport_info->set_content_type = NULL; + http_out_transport_info->set_cookie_header = NULL; + http_out_transport_info->set_session = NULL; + http_out_transport_info->free_function = NULL; + + http_out_transport_info->set_char_encoding + = axis2_http_out_transport_info_impl_set_char_encoding; + http_out_transport_info->set_content_type = axis2_http_out_transport_info_impl_set_content_type; + http_out_transport_info->set_cookie_header = axis2_http_out_transport_info_impl_set_cookie_header; + http_out_transport_info->set_session = axis2_http_out_transport_info_impl_set_session; + http_out_transport_info->free_function = axis2_http_out_transport_info_impl_free; + + return http_out_transport_info; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_free( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env) +{ + http_out_transport_info->free_function(http_out_transport_info, env); + return; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + transport_info_l = AXIS2_INTF_TO_IMPL(transport_info); + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_set_content_type( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + return http_out_transport_info->set_content_type(http_out_transport_info, env, content_type); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + return http_out_transport_info->set_char_encoding(http_out_transport_info, env, encoding); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_set_cookie_header( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * set_cookie) +{ + return http_out_transport_info->set_cookie_header(http_out_transport_info, env, set_cookie); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_out_transport_info_set_session( + axis2_http_out_transport_info_t * http_out_transport_info, + const axutil_env_t * env, + const axis2_char_t * session_id, + const axis2_char_t * session_value) +{ + return http_out_transport_info->set_session(http_out_transport_info, env, session_id, + session_value); +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_set_char_encoding_func( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + axis2_status_t(AXIS2_CALL * set_char_encoding) + (axis2_http_out_transport_info_t *, + const axutil_env_t *, + const axis2_char_t *)) +{ + out_transport_info->set_char_encoding = set_char_encoding; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_set_content_type_func( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + axis2_status_t(AXIS2_CALL * + set_content_type) (axis2_http_out_transport_info_t *, + const axutil_env_t *, + const axis2_char_t *)) +{ + out_transport_info->set_content_type = set_content_type; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_set_cookie_header_func( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + axis2_status_t(AXIS2_CALL * + set_cookie_header) (axis2_http_out_transport_info_t *, + const axutil_env_t *, + const axis2_char_t *)) +{ + out_transport_info->set_cookie_header = set_cookie_header; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_set_session_func( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + axis2_status_t(AXIS2_CALL * + set_session) (axis2_http_out_transport_info_t *, + const axutil_env_t *, + const axis2_char_t *, + const axis2_char_t *)) +{ + out_transport_info->set_session = set_session; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_out_transport_info_set_free_func( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + void (AXIS2_CALL * free_function) (axis2_http_out_transport_info_t *, + const axutil_env_t *)) +{ + out_transport_info->free_function = free_function; +} + diff --git a/src/core/transport/http/common/http_request_line.c b/src/core/transport/http/common/http_request_line.c new file mode 100644 index 0000000..f12cbba --- /dev/null +++ b/src/core/transport/http/common/http_request_line.c @@ -0,0 +1,227 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include + +struct axis2_http_request_line +{ + axis2_char_t *http_version; + axis2_char_t *method; + axis2_char_t *uri; +}; + +AXIS2_EXTERN axis2_http_request_line_t *AXIS2_CALL +axis2_http_request_line_create( + const axutil_env_t * env, + const axis2_char_t * method, + const axis2_char_t * uri, + const axis2_char_t * http_version) +{ + axis2_http_request_line_t *request_line = NULL; + + AXIS2_PARAM_CHECK(env->error, method, NULL); + AXIS2_PARAM_CHECK(env->error, uri, NULL); + AXIS2_PARAM_CHECK(env->error, http_version, NULL); + + request_line = (axis2_http_request_line_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_request_line_t)); + + if(!request_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)request_line, 0, sizeof(axis2_http_request_line_t)); + request_line->method = (axis2_char_t *)axutil_strdup(env, method); + request_line->uri = (axis2_char_t *)axutil_strdup(env, uri); + request_line->http_version = (axis2_char_t *)axutil_strdup(env, http_version); + + return request_line; +} + +void AXIS2_CALL +axis2_http_request_line_free( + axis2_http_request_line_t * request_line, + const axutil_env_t * env) +{ + + if(!request_line) + { + return; + } + + if(request_line->method) + { + AXIS2_FREE(env->allocator, request_line->method); + } + if(request_line->uri) + { + AXIS2_FREE(env->allocator, request_line->uri); + } + if(request_line->http_version) + { + AXIS2_FREE(env->allocator, request_line->http_version); + } + + AXIS2_FREE(env->allocator, request_line); + return; +} + +/** + * Parses a line " CRLF" and creates http_request_line + * object. E.g "POST /axis2/services/echo HTTP/1.1\r\n" + * @param env pointer to environment struct + * @param str pointer to the line to be parsed + * @return created object if success. NULL otherwise + */ +AXIS2_EXTERN axis2_http_request_line_t *AXIS2_CALL +axis2_http_request_line_parse_line( + const axutil_env_t * env, + const axis2_char_t * str) +{ + /*axis2_char_t *req_line = NULL;*/ + axis2_char_t *method = NULL; + axis2_char_t *uri = NULL; + axis2_char_t *http_version = NULL; + axis2_http_request_line_t *ret = NULL; + axis2_char_t *tmp = NULL; + int i = 0; + + if(!str) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Invalid parameter is given to parse"); + return NULL; + } + + tmp = axutil_strstr(str, AXIS2_HTTP_CRLF); + if(!tmp) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + + i = (int)(tmp - str); /* We are sure that the difference lies within the int range */ + + /* + req_line = AXIS2_MALLOC(env->allocator, i * sizeof(axis2_char_t) + 1); + if(!req_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memcpy(req_line, str, i * sizeof(axis2_char_t)); + req_line[i] = AXIS2_ESC_NULL; + tmp = req_line; + */ + /* we don't need to do a malloc and memcpy, because this method is only used by + * axis2_simple_http_svr_conn_read_request and it passes a temporary string. So, we can just + * set it as req_line and set the escape characters. this is done after 1.6.0 and if no issues + * found until 1.8.0, above code comment can be removed after 1.8.0 + */ + + tmp = (axis2_char_t *)str; + tmp[i] = AXIS2_ESC_NULL; + + /* find http method */ + method = tmp; + tmp = strchr(tmp, AXIS2_SPACE); + if(!tmp) + { + /*AXIS2_FREE(env->allocator, req_line);*/ + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + *tmp++ = AXIS2_ESC_NULL; + + /* find URI */ + uri = tmp; + tmp = strrchr(tmp, AXIS2_SPACE); + if(!tmp) + { + /*AXIS2_FREE(env->allocator, req_line);*/ + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + *tmp++ = AXIS2_ESC_NULL; + + /* find HTTP version */ + http_version = tmp; + ret = axis2_http_request_line_create(env, method, uri, http_version); + /*AXIS2_FREE(env->allocator, req_line);*/ + + return ret; +} + +axis2_char_t *AXIS2_CALL +axis2_http_request_line_get_method( + const axis2_http_request_line_t * request_line, + const axutil_env_t * env) +{ + return request_line->method; +} + +axis2_char_t *AXIS2_CALL +axis2_http_request_line_get_http_version( + const axis2_http_request_line_t * request_line, + const axutil_env_t * env) +{ + return request_line->http_version; +} + +axis2_char_t *AXIS2_CALL +axis2_http_request_line_get_uri( + const axis2_http_request_line_t * request_line, + const axutil_env_t * env) +{ + return request_line->uri; +} + +axis2_char_t *AXIS2_CALL +axis2_http_request_line_to_string( + axis2_http_request_line_t * request_line, + const axutil_env_t * env) +{ + int alloc_len = 0; + axis2_char_t *ret = NULL; + + alloc_len = axutil_strlen(request_line->method) + axutil_strlen(request_line->uri) + + axutil_strlen(request_line->http_version) + 6; + /* 5 = 2 * spaces + '/' +CR + LF + '\0' */ + + ret = AXIS2_MALLOC(env->allocator, alloc_len * sizeof(axis2_char_t)); + if(!ret) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + if(request_line->uri[0] != AXIS2_F_SLASH) + { + sprintf(ret, "%s /%s %s%s", request_line->method, request_line->uri, + request_line->http_version, AXIS2_HTTP_CRLF); + } + else + { + sprintf(ret, "%s %s %s%s", request_line->method, request_line->uri, + request_line->http_version, AXIS2_HTTP_CRLF); + } + return ret; +} diff --git a/src/core/transport/http/common/http_response_writer.c b/src/core/transport/http/common/http_response_writer.c new file mode 100644 index 0000000..eec2422 --- /dev/null +++ b/src/core/transport/http/common/http_response_writer.c @@ -0,0 +1,176 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +struct axis2_http_response_writer +{ + axutil_stream_t *stream; + axis2_char_t *encoding; +}; + +AXIS2_EXTERN axis2_http_response_writer_t *AXIS2_CALL +axis2_http_response_writer_create( + const axutil_env_t * env, + axutil_stream_t * stream) +{ + return axis2_http_response_writer_create_with_encoding(env, stream, + AXIS2_HTTP_DEFAULT_CONTENT_CHARSET); +} + +AXIS2_EXTERN axis2_http_response_writer_t *AXIS2_CALL +axis2_http_response_writer_create_with_encoding( + const axutil_env_t * env, + axutil_stream_t * stream, + const axis2_char_t * encoding) +{ + axis2_http_response_writer_t *response_writer = NULL; + response_writer = (axis2_http_response_writer_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_response_writer_t)); + if(!response_writer) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + response_writer->stream = stream; + response_writer->encoding = (axis2_char_t *)axutil_strdup(env, encoding); + return response_writer; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_response_writer_free( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env) +{ + AXIS2_FREE(env->allocator, response_writer->encoding); + AXIS2_FREE(env->allocator, response_writer); +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_response_writer_get_encoding( + const axis2_http_response_writer_t * response_writer, + const axutil_env_t * env) +{ + return response_writer->encoding; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_response_writer_write_char( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env, + char c) +{ + int write = -1; + if(!response_writer->stream) + { + return AXIS2_FAILURE; + } + + write = axutil_stream_write(response_writer->stream, env, &c, 1); + if(write < 0) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_response_writer_write_buf( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env, + char *buf, + int offset, + axis2_ssize_t len) +{ + int write = -1; + + AXIS2_PARAM_CHECK(env->error, response_writer, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + + if(!response_writer->stream) + { + return AXIS2_FAILURE; + } + write = axutil_stream_write(response_writer->stream, env, buf, len); + if(write < 0) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_response_writer_print_str( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env, + const char *str) +{ + int write = -1; + int len = -1; + + len = axutil_strlen(str); + if(!response_writer->stream) + { + return AXIS2_FAILURE; + } + write = axutil_stream_write(response_writer->stream, env, str, len); + + if(write < 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "failed to write to stream string %s of length %d", str, len); + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_response_writer_print_int( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env, + int i) +{ + axis2_char_t int_str[10]; + sprintf(int_str, "%10d", i); + return axis2_http_response_writer_print_str(response_writer, env, int_str); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_response_writer_println_str( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env, + const char *str) +{ + if(AXIS2_SUCCESS == axis2_http_response_writer_print_str(response_writer, env, str)) + { + return axis2_http_response_writer_print_str(response_writer, env, AXIS2_HTTP_CRLF); + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_response_writer_println( + axis2_http_response_writer_t * response_writer, + const axutil_env_t * env) +{ + return axis2_http_response_writer_print_str(response_writer, env, AXIS2_HTTP_CRLF); +} diff --git a/src/core/transport/http/common/http_simple_request.c b/src/core/transport/http/common/http_simple_request.c new file mode 100644 index 0000000..9e10ce1 --- /dev/null +++ b/src/core/transport/http/common/http_simple_request.c @@ -0,0 +1,433 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +struct axis2_http_simple_request +{ + axis2_http_request_line_t *request_line; + axutil_array_list_t *header_group; + axutil_stream_t *stream; + axis2_bool_t owns_stream; +}; + +AXIS2_EXTERN axis2_http_simple_request_t *AXIS2_CALL +axis2_http_simple_request_create( + const axutil_env_t * env, + axis2_http_request_line_t * request_line, + axis2_http_header_t ** http_headers, + axis2_ssize_t http_hdr_count, + axutil_stream_t * content) +{ + axis2_http_simple_request_t *simple_request = NULL; + simple_request = (axis2_http_simple_request_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_simple_request_t)); + if(!simple_request) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset((void *)simple_request, 0, sizeof(axis2_http_simple_request_t)); + simple_request->request_line = request_line; + simple_request->stream = content; + + if(!(simple_request->stream)) + { + simple_request->stream = axutil_stream_create_basic(env); + if(!simple_request->stream) + { + axis2_http_simple_request_free(simple_request, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + simple_request->owns_stream = AXIS2_TRUE; + } + + if((http_hdr_count > 0) && http_headers) + { + int i = 0; + simple_request->header_group = axutil_array_list_create(env, http_hdr_count); + + for(i = 0; i < (int)http_hdr_count; i++) + /* We are sure that the difference lies within the int range */ + { + axutil_array_list_add(simple_request->header_group, env, (void *)http_headers[i]); + } + } + + return simple_request; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_simple_request_free( + axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + /* free the stream only if we own it. Otherwise shouldn't free the stream + * since it belongs to the socket + */ + if(simple_request->owns_stream) + { + axutil_stream_free(simple_request->stream, env); + } + + if(simple_request->request_line) + { + axis2_http_request_line_free(simple_request->request_line, env); + } + + if(simple_request->header_group) + { + int i = 0; + axis2_http_header_t *tmp = NULL; + for(i = 0; i < axutil_array_list_size(simple_request->header_group, env); i++) + { + tmp = (axis2_http_header_t*)axutil_array_list_get(simple_request->header_group, env, i); + axis2_http_header_free(tmp, env); + } + axutil_array_list_free(simple_request->header_group, env); + } + AXIS2_FREE(env->allocator, simple_request); +} + +AXIS2_EXTERN axis2_http_request_line_t *AXIS2_CALL +axis2_http_simple_request_get_request_line( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + return simple_request->request_line; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_simple_request_set_request_line( + axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + axis2_http_request_line_t * request_line) +{ + AXIS2_PARAM_CHECK(env->error, request_line, AXIS2_FAILURE); + simple_request->request_line = request_line; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_simple_request_contains_header( + axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + const axis2_char_t * name) +{ + int i = 0; + axis2_char_t *header_name = NULL; + int count = 0; + + AXIS2_PARAM_CHECK(env->error, name, AXIS2_FAILURE); + + if(!simple_request->header_group) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, + "http simple request \ +does not contain headers, unable to find: %s header", name); + return AXIS2_FALSE; + } + + count = axutil_array_list_size(simple_request->header_group, env); + + if(0 == count) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, + "http simple request \ +contains zero headers, unable to find: %s header", name); + return AXIS2_FALSE; + } + + for(i = 0; i < count; i++) + { + header_name = axis2_http_header_get_name((axis2_http_header_t *)axutil_array_list_get( + simple_request->header_group, env, i), env); + if(0 == axutil_strcasecmp(name, header_name)) + { + return AXIS2_TRUE; + } + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_http_simple_request_get_headers( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + return simple_request->header_group; +} + +AXIS2_EXTERN axis2_http_header_t *AXIS2_CALL +axis2_http_simple_request_get_first_header( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + const axis2_char_t * str) +{ + axutil_array_list_t *header_group = NULL; + int i = 0; + int count = 0; + + AXIS2_PARAM_CHECK(env->error, str, NULL); + + header_group = simple_request->header_group; + if(!simple_request->header_group) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "http simple request does not contain any headers; unable to find: %s header", str); + return NULL; + } + + if(0 == axutil_array_list_size(header_group, env)) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, + "http simple request contain zero headers, unable to find: %s header", str); + return NULL; + } + + count = axutil_array_list_size(header_group, env); + for(i = 0; i < count; i++) + { + axis2_http_header_t *tmp_header = NULL; + axis2_char_t *tmp_name = NULL; + tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i); + tmp_name = axis2_http_header_get_name(tmp_header, env); + if(0 == axutil_strcasecmp(str, tmp_name)) + { + return tmp_header; + } + } + return NULL; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_simple_request_remove_headers( + axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + const axis2_char_t * str) +{ + axis2_http_header_t *tmp_header = 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, str, AXIS2_FAILURE); + + header_group = simple_request->header_group; + + if(!header_group) + { + /* Even though we couldn't complete the op, we are sure that the + * requred header is no more in the request. So we can proceed without a + * problem. + */ + return AXIS2_SUCCESS; + } + + count = axutil_array_list_size(header_group, env); + + for(i = 0; i < count; i++) + { + tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i); + tmp_name = axis2_http_header_get_name(tmp_header, env); + if(0 == axutil_strcasecmp(str, tmp_name)) + { + axis2_http_header_free(tmp_header, env); + axutil_array_list_remove(header_group, env, i); + break; + } + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_simple_request_add_header( + axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + axis2_http_header_t * header) +{ + AXIS2_PARAM_CHECK(env->error, header, AXIS2_FAILURE); + + if(!simple_request->header_group) + { + simple_request->header_group = axutil_array_list_create(env, 1); + } + return axutil_array_list_add(simple_request->header_group, env, header); +} + +AXIS2_EXTERN const axis2_char_t *AXIS2_CALL +axis2_http_simple_request_get_content_type( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header = NULL; + + tmp_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(tmp_header) + { + return axis2_http_header_get_value(tmp_header, env); + } + + return AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN; +} + +AXIS2_EXTERN const axis2_char_t *AXIS2_CALL +axis2_http_simple_request_get_charset( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header = NULL; + + tmp_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(tmp_header) + { + axis2_char_t *value = axis2_http_header_get_value(tmp_header, env); + axis2_char_t *charset = (axis2_char_t *)strstr((char *)value, + (char *)AXIS2_HTTP_CHAR_SET_ENCODING); + if(charset) + { + charset = strchr((char *)charset, AXIS2_EQ); + return charset; + } + } + + return AXIS2_HTTP_DEFAULT_CONTENT_CHARSET; +} + +AXIS2_EXTERN axis2_ssize_t AXIS2_CALL +axis2_http_simple_request_get_content_length( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header = NULL; + int error_return = -1; + + tmp_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH); + if(tmp_header) + { + return AXIS2_ATOI(axis2_http_header_get_value(tmp_header, env)); + } + return error_return; +} + +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axis2_http_simple_request_get_body( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env) +{ + return simple_request->stream; +} + +AXIS2_EXTERN axis2_ssize_t AXIS2_CALL +axis2_http_simple_request_get_body_bytes( + const axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + char **buf) +{ + axutil_stream_t *body = NULL; + char *tmp_buf = NULL; + char *tmp_buf2 = NULL; + char *tmp_buf3 = NULL; + int length = 0; + int read_len = 0; + + body = simple_request->stream; + if(!body) + { + *buf = (char *)AXIS2_MALLOC(env->allocator, 1); + *buf[0] = '\0'; + return 0; + } + + length = axis2_http_simple_request_get_content_length(simple_request, env); + if(length > 0) + { + *buf = (char *)AXIS2_MALLOC(env->allocator, length + 1); + read_len = axutil_stream_read(body, env, *buf, length + 1); + return read_len; + } + + tmp_buf2 = AXIS2_MALLOC(env->allocator, 128 * sizeof(char)); + while(axutil_stream_read(body, env, tmp_buf2, 128) > 0) + { + tmp_buf3 = axutil_stracat(env, tmp_buf, tmp_buf2); + if(tmp_buf) + { + AXIS2_FREE(env->allocator, tmp_buf); + tmp_buf = NULL; + } + tmp_buf = tmp_buf3; + + } + + if(tmp_buf2) + { + AXIS2_FREE(env->allocator, tmp_buf2); + tmp_buf2 = NULL; + } + + if(tmp_buf) + { + *buf = tmp_buf; + return axutil_strlen(tmp_buf); + } + + *buf = (char *)AXIS2_MALLOC(env->allocator, 1); + *buf[0] = AXIS2_ESC_NULL; + return 0; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_simple_request_set_body_string( + axis2_http_simple_request_t * simple_request, + const axutil_env_t * env, + void *str, + unsigned int str_len) +{ + axutil_stream_t *body_stream = NULL; + + AXIS2_PARAM_CHECK(env->error, str, AXIS2_FAILURE); + + body_stream = simple_request->stream; + if(!body_stream) + { + body_stream = axutil_stream_create_basic(env); + if(!body_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "unable to create stream\ +for stream %s of %d length", (axis2_char_t *)str, str_len); + return AXIS2_FAILURE; + } + simple_request->stream = body_stream; + simple_request->owns_stream = AXIS2_TRUE; + } + + axutil_stream_write(body_stream, env, str, str_len); + return AXIS2_SUCCESS; +} diff --git a/src/core/transport/http/common/http_simple_response.c b/src/core/transport/http/common/http_simple_response.c new file mode 100644 index 0000000..74acb80 --- /dev/null +++ b/src/core/transport/http/common/http_simple_response.c @@ -0,0 +1,615 @@ +/* + * 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. + */ +#include +#include +#include +#include +#include +#include +#include + +#define AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE 2048 + +struct axis2_http_simple_response +{ + axis2_http_status_line_t *status_line; + axutil_array_list_t *header_group; + axutil_stream_t *stream; + axutil_array_list_t *mime_parts; + axis2_char_t *mtom_sending_callback_name; +}; + +AXIS2_EXTERN axis2_http_simple_response_t *AXIS2_CALL +axis2_http_simple_response_create( + const axutil_env_t * env, + axis2_http_status_line_t * status_line, + const axis2_http_header_t ** http_headers, + const axis2_ssize_t http_hdr_count, + axutil_stream_t * content) +{ + axis2_http_simple_response_t *ret = NULL; + ret = axis2_http_simple_response_create_default(env); + if(!ret) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 http simple response creation failed"); + return NULL; + } + + ret->status_line = status_line; + if(http_hdr_count > 0 && http_headers) + { + int i = 0; + ret->header_group = axutil_array_list_create(env, http_hdr_count); + + for(i = 0; i < (int)http_hdr_count; i++) + /* We are sure that the difference lies within the int range */ + { + axutil_array_list_add(ret->header_group, env, (void *)http_headers[i]); + } + } + ret->stream = content; + return ret; +} + +AXIS2_EXTERN axis2_http_simple_response_t *AXIS2_CALL +axis2_http_simple_response_create_default( + const axutil_env_t * env) +{ + axis2_http_simple_response_t *simple_response = NULL; + simple_response = (axis2_http_simple_response_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_simple_response_t)); + if(!simple_response) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset((void *)simple_response, 0, sizeof(axis2_http_simple_response_t)); + return simple_response; +} + +void AXIS2_CALL +axis2_http_simple_response_free( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + if(simple_response->status_line) + { + axis2_http_status_line_free(simple_response->status_line, env); + } + + if(simple_response->header_group) + { + int i = 0; + for(i = 0; i < axutil_array_list_size(simple_response->header_group, env); i++) + { + void *tmp = NULL; + tmp = axutil_array_list_get(simple_response-> header_group, env, i); + if(tmp) + { + axis2_http_header_free((axis2_http_header_t *)tmp, env); + } + } + axutil_array_list_free(simple_response->header_group, env); + } + + if(simple_response->mime_parts) + { + int i = 0; + for(i = 0; i < axutil_array_list_size(simple_response->mime_parts, env); i++) + { + void *mime_part = NULL; + mime_part = axutil_array_list_get(simple_response->mime_parts, env, i); + if(mime_part) + { + axiom_mime_part_free((axiom_mime_part_t *)mime_part, env); + } + } + axutil_array_list_free(simple_response->mime_parts, env); + } + + /* Stream is not freed. Assumption : stream doesn't belong to the response */ + + AXIS2_FREE(env->allocator, simple_response); +} + +axis2_status_t AXIS2_CALL +axis2_http_simple_response_set_status_line( + struct axis2_http_simple_response * simple_response, + const axutil_env_t * env, + const axis2_char_t * http_ver, + const int status_code, + const axis2_char_t * phrase) +{ + if(!http_ver || !phrase || !status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "invalid parameter given"); + return AXIS2_FAILURE; + } + + if(simple_response->status_line) + { + axis2_http_status_line_free(simple_response->status_line, env); + } + + simple_response->status_line = axis2_http_status_line_create_with_values( + env, http_ver, status_code, phrase); + if(!simple_response->status_line) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "http status line creation failed for string %s %3d %s", http_ver, status_code, phrase); + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +axis2_char_t *AXIS2_CALL +axis2_http_simple_response_get_phrase( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + if(!(simple_response->status_line)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2 simple response , status line is not available"); + return NULL; + } + + return axis2_http_status_line_get_reason_phrase(simple_response-> status_line, env); +} + +int AXIS2_CALL +axis2_http_simple_response_get_status_code( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + if(!(simple_response->status_line)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2 simple response , status line is not available"); + return -1; + } + return axis2_http_status_line_get_status_code(simple_response->status_line, env); +} + +axis2_char_t *AXIS2_CALL +axis2_http_simple_response_get_http_version( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + if(!(simple_response->status_line)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2 simple response , status line is not available"); + + return NULL; + } + return axis2_http_status_line_get_http_version(simple_response->status_line, env); +} + +axis2_status_t AXIS2_CALL +axis2_http_simple_response_set_http_version( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axis2_char_t *http_version) +{ + if(!(simple_response->status_line)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2 simple response , status line is not available"); + + return AXIS2_FAILURE; + } + axis2_http_status_line_set_http_version(simple_response->status_line, env, http_version); + return AXIS2_SUCCESS; +} + +axis2_char_t *AXIS2_CALL +axis2_http_simple_response_get_status_line( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + + if(!(simple_response->status_line)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2 simple response , status line is not available"); + + return NULL; + } + return axis2_http_status_line_to_string(simple_response->status_line, env); +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_http_simple_response_get_headers( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + return simple_response->header_group; +} + +axutil_array_list_t *AXIS2_CALL +axis2_http_simple_response_extract_headers( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + axutil_array_list_t *temp = NULL; + temp = simple_response->header_group; + if(temp) + { + simple_response->header_group = NULL; + } + return temp; +} + +axis2_http_header_t *AXIS2_CALL +axis2_http_simple_response_get_first_header( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + const axis2_char_t * str) +{ + axis2_http_header_t *tmp_header = 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, str, NULL); + + header_group = simple_response->header_group; + if(!simple_response->header_group) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 simple response , headers not available"); + return NULL; + } + + if(0 == axutil_array_list_size(header_group, env)) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "axis2 simple response , contains zero headers"); + + return NULL; + } + + count = axutil_array_list_size(header_group, env); + + for(i = 0; i < count; i++) + { + tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i); + tmp_name = axis2_http_header_get_name(tmp_header, env); + if(0 == axutil_strcasecmp(str, tmp_name)) + { + return tmp_header; + } + } + return NULL; + +} + +axis2_status_t AXIS2_CALL +axis2_http_simple_response_remove_headers( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + const axis2_char_t * str) +{ + axutil_array_list_t *header_group = NULL; + int i = 0; + int count = 0; + + AXIS2_PARAM_CHECK(env->error, str, AXIS2_FAILURE); + + header_group = simple_response->header_group; + if(!header_group) + { + /* Even though we couldn't complete the op, we are sure that the + * required header is no more in the request. So we can proceed without a + * problem. + */ + return AXIS2_SUCCESS; + } + + count = axutil_array_list_size(header_group, env); + for(i = 0; i < count; i++) + { + axis2_http_header_t *tmp_header = NULL; + axis2_char_t *tmp_name = NULL; + tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i); + tmp_name = axis2_http_header_get_name(tmp_header, env); + if(0 == axutil_strcasecmp(str, tmp_name)) + { + axis2_http_header_free(tmp_header, env); + axutil_array_list_remove(header_group, env, i); + break; + } + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_http_simple_response_set_header( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axis2_http_header_t * header) +{ + int i = 0; + int count = 0; + axutil_array_list_t *header_group = NULL; + + AXIS2_PARAM_CHECK(env->error, header, AXIS2_FAILURE); + + if(!simple_response->header_group) + { + simple_response->header_group = axutil_array_list_create(env, 10); + axutil_array_list_add(simple_response->header_group, env, header); + return AXIS2_SUCCESS; + } + + /* If a header with the same name exists search and remove the old header */ + header_group = simple_response->header_group; + count = axutil_array_list_size(header_group, env); + for(i = 0; i < count; i++) + { + axis2_http_header_t *tmp_header = NULL; + axis2_char_t *tmp_name = NULL; + tmp_header = (axis2_http_header_t *)axutil_array_list_get(header_group, env, i); + tmp_name = axis2_http_header_get_name(tmp_header, env); + if(0 == axutil_strcasecmp(axis2_http_header_get_name(header, env), tmp_name)) + { + axis2_http_header_free(tmp_header, env); + axutil_array_list_set(header_group, env, i, header); + return AXIS2_SUCCESS; + } + } + + /* if header is not found, then we have to add it */ + axutil_array_list_add(header_group, env, header); + return AXIS2_SUCCESS; +} + +const axis2_char_t *AXIS2_CALL +axis2_http_simple_response_get_charset( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header = NULL; + + tmp_header = axis2_http_simple_response_get_first_header(simple_response, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(tmp_header) + { + axis2_char_t *value = axis2_http_header_get_value(tmp_header, env); + axis2_char_t *charset = (axis2_char_t *)strstr((char *)value, + (char *)AXIS2_HTTP_CHAR_SET_ENCODING); + if(charset) + { + charset = strchr((char *)charset, AXIS2_EQ); + return charset; + } + } + + return AXIS2_HTTP_DEFAULT_CONTENT_CHARSET; +} + +axis2_ssize_t AXIS2_CALL +axis2_http_simple_response_get_content_length( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header = NULL; + int error_return = -1; + + tmp_header = axis2_http_simple_response_get_first_header(simple_response, env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH); + if(tmp_header) + { + return AXIS2_ATOI(axis2_http_header_get_value(tmp_header, env)); + } + return error_return; +} + +const axis2_char_t *AXIS2_CALL +axis2_http_simple_response_get_content_type( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + axis2_http_header_t *tmp_header = NULL; + + tmp_header = axis2_http_simple_response_get_first_header(simple_response, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(tmp_header) + { + return axis2_http_header_get_value(tmp_header, env); + } + + return AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN; +} + +axis2_status_t AXIS2_CALL +axis2_http_simple_response_set_body_string( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axis2_char_t * str) +{ + axutil_stream_t *body_stream = NULL; + + AXIS2_PARAM_CHECK(env->error, str, AXIS2_FAILURE); + + body_stream = simple_response->stream; + if(!body_stream) + { + body_stream = axutil_stream_create_basic(env); + if(!body_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "unable to create basic stream for string %s", + str); + return AXIS2_FAILURE; + } + simple_response->stream = body_stream; + } + axutil_stream_write(body_stream, env, str, axutil_strlen(str)); + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_http_simple_response_set_body_stream( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axutil_stream_t * stream) +{ + /* + * We don't free the stream + * Problem in freeing is most of the time the stream doesn't belong + * to the http_simple_response + */ + simple_response->stream = stream; + return AXIS2_SUCCESS; +} + +axutil_stream_t *AXIS2_CALL +axis2_http_simple_response_get_body( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + return simple_response->stream; +} + +axis2_ssize_t AXIS2_CALL +axis2_http_simple_response_get_body_bytes( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axis2_char_t ** buffer) +{ + axutil_stream_t *tmp_stream = NULL; + axis2_bool_t loop_state = AXIS2_TRUE; + int return_size = -1; + + if(!simple_response->stream) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_BODY, AXIS2_FAILURE); + return return_size; + } + tmp_stream = axutil_stream_create_basic(env); + while(loop_state) + { + int read = 0; + int write = 0; + char buf[AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE]; + + read = axutil_stream_read(simple_response->stream, env, buf, + AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE); + if(read < 0) + { + break; + } + write = axutil_stream_write(tmp_stream, env, buf, read); + if(read < (AXIS2_HTTP_SIMPLE_RESPONSE_READ_SIZE - 1)) + { + break; + } + } + return_size = axutil_stream_get_len(tmp_stream, env); + + if(return_size > 0) + { + *buffer = (char *)AXIS2_MALLOC(env->allocator, sizeof(char) * (return_size + 1)); + + if(!buffer) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return -1; + } + + return_size = axutil_stream_read(tmp_stream, env, *buffer, return_size + 1); + } + axutil_stream_free(tmp_stream, env); + return return_size; +} + +axis2_bool_t AXIS2_CALL +axis2_http_simple_response_contains_header( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + const axis2_char_t * name) +{ + axis2_char_t *header_name = NULL; + int count = 0; + int i = 0; + + AXIS2_PARAM_CHECK(env->error, name, AXIS2_FAILURE); + if(!simple_response->header_group) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 simple response , headers not available"); + return AXIS2_FALSE; + } + + count = axutil_array_list_size(simple_response->header_group, env); + if(0 == count) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "axis2 simple response , contains zero headers"); + return AXIS2_FALSE; + } + + for(i = 0; i < count; i++) + { + axis2_http_header_t *header = (axis2_http_header_t *)axutil_array_list_get( + simple_response->header_group, env, i); + header_name = axis2_http_header_get_name(header, env); + if(0 == axutil_strcasecmp(name, header_name)) + { + return AXIS2_TRUE; + } + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_http_simple_response_get_mime_parts( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + + return simple_response->mime_parts; + +} + +void AXIS2_EXTERN AXIS2_CALL +axis2_http_simple_response_set_mime_parts( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axutil_array_list_t *mime_parts) +{ + + simple_response->mime_parts = mime_parts; + +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_simple_response_get_mtom_sending_callback_name( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env) +{ + return simple_response->mtom_sending_callback_name; +} + +void AXIS2_EXTERN AXIS2_CALL +axis2_http_simple_response_set_mtom_sending_callback_name( + axis2_http_simple_response_t * simple_response, + const axutil_env_t * env, + axis2_char_t *mtom_sending_callback_name) +{ + simple_response->mtom_sending_callback_name = + mtom_sending_callback_name; +} diff --git a/src/core/transport/http/common/http_status_line.c b/src/core/transport/http/common/http_status_line.c new file mode 100644 index 0000000..fdf0fea --- /dev/null +++ b/src/core/transport/http/common/http_status_line.c @@ -0,0 +1,267 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +struct axis2_http_status_line +{ + axis2_char_t *line; + axis2_char_t *http_version; + axis2_char_t *status_code; + axis2_char_t *reason_phrase; +}; + +AXIS2_EXTERN axis2_http_status_line_t *AXIS2_CALL +axis2_http_status_line_create( + const axutil_env_t * env, + const axis2_char_t * str) +{ + axis2_char_t *tmp_status_line = NULL; + axis2_char_t *reason_phrase = NULL; + axis2_char_t *status_code = NULL; + axis2_char_t *http_version = NULL; + int i = 0; + axis2_char_t *tmp = NULL; + axis2_http_status_line_t *status_line = NULL; + + status_line = (axis2_http_status_line_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_status_line_t)); + + if(!status_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)status_line, 0, sizeof(axis2_http_status_line_t)); + status_line->line = (axis2_char_t *)axutil_strdup(env, str); + + /* extract status code, phrase and version from given string */ + tmp = strstr(str, AXIS2_HTTP_CRLF); + if(!tmp) + { + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + + i = (int)(tmp - str); /* We are sure that the difference lies within the int range */ + + tmp_status_line = AXIS2_MALLOC(env->allocator, i * sizeof(axis2_char_t) + 1); + if(!tmp_status_line) + { + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memcpy(tmp_status_line, str, i * sizeof(axis2_char_t)); + tmp_status_line[i] = AXIS2_ESC_NULL; + tmp = tmp_status_line; + + /* get HTTP version */ + http_version = tmp; + tmp = strchr(tmp, AXIS2_SPACE); + if(!tmp) + { + AXIS2_FREE(env->allocator, tmp_status_line); + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + *tmp++ = AXIS2_ESC_NULL; + + /* get status code */ + status_code = tmp; + tmp = strchr(tmp, AXIS2_SPACE); + if(!tmp) + { + AXIS2_FREE(env->allocator, tmp_status_line); + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + *tmp++ = AXIS2_ESC_NULL; + + /* get reason phrase */ + reason_phrase = tmp; + + /* populate values */ + status_line->http_version = (axis2_char_t *)axutil_strdup(env, http_version); + status_line->status_code = (axis2_char_t *)axutil_strdup(env, status_code); + status_line->reason_phrase = (axis2_char_t *)axutil_strdup(env, reason_phrase); + AXIS2_FREE(env->allocator, tmp_status_line); + + if(!status_line->http_version || !status_line->reason_phrase || !status_line->status_code) + { + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + return status_line; +} + +AXIS2_EXTERN axis2_http_status_line_t *AXIS2_CALL +axis2_http_status_line_create_with_values( + const axutil_env_t * env, + const axis2_char_t * http_ver, + const int status_code, + const axis2_char_t * phrase) +{ + axis2_http_status_line_t *status_line = NULL; + status_line = (axis2_http_status_line_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_status_line_t)); + if(!status_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)status_line, 0, sizeof(axis2_http_status_line_t)); + + status_line->status_code = AXIS2_MALLOC(env->allocator, 6 * sizeof(axis2_char_t *)); + if(!status_line->status_code) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + axis2_http_status_line_free(status_line, env); + return NULL; + } + sprintf(status_line->status_code, "%3d", status_code); + + status_line->http_version = axutil_strdup(env, http_ver); + status_line->reason_phrase = axutil_strdup(env, phrase); + if(!status_line->http_version || !status_line->reason_phrase) + { + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + status_line->line = axutil_strcat(env, http_ver, " ", status_line->status_code, " ", phrase, + AXIS2_HTTP_CRLF, NULL); + if(!status_line->line) + { + axis2_http_status_line_free(status_line, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + return status_line; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_status_line_free( + axis2_http_status_line_t * status_line, + const axutil_env_t * env) +{ + + if(!status_line) + { + return; + } + + if(status_line->line) + { + AXIS2_FREE(env->allocator, status_line->line); + } + if(status_line->http_version) + { + AXIS2_FREE(env->allocator, status_line->http_version); + } + if(status_line->status_code) + { + AXIS2_FREE(env->allocator, status_line->status_code); + } + if(status_line->reason_phrase) + { + AXIS2_FREE(env->allocator, status_line->reason_phrase); + } + + AXIS2_FREE(env->allocator, status_line); + return; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_status_line_get_status_code( + const axis2_http_status_line_t * status_line, + const axutil_env_t * env) +{ + if(status_line->status_code) + { + return AXIS2_ATOI(status_line->status_code); + } + else + { + return AXIS2_CRITICAL_FAILURE; + } + +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_status_line_get_http_version( + const axis2_http_status_line_t * status_line, + const axutil_env_t * env) +{ + return status_line->http_version; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_status_line_set_http_version( + axis2_http_status_line_t * status_line, + const axutil_env_t * env, + axis2_char_t *http_version) +{ + if(status_line->http_version) + { + AXIS2_FREE(env->allocator, status_line->http_version); + status_line->http_version = NULL; + } + + status_line->http_version = (axis2_char_t *)axutil_strdup(env, http_version); + +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_status_line_get_reason_phrase( + const axis2_http_status_line_t * status_line, + const axutil_env_t * env) +{ + return status_line->reason_phrase; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_status_line_starts_with_http( + axis2_http_status_line_t * status_line, + const axutil_env_t * env) +{ + if(0 == axutil_strncasecmp(status_line->line, AXIS2_HTTP, 4)) + { + return AXIS2_TRUE; + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_status_line_to_string( + axis2_http_status_line_t * status_line, + const axutil_env_t * env) +{ + return status_line->line; +} diff --git a/src/core/transport/http/common/http_worker.c b/src/core/transport/http/common/http_worker.c new file mode 100644 index 0000000..26ccce3 --- /dev/null +++ b/src/core/transport/http/common/http_worker.c @@ -0,0 +1,2064 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct axis2_http_worker +{ + axis2_conf_ctx_t *conf_ctx; + int svr_port; + axis2_bool_t is_application_client_side; +}; + +static axis2_status_t +axis2_http_worker_set_response_headers( + axis2_http_worker_t * http_worker, + const axutil_env_t * env, + axis2_simple_http_svr_conn_t * svr_conn, + axis2_http_simple_request_t * simple_request, + axis2_http_simple_response_t * simple_response, + axis2_ssize_t content_length); + +static axutil_hash_t * +axis2_http_worker_get_headers( + axis2_http_worker_t * http_worker, + const axutil_env_t * env, + axis2_http_simple_request_t * request); + +static axis2_http_simple_response_t * +axis2_http_worker_create_simple_response( + axis2_http_worker_t *http_worker, + const axutil_env_t *env); + +AXIS2_EXTERN axis2_http_worker_t *AXIS2_CALL +axis2_http_worker_create( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + axis2_http_worker_t *http_worker = NULL; + + http_worker = (axis2_http_worker_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_http_worker_t)); + + if(!http_worker) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + http_worker->conf_ctx = conf_ctx; + http_worker->svr_port = 9090; /* default - must set later */ + http_worker->is_application_client_side = AXIS2_FALSE; /* default is creating for application + server side */ + + return http_worker; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_worker_free( + axis2_http_worker_t * http_worker, + const axutil_env_t * env) +{ + http_worker->conf_ctx = NULL; + AXIS2_FREE(env->allocator, http_worker); + return; +} + +/* Each in-coming request is passed into this function for process. Basically http method to deliver + * is deduced here and call appropriate http processing function. + * eg. transport_utils_process_http_post_request() function. Once this function call done it will go + * through engine inflow phases and finally hit the message receiver for the operation. + */ +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_worker_process_request( + axis2_http_worker_t * http_worker, + const axutil_env_t * env, + axis2_simple_http_svr_conn_t * svr_conn, + axis2_http_simple_request_t * simple_request) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_msg_ctx_t *msg_ctx = NULL; + axutil_stream_t *request_body = NULL; + + /* Creating out_stream as basic stream */ + axutil_stream_t *out_stream = axutil_stream_create_basic(env); + axis2_http_simple_response_t *response = NULL; + + /* Transport in and out descriptions */ + axis2_transport_out_desc_t *out_desc = NULL; + axis2_transport_in_desc_t *in_desc = NULL; + + axis2_char_t *http_version = NULL; + axis2_char_t *soap_action = NULL; + axutil_string_t *soap_action_str = NULL; + axis2_bool_t processed = AXIS2_FALSE; + axis2_status_t status = AXIS2_FAILURE; + int content_length = -1; + axis2_http_header_t *encoding_header = NULL; + axis2_char_t *encoding_header_value = NULL; + axis2_op_ctx_t *op_ctx = NULL; + axis2_char_t *svr_ip = NULL; + axis2_char_t *peer_ip = NULL; + axutil_url_t *request_url = NULL; + axis2_http_out_transport_info_t *http_out_transport_info = NULL; + axutil_hash_t *headers = NULL; + axis2_char_t *url_external_form = NULL; + axis2_char_t *svc_grp_uuid = NULL; + axis2_char_t *path = NULL; + axutil_property_t *peer_property = NULL; + + /* REST processing variables */ + axis2_bool_t is_get = AXIS2_FALSE; + axis2_bool_t is_head = AXIS2_FALSE; + axis2_bool_t is_put = AXIS2_FALSE; + axis2_bool_t is_delete = AXIS2_FALSE; + axis2_bool_t request_handled = AXIS2_FALSE; + + /* HTTP and Proxy authentication */ + axis2_char_t *cookie_header_value = NULL; + /*axis2_char_t *set_cookie_header_value = NULL; + axis2_http_header_t *set_cookie_header = NULL; + axis2_http_header_t *connection_header = NULL;*/ + axis2_http_header_t *cookie_header = NULL; + axis2_char_t *accept_header_value = NULL; + axis2_http_header_t *accept_header = NULL; + axis2_char_t *accept_charset_header_value = NULL; + axis2_http_header_t *accept_charset_header = NULL; + axis2_char_t *accept_language_header_value = NULL; + axis2_http_header_t *accept_language_header = NULL; + + axis2_char_t *http_method = NULL; + axis2_http_request_line_t *request_line = NULL; + + axutil_hash_t *request_params = NULL; + axis2_char_t *request_uri = NULL; + axis2_char_t *url_ext_form = NULL; + const axis2_char_t *content_type = NULL; + + axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + + AXIS2_PARAM_CHECK(env->error, svr_conn, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, simple_request, AXIS2_FALSE); + + conf_ctx = http_worker->conf_ctx; + if(!conf_ctx) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_CONFIGURATION_CONTEXT, AXIS2_FAILURE); + return AXIS2_FALSE; + } + + content_length = axis2_http_simple_request_get_content_length(simple_request, env); + request_line = axis2_http_simple_request_get_request_line(simple_request, env); + http_method = axis2_http_request_line_get_method(request_line, env); + + http_version = axis2_http_request_line_get_http_version(request_line, env); + if(!http_version) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_HTTP_VERSION, AXIS2_FAILURE); + return AXIS2_FALSE; + } + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Client HTTP version %s", http_version); + + encoding_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING); + if(encoding_header) + { + encoding_header_value = axis2_http_header_get_value(encoding_header, env); + } + + response = axis2_http_worker_create_simple_response(http_worker, env); + if(!response) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "cannot create http simple response"); + return AXIS2_FALSE; + } + + /* if length is not given and it is not chunked, then return error to client */ + if((content_length < 0) && encoding_header_value + && (0 != axutil_strcmp(encoding_header_value, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED))) + { + if(0 == axutil_strcasecmp(http_method, AXIS2_HTTP_POST) + || 0 == axutil_strcasecmp(http_method, AXIS2_HTTP_PUT)) + { + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_LENGTH_REQUIRED_CODE_VAL, + AXIS2_HTTP_RESPONSE_LENGTH_REQUIRED_CODE_NAME); + + status = axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + axis2_http_simple_response_free(response, env); + return status; + } + } + + request_body = axis2_http_simple_request_get_body(simple_request, env); + + out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + + msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc); + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + + cookie_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_COOKIE); + if(cookie_header) + { + char *session_str = NULL; + axis2_char_t *session_id = NULL; + + cookie_header_value = axis2_http_header_get_value(cookie_header, env); + session_id = axis2_http_transport_utils_get_session_id_from_cookie(env, + cookie_header_value); + if(session_id) + session_str = env->get_session_fn((void *) conf_ctx, session_id); + if(session_str) + axis2_http_transport_utils_set_session(env, msg_ctx, session_str); + } + + /*connection_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_CONNECTION); + if(connection_header) + { + axutil_property_t *connection_header_property = NULL; + axis2_char_t *connection_header_value = NULL; + connection_header_value = axis2_http_header_get_value(connection_header, env); + connection_header_property = axutil_property_create_with_args(env, + AXIS2_SCOPE_REQUEST, 0, 0, connection_header_value); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_HEADER_CONNECTION, + connection_header_property); + }*/ + + /* Server and Peer IP's */ + svr_ip = axis2_simple_http_svr_conn_get_svr_ip(svr_conn, env); + peer_ip = axis2_simple_http_svr_conn_get_peer_ip(svr_conn, env); + + if(peer_ip) + { + peer_property = axutil_property_create(env); + axutil_property_set_value(peer_property, env, axutil_strdup(env, peer_ip)); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_SVR_PEER_IP_ADDR, peer_property); + } + + path = axis2_http_request_line_get_uri(request_line, env); + + request_url = axutil_url_create(env, AXIS2_HTTP_PROTOCOL, svr_ip, http_worker->svr_port, path); + if(request_url) + { + url_external_form = axutil_url_to_external_form(request_url, env); + } + + if(!url_external_form) + { + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL, AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_NAME); + status = axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + axis2_http_simple_response_free(response, env); + response = NULL; + return status; + } + + accept_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_ACCEPT); + if(accept_header) + { + accept_header_value = axis2_http_header_get_value(accept_header, env); + } + if(accept_header_value) + { + axutil_array_list_t *accept_header_field_list = NULL; + axutil_array_list_t *accept_record_list = NULL; + accept_header_field_list = axutil_tokenize(env, accept_header_value, AXIS2_COMMA); + if(accept_header_field_list && axutil_array_list_size(accept_header_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_header_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_record_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_header_field_list, env, 0); + } + while(token); + } + if(accept_record_list && axutil_array_list_size(accept_record_list, env) > 0) + { + axis2_msg_ctx_set_http_accept_record_list(msg_ctx, env, accept_record_list); + } + } + + accept_charset_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_ACCEPT_CHARSET); + if(accept_charset_header) + { + accept_charset_header_value = axis2_http_header_get_value(accept_charset_header, env); + } + if(accept_charset_header_value) + { + axutil_array_list_t *accept_charset_header_field_list = NULL; + axutil_array_list_t *accept_charset_record_list = NULL; + accept_charset_header_field_list = axutil_tokenize(env, accept_charset_header_value, + AXIS2_COMMA); + if(accept_charset_header_field_list && axutil_array_list_size( + accept_charset_header_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_charset_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_charset_header_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_charset_record_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_charset_header_field_list, + env, 0); + } + while(token); + } + + if(accept_charset_record_list && axutil_array_list_size(accept_charset_record_list, env) + > 0) + { + axis2_msg_ctx_set_http_accept_charset_record_list(msg_ctx, env, + accept_charset_record_list); + } + } + + accept_language_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_ACCEPT_LANGUAGE); + if(accept_language_header) + { + accept_language_header_value = axis2_http_header_get_value(accept_language_header, env); + } + + if(accept_language_header_value) + { + axutil_array_list_t *accept_language_header_field_list = NULL; + axutil_array_list_t *accept_language_record_list = NULL; + accept_language_header_field_list = axutil_tokenize(env, accept_language_header_value, + AXIS2_COMMA); + if(accept_language_header_field_list && axutil_array_list_size( + accept_language_header_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_language_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_language_header_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_language_record_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_language_header_field_list, + env, 0); + } + while(token); + } + if(accept_language_record_list && axutil_array_list_size(accept_language_record_list, env) + > 0) + { + axis2_msg_ctx_set_http_accept_language_record_list(msg_ctx, env, + accept_language_record_list); + } + } + + /* Here out_stream is set into the in message context. out_stream is copied from in message context + * into the out message context later in core_utils_create_out_msg_ctx() function. The buffer in + * out_stream is finally filled with the soap envelope in http_transport_sender_invoke() function. + * To avoid double freeing of out_stream we reset the out message context at the end of engine + * receive function. + */ + axis2_msg_ctx_set_transport_out_stream(msg_ctx, env, out_stream); + + headers = axis2_http_worker_get_headers(http_worker, env, simple_request); + axis2_msg_ctx_set_transport_headers(msg_ctx, env, headers); + + svc_grp_uuid = axutil_uuid_gen(env); + if(svc_grp_uuid) + { + axutil_string_t *svc_grp_uuid_str = axutil_string_create_assume_ownership(env, + &svc_grp_uuid); + axis2_msg_ctx_set_svc_grp_ctx_id(msg_ctx, env, svc_grp_uuid_str); + axutil_string_free(svc_grp_uuid_str, env); + } + + http_out_transport_info = axis2_http_out_transport_info_create(env, response); + axis2_msg_ctx_set_out_transport_info(msg_ctx, env, &(http_out_transport_info->out_transport)); + + if(axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_SOAP_ACTION)) + { + soap_action = axis2_http_header_get_value(axis2_http_simple_request_get_first_header( + simple_request, env, AXIS2_HTTP_HEADER_SOAP_ACTION), env); + soap_action_str = axutil_string_create(env, soap_action); + } + + if(0 == axutil_strcasecmp(http_method, AXIS2_HTTP_GET)) + { + is_get = AXIS2_TRUE; + } + else if(0 == axutil_strcasecmp(http_method, AXIS2_HTTP_HEAD)) + { + is_head = AXIS2_TRUE; + } + else if(0 == axutil_strcasecmp(http_method, AXIS2_HTTP_DELETE)) + { + is_delete = AXIS2_TRUE; + } + else if(0 == axutil_strcasecmp(http_method, AXIS2_HTTP_PUT)) + { + is_put = AXIS2_TRUE; + } + + request_uri = axis2_http_request_line_get_uri(request_line, env); + request_params = axis2_http_transport_utils_get_request_params(env, request_uri); + url_ext_form = axutil_url_to_external_form(request_url, env); + + content_type = axis2_http_simple_request_get_content_type(simple_request, env); + + if(is_get || is_head || is_delete) + { + + if(is_get) + { + /* HTTP GET */ + processed = axis2_http_transport_utils_process_http_get_request(env, msg_ctx, + request_body, out_stream, content_type, soap_action_str, url_ext_form, conf_ctx, + request_params); + } + else if(is_delete) + { + /* HTTP DELETE */ + processed = axis2_http_transport_utils_process_http_delete_request(env, msg_ctx, + request_body, out_stream, content_type, soap_action_str, url_ext_form, conf_ctx, + request_params); + } + else if(is_head) + { + /* HTTP HEAD */ + processed = axis2_http_transport_utils_process_http_head_request(env, msg_ctx, + request_body, out_stream, content_type, soap_action_str, url_ext_form, conf_ctx, + request_params); + } + + if(AXIS2_FALSE == processed) + { + axis2_http_header_t *cont_len = NULL; + axis2_http_header_t *cont_type = NULL; + axis2_char_t *body_string = NULL; + axis2_char_t *wsdl = NULL; + axis2_bool_t is_services_path = AXIS2_FALSE; + + if(!is_delete) + { + axis2_char_t *temp = NULL; + /* check whether request url have "/services" */ + temp = strstr(axutil_url_get_path(request_url, env), AXIS2_REQUEST_URL_PREFIX); + if(temp) + { + temp += strlen(AXIS2_REQUEST_URL_PREFIX); + if(*temp == AXIS2_F_SLASH) + { + temp++; + } + if(!*temp || *temp == AXIS2_Q_MARK || *temp == AXIS2_H_MARK) + { + is_services_path = AXIS2_TRUE; + } + } + + } + + /* processing request for WSDL via "?wsdl" */ + wsdl = strstr(url_external_form, AXIS2_REQUEST_WSDL); + if(is_services_path) + { + /* request for service */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_OK_CODE_VAL, AXIS2_HTTP_RESPONSE_OK_CODE_NAME); + body_string = axis2_http_transport_utils_get_services_html(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(!is_delete && wsdl) + { + /* Request is not for delete and ask for wsdl */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_OK_CODE_VAL, AXIS2_HTTP_RESPONSE_OK_CODE_NAME); + body_string = axis2_http_transport_utils_get_services_static_wsdl(env, conf_ctx, + url_external_form); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_APPLICATION_XML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND) + { + + /* Processing SVC or Operation Not found case */ + axutil_array_list_t *method_list = NULL; + int size = 0; + method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env); + size = axutil_array_list_size(method_list, env); + if(method_list && size) + { + axis2_http_header_t *allow_header = NULL; + axis2_char_t *method_list_str = NULL; + axis2_char_t *temp; + int i = 0; + method_list_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 29); + + if(!method_list_str) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FALSE); + } + + temp = method_list_str; + for(i = 0; i < size; i++) + { + if(i) + { + sprintf(temp, AXIS2_COMMA_SPACE_STR); + temp += 2; + } + sprintf(temp, "%s", (axis2_char_t *)axutil_array_list_get(method_list, env, + i)); + temp += strlen(temp); + } + *temp = AXIS2_ESC_NULL; + + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_VAL, + AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_NAME); + + body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx); + allow_header = axis2_http_header_create(env, AXIS2_HTTP_HEADER_ALLOW, + method_list_str); + axis2_http_simple_response_set_header(response, env, allow_header); + AXIS2_FREE(env->allocator, method_list_str); + } + else + { + /* 404 Not Found */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_VAL, + AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_NAME); + + body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx); + } + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL) + { + /* 400 Bad Request */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL, + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_NAME); + + body_string = axis2_http_transport_utils_get_bad_request(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL) + { + + /* 408 , Request Time Out */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL, + AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_NAME); + + body_string = axis2_http_transport_utils_get_request_timeout(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL) + { + /* 409, Conflict */ + + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL, AXIS2_HTTP_RESPONSE_CONFLICT_CODE_NAME); + + body_string = axis2_http_transport_utils_get_conflict(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_GONE_CODE_VAL) + { + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_GONE_CODE_VAL, AXIS2_HTTP_RESPONSE_GONE_CODE_NAME); + + body_string = axis2_http_transport_utils_get_gone(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL) + { + /* 412 Precondition failed */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL, + AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_NAME); + + body_string = axis2_http_transport_utils_get_precondition_failed(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL) + { + /* 413 entity too large */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL, + AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_NAME); + + body_string + = axis2_http_transport_utils_get_request_entity_too_large(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL) + { + /* 503, Service Unavailable*/ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL, + AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_NAME); + + body_string = axis2_http_transport_utils_get_service_unavailable(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else + { + /* 500 Internal Server Error */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL, + AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_NAME); + + body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + + if(body_string) + { + axis2_char_t str_len[10]; + if(!is_head) + { + axis2_http_simple_response_set_body_string(response, env, body_string); + } + sprintf(str_len, "%d", axutil_strlen(body_string)); + cont_len = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_LENGTH, str_len); + axis2_http_simple_response_set_header(response, env, cont_len); + } + + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, simple_request, + response, 0); + + axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + request_handled = AXIS2_TRUE; + status = AXIS2_TRUE; + } + } + else if(0 == axutil_strcasecmp(http_method, AXIS2_HTTP_POST) || is_put) + { + if(is_put) + { + axutil_property_t *property = NULL; + if(http_worker->is_application_client_side) + { + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_TRUE, 0, + AXIS2_VALUE_TRUE); + } + else + { + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_FALSE, + 0, AXIS2_VALUE_FALSE); + } + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANPORT_IS_APPLICATION_CLIENT_SIDE, + property); + status = axis2_http_transport_utils_process_http_put_request(env, msg_ctx, + request_body, out_stream, content_type, content_length, soap_action_str, + url_ext_form); + + } + else + { + axutil_property_t *property = NULL; + if(http_worker->is_application_client_side) + { + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_TRUE, 0, + AXIS2_VALUE_TRUE); + } + else + { + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_FALSE, + 0, AXIS2_VALUE_FALSE); + } + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANPORT_IS_APPLICATION_CLIENT_SIDE, + property); + status = axis2_http_transport_utils_process_http_post_request(env, msg_ctx, + request_body, out_stream, content_type, content_length, soap_action_str, + url_ext_form); + + } + if(url_ext_form) + AXIS2_FREE(env->allocator, url_ext_form); + if(AXIS2_FAILURE == status && (is_put || axis2_msg_ctx_get_doing_rest(msg_ctx, env))) + { + /* Failure Occur while processing REST */ + + axis2_http_header_t *cont_len = NULL; + axis2_http_header_t *cont_type = NULL; + axis2_char_t *body_string = NULL; + if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND) + { + axutil_array_list_t *method_list = NULL; + int size = 0; + method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env); + size = axutil_array_list_size(method_list, env); + if(method_list && size) + { + axis2_http_header_t *allow_header = NULL; + axis2_char_t *method_list_str = NULL; + axis2_char_t *temp; + int i = 0; + method_list_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 29); + if(!method_list_str) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FALSE); + } + + temp = method_list_str; + for(i = 0; i < size; i++) + { + if(i) + { + sprintf(temp, AXIS2_COMMA_SPACE_STR); + temp += 2; + } + sprintf(temp, "%s", (axis2_char_t *)axutil_array_list_get(method_list, env, + i)); + temp += strlen(temp); + } + *temp = AXIS2_ESC_NULL; + + /* 405 Method Not Allowed */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_VAL, + AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_NAME); + + body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx); + allow_header = axis2_http_header_create(env, AXIS2_HTTP_HEADER_ALLOW, + method_list_str); + axis2_http_simple_response_set_header(response, env, allow_header); + AXIS2_FREE(env->allocator, method_list_str); + } + else + { + /* 404 Not Found */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_VAL, + AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_NAME); + + body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx); + } + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL) + { + /* 400, Bad Request */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL, + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_NAME); + + body_string = axis2_http_transport_utils_get_bad_request(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL) + { + /* 408, Request Timeout */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL, + AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_NAME); + + body_string = axis2_http_transport_utils_get_request_timeout(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL) + { + /* 409, Conflict Types */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL, AXIS2_HTTP_RESPONSE_CONFLICT_CODE_NAME); + + body_string = axis2_http_transport_utils_get_conflict(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_GONE_CODE_VAL) + { + /* 410, Gone. Resource no longer available */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_GONE_CODE_VAL, AXIS2_HTTP_RESPONSE_GONE_CODE_NAME); + + body_string = axis2_http_transport_utils_get_gone(env, conf_ctx); + + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL) + { + /*410, Precondition for the url failed */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL, + AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_NAME); + + body_string = axis2_http_transport_utils_get_precondition_failed(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL) + { + /* 413, Request entity too large */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL, + AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_NAME); + + body_string + = axis2_http_transport_utils_get_request_entity_too_large(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL) + { + /* 513, Service Unavailable */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL, + AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_NAME); + + body_string = axis2_http_transport_utils_get_service_unavailable(env, conf_ctx); + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + else + { + /* 500, Internal Server Error */ + axis2_http_simple_response_set_status_line(response, env, http_version, + AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL, + AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_NAME); + + body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx); + + cont_type = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + } + + if(body_string) + { + axis2_char_t str_len[10]; + if(!is_head) + { + axis2_http_simple_response_set_body_string(response, env, body_string); + } + sprintf(str_len, "%d", axutil_strlen(body_string)); + cont_len = axis2_http_header_create(env, AXIS2_HTTP_HEADER_CONTENT_LENGTH, str_len); + axis2_http_simple_response_set_header(response, env, cont_len); + } + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, simple_request, + response, 0); + axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + request_handled = AXIS2_TRUE; + status = AXIS2_TRUE; + } + else if(status == AXIS2_FAILURE) + { + axis2_msg_ctx_t *fault_ctx = NULL; + axis2_engine_t *engine = axis2_engine_create(env, conf_ctx); + axis2_http_request_line_t *req_line = NULL; + axis2_http_status_line_t *tmp_stat_line = NULL; + axis2_char_t status_line_str[100]; + axutil_property_t *http_error_property = NULL; + axis2_char_t *http_error_value = NULL; + axis2_char_t *fault_code = NULL; + int status_code = 0; + axis2_char_t *reason_phrase = NULL; + int stream_len = 0; + + if(!engine) + { + return AXIS2_FALSE; + } + + http_error_property = axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_TRANSPORT_ERROR); + + if(http_error_property) + http_error_value = (axis2_char_t *)axutil_property_get_value(http_error_property, + env); + + if(axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX AXIS2_COLON_STR + AXIOM_SOAP11_FAULT_CODE_SENDER; + } + else + { + fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX AXIS2_COLON_STR + AXIOM_SOAP12_SOAP_FAULT_VALUE_SENDER; + } + + fault_ctx = axis2_engine_create_fault_msg_ctx(engine, env, msg_ctx, + fault_code, + axutil_error_get_message + (env->error)); + req_line = + axis2_http_simple_request_get_request_line(simple_request, env); + if (req_line) + { + if (!http_error_value) + { + sprintf(status_line_str, "%s %s\r\n", + http_version, + AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR); + } + else + { + sprintf(status_line_str, "%s %s", + http_version, + http_error_value); + } + } + else + { + sprintf(status_line_str, "%s %s\r\n", + AXIS2_HTTP_HEADER_PROTOCOL_11, + AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR); + } + + tmp_stat_line = axis2_http_status_line_create(env, status_line_str); + + if (!http_error_value) + { + axis2_engine_send_fault(engine, env, fault_ctx); + } + + status_code = axis2_http_status_line_get_status_code(tmp_stat_line, env); + reason_phrase = axis2_http_status_line_get_reason_phrase(tmp_stat_line, env); + + axis2_http_simple_response_set_status_line(response, env, + http_version, + status_code, + reason_phrase); + + axis2_http_simple_response_set_body_stream(response, env, + out_stream); + + stream_len = axutil_stream_get_len (out_stream, env); + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, + stream_len); + + status = axis2_simple_http_svr_conn_write_response(svr_conn, env, + response); + request_handled = AXIS2_TRUE; + if(tmp_stat_line) + { + axis2_http_status_line_free(tmp_stat_line, env); + tmp_stat_line = NULL; + } + } + } + else + { + /* Other case than, PUT, DELETE, HEAD, GET and POST */ + /* 501, Request method is not implemented */ + axis2_http_header_t *cont_len = NULL; + axis2_http_header_t *cont_type = NULL; + axis2_char_t *body_string = NULL; + axis2_http_simple_response_set_status_line( + response, env, + http_version, + AXIS2_HTTP_RESPONSE_NOT_IMPLEMENTED_CODE_VAL, + AXIS2_HTTP_RESPONSE_NOT_IMPLEMENTED_CODE_NAME); + + body_string = + axis2_http_transport_utils_get_not_implemented(env, + conf_ctx); + cont_type = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + axis2_http_simple_response_set_header(response, env, cont_type); + + if (body_string) + { + axis2_char_t str_len[10]; + axis2_http_simple_response_set_body_string(response, env, + body_string); + sprintf(str_len, "%d", axutil_strlen(body_string)); + cont_len = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH, + str_len); + axis2_http_simple_response_set_header(response, env, cont_len); + } + + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, 0); + axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + request_handled = AXIS2_TRUE; + status = AXIS2_TRUE; + } + + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + if (op_ctx) + { + /*axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL;*/ + axis2_char_t *language_str = NULL; + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + if (out_msg_ctx) + { + language_str = axis2_msg_ctx_get_content_language(out_msg_ctx, env); + } + + if (language_str && *language_str && !request_handled) + { + axis2_http_header_t *language = NULL; + language = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_LANGUAGE, + language_str); + axis2_http_simple_response_set_header(response, env, language); + } + } + + if (!request_handled) + { + axis2_bool_t do_rest = AXIS2_FALSE; + axis2_bool_t response_written = AXIS2_FALSE; + if (is_get || is_head || is_put || is_delete || + axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + do_rest = AXIS2_TRUE; + } + + if ((accept_header_value || accept_charset_header_value || + accept_language_header_value) && do_rest) + { + axis2_char_t *content_type_header_value = NULL; + axis2_http_header_t *content_type_header = NULL; + axis2_char_t *temp = NULL; + axis2_char_t *language_header_value = NULL; + axis2_http_header_t *language_header = NULL; + content_type_header = axis2_http_simple_response_get_first_header( + response, + env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + + language_header = axis2_http_simple_response_get_first_header( + response, + env, + AXIS2_HTTP_HEADER_CONTENT_LANGUAGE); + + if (content_type_header) + { + content_type_header_value = axis2_http_header_get_value(content_type_header, + env); + } + + if (content_type_header_value) + { + temp = axutil_strdup(env, content_type_header_value); + } + + if (language_header) + { + language_header_value = axis2_http_header_get_value(language_header, + env); + } + + if (temp) + { + axis2_char_t *content_type = NULL; + axis2_char_t *char_set = NULL; + axis2_char_t *temp2 = NULL; + + temp2 = strchr(temp, AXIS2_SEMI_COLON); + if (temp2) + { + *temp2 = AXIS2_ESC_NULL; + temp2++; + char_set = axutil_strcasestr(temp2, AXIS2_HTTP_CHAR_SET_ENCODING); + } + + if (char_set) + { + char_set = axutil_strltrim(env, char_set, AXIS2_SPACE_TAB_EQ); + } + + content_type = axutil_strtrim(env, temp, NULL); + + if (temp) + { + AXIS2_FREE(env->allocator, temp); + temp = NULL; + } + + if (content_type && accept_header_value && + !axutil_strcasestr(accept_header_value, content_type)) + { + temp2 = strchr(content_type, AXIS2_F_SLASH); + if (temp2) + { + *temp2 = AXIS2_ESC_NULL; + temp = AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * + ((int)strlen(content_type) + 3)); + if (!temp) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return AXIS2_FALSE; + } + + sprintf(temp, "%s/*", content_type); + if (!axutil_strcasestr(accept_header_value, temp) && + !strstr(accept_header_value, AXIS2_HTTP_HEADER_ACCEPT_ALL)) + { + /* 406, Not Acceptable */ + axis2_http_header_t *cont_len = NULL; + axis2_http_header_t *cont_type = NULL; + axis2_char_t *body_string = NULL; + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_VAL, + AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_NAME); + + body_string = + axis2_http_transport_utils_get_not_acceptable(env, + conf_ctx); + cont_type = + axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + if (body_string) + { + axis2_char_t str_len[10]; + axis2_http_simple_response_set_body_string(response, env, + body_string); + sprintf(str_len, "%d", axutil_strlen(body_string)); + cont_len = + axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH, + str_len); + + axis2_http_simple_response_set_header(response, + env, + cont_len); + } + + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, 0); + axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + request_handled = AXIS2_TRUE; + status = AXIS2_TRUE; + response_written = AXIS2_TRUE; + } + AXIS2_FREE(env->allocator, temp); + } + } + + if (content_type) + { + AXIS2_FREE(env->allocator, content_type); + } + + if (char_set) + { + temp2 = strchr(char_set, AXIS2_EQ); + } + + if (temp2) + { + ++temp2; + } + + if (char_set && accept_charset_header_value && + !axutil_strcasestr(accept_charset_header_value, char_set) && + !axutil_strcasestr(accept_charset_header_value, temp2)) + { + /* 406, Not Acceptable */ + axis2_http_header_t *cont_len = NULL; + axis2_http_header_t *cont_type = NULL; + axis2_char_t *body_string = NULL; + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_VAL, + AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_NAME); + body_string = + axis2_http_transport_utils_get_not_acceptable(env, + conf_ctx); + cont_type = + axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + if (body_string) + { + axis2_char_t str_len[10]; + axis2_http_simple_response_set_body_string(response, env, + body_string); + sprintf(str_len, "%d", axutil_strlen(body_string)); + cont_len = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH, + str_len); + axis2_http_simple_response_set_header(response, env, cont_len); + } + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, 0); + axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + request_handled = AXIS2_TRUE; + status = AXIS2_TRUE; + response_written = AXIS2_TRUE; + } + if (char_set) + { + AXIS2_FREE(env->allocator, char_set); + } + } + + if (language_header_value) + { + if (accept_language_header_value && + !axutil_strcasestr(accept_language_header_value, + language_header_value)) + { + /* 406, Not acceptable */ + axis2_http_header_t *cont_len = NULL; + axis2_http_header_t *cont_type = NULL; + axis2_char_t *body_string = NULL; + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_VAL, + AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_NAME); + + body_string = + axis2_http_transport_utils_get_not_acceptable(env, + conf_ctx); + cont_type = + axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_TYPE, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML); + + axis2_http_simple_response_set_header(response, env, cont_type); + axis2_http_simple_response_remove_headers( + response, + env, + AXIS2_HTTP_HEADER_CONTENT_LANGUAGE); + + if (body_string) + { + axis2_char_t str_len[10]; + axis2_http_simple_response_set_body_string(response, env, + body_string); + sprintf(str_len, "%d", axutil_strlen(body_string)); + cont_len = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH, + str_len); + axis2_http_simple_response_set_header(response, env, cont_len); + } + + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, 0); + axis2_simple_http_svr_conn_write_response(svr_conn, env, response); + request_handled = AXIS2_TRUE; + status = AXIS2_TRUE; + response_written = AXIS2_TRUE; + } + } + } + + if (!response_written) + { + /* If in there is a soap message is to to be sent in the back channel then we go inside this + * block. Somewhere in the receiveing end axis2_op_ctx_set_response_written() function has + * been called by this time to indicate to append the message into the http back channel. + */ + if (op_ctx && axis2_op_ctx_get_response_written(op_ctx, env)) + { + if (do_rest) + { + /*axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL;*/ + + /*msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT];*/ + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + if (in_msg_ctx) + { + /* TODO: Add neccessary handling */ + } + if (out_msg_ctx) + { + int size = 0; + axutil_array_list_t *output_header_list = NULL; + output_header_list = + axis2_msg_ctx_get_http_output_headers(out_msg_ctx, + env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, + env); + } + while (size) + { + axis2_http_header_t *simple_header = NULL; + size--; + simple_header = (axis2_http_header_t *) + axutil_array_list_get(output_header_list, + env, size); + axis2_http_simple_response_set_header(response, + env, + simple_header); + } + + if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = 0; + axis2_char_t *status_code_str = NULL; + status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_CONTINUE_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_ACK_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_ACK_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_CONFLICT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_GONE_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_NAME; + break; + default: + status_code = AXIS2_HTTP_RESPONSE_OK_CODE_VAL; + status_code_str = + AXIS2_HTTP_RESPONSE_OK_CODE_NAME; + break; + } + + axis2_http_simple_response_set_status_line(response, env, + http_version, + status_code, + status_code_str); + request_handled = AXIS2_TRUE; + } + } + } + + if (!request_handled) + { + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_OK_CODE_VAL, + AXIS2_HTTP_RESPONSE_OK_CODE_NAME); + + if (!is_head) + { + /* This is where we append the message into the http back channel.*/ + axis2_http_simple_response_set_body_stream(response, env, out_stream); + } + } + } + else if (op_ctx) + { + /* If response is not written */ + if (do_rest) + { + /*axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL;*/ + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + if (in_msg_ctx) + { + /* TODO: Add neccssary handling */ + } + if (out_msg_ctx) + { + int size = 0; + axutil_array_list_t *output_header_list = NULL; + output_header_list = + axis2_msg_ctx_get_http_output_headers(out_msg_ctx, + env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, + env); + } + + while (size) + { + axis2_http_header_t *simeple_header = NULL; + size--; + simeple_header = (axis2_http_header_t *) + axutil_array_list_get(output_header_list, + env, size); + axis2_http_simple_response_set_header(response, env, + simeple_header); + } + + if (axis2_msg_ctx_get_no_content(out_msg_ctx, env)) + { + if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + axis2_char_t *status_code_str = NULL; + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_RESET_CONTENT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_RESET_CONTENT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_NAME; + break; + default: + status_code = + AXIS2_HTTP_RESPONSE_NO_CONTENT_CODE_VAL; + status_code_str = + AXIS2_HTTP_RESPONSE_NO_CONTENT_CODE_NAME; + break; + } + axis2_http_simple_response_set_status_line( + response, env, http_version, + status_code, + status_code_str); + } + else + { + /* status code not available in msg_ctx */ + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_NO_CONTENT_CODE_VAL, + AXIS2_HTTP_RESPONSE_NO_CONTENT_CODE_NAME); + } + + request_handled = AXIS2_TRUE; + } + else if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + axis2_char_t *status_code_str = NULL; + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_CONTINUE_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_OK_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_OK_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_CONFLICT_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_GONE_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_NAME; + break; + case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL: + status_code_str = + AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_NAME; + break; + default: + status_code = AXIS2_HTTP_RESPONSE_ACK_CODE_VAL; + status_code_str = + AXIS2_HTTP_RESPONSE_ACK_CODE_NAME; + break; + } + axis2_http_simple_response_set_status_line( + response, env, http_version, + status_code, + status_code_str); + + request_handled = AXIS2_TRUE; + } + } + } + if (!request_handled) + { + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_ACK_CODE_VAL, + AXIS2_HTTP_RESPONSE_ACK_CODE_NAME); + } + } + else + { + axis2_http_simple_response_set_status_line( + response, env, http_version, + AXIS2_HTTP_RESPONSE_ACK_CODE_VAL, + AXIS2_HTTP_RESPONSE_ACK_CODE_NAME); + } + + if (!response_written) + { + int stream_len = 0; + stream_len = axutil_stream_get_len(out_stream, env); + + /*axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, + stream_len);*/ + + /* This is where it actually write to the wire in the http back channel + * append case. */ + if(out_msg_ctx) + { + axutil_array_list_t *mime_parts = NULL; + mime_parts = axis2_msg_ctx_get_mime_parts(out_msg_ctx, env); + /* If mime_parts is there then that means we send MTOM. So + * in order to send MTOM we are enabling HTTP1.1 and cunk transfer + * encoding */ + + if(mime_parts) + { + axis2_http_header_t *transfer_enc_header = NULL; + axutil_param_t *callback_name_param = NULL; + axis2_char_t *mtom_sending_callback_name = NULL; + + /* Getting the sender callback name paramter if it is + * specified in the configuration file */ + + callback_name_param = axis2_msg_ctx_get_parameter(out_msg_ctx, env , + AXIS2_MTOM_SENDING_CALLBACK); + if(callback_name_param) + { + mtom_sending_callback_name = + (axis2_char_t *) axutil_param_get_value (callback_name_param, env); + if(mtom_sending_callback_name) + { + axis2_http_simple_response_set_mtom_sending_callback_name( + response, env, mtom_sending_callback_name); + } + } + + axis2_http_simple_response_set_mime_parts(response, env, mime_parts); + + axis2_http_simple_response_set_http_version(response, env, + AXIS2_HTTP_HEADER_PROTOCOL_11); + + transfer_enc_header = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED); + + axis2_http_simple_response_set_header(response, env, + transfer_enc_header); + + /* In the chunking case content-length is zero */ + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, + 0); + } + else + { + axis2_http_worker_set_response_headers(http_worker, env, svr_conn, + simple_request, response, + stream_len); + } + } + status = axis2_simple_http_svr_conn_write_response(svr_conn, + env, + response); + } + } + } + + if (url_external_form) + { + AXIS2_FREE(env->allocator, url_external_form); + url_external_form = NULL; + } + if (op_ctx) + { + axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + axis2_char_t *msg_id = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + + if (out_msg_ctx) + { + axis2_msg_ctx_free(out_msg_ctx, env); + out_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = NULL; + } + + if (in_msg_ctx) + { + msg_id = axutil_strdup(env, axis2_msg_ctx_get_msg_id(in_msg_ctx, env)); + conf_ctx = axis2_msg_ctx_get_conf_ctx(in_msg_ctx, env); + + axis2_msg_ctx_free(in_msg_ctx, env); + in_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = NULL; + } + + if (!axis2_op_ctx_is_in_use(op_ctx, env)) + { + axis2_op_ctx_destroy_mutex(op_ctx, env); + if (conf_ctx && msg_id) + { + axis2_conf_ctx_register_op_ctx(conf_ctx, env, msg_id, NULL); + + AXIS2_FREE(env->allocator, msg_id); + } + axis2_op_ctx_free(op_ctx, env); + } + + } /* Done freeing message contexts */ + + msg_ctx = NULL; + axutil_url_free(request_url, env); + axutil_string_free(soap_action_str, env); + request_url = NULL; + return status; +} + +static axis2_status_t +axis2_http_worker_set_response_headers( + axis2_http_worker_t * http_worker, + const axutil_env_t * env, + axis2_simple_http_svr_conn_t * svr_conn, + axis2_http_simple_request_t * simple_request, + axis2_http_simple_response_t * simple_response, + axis2_ssize_t content_length) +{ + axis2_http_header_t *conn_header = NULL; + + AXIS2_PARAM_CHECK(env->error, svr_conn, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, simple_request, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, simple_response, AXIS2_FAILURE); + + if(AXIS2_FALSE == axis2_http_simple_response_contains_header(simple_response, env, + AXIS2_HTTP_HEADER_CONNECTION)) + { + conn_header = axis2_http_simple_request_get_first_header(simple_request, env, + AXIS2_HTTP_HEADER_CONNECTION); + if(conn_header) + { + axis2_char_t *value = NULL; + value = axis2_http_header_get_value(conn_header, env); + + if(0 == axutil_strcasecmp(value, AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE)) + { + /* Comment these until keep alive support is completed for simple Axis2/C server */ + /*axis2_http_header_t *header = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONNECTION, AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + + axis2_http_simple_response_set_header(simple_response, env, header); + axis2_simple_http_svr_conn_set_keep_alive(svr_conn, env, AXIS2_TRUE);*/ + } + + if(0 == axutil_strcasecmp(value, AXIS2_HTTP_HEADER_CONNECTION_CLOSE)) + { + axis2_http_header_t *header = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONNECTION, AXIS2_HTTP_HEADER_CONNECTION_CLOSE); + + axis2_http_simple_response_set_header(simple_response, env, header); + axis2_simple_http_svr_conn_set_keep_alive(svr_conn, env, AXIS2_FALSE); + } + } + else + { /* Connection Header not available */ + axis2_char_t *http_version = NULL; + http_version = axis2_http_simple_response_get_http_version(simple_response, env); + if(http_version && !axutil_strcasecmp(http_version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + /* Comment these until keep alive support is completed for simple Axis2/C server */ + /*axis2_simple_http_svr_conn_set_keep_alive(svr_conn, env, AXIS2_TRUE);*/ + /* Instead add following to always send close connection header to indicate that + * we don't support http keep alive yet in simple Axis2/C server + */ + axis2_http_header_t *header = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONNECTION, AXIS2_HTTP_HEADER_CONNECTION_CLOSE); + + axis2_http_simple_response_set_header(simple_response, env, header); + /*axis2_simple_http_svr_conn_set_keep_alive(svr_conn, env, AXIS2_FALSE);*/ + } + else + { + axis2_simple_http_svr_conn_set_keep_alive(svr_conn, env, AXIS2_FALSE); + } + } + + if(!axis2_http_simple_response_contains_header(simple_response, env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING)) + { + if(AXIS2_FALSE == axis2_http_simple_request_contains_header(simple_request, env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING)) + { + if(0 != content_length) + { + axis2_char_t content_len_str[10]; + axis2_http_header_t *content_len_hdr = NULL; + + sprintf(content_len_str, "%d", content_length); + content_len_hdr = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH, content_len_str); + axis2_http_simple_response_set_header(simple_response, env, content_len_hdr); + } + } + else + { + /* Having Transfer encoding Header */ + axis2_http_header_t *transfer_enc_header = axis2_http_header_create(env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED); + + axis2_http_simple_response_set_header(simple_response, env, transfer_enc_header); + } + } + } + return AXIS2_SUCCESS; +} + +static axutil_hash_t * +axis2_http_worker_get_headers( + axis2_http_worker_t * http_worker, + const axutil_env_t * env, + axis2_http_simple_request_t * request) +{ + axutil_array_list_t *header_list = NULL; + int hdr_count = 0; + int i = 0; + axutil_hash_t *header_map = NULL; + + AXIS2_PARAM_CHECK(env->error, request, NULL); + + header_list = axis2_http_simple_request_get_headers(request, env); + if(!header_list) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "http simple request" + "doesn't contain a header list"); + return NULL; + } + hdr_count = axutil_array_list_size(header_list, env); + if(0 == hdr_count) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "http simple request , " + "header list contains zero headers"); + return NULL; + } + + for(i = 0; i < hdr_count; i++) + { + axis2_http_header_t *tmp_hdr = NULL; + tmp_hdr = axutil_array_list_get(header_list, env, i); + if(!tmp_hdr) + { + continue; + } + if(!header_map) + { + header_map = axutil_hash_make(env); + if(!header_map) + { + return NULL; + } + } + axutil_hash_set(header_map, axis2_http_header_get_name(tmp_hdr, env), + AXIS2_HASH_KEY_STRING, tmp_hdr); + } + return header_map; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_worker_set_svr_port( + axis2_http_worker_t * worker, + const axutil_env_t * env, + int port) +{ + worker->svr_port = port; + return AXIS2_SUCCESS; +} +#if 0 +static axis2_char_t * +axis2_http_worker_get_server_time( + axis2_http_worker_t * http_worker, + const axutil_env_t * env) +{ + time_t tp; + char *time_str; + tp = time(&tp); + time_str = ctime(&tp); + if(!time_str) + { + return NULL; + } + if(AXIS2_NEW_LINE == time_str[strlen(time_str) - 1]) + { + time_str[strlen(time_str) - 1] = AXIS2_ESC_NULL; + } + /* We use the ANSI C Date Format, which is Legal according to RFC2616, + * Section 3.3.1. We are not a HTTP/1.1 only server, and thus, it suffices. + */ + return time_str; +} +#endif + +static axis2_http_simple_response_t * +axis2_http_worker_create_simple_response( + axis2_http_worker_t *http_worker, + const axutil_env_t *env) +{ + axis2_http_simple_response_t *response = NULL; + response = axis2_http_simple_response_create_default(env); + if(response) + { + axis2_http_header_t *server = NULL; + axis2_http_header_t *server_date = NULL; + axis2_char_t *date_str = NULL; + char *date_str_tmp = NULL; + time_t tp; + size_t date_str_len = 0; + + /* create "Date: xxxx GMT" HTTP header */ + tp = time(&tp); + date_str_tmp = ctime(&tp); + if(!date_str_tmp) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "cannot get server time"); + return NULL; + } + + date_str_len = strlen(date_str_tmp); + if(AXIS2_NEW_LINE == date_str_tmp[date_str_len - 1]) + { + date_str_len -= 1; + date_str_tmp[date_str_len] = AXIS2_ESC_NULL; + } + /* We use the ANSI C Date Format, which is Legal according to RFC2616, + * Section 3.3.1. We are not a HTTP/1.1 only server, and thus, it suffices. + */ + + date_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (date_str_len + 5)); + if(!date_str) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + + } + sprintf(date_str, "%s GMT", date_str_tmp); + server_date = axis2_http_header_create(env, AXIS2_HTTP_HEADER_DATE, date_str); + AXIS2_FREE(env->allocator, date_str); + axis2_http_simple_response_set_header(response, env, server_date); + + /* create "Server: Axis2C/x.x.x (Simple Axis2 HTTP Server)" HTTP Header */ + server = axis2_http_header_create(env, AXIS2_HTTP_HEADER_SERVER, + AXIS2_HTTP_HEADER_SERVER_AXIS2C AXIS2_HTTP_SERVER); + axis2_http_simple_response_set_header(response, env, server); + } + return response; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_worker_set_is_application_client_side( + axis2_http_worker_t *http_worker, + const axutil_env_t *env, + axis2_bool_t application_client_side) +{ + http_worker->is_application_client_side = application_client_side; +} + + diff --git a/src/core/transport/http/common/simple_http_svr_conn.c b/src/core/transport/http/common/simple_http_svr_conn.c new file mode 100644 index 0000000..a68c48e --- /dev/null +++ b/src/core/transport/http/common/simple_http_svr_conn.c @@ -0,0 +1,504 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct axis2_simple_http_svr_conn +{ + int socket; + axutil_stream_t *stream; + axis2_bool_t keep_alive; +}; + +static axis2_char_t * +axis2_simple_http_svr_conn_read_line( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env); + +AXIS2_EXTERN axis2_simple_http_svr_conn_t *AXIS2_CALL +axis2_simple_http_svr_conn_create( + const axutil_env_t * env, + int sockfd) +{ + axis2_simple_http_svr_conn_t *svr_conn = NULL; + svr_conn = (axis2_simple_http_svr_conn_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_simple_http_svr_conn_t)); + if(!svr_conn) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "server connection failed. Insufficient memory"); + return NULL; + } + + memset((void *)svr_conn, 0, sizeof(axis2_simple_http_svr_conn_t)); + svr_conn->socket = sockfd; + + if(-1 != svr_conn->socket) + { + svr_conn->stream = axutil_stream_create_socket(env, svr_conn->socket); + if(!svr_conn->stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "socket creation failed, socket %d", sockfd); + axis2_simple_http_svr_conn_free(svr_conn, env); + return NULL; + } + } + return svr_conn; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_simple_http_svr_conn_free( + axis2_simple_http_svr_conn_t *svr_conn, + const axutil_env_t * env) +{ + axis2_simple_http_svr_conn_close(svr_conn, env); + AXIS2_FREE(env->allocator, svr_conn); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_simple_http_svr_conn_close( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + axutil_stream_free(svr_conn->stream, env); + if(-1 != svr_conn->socket) + { + axutil_network_handler_close_socket(env, svr_conn->socket); + svr_conn->socket = -1; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_simple_http_svr_conn_is_open( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + if(-1 != svr_conn->socket) + { + return AXIS2_TRUE; + } + return AXIS2_FALSE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_simple_http_svr_conn_set_keep_alive( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env, + axis2_bool_t keep_alive) +{ + svr_conn->keep_alive = keep_alive; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_simple_http_svr_conn_is_keep_alive( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + return svr_conn->keep_alive; +} + +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axis2_simple_http_svr_conn_get_stream( + const axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + return svr_conn->stream; +} + +AXIS2_EXTERN axis2_http_response_writer_t *AXIS2_CALL +axis2_simple_http_svr_conn_get_writer( + const axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + return axis2_http_response_writer_create(env, svr_conn->stream); +} + +AXIS2_EXTERN axis2_http_simple_request_t *AXIS2_CALL +axis2_simple_http_svr_conn_read_request( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + axis2_char_t* str_line = NULL; + axis2_bool_t end_of_headers = AXIS2_FALSE; + axis2_http_request_line_t *request_line = NULL; + axis2_http_simple_request_t *request = NULL; + + /* read first line of the request (which is CRLF */ + str_line = axis2_simple_http_svr_conn_read_line(svr_conn, env); + if(str_line) + { + request_line = axis2_http_request_line_parse_line(env, str_line); + AXIS2_FREE(env->allocator, str_line); + str_line = NULL; + } + + if(!request_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + return NULL; + } + request = axis2_http_simple_request_create(env, request_line, NULL, 0, svr_conn->stream); + + /* now read the headers until we find a line only having CRLF */ + while(AXIS2_FALSE == end_of_headers) + { + str_line = axis2_simple_http_svr_conn_read_line(svr_conn, env); + if(!str_line) + { + /*if nothing is read, this loop should be broken. Otherwise, going to be endless loop */ + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "reading http header failed"); + break; + } + + if(0 == axutil_strcmp(str_line, AXIS2_HTTP_CRLF)) + { + /* line contains only CRLF, so should be end of headers */ + end_of_headers = AXIS2_TRUE; + } + else + { + axis2_http_header_t *tmp_header = axis2_http_header_create_by_str(env, str_line); + if(tmp_header) + { + axis2_http_simple_request_add_header(request, env, tmp_header); + } + } + + AXIS2_FREE(env->allocator, str_line); + str_line = NULL; + } + return request; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_simple_http_svr_conn_write_response( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env, + axis2_http_simple_response_t * response) +{ + axis2_http_response_writer_t *response_writer = NULL; + axutil_array_list_t *headers = NULL; + axutil_stream_t *response_stream = NULL; + axis2_char_t *response_body = NULL; + int body_size = 0; + + axis2_http_header_t *enc_header = NULL; + axis2_bool_t chuked_encoding = AXIS2_FALSE; + axis2_char_t *status_line = NULL; + axis2_bool_t binary_content = AXIS2_FALSE; + axis2_char_t *content_type = NULL; + + AXIS2_PARAM_CHECK(env->error, response, AXIS2_FAILURE); + + response_writer = axis2_http_response_writer_create(env, svr_conn->stream); + if(!response_writer) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create http response writer"); + return AXIS2_FAILURE; + } + + content_type = (axis2_char_t *)axis2_http_simple_response_get_content_type(response, env); + if(content_type) + { + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED) + && strstr(content_type,AXIS2_HTTP_HEADER_ACCEPT_XOP_XML)) + { + binary_content = AXIS2_TRUE; + } + } + + enc_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING); + if(enc_header) + { + axis2_char_t *enc_value = axis2_http_header_get_value(enc_header, env); + if(enc_value && (0 == axutil_strcmp(enc_value, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED))) + { + chuked_encoding = AXIS2_TRUE; + + /* remove the content length header */ + axis2_http_simple_response_remove_headers(response, env, + AXIS2_HTTP_HEADER_CONTENT_LENGTH); + } + } + + /* print status line */ + status_line = axis2_http_simple_response_get_status_line(response, env); + if(!status_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + axis2_http_response_writer_free(response_writer, env); + return AXIS2_FAILURE; + } + axis2_http_response_writer_print_str(response_writer, env, status_line); + + headers = axis2_http_simple_response_get_headers(response, env); + if(headers) + { + int i = 0; + int count = axutil_array_list_size(headers, env); + for(; i < count; i++) + { + axis2_http_header_t *header = + (axis2_http_header_t *)axutil_array_list_get(headers, env, i); + if(header) + { + axis2_char_t *header_ext_form = axis2_http_header_to_external_form(header, env); + axis2_http_response_writer_print_str(response_writer, env, header_ext_form); + AXIS2_FREE(env->allocator, header_ext_form); + } + } + } + + /* write empty line after http headers */ + axis2_http_response_writer_print_str(response_writer, env, AXIS2_HTTP_CRLF); + + /* write the body */ + response_stream = axis2_http_simple_response_get_body(response, env); + if(response_stream) + { + body_size = axutil_stream_get_len(response_stream, env); + response_body = axutil_stream_get_buffer(response_stream, env); + axutil_stream_flush_buffer(response_stream, env); + response_body[body_size] = AXIS2_ESC_NULL; + } + + if(body_size <= 0 && !binary_content) + { + /* no body available to write. Note that this is not an error. We might want to write only + * status information and hence, this is a valid case */ + axis2_http_response_writer_free(response_writer, env); + return AXIS2_SUCCESS; + } + + if(!chuked_encoding && !binary_content) + { + /* This sending a normal SOAP response without chunk transfer encoding */ + axis2_status_t write_stat = AXIS2_FAILURE; + write_stat = axis2_http_response_writer_println_str(response_writer, env, response_body); + if(write_stat != AXIS2_SUCCESS) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_WRITING_RESPONSE, AXIS2_FAILURE); + axis2_http_response_writer_free(response_writer, env); + return AXIS2_FAILURE; + } + } + else if(!binary_content) + { + /* Sending a normal SOAP response enabling http chunking */ + axutil_http_chunked_stream_t *chunked_stream = NULL; + int left = body_size; + chunked_stream = axutil_http_chunked_stream_create(env, svr_conn->stream); + while(left > 0) + { + int len = -1; + len = axutil_http_chunked_stream_write(chunked_stream, env, response_body, body_size); + if(len <= 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "cannot write data to chunked stream"); + axutil_http_chunked_stream_free(chunked_stream, env); + axis2_http_response_writer_free(response_writer, env); + return AXIS2_FAILURE; + } + left -= len; + } + axutil_http_chunked_stream_write_last_chunk(chunked_stream, env); + axutil_http_chunked_stream_free(chunked_stream, env); + } + else + { + /* In the MTOM case we enable chunking in order to send the attachment */ + axutil_http_chunked_stream_t *chunked_stream = NULL; + axis2_status_t write_stat = AXIS2_FAILURE; + axutil_array_list_t *mime_parts = NULL; + axis2_char_t *mtom_sending_callback_name = NULL; + + mime_parts = axis2_http_simple_response_get_mime_parts(response, env); + if(!mime_parts) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No mime parts are given"); + axis2_http_response_writer_free(response_writer, env); + return AXIS2_FAILURE; + } + + /* If the callback name is not there, then we will check whether there + * is any mime_parts which has type callback. If we found then no point + * of continuing we should return a failure */ + mtom_sending_callback_name = axis2_http_simple_response_get_mtom_sending_callback_name( + response, env); + if(!mtom_sending_callback_name) + { + if(axis2_http_transport_utils_is_callback_required(env, mime_parts)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Sender callback not specified"); + axis2_http_response_writer_free(response_writer, env); + return AXIS2_FAILURE; + } + } + + chunked_stream = axutil_http_chunked_stream_create(env, svr_conn->stream); + write_stat = axis2_http_transport_utils_send_mtom_message(chunked_stream, env, mime_parts, + mtom_sending_callback_name); + axutil_http_chunked_stream_free(chunked_stream, env); + + if(write_stat != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "writing mime parts failed"); + axis2_http_response_writer_free(response_writer, env); + return AXIS2_FAILURE; + } + } + + axis2_http_response_writer_free(response_writer, env); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_simple_http_svr_conn_set_rcv_timeout( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env, + int timeout) +{ + return axutil_network_handler_set_sock_option(env, svr_conn->socket, SO_RCVTIMEO, timeout); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_simple_http_svr_conn_set_snd_timeout( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env, + int timeout) +{ + return axutil_network_handler_set_sock_option(env, svr_conn->socket, SO_SNDTIMEO, timeout); +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_simple_http_svr_conn_get_svr_ip( + const axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + return axutil_network_handler_get_svr_ip(env, svr_conn->socket); +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_simple_http_svr_conn_get_peer_ip( + const axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + return axutil_network_handler_get_peer_ip(env, svr_conn->socket); +} + +static axis2_char_t * +axis2_simple_http_svr_conn_read_line( + axis2_simple_http_svr_conn_t * svr_conn, + const axutil_env_t * env) +{ + axis2_char_t* str_line = NULL; + axis2_char_t tmp_buf[2048]; + int read = -1; + + /* peek for 2047 characters to verify whether it contains CRLF character */ + while((read = axutil_stream_peek_socket(svr_conn->stream, env, tmp_buf, 2048 - 1)) > 0) + { + axis2_char_t *start = tmp_buf; + axis2_char_t *end = NULL; + tmp_buf[read] = AXIS2_ESC_NULL; + end = strstr(tmp_buf, AXIS2_HTTP_CRLF); + if(end) + { + axis2_char_t *buffer = NULL; + if(str_line) + { + /* header is more than 2048 character. this is not a common case, and not optimized + * for performance (reading in a temp buffer and then strcat to get final buffer */ + buffer = tmp_buf; + } + else + { + /* header is less than 2048 characters, this is the common case. So to improve + * the performance, the buffer is malloc and then used to read the stream. */ + buffer = (axis2_char_t *)AXIS2_MALLOC(env->allocator, end - start + 3); + } + + /* read the data including CRLF (hence the size = end - start + 2) */ + read = axutil_stream_read(svr_conn->stream, env, buffer, end - start + 2); + if(read > 0) + { + buffer[read] = AXIS2_ESC_NULL; + + if(str_line) + { + axis2_char_t* tmp_str_line = NULL; + tmp_str_line = axutil_stracat(env, str_line, buffer); + if(tmp_str_line) + { + AXIS2_FREE(env->allocator, str_line); + str_line = tmp_str_line; + } + } + else + { + str_line = buffer; + } + } + else + { + /* read returns 0 or negative value, this could be an error */ + if(str_line) + { + AXIS2_FREE(env->allocator, str_line); + str_line = NULL; + } + else + { + AXIS2_FREE(env->allocator, buffer); + } + } + break; + } + else + { + /* not reached end yet */ + read = axutil_stream_read(svr_conn->stream, env, tmp_buf, 2048 - 1); + if(read > 0) + { + axis2_char_t* tmp_str_line = NULL; + tmp_buf[read] = AXIS2_ESC_NULL; + tmp_str_line = axutil_stracat(env, str_line, tmp_buf); + if(tmp_str_line) + { + if(str_line) + { + AXIS2_FREE(env->allocator, str_line); + } + str_line = tmp_str_line; + } + } + } + } + + return str_line; +} diff --git a/src/core/transport/http/receiver/Makefile.am b/src/core/transport/http/receiver/Makefile.am new file mode 100644 index 0000000..0af4e22 --- /dev/null +++ b/src/core/transport/http/receiver/Makefile.am @@ -0,0 +1,21 @@ +lib_LTLIBRARIES = libaxis2_http_receiver.la +libaxis2_http_receiver_la_LIBADD=$(top_builddir)/util/src/libaxutil.la\ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la + + +libaxis2_http_receiver_la_SOURCES = http_receiver.c\ + http_svr_thread.c + + +libaxis2_http_receiver_la_LDFLAGS = -version-info $(VERSION_NO) + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/transport\ + -I$(top_builddir)/src/core/transport/http \ + -I$(top_builddir)/src/core/description \ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/src/core/deployment \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/receiver/http_receiver.c b/src/core/transport/http/receiver/http_receiver.c new file mode 100644 index 0000000..c8517b0 --- /dev/null +++ b/src/core/transport/http/receiver/http_receiver.c @@ -0,0 +1,508 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * @brief HTTP Client struct impl + * Axis2 HTTP Client impl + */ + +typedef struct axis2_http_server_impl +{ + axis2_transport_receiver_t http_server; + axis2_http_svr_thread_t *svr_thread; + int port; + axis2_char_t *svr_ip; + axis2_conf_ctx_t *conf_ctx; + axis2_conf_ctx_t *conf_ctx_private; + axis2_bool_t is_application_client_side; +} axis2_http_server_impl_t; + +#define AXIS2_INTF_TO_IMPL(http_server) \ + ((axis2_http_server_impl_t *)(http_server)) + +/***************************** Function headers *******************************/ + +static axis2_status_t AXIS2_CALL +axis2_http_server_init( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_transport_in_desc_t * in_desc); + +static axis2_status_t AXIS2_CALL +axis2_http_server_start( + axis2_transport_receiver_t * server, + const axutil_env_t * env); + +axis2_status_t AXIS2_CALL +axis2_http_server_stop( + axis2_transport_receiver_t * server, + const axutil_env_t * env); + +static axis2_conf_ctx_t *AXIS2_CALL +axis2_http_server_get_conf_ctx( + axis2_transport_receiver_t * server, + const axutil_env_t * env); + +static axis2_endpoint_ref_t *AXIS2_CALL +axis2_http_server_get_reply_to_epr( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + const axis2_char_t * svc_name); + +static axis2_endpoint_ref_t *AXIS2_CALL +axis2_http_server_get_epr_for_service( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + const axis2_char_t * svc_name); + +static axis2_bool_t AXIS2_CALL +axis2_http_server_is_running( + axis2_transport_receiver_t * server, + const axutil_env_t * env); + +static void AXIS2_CALL +axis2_http_server_set_is_application_client_side( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + axis2_bool_t is_application_client_side); + +static void AXIS2_CALL +axis2_http_server_free( + axis2_transport_receiver_t * server, + const axutil_env_t * env); + +static axis2_char_t* AXIS2_CALL +axis2_http_server_get_server_ip( +axis2_transport_receiver_t *transport_receiver, +const axutil_env_t *env); + +static void AXIS2_CALL +axis2_http_server_set_server_ip( +axis2_transport_receiver_t *transport_receiver, +const axutil_env_t *env, + axis2_char_t *serverip); + +static const axis2_transport_receiver_ops_t http_transport_receiver_ops_var = { + axis2_http_server_init, + axis2_http_server_start, + axis2_http_server_get_reply_to_epr, + axis2_http_server_get_epr_for_service, + axis2_http_server_get_server_ip, + axis2_http_server_set_server_ip, + axis2_http_server_get_conf_ctx, + axis2_http_server_is_running, + axis2_http_server_set_is_application_client_side, + axis2_http_server_stop, + axis2_http_server_free }; + +AXIS2_EXTERN axis2_transport_receiver_t *AXIS2_CALL +axis2_http_server_create( + const axutil_env_t * env, + const axis2_char_t * repo, + const int port) +{ + axis2_http_server_impl_t *server_impl = NULL; + + server_impl = (axis2_http_server_impl_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_server_impl_t)); + + if(!server_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + server_impl->svr_thread = NULL; + server_impl->conf_ctx = NULL; + server_impl->conf_ctx_private = NULL; + server_impl->port = port; + server_impl->svr_ip = NULL; + server_impl->is_application_client_side = AXIS2_FALSE; + + server_impl->http_server.ops = &http_transport_receiver_ops_var; + + if(repo) + { + axis2_transport_in_desc_t *transport_in = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_receiver_t *receiver = NULL; + /** + * We first create a private conf ctx which is owned by this server + * we only free this private conf context. We should never free the + * server_impl->conf_ctx because it may own to any other object which + * may lead to double free + */ + server_impl->conf_ctx_private = axis2_build_conf_ctx(env, repo); + + if(!server_impl->conf_ctx_private) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "unable to create private configuration context for repo path %s", repo); + axis2_http_server_free((axis2_transport_receiver_t *)server_impl, env); + return NULL; + } + conf = axis2_conf_ctx_get_conf(server_impl->conf_ctx_private, env); + transport_in = axis2_conf_get_transport_in(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + receiver = axis2_transport_in_desc_get_recv(transport_in, env); + AXIS2_INTF_TO_IMPL(receiver)->port = port; + + server_impl->conf_ctx = server_impl->conf_ctx_private; + } + + return &(server_impl->http_server); +} + +AXIS2_EXTERN axis2_transport_receiver_t *AXIS2_CALL +axis2_http_server_create_with_file( + const axutil_env_t * env, + const axis2_char_t * file, + const int port) +{ + axis2_http_server_impl_t *server_impl = NULL; + + server_impl = (axis2_http_server_impl_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_server_impl_t)); + + if(!server_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + server_impl->svr_thread = NULL; + server_impl->conf_ctx = NULL; + server_impl->conf_ctx_private = NULL; + server_impl->port = port; + server_impl->svr_ip = NULL; + server_impl->http_server.ops = &http_transport_receiver_ops_var; + + if(file) + { + axis2_transport_in_desc_t *transport_in = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_receiver_t *receiver = NULL; + /** + * We first create a private conf ctx which is owned by this server + * we only free this private conf context. We should never free the + * server_impl->conf_ctx because it may own to any other object which + * may lead to double free + */ + server_impl->conf_ctx_private = axis2_build_conf_ctx_with_file(env, file); + + if(!server_impl->conf_ctx_private) + { + axis2_http_server_free((axis2_transport_receiver_t *)server_impl, env); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "unable to create configuration context for file %s", file); + return NULL; + } + conf = axis2_conf_ctx_get_conf(server_impl->conf_ctx_private, env); + transport_in = axis2_conf_get_transport_in(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + receiver = axis2_transport_in_desc_get_recv(transport_in, env); + AXIS2_INTF_TO_IMPL(receiver)->port = port; + + + server_impl->conf_ctx = server_impl->conf_ctx_private; + } + + return &(server_impl->http_server); +} + +static void AXIS2_CALL +axis2_http_server_free( + axis2_transport_receiver_t * server, + const axutil_env_t * env) +{ + axis2_http_server_impl_t *server_impl = NULL; + + if(!server) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "failure, server value is null , nothing to free"); + return; + } + + server_impl = AXIS2_INTF_TO_IMPL(server); + if(server_impl->svr_thread) + { + axis2_http_svr_thread_destroy(server_impl->svr_thread, env); + axis2_http_svr_thread_free(server_impl->svr_thread, env); + server_impl->svr_thread = NULL; + } + + if(server_impl->conf_ctx_private) + { + axis2_conf_ctx_free(server_impl->conf_ctx_private, env); + server_impl->conf_ctx_private = NULL; + } + + /** + * Do not free this. It may own to some other object + */ + server_impl->conf_ctx = NULL; + + AXIS2_FREE(env->allocator, server_impl); +} + +static axis2_status_t AXIS2_CALL +axis2_http_server_init( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_transport_in_desc_t * in_desc) +{ + axis2_http_server_impl_t *server_impl = NULL; + axis2_char_t *port_str = NULL; + axutil_param_t *param = NULL; + + AXIS2_PARAM_CHECK(env->error, server, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, conf_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, in_desc, AXIS2_FAILURE); + + server_impl = AXIS2_INTF_TO_IMPL(server); + + server_impl->conf_ctx = conf_ctx; + param = (axutil_param_t *)axutil_param_container_get_param( + axis2_transport_in_desc_param_container(in_desc, env), env, AXIS2_PORT_STRING); + if(param) + { + port_str = axutil_param_get_value(param, env); + } + + if(port_str) + { + server_impl->port = atoi(port_str); + } + return AXIS2_SUCCESS; +} + +static axis2_status_t AXIS2_CALL +axis2_http_server_start( + axis2_transport_receiver_t * server, + const axutil_env_t * env) +{ + axis2_http_server_impl_t *server_impl = NULL; + axis2_http_worker_t *worker = NULL; + + server_impl = AXIS2_INTF_TO_IMPL(server); + server_impl->svr_thread = axis2_http_svr_thread_create(env, server_impl->port); + if(!server_impl->svr_thread) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "unable to create server thread for port %d", + server_impl->port); + return AXIS2_FAILURE; + } + + worker = axis2_http_worker_create(env, server_impl->conf_ctx); + if(!worker) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "axis2 http worker creation failed"); + axis2_http_svr_thread_free(server_impl->svr_thread, env); + return AXIS2_FAILURE; + } + axis2_http_worker_set_is_application_client_side(worker, env, + server_impl->is_application_client_side); + axis2_http_worker_set_svr_port(worker, env, server_impl->port); + {/** Obtain server IP and set it + axis2_transport_in_desc_t *transport_in = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_receiver_t *receiver = NULL; + conf = axis2_conf_ctx_get_conf(server_impl->conf_ctx_private, env); + transport_in = axis2_conf_get_transport_in(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + receiver = axis2_transport_in_desc_get_recv(transport_in, env); + if(receiver) + { + int listen_socket = axis2_http_svr_thread_get_listen_socket(server_impl->svr_thread, env); + server_impl->svr_ip = axutil_network_handler_get_svr_ip(env, listen_socket); + AXIS2_INTF_TO_IMPL(receiver)->svr_ip = server_impl->svr_ip; + } + */ + } + AXIS2_LOG_INFO(env->log, "Starting HTTP server thread"); + axis2_http_svr_thread_set_worker(server_impl->svr_thread, env, worker); + axis2_http_svr_thread_run(server_impl->svr_thread, env); + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_server_stop( + axis2_transport_receiver_t * server, + const axutil_env_t * env) +{ + AXIS2_LOG_INFO(env->log, "Terminating HTTP server thread"); + if(AXIS2_INTF_TO_IMPL(server)->svr_thread) + { + axis2_http_svr_thread_destroy(AXIS2_INTF_TO_IMPL(server)->svr_thread, env); + } + AXIS2_LOG_INFO(env->log, "Successfully terminated HTTP server thread"); + return AXIS2_SUCCESS; +} + +static axis2_conf_ctx_t *AXIS2_CALL +axis2_http_server_get_conf_ctx( + axis2_transport_receiver_t * server, + const axutil_env_t * env) +{ + return AXIS2_INTF_TO_IMPL(server)->conf_ctx; +} + +static axis2_endpoint_ref_t *AXIS2_CALL +axis2_http_server_get_reply_to_epr( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + const axis2_char_t * svc_name) +{ + axis2_endpoint_ref_t *epr = NULL; + const axis2_char_t *host_address = NULL; + axis2_char_t *svc_path = NULL; + axutil_url_t *url = NULL; + + host_address = AXIS2_DEFAULT_HOST_ADDRESS; /* TODO : get from axis2.xml */ + svc_path = axutil_stracat(env, AXIS2_DEFAULT_SVC_PATH, svc_name); + url = axutil_url_create(env, AXIS2_HTTP_PROTOCOL, host_address, + AXIS2_INTF_TO_IMPL(server)->port, svc_path); + + AXIS2_FREE(env->allocator, svc_path); + if(!url) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create reply to epr for service %s.", + svc_name); + return NULL; + } + epr = axis2_endpoint_ref_create(env, axutil_url_to_external_form(url, env)); + axutil_url_free(url, env); + return epr; +} + +static axis2_endpoint_ref_t *AXIS2_CALL +axis2_http_server_get_epr_for_service( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + const axis2_char_t * svc_name) +{ + axis2_endpoint_ref_t *epr = NULL; + const axis2_char_t *host_address = NULL; + axis2_char_t *svc_path = NULL; + axutil_url_t *url = NULL; + + if(AXIS2_INTF_TO_IMPL(server)->svr_ip) + { + host_address = AXIS2_INTF_TO_IMPL(server)->svr_ip; + }else + { + host_address = AXIS2_DEFAULT_HOST_ADDRESS; /* TODO : get from axis2.xml */ + } + svc_path = axutil_stracat(env, AXIS2_DEFAULT_SVC_PATH, svc_name); + + url = axutil_url_create(env, AXIS2_HTTP_PROTOCOL, host_address, + AXIS2_INTF_TO_IMPL(server)->port, svc_path); + + AXIS2_FREE(env->allocator, svc_path); + if(!url) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot create reply to epr for service %s.", + svc_name); + return NULL; + } + epr = axis2_endpoint_ref_create(env, axutil_url_to_external_form(url, env)); + axutil_url_free(url, env); + return epr; +} + +static axis2_bool_t AXIS2_CALL +axis2_http_server_is_running( + axis2_transport_receiver_t * server, + const axutil_env_t * env) +{ + axis2_http_server_impl_t *server_impl = NULL; + server_impl = AXIS2_INTF_TO_IMPL(server); + if(server_impl->svr_thread) + { + return axis2_http_svr_thread_is_running(server_impl->svr_thread, env); + } + return AXIS2_FALSE; +} + +static void AXIS2_CALL +axis2_http_server_set_is_application_client_side( + axis2_transport_receiver_t * server, + const axutil_env_t * env, + axis2_bool_t is_application_client_side) +{ + axis2_http_server_impl_t *server_impl = NULL; + server_impl = AXIS2_INTF_TO_IMPL(server); + server_impl->is_application_client_side = is_application_client_side; +} + +static axis2_char_t* AXIS2_CALL +axis2_http_server_get_server_ip( +axis2_transport_receiver_t *server, +const axutil_env_t *env) +{ + return AXIS2_INTF_TO_IMPL(server)->svr_ip; +} + +static void AXIS2_CALL +axis2_http_server_set_server_ip( +axis2_transport_receiver_t *server, +const axutil_env_t *env, + axis2_char_t *serverip) +{ + AXIS2_INTF_TO_IMPL(server)->svr_ip = serverip; +} + +/** + * Following block distinguish the exposed part of the dll. + */ +AXIS2_EXPORT int +axis2_get_instance( + struct axis2_transport_receiver **inst, + const axutil_env_t * env) +{ + *inst = axis2_http_server_create(env, NULL, -1); + if(!(*inst)) + { + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXPORT int +axis2_remove_instance( + axis2_transport_receiver_t * inst, + const axutil_env_t * env) +{ + if(inst) + { + axis2_transport_receiver_free(inst, env); + } + return AXIS2_SUCCESS; +} + diff --git a/src/core/transport/http/receiver/http_svr_thread.c b/src/core/transport/http/receiver/http_svr_thread.c new file mode 100644 index 0000000..1806815 --- /dev/null +++ b/src/core/transport/http/receiver/http_svr_thread.c @@ -0,0 +1,315 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +AXIS2_EXPORT int axis2_http_socket_read_timeout = AXIS2_HTTP_DEFAULT_SO_TIMEOUT; + +struct axis2_http_svr_thread +{ + int listen_socket; + axis2_bool_t stopped; + axis2_http_worker_t *worker; + int port; +}; + +typedef struct axis2_http_svr_thd_args +{ + axutil_env_t *env; + axis2_socket_t socket; + axis2_http_worker_t *worker; + axutil_thread_t *thread; +} axis2_http_svr_thd_args_t; + +static void *AXIS2_THREAD_FUNC +axis2_svr_thread_worker_func( + axutil_thread_t * thd, + void *data); + +axis2_http_svr_thread_t *AXIS2_CALL +axis2_http_svr_thread_create( + const axutil_env_t * env, + int port) +{ + axis2_http_svr_thread_t *svr_thread = NULL; + + svr_thread = (axis2_http_svr_thread_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_svr_thread_t)); + + if(!svr_thread) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset((void *)svr_thread, 0, sizeof(axis2_http_svr_thread_t)); + + svr_thread->port = port; + svr_thread->listen_socket = (int)axutil_network_handler_create_server_socket(env, + svr_thread->port); + if(-1 == svr_thread->listen_socket) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Http server thread socket creation failed."); + axis2_http_svr_thread_free((axis2_http_svr_thread_t *)svr_thread, env); + return NULL; + } + + return svr_thread; +} + +void AXIS2_CALL +axis2_http_svr_thread_free( + axis2_http_svr_thread_t * svr_thread, + const axutil_env_t * env) +{ + if(!svr_thread) + { + return; + } + + if(svr_thread->worker) + { + axis2_http_worker_free(svr_thread->worker, env); + svr_thread->worker = NULL; + } + if(-1 != svr_thread->listen_socket) + { + axutil_network_handler_close_socket(env, svr_thread->listen_socket); + svr_thread->listen_socket = -1; + } + svr_thread->stopped = AXIS2_TRUE; + + AXIS2_FREE(env->allocator, svr_thread); +} + +axis2_status_t AXIS2_CALL +axis2_http_svr_thread_run( + axis2_http_svr_thread_t * svr_thread, + const axutil_env_t * env) +{ + while(AXIS2_FALSE == svr_thread->stopped) + { + int socket = -1; + axis2_http_svr_thd_args_t *arg_list = NULL; +#ifdef AXIS2_SVR_MULTI_THREADED + axutil_thread_t *worker_thread = NULL; +#endif + + socket = (int)axutil_network_handler_svr_socket_accept(env, svr_thread-> listen_socket); + if(!svr_thread->worker) + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, + "Worker not ready yet. Cannot serve the request"); + axutil_network_handler_close_socket(env, socket); + continue; + } + + arg_list = AXIS2_MALLOC(env->allocator, sizeof(axis2_http_svr_thd_args_t)); + if(!arg_list) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Memory allocation error in the svr thread loop"); + continue; + } + + arg_list->env = (axutil_env_t *)env; + arg_list->socket = socket; + arg_list->worker = svr_thread->worker; +#ifdef AXIS2_SVR_MULTI_THREADED + worker_thread = axutil_thread_pool_get_thread(env->thread_pool, + axis2_svr_thread_worker_func, (void *) arg_list); + if (!worker_thread) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Thread creation failed server thread loop"); + continue; + } + axutil_thread_pool_thread_detach(env->thread_pool, worker_thread); +#else + axis2_svr_thread_worker_func(NULL, (void *)arg_list); +#endif + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_svr_thread_destroy( + axis2_http_svr_thread_t * svr_thread, + const axutil_env_t * env) +{ + if(AXIS2_TRUE == svr_thread->stopped) + { + return AXIS2_SUCCESS; + } + + svr_thread->stopped = AXIS2_TRUE; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Terminating HTTP server thread."); + if(svr_thread->listen_socket) + { + axutil_network_handler_close_socket(env, svr_thread->listen_socket); + svr_thread->listen_socket = -1; + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_svr_thread_get_local_port( + const axis2_http_svr_thread_t * svr_thread, + const axutil_env_t * env) +{ + return svr_thread->port; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_svr_thread_is_running( + axis2_http_svr_thread_t * svr_thread, + const axutil_env_t * env) +{ + return !(svr_thread->stopped); +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_svr_thread_set_worker( + axis2_http_svr_thread_t * svr_thread, + const axutil_env_t * env, + axis2_http_worker_t * worker) +{ + AXIS2_PARAM_CHECK(env->error, worker, AXIS2_FAILURE); + svr_thread->worker = worker; + return AXIS2_SUCCESS; +} + +/** + * Thread worker function. + */ +static void *AXIS2_THREAD_FUNC +axis2_svr_thread_worker_func( + axutil_thread_t * thd, + void *data) +{ + struct AXIS2_PLATFORM_TIMEB t1, t2; + axis2_simple_http_svr_conn_t *svr_conn = NULL; + axis2_http_simple_request_t *request = NULL; + int millisecs = 0; + double secs = 0; + axis2_http_worker_t *tmp = NULL; + axis2_status_t status = AXIS2_FAILURE; + axutil_env_t *env = NULL; + axis2_socket_t socket; + axutil_env_t *thread_env = NULL; + axis2_http_svr_thd_args_t *arg_list = NULL; + +#ifndef WIN32 +#ifdef AXIS2_SVR_MULTI_THREADED + signal(SIGPIPE, SIG_IGN); +#endif +#endif + + if(!data) + { + return NULL; + } + arg_list = (axis2_http_svr_thd_args_t *)data; + + env = arg_list->env; + thread_env = axutil_init_thread_env(env); + + IF_AXIS2_LOG_DEBUG_ENABLED(env->log) + { + AXIS2_PLATFORM_GET_TIME_IN_MILLIS(&t1); + } + + socket = arg_list->socket; + svr_conn = axis2_simple_http_svr_conn_create(thread_env, (int)socket); + if(!svr_conn) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "creating simple_http_svr_connection failed"); + return NULL; + } + + axis2_simple_http_svr_conn_set_rcv_timeout(svr_conn, thread_env, axis2_http_socket_read_timeout); + + /* read HTTPMethod, URL, HTTP Version and http headers. Leave the remaining in the stream */ + request = axis2_simple_http_svr_conn_read_request(svr_conn, thread_env); + if(!request) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Could not create request"); + return NULL; + } + + tmp = arg_list->worker; + status = axis2_http_worker_process_request(tmp, thread_env, svr_conn, request); + axis2_simple_http_svr_conn_free(svr_conn, thread_env); + axis2_http_simple_request_free(request, thread_env); + + IF_AXIS2_LOG_DEBUG_ENABLED(env->log) + { + AXIS2_PLATFORM_GET_TIME_IN_MILLIS(&t2); + millisecs = t2.millitm - t1.millitm; + secs = difftime(t2.time, t1.time); + if(millisecs < 0) + { + millisecs += 1000; + secs--; + } + secs += millisecs / 1000.0; + +#if defined(WIN32) + AXIS2_LOG_DEBUG(thread_env->log, AXIS2_LOG_SI, "Request processed..."); +#else + AXIS2_LOG_DEBUG(thread_env->log, AXIS2_LOG_SI, "Request processed in %.3f seconds", secs); +#endif + } + + if(status == AXIS2_SUCCESS) + { + AXIS2_LOG_DEBUG(thread_env->log, AXIS2_LOG_SI, "Request served successfully"); + } + else + { + AXIS2_LOG_WARNING(thread_env->log, AXIS2_LOG_SI, "Error occurred in processing request "); + } + + AXIS2_FREE(thread_env->allocator, arg_list); + axutil_free_thread_env(thread_env); + thread_env = NULL; + +#ifdef AXIS2_SVR_MULTI_THREADED + axutil_thread_pool_exit_thread(env->thread_pool, thd); +#endif + + return NULL; +} + +AXIS2_EXTERN int AXIS2_CALL + axis2_http_svr_thread_get_listen_socket( + axis2_http_svr_thread_t *svr_thread, + const axutil_env_t *env) +{ + return svr_thread->listen_socket; + +} diff --git a/src/core/transport/http/sender/Makefile.am b/src/core/transport/http/sender/Makefile.am new file mode 100644 index 0000000..399ed39 --- /dev/null +++ b/src/core/transport/http/sender/Makefile.am @@ -0,0 +1,51 @@ +SUBDIRS=ssl libcurl +lib_LTLIBRARIES = libaxis2_http_sender.la + + + +if AXIS2_LIBCURL_ENABLED +LIBCURL_SOURCES=libcurl/axis2_libcurl.c\ + libcurl/libcurl_stream.c +LIBCURL_LIBS=-lssl -lcrypto -lcurl -ldl -lz +else +LIBCURL_SOURCES= +LIBCURL_LIBS= +endif + + +if AXIS2_SSL_ENABLED +SSL_SOURCES = ssl/ssl_stream.c\ + ssl/ssl_utils.c +SSL_LIBS = -lssl -lcrypto +else +SSL_SOURCES= +SSL_LIBS= +endif + +libaxis2_http_sender_la_SOURCES = http_transport_sender.c \ + http_sender.c \ + http_client.c \ + $(SSL_SOURCES) \ + $(LIBCURL_SOURCES) + +libaxis2_http_sender_la_LIBADD = $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la\ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la\ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la\ + $(top_builddir)/util/src/libaxutil.la\ + $(LIBCURL_LIBS)\ + $(SSL_LIBS) + + +libaxis2_http_sender_la_LDFLAGS = -version-info $(VERSION_NO) + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/transport\ + -I$(top_builddir)/src/core/transport/http \ + -I$(top_builddir)/src/core/transport/http/sender/libcurl \ + -I$(top_builddir)/src/core/description \ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/src/core/deployment \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/sender/http_client.c b/src/core/transport/http/sender/http_client.c new file mode 100644 index 0000000..80e7ee3 --- /dev/null +++ b/src/core/transport/http/sender/http_client.c @@ -0,0 +1,965 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AXIS2_SSL_ENABLED +#include "ssl/ssl_stream.h" +#endif + +struct axis2_http_client +{ + int sockfd; + axutil_stream_t *data_stream; + axutil_url_t *url; + axis2_http_simple_response_t *response; + axis2_bool_t request_sent; + int timeout; + axis2_bool_t proxy_enabled; + axis2_char_t *proxy_host; + int proxy_port; + axis2_char_t *proxy_host_port; + axis2_bool_t dump_input_msg; + axis2_char_t *server_cert; + axis2_char_t *key_file; + axis2_char_t *req_body; + int req_body_size; + + /* These are for mtom case */ + axutil_array_list_t *mime_parts; + axis2_bool_t doing_mtom; + axis2_char_t *mtom_sending_callback_name; +}; + +AXIS2_EXTERN axis2_http_client_t *AXIS2_CALL +axis2_http_client_create( + const axutil_env_t * env, + axutil_url_t * url) +{ + axis2_http_client_t *http_client = NULL; + + http_client = (axis2_http_client_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_http_client_t)); + + if(!http_client) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset(http_client, 0, sizeof(axis2_http_client_t)); + + http_client->url = url; + http_client->data_stream = NULL; + http_client->sockfd = -1; + http_client->response = NULL; + http_client->request_sent = AXIS2_FALSE; + + /* default timeout is 60000 milliseconds */ + http_client->timeout = AXIS2_HTTP_DEFAULT_CONNECTION_TIMEOUT; + http_client->proxy_enabled = AXIS2_FALSE; + http_client->proxy_port = 0; + http_client->proxy_host = NULL; + http_client->proxy_host_port = NULL; + http_client->dump_input_msg = AXIS2_FALSE; + http_client->server_cert = NULL; + http_client->key_file = NULL; + http_client->req_body = NULL; + http_client->req_body_size = 0; + http_client->mime_parts = NULL; + http_client->doing_mtom = AXIS2_FALSE; + http_client->mtom_sending_callback_name = NULL; + + return http_client; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_client_free( + axis2_http_client_t * http_client, + const axutil_env_t * env) +{ + if(http_client->proxy_host) + { + AXIS2_FREE(env->allocator, http_client->proxy_host); + } + if(http_client->proxy_host_port) + { + AXIS2_FREE(env->allocator, http_client->proxy_host_port); + } + if(http_client->url) + { + axutil_url_free(http_client->url, env); + } + if(http_client->response) + { + axis2_http_simple_response_free(http_client->response, env); + } + if(-1 != http_client->sockfd) + { + axutil_network_handler_close_socket(env, http_client->sockfd); + http_client->sockfd = -1; + } + + if(http_client->req_body) + { + AXIS2_FREE(env->allocator, http_client->req_body); + } + + /* There is no other appropriate place to free the mime_part list when a + * particular client send requests. */ + + if(http_client->mime_parts) + { + int i = 0; + for(i = 0; i < axutil_array_list_size(http_client->mime_parts, env); i++) + { + axiom_mime_part_t *mime_part = NULL; + mime_part = (axiom_mime_part_t *)axutil_array_list_get(http_client->mime_parts, env, i); + if(mime_part) + { + axiom_mime_part_free(mime_part, env); + } + } + axutil_array_list_free(http_client->mime_parts, env); + } + + AXIS2_FREE(env->allocator, http_client); + return; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_client_free_void_arg( + void *client, + const axutil_env_t * env) +{ + axis2_http_client_t *client_l = NULL; + + client_l = (axis2_http_client_t *)client; + axis2_http_client_free(client_l, env); + return; +} + +/* This is the main method which writes to the socket in the case of a client + * sends an http_request. Previously this method does not distinguish between a + * mtom request and non mtom request. Because what finally it had was the + * complete buffer with the request. But now MTOM invocations are done + * differently in order to support large attachments so this method should + * distinguish those invocations */ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_send( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_http_simple_request_t * request, + axis2_char_t * ssl_pp) +{ + char *wire_format = NULL; + axutil_array_list_t *headers = NULL; + char *str_header = NULL; + char *str_request_line = NULL; + int written = 0; + axis2_status_t status = AXIS2_FAILURE; + axis2_bool_t chunking_enabled = AXIS2_FALSE; + axis2_char_t *host = NULL; + unsigned int port = 0; + + /* In the MTOM case request body is not set. Instead mime_parts + array_list is there */ + + if(client->req_body) + { + AXIS2_FREE(env->allocator, client->req_body); + client->req_body = NULL; + } + if(!client->req_body && !(client->doing_mtom)) + { + client->req_body_size = axis2_http_simple_request_get_body_bytes(request, env, + &client->req_body); + } + + if(client->dump_input_msg == AXIS2_TRUE) + { + return AXIS2_SUCCESS; + } + + if(!client->url) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_URL, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Request url not set"); + return AXIS2_FAILURE; + } + + host = axutil_url_get_host(client->url, env); + port = axutil_url_get_port(client->url, env); + + if(client->proxy_enabled) + { + if(!client->proxy_host || client->proxy_port <= 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy port or Host not set"); + return AXIS2_FAILURE; + } + + if(client->sockfd < 0) + { + client->sockfd = (int)axutil_network_handler_open_socket(env, client->proxy_host, + client->proxy_port); + } + } + else + { + /*Proxy is not enabled*/ + + if(client->sockfd < 0) + { + client->sockfd = (int)axutil_network_handler_open_socket(env, host, port); + } + } + + if(client->sockfd < 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SOCKET_ERROR, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Socket Creation failed."); + return AXIS2_FAILURE; + } + + if(client->timeout > 0) + { + /*Set the receiving time out*/ + axutil_network_handler_set_sock_option(env, client->sockfd, SO_RCVTIMEO, client->timeout); + /*Set the sending time out*/ + + axutil_network_handler_set_sock_option(env, client->sockfd, SO_SNDTIMEO, client->timeout); + } + + if(0 == axutil_strcasecmp(axutil_url_get_protocol(client->url, env), AXIS2_TRANSPORT_URL_HTTPS)) + { +#ifdef AXIS2_SSL_ENABLED + if (client->proxy_enabled) + { + if (AXIS2_SUCCESS != axis2_http_client_connect_ssl_host(client, env, host, port)) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTPS connection creation failed"); + return AXIS2_FAILURE; + } + } + client->data_stream = + axutil_stream_create_ssl(env, client->sockfd, axis2_http_client_get_server_cert(client, + env), axis2_http_client_get_key_file(client, env), ssl_pp); +#else + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_TRANSPORT_PROTOCOL, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Invalid Transport Protocol, HTTPS transport not enabled."); + + return AXIS2_FAILURE; +#endif + } + else + { + client->data_stream = axutil_stream_create_socket(env, client->sockfd); + } + + if(!client->data_stream) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Data stream creation failed for Host %s and %d port", host, port); + + return AXIS2_FAILURE; + } + + /*Accessing HTTP headers*/ + + headers = axis2_http_simple_request_get_headers(request, env); + if(headers) + { + int header_count = axutil_array_list_size(headers, env); + int i = 0; + char *str_header2 = NULL; + for(i = 0; i < header_count; i++) + { + axis2_char_t *header_ext_form = NULL; + axis2_http_header_t *tmp_header = (axis2_http_header_t *)axutil_array_list_get(headers, + env, i); + + if(!tmp_header) + { + /* This continue is added as a safey mechanism, + * However I see a problem with this logic, AFAIC + * see there can't be null headers in the headers + * array list, because number of headers in "headers" + * array list count with axutil_array_list_size, + * therefore this check and continue might not have a + * real effect.*/ + + continue; + } + + /* check whether we have transfer encoding and then see whether the + * value is "chunked" */ + if(!axutil_strcmp(axis2_http_header_get_name(tmp_header, env), + AXIS2_HTTP_HEADER_TRANSFER_ENCODING) && !axutil_strcmp(axis2_http_header_get_value( + tmp_header, env), AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + chunking_enabled = AXIS2_TRUE; + } + + header_ext_form = axis2_http_header_to_external_form(tmp_header, env); + + /* str_header2 is to hold intermediate value of str_header */ + str_header2 = axutil_stracat(env, str_header, header_ext_form); + if(str_header) + { + AXIS2_FREE(env->allocator, str_header); + str_header = NULL; + } + if(header_ext_form) + { + AXIS2_FREE(env->allocator, header_ext_form); + header_ext_form = NULL; + } + + /* str_header has all HTTP headers to send. */ + str_header = str_header2; + } + } + + if(AXIS2_FALSE == client->proxy_enabled) + { + str_request_line = axis2_http_request_line_to_string( + axis2_http_simple_request_get_request_line(request, env), env); + } + else + { + /* proxy enabled case */ + + /* we need the request line in the format + * POST http://host:port/path HTTP/1.x if we have enabled proxies + */ + axis2_char_t *host_port_str = NULL; + axis2_char_t *host = axutil_url_get_host(client->url, env); + axis2_http_request_line_t *request_line = axis2_http_simple_request_get_request_line( + request, env); + axis2_char_t *path = axis2_http_request_line_get_uri(request_line, env); + + host_port_str = AXIS2_MALLOC(env->allocator, axutil_strlen(host) + axutil_strlen(path) + 20 + * sizeof(axis2_char_t)); + + if(!host_port_str) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Memory allocation failed for host %s and %s path", host, path); + + return AXIS2_FAILURE; + } + + sprintf(host_port_str, "http://%s:%d%s", host, axutil_url_get_port(client->url, env), path); + str_request_line = AXIS2_MALLOC(env->allocator, axutil_strlen(host_port_str) + 20 + * sizeof(axis2_char_t)); + + if(!str_request_line) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_FREE(env->allocator, host_port_str); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "memory allocation failed for host %s and %s path", host, path); + + return AXIS2_FAILURE; + } + + sprintf(str_request_line, "%s %s %s\r\n", axis2_http_request_line_get_method(request_line, + env), host_port_str, axis2_http_request_line_get_http_version(request_line, env)); + + AXIS2_FREE(env->allocator, host_port_str); + host_port_str = NULL; + + } + + /* Here first we send the http header part */ + + wire_format = axutil_stracat(env, str_request_line, str_header); + AXIS2_FREE(env->allocator, str_header); + str_header = NULL; + AXIS2_FREE(env->allocator, str_request_line); + str_request_line = NULL; + written + = axutil_stream_write(client->data_stream, env, wire_format, axutil_strlen(wire_format)); + AXIS2_FREE(env->allocator, wire_format); + wire_format = NULL; + + /* Then we write the two new line charaters before the http body*/ + + written = axutil_stream_write(client->data_stream, env, AXIS2_HTTP_CRLF, 2); + + /* When sending MTOM it is bit different. We keep the attachment + other + mime headers in an array_list and send them one by one */ + + if(client->doing_mtom) + { + axis2_status_t status = AXIS2_SUCCESS; + axutil_http_chunked_stream_t *chunked_stream = NULL; + + /* If the callback name is not there, then we will check whether there + * is any mime_parts which has type callback. If we found then no point + * of continuing we should return a failure */ + + if(!(client->mtom_sending_callback_name)) + { + if(axis2_http_transport_utils_is_callback_required(env, client->mime_parts)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Sender callback not specified"); + return AXIS2_FAILURE; + } + } + + /* For MTOM we automatically enabled chunking */ + chunked_stream = axutil_http_chunked_stream_create(env, client->data_stream); + + /* This method will write the Attachment + data to the wire */ + + status = axis2_http_transport_utils_send_mtom_message(chunked_stream, env, + client->mime_parts, client->mtom_sending_callback_name); + + axutil_http_chunked_stream_free(chunked_stream, env); + chunked_stream = NULL; + + } + /* Non MTOM case */ + else if(client->req_body_size > 0 && client->req_body) + { + int len = 0; + written = 0; + + /* Keep on writing data in a loop until we finised + with all the data in the buffer */ + + if(!chunking_enabled) + { + status = AXIS2_SUCCESS; + while(written < client->req_body_size) + { + len = 0; + len = axutil_stream_write(client->data_stream, env, client->req_body + written, + client->req_body_size - written); + if(-1 == len) + { + status = AXIS2_FAILURE; + break; + } + else + { + written += len; + } + } + } + else + { + /* Not MTOM but chunking is enabled */ + axutil_http_chunked_stream_t *chunked_stream = NULL; + chunked_stream = axutil_http_chunked_stream_create(env, client->data_stream); + status = AXIS2_SUCCESS; + if(!chunked_stream) + { + axutil_network_handler_close_socket(env, client->sockfd); + client->sockfd = -1; + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Creatoin of chunked stream failed"); + return AXIS2_FAILURE; + } + + while(written < client->req_body_size) + { + written = axutil_http_chunked_stream_write(chunked_stream, env, client->req_body, + client->req_body_size); + + if(-1 == written) + { + status = AXIS2_FAILURE; + break; + } + } + + if(AXIS2_SUCCESS == status) + { + /* Writing the trailing null charactor */ + axutil_http_chunked_stream_write_last_chunk(chunked_stream, env); + } + + axutil_http_chunked_stream_free(chunked_stream, env); + } + } + + client->request_sent = AXIS2_TRUE; + return status; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_client_recieve_header( + axis2_http_client_t * client, + const axutil_env_t * env) +{ + int status_code = -1; + axis2_http_status_line_t *status_line = NULL; + axis2_char_t str_status_line[512]; + axis2_char_t tmp_buf[3]; + axis2_char_t str_header[512]; + int read = 0; + int http_status = 0; + axis2_bool_t end_of_line = AXIS2_FALSE; + axis2_bool_t end_of_headers = AXIS2_FALSE; + + if(-1 == client->sockfd || !client->data_stream || AXIS2_FALSE == client->request_sent) + { + axis2_char_t *host; + unsigned int port; + host = axutil_url_get_host(client->url, env); + port = axutil_url_get_port(client->url, env); + + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "client data stream null or socket error for host \ +%s and %d port", host, port); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_REQUEST_NOT_SENT, AXIS2_FAILURE); + return -1; + } + + /* read the status line */ + do + { + memset(str_status_line, 0, 512); + while((read = axutil_stream_read(client->data_stream, env, tmp_buf, 1)) > 0) + { + /* "read" variable is number of characters read by stream */ + tmp_buf[read] = '\0'; + strcat(str_status_line, tmp_buf); + if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + + if(read < 0) + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "http client , response timed out"); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_TIMED_OUT, AXIS2_FAILURE); + return -1; + } + else if(read == 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_SERVER_SHUTDOWN, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Response error, Server Shutdown"); + return 0; + } + + status_line = axis2_http_status_line_create(env, str_status_line); + if(!status_line) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "axis2_http_status_line_create failed for \ +str_status_line %s", str_status_line); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + http_status = 0; + continue; + + } + http_status = axis2_http_status_line_get_status_code(status_line, env); + + } + while(AXIS2_HTTP_RESPONSE_OK_CODE_VAL > http_status); + + if(client->response) + axis2_http_simple_response_free(client->response, env); + client->response = axis2_http_simple_response_create_default(env); + axis2_http_simple_response_set_status_line(client->response, env, + axis2_http_status_line_get_http_version(status_line, env), + axis2_http_status_line_get_status_code(status_line, env), + axis2_http_status_line_get_reason_phrase(status_line, env)); + + /* now read the headers */ + memset(str_header, 0, 512); + end_of_line = AXIS2_FALSE; + while(AXIS2_FALSE == end_of_headers) + { + while((read = axutil_stream_read(client->data_stream, env, tmp_buf, 1)) > 0) + { + tmp_buf[read] = '\0'; + strcat(str_header, tmp_buf); + if(0 != strstr(str_header, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + if(AXIS2_TRUE == end_of_line) + { + if(0 == axutil_strcmp(str_header, AXIS2_HTTP_CRLF)) + { + end_of_headers = AXIS2_TRUE; + } + else + { + axis2_http_header_t *tmp_header = axis2_http_header_create_by_str(env, str_header); + memset(str_header, 0, 512); + if(tmp_header) + { + axis2_http_simple_response_set_header(client->response, env, tmp_header); + } + } + } + end_of_line = AXIS2_FALSE; + } + axis2_http_simple_response_set_body_stream(client->response, env, client->data_stream); + if(status_line) + { + status_code = axis2_http_status_line_get_status_code(status_line, env); + axis2_http_status_line_free(status_line, env); + status_line = NULL; + } + + if(AXIS2_FALSE == axis2_http_simple_response_contains_header(client->response, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE) && 202 != status_code + && axis2_http_simple_response_get_content_length(client->response, env) > 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_CONTENT_TYPE_MISSING, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Response does not contain" " Content-Type"); + return -1; + } + return status_code; +} + +AXIS2_EXTERN axis2_http_simple_response_t *AXIS2_CALL +axis2_http_client_get_response( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->response; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_url( + axis2_http_client_t * client, + const axutil_env_t * env, + axutil_url_t * url) +{ + AXIS2_PARAM_CHECK(env->error, url, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + + if(client->url) + { + axutil_url_free(client->url, env); + client->url = NULL; + } + client->url = url; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_url_t *AXIS2_CALL +axis2_http_client_get_url( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, client, NULL); + return client->url; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_timeout( + axis2_http_client_t * client, + const axutil_env_t * env, + int timeout_ms) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + client->timeout = timeout_ms; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_client_get_timeout( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + return client->timeout; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_proxy( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * proxy_host, + int proxy_port) +{ + AXIS2_PARAM_CHECK(env->error, proxy_host, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + + if(proxy_port <= 0) + { + return AXIS2_FAILURE; + } + + client->proxy_port = proxy_port; + if(client->proxy_host) + { + AXIS2_FREE(env->allocator, client->proxy_host); + client->proxy_host = NULL; + } + + if(client->proxy_host_port) + { + AXIS2_FREE(env->allocator, client->proxy_host_port); + client->proxy_host_port = NULL; + } + + client->proxy_host = axutil_strdup(env, proxy_host); + if(!client->proxy_host) + { + return AXIS2_FAILURE; + } + + client->proxy_host_port = AXIS2_MALLOC(env->allocator, axutil_strlen(proxy_host) + 10 + * sizeof(axis2_char_t)); + + sprintf(client->proxy_host_port, "%s:%d", proxy_host, proxy_port); + client->proxy_enabled = AXIS2_TRUE; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_client_get_proxy( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + AXIS2_PARAM_CHECK(env->error, client, NULL); + return client->proxy_host_port; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_connect_ssl_host( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * host, + int port) +{ + axutil_stream_t *tmp_stream = NULL; + axis2_char_t *connect_string = NULL; + axis2_char_t str_status_line[512]; + axis2_char_t tmp_buf[3]; + int read = 0; + axis2_bool_t end_of_line = AXIS2_FALSE; + axis2_bool_t end_of_response = AXIS2_FALSE; + axis2_http_status_line_t *status_line = NULL; + + AXIS2_PARAM_CHECK(env->error, host, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, client->url, AXIS2_FAILURE); + /* This host and port will use for give undersandable log messages + * */ + + if(port <= 0) + { + return AXIS2_FAILURE; + } + + tmp_stream = axutil_stream_create_socket(env, client->sockfd); + if(!tmp_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "unable to create open socket for ssl host %s and %d \ +port", host, port); + return AXIS2_FAILURE; + } + + connect_string = AXIS2_MALLOC(env->allocator, axutil_strlen(host) * sizeof(axis2_char_t) + 30 + * sizeof(axis2_char_t)); + sprintf(connect_string, "CONNECT %s:%d HTTP/1.0\r\n\r\n", host, port); + axutil_stream_write(tmp_stream, env, connect_string, axutil_strlen(connect_string) + * sizeof(axis2_char_t)); + + memset(str_status_line, 0, 512); + while((read = axutil_stream_read(tmp_stream, env, tmp_buf, 1)) > 0) + { + tmp_buf[read] = '\0'; + strcat(str_status_line, tmp_buf); + if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + if(read < 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_RESPONSE_TIMED_OUT, AXIS2_FAILURE); + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_FAILURE; + } + status_line = axis2_http_status_line_create(env, str_status_line); + if(!status_line) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_INVALID_HTTP_HEADER_START_LINE, AXIS2_FAILURE); + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_FAILURE; + } + if(200 != axis2_http_status_line_get_status_code(status_line, env)) + { + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_FAILURE; + } + /* We need to empty the stream before we return + */ + memset(str_status_line, 0, 512); + while(AXIS2_FALSE == end_of_response) + { + while((read = axutil_stream_read(tmp_stream, env, tmp_buf, 1)) > 0) + { + tmp_buf[read] = '\0'; + strcat(str_status_line, tmp_buf); + if(0 != strstr(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_line = AXIS2_TRUE; + break; + } + } + if(AXIS2_TRUE == end_of_line) + { + if(0 == axutil_strcmp(str_status_line, AXIS2_HTTP_CRLF)) + { + end_of_response = AXIS2_TRUE; + } + } + } + AXIS2_FREE(env->allocator, connect_string); + axutil_stream_free(tmp_stream, env); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_dump_input_msg( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_bool_t dump_input_msg) +{ + client->dump_input_msg = dump_input_msg; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_server_cert( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * server_cert) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, server_cert, AXIS2_FAILURE); + client->server_cert = server_cert; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_client_get_server_cert( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->server_cert; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_key_file( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t * key_file) +{ + AXIS2_PARAM_CHECK(env->error, client, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, key_file, AXIS2_FAILURE); + client->key_file = key_file; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_client_get_key_file( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->key_file; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_mime_parts( + axis2_http_client_t * client, + const axutil_env_t * env, + axutil_array_list_t *mime_parts) +{ + client->mime_parts = mime_parts; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_http_client_get_mime_parts( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->mime_parts; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_doing_mtom( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_bool_t doing_mtom) +{ + client->doing_mtom = doing_mtom; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_client_get_doing_mtom( + const axis2_http_client_t * client, + const axutil_env_t * env) +{ + return client->doing_mtom; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_client_set_mtom_sending_callback_name( + axis2_http_client_t * client, + const axutil_env_t * env, + axis2_char_t *callback_name) +{ + client->mtom_sending_callback_name = callback_name; + return AXIS2_SUCCESS; +} diff --git a/src/core/transport/http/sender/http_sender.c b/src/core/transport/http/sender/http_sender.c new file mode 100644 index 0000000..56f11e0 --- /dev/null +++ b/src/core/transport/http/sender/http_sender.c @@ -0,0 +1,3332 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AXIS2_LIBCURL_ENABLED +#include "libcurl/axis2_libcurl.h" +#else +#define CLIENT_NONCE_LENGTH 8 +#endif + +struct axis2_http_sender +{ + axis2_char_t *http_version; + axis2_bool_t chunked; + int so_timeout; + axiom_output_t *om_output; + axis2_http_client_t *client; + axis2_bool_t is_soap; + axis2_bool_t keep_alive; +}; + +#ifndef AXIS2_LIBCURL_ENABLED +static void +axis2_http_sender_add_header_list( + axis2_http_simple_request_t * request, + const axutil_env_t * env, + axutil_array_list_t * array_list); + +static axis2_status_t +axis2_http_sender_configure_proxy( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_status_t +axis2_http_sender_configure_server_cert( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_status_t +axis2_http_sender_configure_key_file( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +static axis2_status_t +axis2_http_sender_configure_http_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_proxy_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_set_http_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_set_proxy_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_http_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_proxy_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request); + +static axis2_status_t +axis2_http_sender_configure_http_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data); + +static axis2_status_t +axis2_http_sender_configure_proxy_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data); + + + +#endif + +static axutil_hash_t * +axis2_http_sender_connection_map_create( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx); + +static void +axis2_http_sender_connection_map_remove( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client); + +static void +axis2_http_sender_connection_map_add( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client); + +static axis2_http_client_t * +axis2_http_sender_connection_map_get( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx); + +static void AXIS2_CALL +axis2_http_sender_connection_map_free( + void *cm_void, + const axutil_env_t *env); + +AXIS2_EXTERN axis2_http_sender_t *AXIS2_CALL +axis2_http_sender_create( + const axutil_env_t * env) +{ + axis2_http_sender_t *sender = NULL; + + sender = (axis2_http_sender_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_http_sender_t)); + + if(!sender) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset(sender, 0, sizeof(axis2_http_sender_t)); + sender->http_version = (axis2_char_t *)AXIS2_HTTP_HEADER_PROTOCOL_11; + sender->so_timeout = AXIS2_HTTP_DEFAULT_SO_TIMEOUT; + /* unlike the java impl we don't have a default om output + * it should be explicitly set and it's a MUST + */ + sender->om_output = NULL; + sender->chunked = AXIS2_FALSE; + sender->client = NULL; + sender->keep_alive = AXIS2_TRUE; + + return sender; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_sender_free( + axis2_http_sender_t * sender, + const axutil_env_t * env) +{ + if(sender->http_version) + { + AXIS2_FREE(env->allocator, sender->http_version); + } + + /* Do not free this here since it will be required in later processing + * of the response soap message + */ + sender->client = NULL; + AXIS2_FREE(env->allocator, sender); + return; +} + +#ifndef AXIS2_LIBCURL_ENABLED +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_send( + axis2_http_sender_t * sender, + 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) +{ + axis2_http_simple_request_t *request = NULL; + axis2_http_request_line_t *request_line = NULL; + + /* url is to hold url given in str_url */ + axutil_url_t *url = NULL; + axiom_xml_writer_t *xml_writer = NULL; + axis2_char_t *buffer = NULL; + unsigned int buffer_size = 0; + const axis2_char_t *char_set_enc = NULL; + axutil_string_t *char_set_enc_str = NULL; + int status_code = -1; + axis2_http_simple_response_t *response = NULL; + axis2_char_t *content_type = NULL; + axis2_bool_t content_type_deepl_copy = AXIS2_TRUE; + axis2_byte_t *output_stream = NULL; + int output_stream_size = 0; + axis2_bool_t doing_mtom = AXIS2_FALSE; + axutil_property_t *dump_property = NULL; + axutil_param_t *ssl_pp_param = NULL; + /* ssl passphrase */ + axis2_char_t *ssl_pp = NULL; + axutil_property_t *ssl_pp_property = NULL; + axutil_property_t *test_auth_property = NULL; + axis2_char_t *test_auth_property_value = NULL; + axis2_bool_t test_proxy_auth = AXIS2_FALSE; + axis2_bool_t test_http_auth = AXIS2_FALSE; + + /* http proxy authentication */ + axutil_property_t *proxy_auth_property = NULL; + axis2_char_t *proxy_auth_property_value = NULL; + axis2_bool_t force_proxy_auth = AXIS2_FALSE; + axis2_bool_t force_proxy_auth_with_head = AXIS2_FALSE; + axutil_property_t *http_auth_property = NULL; + axis2_char_t *http_auth_property_value = NULL; + axis2_bool_t force_http_auth = AXIS2_FALSE; + axis2_bool_t force_http_auth_with_head = AXIS2_FALSE; + axutil_property_t *content_type_property = NULL; + axutil_hash_t *content_type_hash = NULL; + axis2_char_t *content_type_value = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + + /* handling REST requests */ + axis2_bool_t send_via_get = AXIS2_FALSE; + axis2_bool_t send_via_head = AXIS2_FALSE; + axis2_bool_t send_via_delete = AXIS2_FALSE; + axis2_bool_t send_via_put = AXIS2_FALSE; + axiom_node_t *data_out = NULL; + axiom_node_t *body_node = NULL; + axiom_soap_body_t *soap_body = NULL; + axis2_bool_t is_soap = AXIS2_TRUE; + axis2_bool_t add_keepalive_header = AXIS2_FALSE; + + /* http header property to get HTTP headers from msg_ctx and give + * it to http_sender */ + axutil_property_t *http_property = NULL; + axutil_array_list_t *array_list; + axis2_bool_t http_auth_header_added = AXIS2_FALSE; + 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 = NULL;/* Property for holding http client */ + /*axis2_char_t *header_value = NULL;*/ + axis2_char_t *cookie_str = NULL; + axutil_hash_t *connection_map = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_sender_send"); + soap_body = axiom_soap_envelope_get_body(out, env); + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, str_url, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, soap_action, AXIS2_FAILURE); + + if(AXIS2_TRUE == axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + is_soap = AXIS2_FALSE; + } + else + { + is_soap = AXIS2_TRUE; + } + + url = axutil_url_parse_string(env, str_url); + + if(!is_soap) + { + if(soap_body) + { + body_node = axiom_soap_body_get_base_node(soap_body, env); + } + if(body_node) + { + 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; + } + } + + if(!url) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "url is null for string %s", str_url); + return AXIS2_FAILURE; + } + + /*if(sender->client) + { + axis2_http_client_free(sender->client, env); + sender->client = NULL; + }*/ + + /* This property may be set by the application client. This get the priority over the keep alive + * parameter set in the axix2.xml + */ + property = (axutil_property_t *) axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + if(property) + { + axis2_char_t *keep_alive_value = NULL; + + keep_alive_value = axutil_property_get_value(property, env); + if(!axutil_strcmp(keep_alive_value, AXIS2_VALUE_FALSE)) + { + sender->keep_alive = AXIS2_FALSE; + } + } + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(conf_ctx) + { + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + } + + /* Because keep alive is not still supported at callback receiver we check + * for client side + */ + if(sender->keep_alive && !axis2_msg_ctx_get_server_side(msg_ctx, env)) + { + axutil_property_t *connection_map_property = NULL; + + connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, + AXIS2_HTTP_CONNECTION_MAP); + if(!connection_map_property) + { + connection_map = axis2_http_sender_connection_map_create(env, msg_ctx); + if(!connection_map) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + } + else + { + connection_map = axutil_property_get_value(connection_map_property, env); + if(connection_map) + { + sender->client = axis2_http_sender_connection_map_get(connection_map, env, msg_ctx); + } + } + if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_10)) + { + add_keepalive_header = AXIS2_TRUE; + } + } /* End if sender->keep_alive */ + if(!sender->client) + { + sender->client = axis2_http_client_create(env, url); + } + if(!sender->client) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "sender->client creation failed for url %s", url); + return AXIS2_FAILURE; + } + /* configure proxy settings if we have set so + */ + + axis2_http_sender_configure_proxy(sender, env, msg_ctx); + + if(conf) + { + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + + if(trans_desc) + { + /* get xml declaration details from axis2.xml */ + 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) + { + /* accessing attributes of the HTTP transport's , xml + * declaration element from axis2.xml*/ + + 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(sender->om_output, env); + } + + if(!send_via_get && !send_via_head && !send_via_delete) + { + /* processing POST and PUT methods */ + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "msg_ctx_id:%s", axis2_msg_ctx_get_msg_id(msg_ctx, + env)); + + doing_mtom = axis2_msg_ctx_get_doing_mtom(msg_ctx, env); + + if(!sender->om_output) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_OM_OUTPUT, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "%s", AXIS2_ERROR_GET_MESSAGE(env->error)); + return AXIS2_FAILURE; + } + + xml_writer = axiom_output_get_xml_writer(sender->om_output, env); + + char_set_enc_str = axis2_msg_ctx_get_charset_encoding(msg_ctx, env); + + if(!char_set_enc_str) + { + /* if there is no character encoding details available + * use default one. + * #define AXIS2_DEFAULT_CHAR_SET_ENCODING "UTF-8" + */ + 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) + { + /* HTTP POST case */ + /* dump property use to dump message without sending */ + dump_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_DUMP_INPUT_MSG_TRUE); + if(dump_property) + { + axis2_char_t *dump_true = axutil_property_get_value(dump_property, env); + if(0 == axutil_strcmp(dump_true, AXIS2_VALUE_TRUE)) + { + axis2_http_client_set_dump_input_msg(sender->client, env, AXIS2_TRUE); + } + } + + axiom_output_set_do_optimize(sender->om_output, env, doing_mtom); + axiom_soap_envelope_serialize(out, env, sender->om_output, AXIS2_FALSE); + } + 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 + { + if(!data_out) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "body node payload is NULL"); + return AXIS2_FAILURE; + } + axiom_node_serialize(data_out, env, sender->om_output); + } + + if(doing_mtom) + { + axutil_param_t *callback_name_param = NULL; + axis2_status_t mtom_status = AXIS2_FAILURE; + axutil_array_list_t *mime_parts = NULL; + axis2_char_t *mtom_sending_callback_name = NULL; + + /* Getting the sender callback name paramter if it is + * specified in the configuration file */ + + callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env, + AXIS2_MTOM_SENDING_CALLBACK); + if(callback_name_param) + { + mtom_sending_callback_name = (axis2_char_t *)axutil_param_get_value( + callback_name_param, env); + if(mtom_sending_callback_name) + { + axis2_http_client_set_mtom_sending_callback_name(sender->client, env, + mtom_sending_callback_name); + } + } + + /* Here we put all the attachment related stuff in a array_list + After this method we have the message in parts */ + + mtom_status = axiom_output_flush(sender->om_output, env); + if(mtom_status == AXIS2_FAILURE) + { + return mtom_status; + } + /* HTTP client should distinguish an MTOM invocation because the way + of sending the message in MTOM case is different */ + axis2_http_client_set_doing_mtom(sender->client, env, doing_mtom); + + /* HTTP client will keep this mime_parts, which it will send in chunks at + th end */ + mime_parts = axiom_output_get_mime_parts(sender->om_output, env); + if(mime_parts) + { + axis2_http_client_set_mime_parts(sender->client, env, mime_parts); + } + } + else + { + buffer = axiom_xml_writer_get_xml(xml_writer, env); + } + + if(!(buffer || doing_mtom)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "NULL xml returned from xml writer"); + return AXIS2_FAILURE; + } + + if(!send_via_put) + { + /* HTTP POST */ + axis2_char_t *path_with_query = NULL; + + path_with_query = axutil_strcat(env, axutil_url_get_path(url, env), + axutil_url_get_query(url, env), NULL); + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_POST, path_with_query, + sender->http_version); + AXIS2_FREE(env->allocator, path_with_query); + } + else + { + /* HTTP PUT */ + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_PUT, axutil_url_get_path( + url, env), sender->http_version); + } + } + else + { + /* Processing HTTP GET, HEAD and DELETE */ + + axis2_char_t *request_params = NULL; + axis2_char_t *path = NULL; + + request_params = axis2_http_sender_get_param_string(sender, env, msg_ctx); + + if(request_params) + { + /* substituting AXIS2_Q_MARK for "?" */ + path = axutil_strcat(env, axutil_url_get_path(url, env), AXIS2_Q_MARK_STR, + request_params, NULL); + AXIS2_FREE(env->allocator, request_params); + request_params = NULL; + } + else + { + path = axutil_strdup(env, axutil_url_get_path(url, env)); + } + + if(send_via_get) + { + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_GET, path, + sender->http_version); + } + else if(send_via_head) + { + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, path, + sender->http_version); + } + else if(send_via_delete) + { + request_line = axis2_http_request_line_create(env, AXIS2_HTTP_DELETE, path, + sender->http_version); + } + + if(path) + { + AXIS2_FREE(env->allocator, path); + path = NULL; + } + } + + request = axis2_http_simple_request_create(env, request_line, NULL, 0, NULL); + if(add_keepalive_header) + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_CONNECTION, + AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + } + /** + * If there is a session related stuff handle it + */ + /*header_value = axis2_http_transport_utils_get_session(env, msg_ctx); + if(header_value) + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_SET_COOKIE, header_value); + }*/ + + /** + * In the client side sender if a cookie is sent by server add it to the http header + */ + cookie_str = axis2_http_transport_utils_read_from_cookie_store(env, msg_ctx); + if(cookie_str) + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_COOKIE, cookie_str); + } + + /* User-Agent:Axis2/C header */ + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_USER_AGENT, AXIS2_USER_AGENT); + + http_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_TRANSPORT_HEADER_PROPERTY); + if(http_property) + { + array_list = (axutil_array_list_t *)axutil_property_get_value(http_property, env); + axis2_http_sender_add_header_list(request, env, array_list); + } + + if(!send_via_get && !send_via_head && !send_via_put && !send_via_delete && 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); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_SOAP_ACTION, + tmp_soap_action); + AXIS2_FREE(env->allocator, tmp_soap_action); + } + else + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_SOAP_ACTION, + (const axis2_char_t *)soap_action); + } + } + else if(AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Adding of SOAP Action Failed for REST request"); + + return AXIS2_FAILURE; + } + + if(!send_via_get && !send_via_head && !send_via_delete) + { + /* processing PUT and POST */ + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + + if(AXIS2_FALSE == sender->chunked) + { + axis2_char_t tmp_buf[10]; + if(!buffer) + { + buffer_size = output_stream_size; + } + + if(buffer_size) + { + sprintf(tmp_buf, "%d", buffer_size); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_CONTENT_LENGTH, + tmp_buf); + } + } + else + { + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_TRANSFER_ENCODING, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED); + } + + if(!send_via_put && is_soap) + { + /* HTTP POST */ + if(doing_mtom) + { + content_type = (axis2_char_t *)axiom_output_get_content_type(sender-> om_output, + env); + if(AXIS2_TRUE != axis2_msg_ctx_get_is_soap_11(msg_ctx, env) && 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 + { + content_type_deepl_copy = AXIS2_FALSE; + } + } + else if(AXIS2_TRUE == axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + /* SOAP 1.1 without MTOM */ + 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 + { + /* SOAP 1.2 without MTOM */ + 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_ESC_DOUBLE_QUOTE_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 + { + 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; + } + + content_type_deepl_copy = AXIS2_FALSE; + } + + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_CONTENT_TYPE, + content_type); + + if(content_type_deepl_copy && content_type) + { + AXIS2_FREE(env->allocator, content_type); + content_type = NULL; + } + /* Finished Processing PUT and POST */ + } + + if(0 == axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + /* HTTP 1.1 */ + axis2_char_t *header = NULL; + int host_len = 0; + host_len = axutil_strlen(axutil_url_get_host(url, env)); + header = AXIS2_MALLOC(env->allocator, host_len + 10 * sizeof(axis2_char_t)); + sprintf(header, "%s:%d", axutil_url_get_host(url, env), axutil_url_get_port(url, env)); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_HOST, header); + AXIS2_FREE(env->allocator, header); + header = NULL; + } + + /* If this is a normal invocation the buffer has the full SOAP message + which needs to be send. In the MTOM case instead of this buffer + it has the mime_parts array_list */ + + if(!doing_mtom) + { + axis2_http_simple_request_set_body_string(request, env, buffer, buffer_size); + } + + /* HTTPS request processing */ + axis2_http_sender_configure_server_cert(sender, env, msg_ctx); + + axis2_http_sender_configure_key_file(sender, env, msg_ctx); + + axis2_http_sender_get_timeout_values(sender, env, msg_ctx); + axis2_http_client_set_timeout(sender->client, env, sender->so_timeout); + + ssl_pp_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_PASSPHRASE); + + if(ssl_pp_property) + { + ssl_pp = (axis2_char_t *)axutil_property_get_value(ssl_pp_property, env); + } + else + { + ssl_pp_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_SSL_PASSPHRASE); + + if(ssl_pp_param) + { + ssl_pp = axutil_param_get_value(ssl_pp_param, env); + } + } + + test_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_TEST_PROXY_AUTH); + if(test_auth_property) + { + test_auth_property_value = (axis2_char_t *)axutil_property_get_value(test_auth_property, + env); + } + + if(test_auth_property_value && 0 == axutil_strcmp(test_auth_property_value, AXIS2_VALUE_TRUE)) + { + test_proxy_auth = AXIS2_TRUE; + } + + test_auth_property = NULL; + test_auth_property_value = NULL; + + test_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_TEST_HTTP_AUTH); + if(test_auth_property) + { + test_auth_property_value = (axis2_char_t *)axutil_property_get_value(test_auth_property, + env); + } + + if(test_auth_property_value && 0 == axutil_strcmp(test_auth_property_value, AXIS2_VALUE_TRUE)) + { + test_http_auth = AXIS2_TRUE; + } + + if(!test_proxy_auth) + { + proxy_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_PROXY_AUTH); + } + if(proxy_auth_property) + { + proxy_auth_property_value = (axis2_char_t *)axutil_property_get_value(proxy_auth_property, + env); + } + + if(proxy_auth_property_value && 0 == axutil_strcmp(proxy_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_proxy_auth = AXIS2_TRUE; + } + + proxy_auth_property = NULL; + proxy_auth_property_value = NULL; + + if(force_proxy_auth) + { + proxy_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_PROXY_AUTH_TYPE); + } + + if(proxy_auth_property) + { + proxy_auth_property_value = (axis2_char_t *)axutil_property_get_value(proxy_auth_property, + env); + } + + if(proxy_auth_property_value && 0 == axutil_strcmp(proxy_auth_property_value, + AXIS2_PROXY_AUTH_TYPE_DIGEST)) + { + force_proxy_auth = AXIS2_FALSE; + force_proxy_auth_with_head = AXIS2_TRUE; + } + + if(!test_http_auth) + { + http_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_HTTP_AUTH); + } + + if(http_auth_property) + { + http_auth_property_value = (axis2_char_t *)axutil_property_get_value(http_auth_property, + env); + } + + if(http_auth_property_value && 0 == axutil_strcmp(http_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_http_auth = AXIS2_TRUE; + } + + http_auth_property = NULL; + http_auth_property_value = NULL; + + if(force_http_auth) + { + http_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_AUTH_TYPE); + } + + if(http_auth_property) + { + http_auth_property_value = (axis2_char_t *)axutil_property_get_value(http_auth_property, + env); + } + + if(http_auth_property_value && 0 == axutil_strcmp(http_auth_property_value, + AXIS2_HTTP_AUTH_TYPE_DIGEST)) + { + force_http_auth = AXIS2_FALSE; + force_http_auth_with_head = AXIS2_TRUE; + } + + axis2_msg_ctx_set_auth_type(msg_ctx, env, NULL); + + if(force_proxy_auth || force_proxy_auth_with_head) + { + status_code = AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL; + } + else + { + /* NOT forcing proxy authentication */ + if(force_http_auth) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication header"); + } + http_auth_header_added = AXIS2_TRUE; + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + else if(force_http_auth_with_head) + { + axis2_http_request_line_t *head_request_line = NULL; + axis2_http_request_line_t *temp = NULL; + + temp = axis2_http_simple_request_get_request_line(request, env); + head_request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, + axis2_http_request_line_get_uri(temp, env), + axis2_http_request_line_get_http_version(temp, env)); + axis2_http_simple_request_set_request_line(request, env, head_request_line); + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + axis2_http_simple_request_set_request_line(request, env, temp); + axis2_http_request_line_free(head_request_line, env); + + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication\ + header"); + } + http_auth_header_added = AXIS2_TRUE; + } + + if(status_code != AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL) + { + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + http_auth_header_added = AXIS2_FALSE; + force_http_auth_with_head = AXIS2_FALSE; + } + } + } + else + { + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + } + + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code + && !test_proxy_auth) + { + if(force_proxy_auth_with_head) + { + axis2_http_request_line_t *head_request_line = NULL; + axis2_http_request_line_t *temp = NULL; + + temp = axis2_http_simple_request_get_request_line(request, env); + head_request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, + axis2_http_request_line_get_uri(temp, env), + axis2_http_request_line_get_http_version(temp, env)); + axis2_http_simple_request_set_request_line(request, env, head_request_line); + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + axis2_http_simple_request_set_request_line(request, env, temp); + axis2_http_request_line_free(head_request_line, env); + + if(status_code == AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_proxy_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting Proxy Authentication\ + header"); + } + + if((force_http_auth_with_head || force_http_auth) && !http_auth_header_added) + { + status_code = AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL; + } + else + { + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + } + else if(status_code != AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + /* Proxies have no idea about HTTP Methods therefore, if + * it fails no need to re-check */ + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + } + } + else + { + + /* not forcing proxy auth with head */ + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_proxy_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting Proxy Authentication \ +header"); + } + + if((force_http_auth_with_head || force_http_auth) && !http_auth_header_added) + { + status_code = AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL; + } + else + { + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + } + } + } + } + else if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + axis2_http_sender_set_proxy_auth_type(sender, env, msg_ctx, request); + } + + if(AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL == status_code && !test_http_auth) + { + if(!http_auth_header_added) + { + if(force_proxy_auth_with_head) + { + axis2_http_request_line_t *head_request_line = NULL; + axis2_http_request_line_t *temp = NULL; + + temp = axis2_http_simple_request_get_request_line(request, env); + head_request_line = axis2_http_request_line_create(env, AXIS2_HTTP_HEAD, + axis2_http_request_line_get_uri(temp, env), + axis2_http_request_line_get_http_version(temp, env)); + axis2_http_simple_request_set_request_line(request, env, head_request_line); + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + axis2_http_simple_request_set_request_line(request, env, temp); + axis2_http_request_line_free(head_request_line, env); + + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, + request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication \ +header"); + } + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + if(status_code == AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL) + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, + request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP \ +Authentication header"); + } + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + } + } + else + { + axis2_status_t auth_status; + auth_status = axis2_http_sender_configure_http_auth(sender, env, msg_ctx, request); + + if(auth_status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in setting HTTP Authentication \ +header"); + } + + status_code = axis2_http_client_send(sender->client, env, request, ssl_pp); + + status_code = axis2_http_client_recieve_header(sender->client, env); + } + + if(AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTP Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_TRUE); + } + + if(AXIS2_HTTP_RESPONSE_PROXY_AUTHENTICATION_REQUIRED_CODE_VAL == status_code) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Proxy Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_FALSE); + } + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "HTTP Authentication failed"); + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_TRUE); + } + } + else if(AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL == status_code) + { + axis2_msg_ctx_set_auth_failed(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_required_auth_is_http(msg_ctx, env, AXIS2_TRUE); + axis2_http_sender_set_http_auth_type(sender, env, msg_ctx, request); + } + + axis2_http_simple_request_free(request, env); + request = NULL; + + if(output_stream) + { + AXIS2_FREE(env->allocator, output_stream); + output_stream = NULL; + } + + if(status_code < 0) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "status_code < 0"); + return AXIS2_FAILURE; + } + + axis2_msg_ctx_set_status_code(msg_ctx, env, status_code); + + /* Start processing response */ + response = axis2_http_client_get_response(sender->client, env); + if(!is_soap) + { + return axis2_http_sender_process_response(sender, env, msg_ctx, response); + } + else if(AXIS2_HTTP_RESPONSE_OK_CODE_VAL == status_code || AXIS2_HTTP_RESPONSE_ACK_CODE_VAL + == status_code) + { + return axis2_http_sender_process_response(sender, env, msg_ctx, response); + } + else if(AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL == status_code) + { + axis2_http_header_t *tmp_header = NULL; + axis2_char_t *tmp_header_val = NULL; + axis2_op_t *op = NULL; + + op = axis2_msg_ctx_get_op(msg_ctx, env); + if(op) + { + const axis2_char_t *mep = axis2_op_get_msg_exchange_pattern(op, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + /* handle one way case */ + + if(!axutil_strcmp(mep, AXIS2_MEP_URI_OUT_ONLY)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "mep is AXIS2_MEP_URI_OUT_ONLY"); + return AXIS2_FAILURE; + } + } + + /* set an error to indicate error code status */ + tmp_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(tmp_header) + { + tmp_header_val = axis2_http_header_get_value(tmp_header, env); + } + + if(tmp_header_val && (axutil_strstr(tmp_header_val, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP) + || axutil_strstr(tmp_header_val, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML))) + { + return axis2_http_sender_process_response(sender, env, msg_ctx, response); + } + } + + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_sender_send"); + return AXIS2_FAILURE; +} +#endif + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_set_chunked( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_bool_t chunked) +{ + sender->chunked = chunked; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_set_om_output( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axiom_output_t * om_output) +{ + sender->om_output = om_output; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_get_header_info( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_response_t * response) +{ + axutil_array_list_t *headers = NULL; + axis2_char_t *charset = NULL; + int i = 0; + axis2_bool_t response_chunked = AXIS2_FALSE; + int *content_length = NULL; + axutil_property_t *property = NULL; + axis2_char_t *content_type = NULL; + int status_code = 0; + axis2_bool_t set_cookie_header_present = AXIS2_FALSE; + axis2_bool_t connection_header_present = AXIS2_FALSE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, response, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, sender, AXIS2_FAILURE); + + headers = axis2_http_simple_response_get_headers(response, env); + if(headers == NULL) + { + return AXIS2_SUCCESS; + } + + for(i = 0; i < axutil_array_list_size(headers, env); i++) + { + axis2_http_header_t *header = axutil_array_list_get(headers, env, i); + axis2_char_t *name = axis2_http_header_get_name((axis2_http_header_t *)header, env); + if(name) + { + if(0 == axutil_strcasecmp(name, AXIS2_HTTP_HEADER_TRANSFER_ENCODING) && 0 + == axutil_strcasecmp(axis2_http_header_get_value(header, env), + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + axis2_char_t *transfer_encoding = NULL; + transfer_encoding = axutil_strdup(env, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED); + response_chunked = AXIS2_TRUE; + axis2_msg_ctx_set_transfer_encoding(msg_ctx, env, transfer_encoding); + + } + if(0 != axutil_strcasecmp(name, AXIS2_HTTP_HEADER_CONTENT_TYPE)) + { + axis2_char_t *tmp_charset = NULL; + axis2_char_t *content_type = axis2_http_header_get_value(header, env); + tmp_charset = strstr(content_type, AXIS2_HTTP_CHAR_SET_ENCODING); + if(charset) + { + charset = axutil_strdup(env, tmp_charset); + break; + } + } + if(!axutil_strcasecmp(name, AXIS2_HTTP_HEADER_SET_COOKIE)) + { + axis2_char_t *cookie_str = axis2_http_header_get_value(header, env); + if(cookie_str) + { + axis2_http_transport_utils_store_cookie(env, msg_ctx, cookie_str); + } + set_cookie_header_present = AXIS2_TRUE; + } + + if(!axutil_strcasecmp(name, AXIS2_HTTP_HEADER_CONNECTION)) + { + axis2_char_t *connection_header_value = NULL; + axutil_property_t *connection_map_property = NULL; + axutil_hash_t *connection_map = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + connection_header_present = AXIS2_TRUE; + connection_header_value = axis2_http_header_get_value(header, env); + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, + AXIS2_HTTP_CONNECTION_MAP); + + if(connection_map_property) + { + connection_map = axutil_property_get_value(connection_map_property, env); + } + /** + * In HTTP1.1 if connection header has value close then drop the connection + */ + if(connection_header_value && !axutil_strcasecmp(connection_header_value, "close")) + { + if(connection_map) + { + axis2_http_sender_connection_map_remove(connection_map, env, + msg_ctx, sender->client); + } + } + else if(connection_header_value && !axutil_strcasecmp(connection_header_value, + "Keep-Alive")) + { + if(connection_map) + { + axis2_http_sender_connection_map_add(connection_map, env, + msg_ctx, sender->client); + } + } + } /* End if name is connection */ + } /* End if name of the header present */ + } + if(!set_cookie_header_present) /* We need to remove any cookie set previously for this endpoint */ + { + axis2_http_transport_utils_store_cookie(env, msg_ctx, NULL); + } + if(!connection_header_present) /* No connection header present */ + { + /** In HTTP1.0 if there is no keep alive header sent back from server we drop the + * connection + */ + axutil_property_t *connection_map_property = NULL; + axutil_hash_t *connection_map = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + + connection_map_property = axis2_conf_ctx_get_property(conf_ctx, env, + AXIS2_HTTP_CONNECTION_MAP); + if(connection_map_property) + { + connection_map = axutil_property_get_value(connection_map_property, env); + } /* End if connectin_map_property */ + if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_10)) + { + if(connection_map) + { + axis2_http_sender_connection_map_remove(connection_map, env, msg_ctx, + sender->client); + } + } /* End if http version 1.0 */ + else if(!axutil_strcasecmp(sender->http_version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + /** + * If keep alive enabled we store the http client for reuse. + */ + if(connection_map) + { + axis2_http_sender_connection_map_add(connection_map, env, msg_ctx, + sender->client); + } + } /* End if http version 1.1 */ + } /* End if !connection_header_present */ + + content_type = (axis2_char_t *)axis2_http_simple_response_get_content_type(response, 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); + } + } + + if(charset) + { + axis2_ctx_t *axis_ctx = axis2_op_ctx_get_base(axis2_msg_ctx_get_op_ctx(msg_ctx, env), env); + if(axis_ctx) + { + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, charset); + axis2_ctx_set_property(axis_ctx, env, AXIS2_CHARACTER_SET_ENCODING, property); + } + } + + if(AXIS2_FALSE == response_chunked) + { + int tmp_len = 0; + content_length = AXIS2_MALLOC(env->allocator, sizeof(int)); + if(!content_length) + { + return AXIS2_FAILURE; + } + tmp_len = axis2_http_simple_response_get_content_length(response, env); + memcpy(content_length, &tmp_len, sizeof(int)); + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_value(property, env, content_length); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_HEADER_CONTENT_LENGTH, property); + } + + status_code = axis2_http_simple_response_get_status_code(response, env); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_process_response( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_response_t * response) +{ + axutil_stream_t *in_stream = NULL; + axutil_property_t *property = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_sender_process_response"); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, response, AXIS2_FAILURE); + + in_stream = axis2_http_simple_response_get_body(response, env); + if(!in_stream) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_STREAM_IN_RESPONSE_BODY, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + axis2_http_sender_get_header_info(sender, env, msg_ctx, response); + axis2_msg_ctx_set_http_output_headers(msg_ctx, env, axis2_http_simple_response_extract_headers( + response, env)); + property = axutil_property_create(env); + axutil_property_set_scope(property, env, AXIS2_SCOPE_REQUEST); + axutil_property_set_free_func(property, env, axutil_stream_free_void_arg); + axutil_property_set_value(property, env, in_stream); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_IN, property); + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_sender_process_response"); + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_get_timeout_values( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_char_t *so_str = NULL; + axis2_char_t *connection_str = NULL; + axutil_param_t *tmp_param = NULL; + axutil_property_t *property = NULL; + + AXIS2_PARAM_CHECK(env->error, sender, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + /* 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) + { + sender->so_timeout = AXIS2_ATOI(value); + return AXIS2_SUCCESS; + } + } + + tmp_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_HTTP_SO_TIMEOUT); + + if(tmp_param) + { + so_str = (axis2_char_t *)axutil_param_get_value(tmp_param, env); + if(so_str) + { + sender->so_timeout = AXIS2_ATOI(so_str); + return AXIS2_SUCCESS; + } + } + + tmp_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_HTTP_CONNECTION_TIMEOUT); + if(tmp_param) + { + connection_str = (axis2_char_t *)axutil_param_get_value(tmp_param, env); + if(connection_str) + { + sender->so_timeout = AXIS2_ATOI(connection_str); + return AXIS2_SUCCESS; + } + } + return AXIS2_FAILURE; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_sender_set_http_version( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_char_t * version) +{ + sender->http_version = axutil_strdup(env, version); + if(!sender->http_version) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; +} + +#ifndef AXIS2_LIBCURL_ENABLED +static void +axis2_http_sender_add_header_list( + axis2_http_simple_request_t * request, + const axutil_env_t * env, + axutil_array_list_t * array_list) +{ + int ii = 0; + int kk = 0; + axis2_http_header_t *http_header = NULL; + ii = axutil_array_list_size(array_list, env); + for(; kk < ii; kk++) + { + http_header = (axis2_http_header_t *)axutil_array_list_get(array_list, env, kk); + axis2_http_simple_request_add_header(request, env, http_header); + } +} + +static axis2_status_t +axis2_http_sender_configure_proxy( + axis2_http_sender_t * sender, + 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; + axis2_char_t *proxy_host = NULL; + axis2_char_t *proxy_port = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + if(!conf_ctx) + { + return AXIS2_FAILURE; + } + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + if(!conf) + { + return AXIS2_FAILURE; + } + + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + if(!trans_desc) + { + return AXIS2_FAILURE; + } + + 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 *host_attr = NULL; + axiom_attribute_t *port_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_HOST, AXIS2_HASH_KEY_STRING); + if(!obj) + { + return AXIS2_FAILURE; + } + host_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + if(!host_attr) + { + return AXIS2_FAILURE; + } + proxy_host = axiom_attribute_get_value(host_attr, env); + if(!proxy_host) + { + return AXIS2_FAILURE; + } + /* Now we get the port */ + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PORT, AXIS2_HASH_KEY_STRING); + port_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + if(!port_attr) + { + return AXIS2_FAILURE; + } + proxy_port = axiom_attribute_get_value(port_attr, env); + if(!proxy_port) + { + return AXIS2_FAILURE; + } + } + } + if(proxy_port && proxy_host) + { + axis2_http_client_set_proxy(sender->client, env, proxy_host, AXIS2_ATOI(proxy_port)); + } + return AXIS2_SUCCESS; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_server_cert( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *server_cert_property = NULL; + axutil_param_t *server_cert_param = NULL; + axis2_char_t *server_cert = NULL; + axis2_status_t status = AXIS2_FAILURE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + server_cert_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_SERVER_CERT); + if(server_cert_property) + { + server_cert = (axis2_char_t *)axutil_property_get_value(server_cert_property, env); + } + else + { + server_cert_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_SSL_SERVER_CERT); + if(server_cert_param) + { + server_cert = (axis2_char_t *)axutil_param_get_value(server_cert_param, env); + } + } + + if(server_cert) + { + status = axis2_http_client_set_server_cert(sender->client, env, server_cert); + } + + return status; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_key_file( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axutil_property_t *key_file_property = NULL; + axutil_param_t *key_file_param = NULL; + axis2_char_t *key_file = NULL; + axis2_status_t status = AXIS2_FAILURE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + key_file_property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_SSL_KEY_FILE); + if(key_file_property) + { + key_file = (axis2_char_t *)axutil_property_get_value(key_file_property, env); + } + else + { + key_file_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_SSL_KEY_FILE); + if(key_file_param) + { + key_file = (axis2_char_t *)axutil_param_get_value(key_file_param, env); + } + } + + if(key_file) + { + status = axis2_http_client_set_key_file(sender->client, env, key_file); + } + + return status; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_http_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axutil_property_t *http_auth_un = NULL; + axutil_property_t *http_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + http_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_UNAME); + http_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_PASSWD); + if(http_auth_un && http_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(http_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(http_auth_pw, env); + } + if(!uname || !passwd) + { + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *http_auth_param = NULL; + axutil_hash_t *transport_attrs = NULL; + + 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) + { + http_auth_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_AUTHENTICATION); + if(http_auth_param) + { + transport_attrs = axutil_param_get_attributes(http_auth_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen; + int plen = axutil_strlen(uname) + axutil_strlen(passwd) + 1; + axis2_char_t *to_encode = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * plen + 1)); + axis2_char_t *encoded = NULL; + axis2_char_t *auth_str = NULL; + sprintf(to_encode, "%s:%s", uname, passwd); + elen = axutil_base64_encode_len(plen); + encoded = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * elen)); + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 6))); + axutil_base64_encode(encoded, to_encode, plen); + sprintf(auth_str, "%s %s", AXIS2_HTTP_AUTH_TYPE_BASIC, encoded); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_AUTHORIZATION, auth_str); + + AXIS2_FREE(env->allocator, to_encode); + to_encode = NULL; + AXIS2_FREE(env->allocator, encoded); + encoded = NULL; + AXIS2_FREE(env->allocator, auth_str); + auth_str = NULL; + + return AXIS2_SUCCESS; + } + + return AXIS2_FAILURE; + +} + +static axis2_status_t +axis2_http_sender_configure_proxy_basic_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axutil_property_t *proxy_auth_un = NULL; + axutil_property_t *proxy_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + proxy_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_UNAME); + proxy_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_PASSWD); + + if(proxy_auth_un && proxy_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(proxy_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(proxy_auth_pw, env); + } + if(!uname || !passwd) + { + 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; + + 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 *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen; + int plen = axutil_strlen(uname) + axutil_strlen(passwd) + 1; + axis2_char_t *to_encode = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * plen + 1)); + axis2_char_t *encoded = NULL; + axis2_char_t *auth_str = NULL; + sprintf(to_encode, "%s:%s", uname, passwd); + elen = axutil_base64_encode_len(plen); + encoded = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * elen)); + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 6))); + axutil_base64_encode(encoded, to_encode, plen); + sprintf(auth_str, "%s %s", AXIS2_PROXY_AUTH_TYPE_BASIC, encoded); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_PROXY_AUTHORIZATION, + auth_str); + + AXIS2_FREE(env->allocator, to_encode); + to_encode = NULL; + AXIS2_FREE(env->allocator, encoded); + encoded = NULL; + AXIS2_FREE(env->allocator, auth_str); + auth_str = NULL; + + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_http_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data) +{ + axutil_property_t *http_auth_un = NULL; + axutil_property_t *http_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + if(!header_data || !*header_data) + return AXIS2_FAILURE; + + http_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_UNAME); + http_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_AUTH_PASSWD); + if(http_auth_un && http_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(http_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(http_auth_pw, env); + } + if(!uname || !passwd) + { + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_conf_t *conf = NULL; + axis2_transport_out_desc_t *trans_desc = NULL; + axutil_param_t *http_auth_param = NULL; + axutil_hash_t *transport_attrs = NULL; + + 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) + { + http_auth_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(trans_desc, env), env, + AXIS2_HTTP_AUTHENTICATION); + if(http_auth_param) + { + transport_attrs = axutil_param_get_attributes(http_auth_param, env); + if(transport_attrs) + { + axutil_generic_obj_t *obj = NULL; + axiom_attribute_t *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + obj = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_AUTHENTICATION_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen = 0; /* length of header content */ + int print_const = 5; /* constant accounts for printing the + quoatation marks, comma, and space */ + int response_length = 32; + axis2_char_t *temp = NULL; + axis2_char_t *alloc_temp = NULL; + axis2_char_t *algo = AXIS2_HTTP_AUTHORIZATION_REQUEST_ALGORITHM_MD5; + axis2_char_t *realm = NULL; + axis2_char_t *qop = NULL; + axis2_char_t *nonce = NULL; + axis2_char_t *opaque = NULL; + axis2_char_t *cnonce = NULL; + axis2_char_t *nc = NULL; + axutil_digest_hash_hex_t h_a1; + axutil_digest_hash_hex_t h_a2; + axutil_digest_hash_hex_t response; + axis2_char_t *auth_str = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + axis2_char_t *url = NULL; + + url = axis2_http_request_line_get_uri(axis2_http_simple_request_get_request_line(request, + env), env); + + if(!url) + { + return AXIS2_FAILURE; + } + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + + axutil_strlen(url); + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + + axutil_strlen(uname); + + 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); + } + else + { + method_value = AXIS2_HTTP_POST; + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM); + if(temp) + { + realm = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(realm) + { + realm++; + temp = axutil_strchr(realm, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - realm + 1))); + strncpy(alloc_temp, realm, (temp - realm)); + if(alloc_temp) + alloc_temp[temp - realm] = AXIS2_ESC_NULL; + realm = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + + axutil_strlen(realm); + } + else + { + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP); + if(temp) + { + qop = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(qop) + { + qop++; + temp = axutil_strchr(qop, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - qop + 1))); + strncpy(alloc_temp, qop, (temp - qop)); + if(alloc_temp) + alloc_temp[temp - qop] = AXIS2_ESC_NULL; + qop = alloc_temp; + alloc_temp = NULL; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE); + if(temp) + { + nonce = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(nonce) + { + nonce++; + temp = axutil_strchr(nonce, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - nonce + 1))); + strncpy(alloc_temp, nonce, (temp - nonce)); + if(alloc_temp) + alloc_temp[temp - nonce] = AXIS2_ESC_NULL; + nonce = alloc_temp; + alloc_temp = NULL; + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + + axutil_strlen(nonce); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE); + if(temp) + { + opaque = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(opaque) + { + opaque++; + temp = axutil_strchr(opaque, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - opaque + 1))); + strncpy(alloc_temp, opaque, (temp - opaque)); + if(alloc_temp) + alloc_temp[temp - opaque] = AXIS2_ESC_NULL; + opaque = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + + axutil_strlen(opaque); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + if(nonce) + AXIS2_FREE(env->allocator, nonce); + return AXIS2_FAILURE; + } + } + + if(qop) + { + nc = AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE; + temp = qop; + if(!axutil_strstr(temp, AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH)) + { + return AXIS2_FAILURE; + } + AXIS2_FREE(env->allocator, qop); + qop = AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH; + temp = axutil_uuid_gen(env); + cnonce = temp; + temp += CLIENT_NONCE_LENGTH; + if(temp) + *temp = AXIS2_ESC_NULL; + elen += 11 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + CLIENT_NONCE_LENGTH + + axutil_strlen(qop); + } + + axutil_digest_calc_get_h_a1(env, algo, uname, realm, passwd, cnonce, nonce, h_a1); + axutil_digest_calc_get_response(env, h_a1, nonce, nc, cnonce, qop, method_value, url, h_a2, + response); + + elen += 4 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE) + axutil_strlen( + AXIS2_HTTP_AUTH_TYPE_DIGEST) + response_length; + + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 1))); + temp = auth_str; + sprintf(temp, "%s %s=\"%s\", ", AXIS2_HTTP_AUTH_TYPE_DIGEST, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME, uname); + temp += ((int)strlen(AXIS2_HTTP_AUTH_TYPE_DIGEST) + (int)strlen( + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + (int)strlen(uname) + 6); + if(realm) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM, realm); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + (int)strlen(realm) + + 5); + } + if(nonce) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE, nonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + (int)strlen(nonce) + + 5); + } + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI, url); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + (int)strlen(url) + 5); + if(qop) + { + sprintf(temp, "%s=%s, %s=%s, %s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP, + qop, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT, nc, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE, cnonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + (int)strlen(qop) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + (int)strlen(nc) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + (int)strlen( + cnonce) + 11); + } + if(opaque) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE, opaque); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + (int)strlen( + opaque) + 5); + } + sprintf(temp, "%s=\"%s\"", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE, response); + + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_AUTHORIZATION, auth_str); + if(realm) + AXIS2_FREE(env->allocator, realm); + if(nonce) + AXIS2_FREE(env->allocator, nonce); + if(cnonce) + AXIS2_FREE(env->allocator, cnonce); + if(opaque) + AXIS2_FREE(env->allocator, opaque); + if(auth_str) + AXIS2_FREE(env->allocator, auth_str); + auth_str = NULL; + + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +static axis2_status_t +axis2_http_sender_configure_proxy_digest_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request, + axis2_char_t * header_data) +{ + axutil_property_t *proxy_auth_un = NULL; + axutil_property_t *proxy_auth_pw = NULL; + axis2_char_t *uname = NULL; + axis2_char_t *passwd = NULL; + + if(!header_data || !*header_data) + return AXIS2_FAILURE; + + proxy_auth_un = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_UNAME); + proxy_auth_pw = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_PROXY_AUTH_PASSWD); + + if(proxy_auth_un && proxy_auth_pw) + { + uname = (axis2_char_t *)axutil_property_get_value(proxy_auth_un, env); + passwd = (axis2_char_t *)axutil_property_get_value(proxy_auth_pw, env); + } + if(!uname || !passwd) + { + 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; + + 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 *username_attr = NULL; + axiom_attribute_t *password_attr = NULL; + + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_USERNAME, + AXIS2_HASH_KEY_STRING); + if(obj) + { + username_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(username_attr) + { + uname = axiom_attribute_get_value(username_attr, env); + } + + obj = NULL; + obj = axutil_hash_get(transport_attrs, AXIS2_HTTP_PROXY_PASSWORD, + AXIS2_HASH_KEY_STRING); + if(obj) + { + password_attr = (axiom_attribute_t *)axutil_generic_obj_get_value(obj, env); + } + if(password_attr) + { + passwd = axiom_attribute_get_value(password_attr, env); + } + } + } + } + } + if(uname && passwd) + { + int elen = 0; /* length of header content */ + int print_const = 5; /* constant accounts for printing the + quoatation marks, comma, and space */ + int response_length = 32; + axis2_char_t *temp = NULL; + axis2_char_t *alloc_temp = NULL; + axis2_char_t *algo = AXIS2_HTTP_AUTHORIZATION_REQUEST_ALGORITHM_MD5; + axis2_char_t *realm = NULL; + axis2_char_t *qop = NULL; + axis2_char_t *nonce = NULL; + axis2_char_t *opaque = NULL; + axis2_char_t *cnonce = NULL; + axis2_char_t *nc = NULL; + axutil_digest_hash_hex_t h_a1; + axutil_digest_hash_hex_t h_a2; + axutil_digest_hash_hex_t response; + axis2_char_t *auth_str = NULL; + axutil_property_t *method = NULL; + axis2_char_t *method_value = NULL; + axis2_char_t *url = NULL; + + url = axis2_http_request_line_get_uri(axis2_http_simple_request_get_request_line(request, + env), env); + + if(!url) + { + return AXIS2_FAILURE; + } + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + + axutil_strlen(url); + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + + axutil_strlen(uname); + + 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); + } + else + { + method_value = AXIS2_HTTP_POST; + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM); + if(temp) + { + realm = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(realm) + { + realm++; + temp = axutil_strchr(realm, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - realm + 1))); + strncpy(alloc_temp, realm, (temp - realm)); + if(alloc_temp) + alloc_temp[temp - realm] = AXIS2_ESC_NULL; + realm = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + + axutil_strlen(realm); + } + else + { + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP); + if(temp) + { + qop = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(qop) + { + qop++; + temp = axutil_strchr(qop, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - qop + 1))); + strncpy(alloc_temp, qop, (temp - qop)); + if(alloc_temp) + alloc_temp[temp - qop] = AXIS2_ESC_NULL; + qop = alloc_temp; + alloc_temp = NULL; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE); + if(temp) + { + nonce = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(nonce) + { + nonce++; + temp = axutil_strchr(nonce, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - nonce + 1))); + strncpy(alloc_temp, nonce, (temp - nonce)); + if(alloc_temp) + alloc_temp[temp - nonce] = AXIS2_ESC_NULL; + nonce = alloc_temp; + alloc_temp = NULL; + + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + + axutil_strlen(nonce); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + return AXIS2_FAILURE; + } + } + + temp = axutil_strstr(header_data, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE); + if(temp) + { + opaque = axutil_strchr(temp, AXIS2_ESC_DOUBLE_QUOTE); + if(opaque) + { + opaque++; + temp = axutil_strchr(opaque, AXIS2_ESC_DOUBLE_QUOTE); + alloc_temp = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) + * (temp - opaque + 1))); + strncpy(alloc_temp, opaque, (temp - opaque)); + if(alloc_temp) + alloc_temp[temp - opaque] = AXIS2_ESC_NULL; + opaque = alloc_temp; + alloc_temp = NULL; + elen += print_const + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + + axutil_strlen(opaque); + } + else + { + if(realm) + AXIS2_FREE(env->allocator, realm); + if(nonce) + AXIS2_FREE(env->allocator, nonce); + return AXIS2_FAILURE; + } + } + + if(qop) + { + nc = AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE; + temp = qop; + if(!axutil_strstr(temp, AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH)) + { + return AXIS2_FAILURE; + } + AXIS2_FREE(env->allocator, qop); + qop = AXIS2_HTTP_AUTHORIZATION_REQUEST_QOP_OPTION_AUTH; + temp = axutil_uuid_gen(env); + cnonce = temp; + temp += CLIENT_NONCE_LENGTH; + if(temp) + *temp = AXIS2_ESC_NULL; + elen += 11 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_DEFAULT_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + CLIENT_NONCE_LENGTH + + axutil_strlen(qop); + } + + axutil_digest_calc_get_h_a1(env, algo, uname, realm, passwd, cnonce, nonce, h_a1); + axutil_digest_calc_get_response(env, h_a1, nonce, nc, cnonce, qop, method_value, url, h_a2, + response); + + elen += 4 + axutil_strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE) + axutil_strlen( + AXIS2_PROXY_AUTH_TYPE_DIGEST) + response_length; + + auth_str + = (axis2_char_t *)(AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (elen + 1))); + temp = auth_str; + sprintf(temp, "%s %s=\"%s\", ", AXIS2_PROXY_AUTH_TYPE_DIGEST, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME, uname); + temp += ((int)strlen(AXIS2_HTTP_AUTH_TYPE_DIGEST) + (int)strlen( + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_USERNAME) + (int)strlen(uname) + 6); + if(realm) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM, realm); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_REALM) + (int)strlen(realm) + + 5); + } + if(nonce) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE, nonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE) + (int)strlen(nonce) + + 5); + } + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI, url); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_URI) + (int)strlen(url) + 5); + if(qop) + { + sprintf(temp, "%s=%s, %s=%s, %s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP, + qop, AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT, nc, + AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE, cnonce); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_QOP) + (int)strlen(qop) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_NONCE_COUNT) + (int)strlen(nc) + + (int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_CLIENT_NONCE) + (int)strlen( + cnonce) + 11); + } + if(opaque) + { + sprintf(temp, "%s=\"%s\", ", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE, opaque); + temp += ((int)strlen(AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_OPAQUE) + (int)strlen( + opaque) + 5); + } + sprintf(temp, "%s=\"%s\"", AXIS2_HTTP_AUTHORIZATION_REQUEST_PARAM_RESPONSE, response); + axis2_http_sender_util_add_header(env, request, AXIS2_HTTP_HEADER_PROXY_AUTHORIZATION, + auth_str); + if(realm) + { + AXIS2_FREE(env->allocator, realm); + } + + if(nonce) + { + AXIS2_FREE(env->allocator, nonce); + } + + if(cnonce) + { + AXIS2_FREE(env->allocator, cnonce); + } + + if(opaque) + { + AXIS2_FREE(env->allocator, opaque); + } + + if(auth_str) + { + AXIS2_FREE(env->allocator, auth_str); + } + + auth_str = NULL; + + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_configure_http_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axutil_property_t *http_auth_property = NULL; + axis2_char_t *http_auth_property_value = NULL; + axis2_bool_t force_http_auth = AXIS2_FALSE; + axutil_property_t *http_auth_type_property = NULL; + axis2_char_t *http_auth_type_property_value = NULL; + axis2_char_t *auth_type_end = NULL; + + http_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_HTTP_AUTH); + if(http_auth_property) + { + http_auth_property_value = (axis2_char_t *)axutil_property_get_value(http_auth_property, + env); + } + + if(http_auth_property_value && 0 == axutil_strcmp(http_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_http_auth = AXIS2_TRUE; + } + + if(force_http_auth) + { + http_auth_type_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_HTTP_AUTH_TYPE); + if(http_auth_type_property) + { + http_auth_type_property_value = (axis2_char_t *)axutil_property_get_value( + http_auth_type_property, env); + } + + if(http_auth_type_property_value) + { + auth_type = http_auth_type_property_value; + } + } + if(!force_http_auth || axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0) + { + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_WWW_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + if(force_http_auth && axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) != 0) + { + auth_type = NULL; + } + } + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC) == 0) + { + status = axis2_http_sender_configure_http_basic_auth(sender, env, msg_ctx, request); + } + else if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_http_sender_configure_http_digest_auth(sender, env, msg_ctx, request, + auth_type_end); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not" + "supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + + return status; +} + +static axis2_status_t +axis2_http_sender_configure_proxy_auth( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axutil_property_t *proxy_auth_property = NULL; + axis2_char_t *proxy_auth_property_value = NULL; + axis2_bool_t force_proxy_auth = AXIS2_FALSE; + axutil_property_t *proxy_auth_type_property = NULL; + axis2_char_t *proxy_auth_type_property_value = NULL; + axis2_char_t *auth_type_end = NULL; + + proxy_auth_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_FORCE_PROXY_AUTH); + if(proxy_auth_property) + { + proxy_auth_property_value = (axis2_char_t *)axutil_property_get_value(proxy_auth_property, + env); + } + + if(proxy_auth_property_value && 0 == axutil_strcmp(proxy_auth_property_value, AXIS2_VALUE_TRUE)) + { + force_proxy_auth = AXIS2_TRUE; + } + + if(force_proxy_auth) + { + proxy_auth_type_property = (axutil_property_t *)axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_PROXY_AUTH_TYPE); + if(proxy_auth_type_property) + { + proxy_auth_type_property_value = (axis2_char_t *)axutil_property_get_value( + proxy_auth_type_property, env); + } + + if(proxy_auth_type_property_value) + { + auth_type = proxy_auth_type_property_value; + } + } + else + { + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_PROXY_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + } + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_BASIC) == 0) + { + status = axis2_http_sender_configure_proxy_basic_auth(sender, env, msg_ctx, request); + } + else if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_http_sender_configure_proxy_digest_auth(sender, env, msg_ctx, request, + auth_type_end); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + + return status; +} +#endif + +#ifndef AXIS2_LIBCURL_ENABLED +static axis2_status_t +axis2_http_sender_set_http_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axis2_char_t *auth_type_end = NULL; + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_WWW_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_BASIC) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_HTTP_AUTH_TYPE_BASIC); + } + else if(axutil_strcasecmp(auth_type, AXIS2_HTTP_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_HTTP_AUTH_TYPE_DIGEST); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + return status; +} + +static axis2_status_t +axis2_http_sender_set_proxy_auth_type( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_http_simple_request_t * request) +{ + axis2_char_t *auth_type = NULL; + axis2_status_t status = AXIS2_FALSE; + axis2_char_t *auth_type_end = NULL; + axis2_http_header_t *auth_header = NULL; + axis2_http_simple_response_t *response = NULL; + + response = axis2_http_client_get_response(sender->client, env); + + if(response) + { + auth_header = axis2_http_simple_response_get_first_header(response, env, + AXIS2_HTTP_HEADER_PROXY_AUTHENTICATE); + } + + if(auth_header) + { + auth_type = axis2_http_header_get_value(auth_header, env); + } + + if(auth_type) + { + auth_type_end = axutil_strchr(auth_type, ' '); + *auth_type_end = AXIS2_ESC_NULL; + auth_type_end++; + /*Read the realm and the rest stuff now from auth_type_end */ + } + + if(auth_type) + { + if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_BASIC) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_PROXY_AUTH_TYPE_BASIC); + } + else if(axutil_strcasecmp(auth_type, AXIS2_PROXY_AUTH_TYPE_DIGEST) == 0) + { + status = axis2_msg_ctx_set_auth_type(msg_ctx, env, AXIS2_PROXY_AUTH_TYPE_DIGEST); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Authtype %s is not supported", auth_type); + } + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_HTTP_CLIENT_TRANSPORT_ERROR, AXIS2_FAILURE); + } + return status; +} +#endif + +#ifdef AXIS2_LIBCURL_ENABLED +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_libcurl_http_send (axis2_libcurl_t * curl, + axis2_http_sender_t * sender, + 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) +{ + return axis2_libcurl_send (curl, sender->om_output, + env, msg_ctx, out, str_url, soap_action); +} +#endif + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_sender_get_param_string( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axiom_soap_envelope_t *soap_env = NULL; + axiom_soap_body_t *soap_body = NULL; + axiom_node_t *body_node = NULL; + axiom_node_t *data_node = NULL; + axiom_element_t *data_element = NULL; + axiom_child_element_iterator_t *iterator = NULL; + axutil_array_list_t *param_list = NULL; + axis2_char_t *param_string = NULL; + int i = 0; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, NULL); + + soap_env = axis2_msg_ctx_get_soap_envelope(msg_ctx, env); + if(!soap_env) + { + return NULL; + } + soap_body = axiom_soap_envelope_get_body(soap_env, env); + body_node = axiom_soap_body_get_base_node(soap_body, env); + if(!body_node) + { + /* This could be the situation where service client does not provide + * a xml payload and instead add url parameters to the endpoint url + */ + return NULL; + } + data_node = axiom_node_get_first_child(body_node, env); + if(!data_node) + { + return NULL; + } + + param_list = axutil_array_list_create(env, AXIS2_ARRAY_LIST_DEFAULT_CAPACITY); + + data_element = axiom_node_get_data_element(data_node, env); + + iterator = axiom_element_get_child_elements(data_element, env, data_node); + + if(iterator) + { + while(AXIS2_TRUE == AXIOM_CHILD_ELEMENT_ITERATOR_HAS_NEXT(iterator, env)) + { + axiom_node_t *node = NULL; + axiom_element_t *element = NULL; + axis2_char_t *name = NULL; + axis2_char_t *value = NULL; + axis2_char_t *encoded_value = NULL; + + node = AXIOM_CHILD_ELEMENT_ITERATOR_NEXT(iterator, env); + element = axiom_node_get_data_element(node, env); + name = axiom_element_get_localname(element, env); + value = axiom_element_get_text(element, env, node); + if(value) + { + encoded_value = (axis2_char_t *)AXIS2_MALLOC(env->allocator, strlen(value)); + memset(encoded_value, 0, strlen(value)); + encoded_value = axutil_url_encode(env, encoded_value, value, (int)strlen(value)); + /* We are sure that the difference lies within the int range */ + + axutil_array_list_add(param_list, env, axutil_strcat(env, name, "=", encoded_value, + NULL)); + AXIS2_FREE(env->allocator, encoded_value); + encoded_value = NULL; + } + } + } + for(i = 0; i < axutil_array_list_size(param_list, env); i++) + { + axis2_char_t *tmp_string = NULL; + axis2_char_t *pair = NULL; + + pair = axutil_array_list_get(param_list, env, i); + if(i == 0) + { + tmp_string = axutil_stracat(env, param_string, pair); + } + else + { + tmp_string = axutil_strcat(env, param_string, AXIS2_AND_SIGN, pair, NULL); + } + + if(param_string) + { + AXIS2_FREE(env->allocator, param_string); + param_string = NULL; + } + AXIS2_FREE(env->allocator, pair); + param_string = tmp_string; + } + axutil_array_list_free(param_list, env); + return param_string; +} + +void AXIS2_CALL +axis2_http_sender_util_add_header( + const axutil_env_t * env, + axis2_http_simple_request_t * request, + axis2_char_t * header_name, + const axis2_char_t * header_value) +{ + axis2_http_header_t *http_header; + http_header = axis2_http_header_create(env, header_name, header_value); + axis2_http_simple_request_add_header(request, env, http_header); +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_sender_set_keep_alive( + axis2_http_sender_t * sender, + const axutil_env_t * env, + axis2_bool_t keep_alive) +{ + sender->keep_alive = keep_alive; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_sender_get_keep_alive( + axis2_http_sender_t * sender, + const axutil_env_t * env) +{ + return sender->keep_alive; +} + +static axutil_hash_t * +axis2_http_sender_connection_map_create( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx) +{ + axutil_hash_t *connection_map = NULL; + connection_map = axutil_hash_make(env); + if(!connection_map) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + } + else + { + axis2_conf_ctx_t *conf_ctx = NULL; + axutil_property_t *connection_map_property = NULL; + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + connection_map_property = axutil_property_create_with_args(env, AXIS2_SCOPE_SESSION, + AXIS2_TRUE, axis2_http_sender_connection_map_free, connection_map); + axis2_conf_ctx_set_property(conf_ctx, env, AXIS2_HTTP_CONNECTION_MAP, + connection_map_property); + } + return connection_map; +} + +static void +axis2_http_sender_connection_map_remove( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client) +{ + axutil_property_t *property = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + /** + * Put the http client into message context with own value true so that it will be freed + * after response processed + */ + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_TRUE, + axis2_http_client_free_void_arg, http_client); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, property); + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + const axis2_char_t *address = NULL; + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = axutil_url_get_server(url, env); + if(server) + { + axutil_hash_set(connection_map, server, AXIS2_HASH_KEY_STRING, NULL); + } + axutil_url_free(url, env); + } + } + } +} + +static void +axis2_http_sender_connection_map_add( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_http_client_t *http_client) +{ + axutil_property_t *property = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + /** + * Put the http client into message context. Is this neccessary? + */ + property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_FALSE, + axis2_http_client_free_void_arg, http_client); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_CLIENT, property); + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + const axis2_char_t *address = NULL; + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = axutil_url_get_server(url, env); + if(server) + { + axutil_hash_set(connection_map, axutil_strdup(env, server), + AXIS2_HASH_KEY_STRING, http_client); + } + axutil_url_free(url, env); + } + } + } +} + +static axis2_http_client_t * +axis2_http_sender_connection_map_get( + axutil_hash_t *connection_map, + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx) +{ + axis2_http_client_t *http_client = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + const axis2_char_t *address = NULL; + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = axutil_url_get_server(url, env); + if(server) + { + http_client = axutil_hash_get(connection_map, server, AXIS2_HASH_KEY_STRING); + } + axutil_url_free(url, env); + } + } + } + return http_client; +} + +static void AXIS2_CALL +axis2_http_sender_connection_map_free( + void *cm_void, + const axutil_env_t *env) +{ + void *val = NULL; + const void *key = NULL; + axutil_hash_index_t *hi = NULL; + axutil_hash_t *ht = (axutil_hash_t *)cm_void; + + for(hi = axutil_hash_first(ht, env); hi; hi = axutil_hash_next(env, hi)) + { + axis2_char_t *name = NULL; + axis2_http_client_t *value = NULL; + + axutil_hash_this(hi, &key, NULL, &val); + name = (axis2_char_t *) key; + if(name) + { + AXIS2_FREE(env->allocator, name); + } + value = (axis2_http_client_t *) val; + if(value) + { + axis2_http_client_free(value, env); + } + } + axutil_hash_free(ht, env); +} + diff --git a/src/core/transport/http/sender/http_transport_sender.c b/src/core/transport/http/sender/http_transport_sender.c new file mode 100644 index 0000000..3ef55b0 --- /dev/null +++ b/src/core/transport/http/sender/http_transport_sender.c @@ -0,0 +1,859 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef AXIS2_LIBCURL_ENABLED +#include "libcurl/axis2_libcurl.h" +#endif + +/** + * HTTP Transport Sender struct impl + * Axis2 HTTP Transport Sender impl + */ + +typedef struct axis2_http_transport_sender_impl +{ + axis2_transport_sender_t transport_sender; + axis2_char_t *http_version; + axis2_bool_t chunked; + int connection_timeout; + int so_timeout; + axis2_bool_t keep_alive; +#ifdef AXIS2_LIBCURL_ENABLED + axis2_libcurl_t *libcurl; +#endif +} axis2_http_transport_sender_impl_t; + +#define AXIS2_WS_RM_ANONYMOUS_URL "http://docs.oasis-open.org/ws-rx/wsmc/200702/anonymous?id=" +#define AXIS2_INTF_TO_IMPL(transport_sender) \ + ((axis2_http_transport_sender_impl_t *)\ + (transport_sender)) + +/***************************** Function headers *******************************/ +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_invoke( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_clean_up( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_init( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_transport_out_desc_t * out_desc); + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_write_message( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_endpoint_ref_t * epr, + axiom_soap_envelope_t * out, + axiom_output_t * om_output); + +void AXIS2_CALL axis2_http_transport_sender_free( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env); + +static const axis2_transport_sender_ops_t http_transport_sender_ops_var = { + axis2_http_transport_sender_init, axis2_http_transport_sender_invoke, + axis2_http_transport_sender_clean_up, axis2_http_transport_sender_free }; + +axis2_transport_sender_t *AXIS2_CALL +axis2_http_transport_sender_create( + const axutil_env_t * env) +{ + axis2_http_transport_sender_impl_t *transport_sender_impl = NULL; + + transport_sender_impl = (axis2_http_transport_sender_impl_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_http_transport_sender_impl_t)); + + if(!transport_sender_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset((void *)transport_sender_impl, 0, sizeof(axis2_http_transport_sender_impl_t)); + + transport_sender_impl->http_version = axutil_strdup(env, AXIS2_HTTP_HEADER_PROTOCOL_11); + transport_sender_impl->chunked = AXIS2_TRUE; + transport_sender_impl->connection_timeout = AXIS2_HTTP_DEFAULT_CONNECTION_TIMEOUT; + transport_sender_impl->so_timeout = AXIS2_HTTP_DEFAULT_SO_TIMEOUT; + transport_sender_impl->keep_alive = AXIS2_TRUE; + transport_sender_impl->transport_sender.ops = &http_transport_sender_ops_var; + +#ifdef AXIS2_LIBCURL_ENABLED + transport_sender_impl->libcurl = axis2_libcurl_create(env); + if (!transport_sender_impl->libcurl) + { + AXIS2_FREE(env->allocator, transport_sender_impl); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } +#endif + + return &(transport_sender_impl->transport_sender); +} + +void AXIS2_CALL +axis2_http_transport_sender_free( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env) +{ + + axis2_http_transport_sender_impl_t *transport_sender_impl = NULL; + if(!transport_sender) + { + return; + } + + transport_sender_impl = AXIS2_INTF_TO_IMPL(transport_sender); + + if(transport_sender_impl->http_version) + { + AXIS2_FREE(env->allocator, transport_sender_impl->http_version); + transport_sender_impl->http_version = NULL; + } + +#ifdef AXIS2_LIBCURL_ENABLED + if (transport_sender_impl->libcurl) + { + axis2_libcurl_free(transport_sender_impl->libcurl, env); + } +#endif + + AXIS2_FREE(env->allocator, transport_sender_impl); + return; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_invoke( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + const axis2_char_t *char_set_enc = NULL; + axutil_string_t *char_set_enc_str = NULL; + axis2_endpoint_ref_t *epr = NULL; + axis2_char_t *transport_url = NULL; + axiom_xml_writer_t *xml_writer = NULL; + axiom_output_t *om_output = NULL; + axis2_char_t *buffer = NULL; + axiom_soap_envelope_t *soap_data_out = NULL; + axis2_bool_t do_mtom; + axutil_property_t *property = NULL; + axiom_node_t *data_out = NULL; + int buffer_size = 0; + axis2_status_t status = AXIS2_SUCCESS; + 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; + axis2_bool_t fault = AXIS2_FALSE; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_transport_sender_invoke"); + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + char_set_enc_str = axis2_msg_ctx_get_charset_encoding(msg_ctx, env); + if(char_set_enc_str) + { + char_set_enc = axutil_string_get_buffer(char_set_enc_str, env); + } + + if(!char_set_enc) + { + axis2_op_ctx_t *op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + if(op_ctx) + { + axis2_ctx_t *ctx = axis2_op_ctx_get_base(op_ctx, env); + if(ctx) + { + property = axis2_ctx_get_property(ctx, env, AXIS2_CHARACTER_SET_ENCODING); + if(property) + { + char_set_enc = axutil_property_get_value(property, env); + property = NULL; + } + } + } + } + + /** + * If we still can't find the char set enc we will + * use default + */ + if(!char_set_enc) + { + char_set_enc = AXIS2_DEFAULT_CHAR_SET_ENCODING; + } + + do_mtom = axis2_http_transport_utils_do_write_mtom(env, msg_ctx); + + transport_url = axis2_msg_ctx_get_transport_url(msg_ctx, env); + if(transport_url) + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "transport_url:%s", transport_url); + epr = axis2_endpoint_ref_create(env, transport_url); + } + else + { + /* when transport url is not available in msg_ctx */ + axis2_endpoint_ref_t *ctx_epr = axis2_msg_ctx_get_to(msg_ctx, env); + if(ctx_epr) + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "ctx_epr:%s", axis2_endpoint_ref_get_address( + ctx_epr, env)); + + if(ctx_epr && axutil_strcmp(AXIS2_WSA_ANONYMOUS_URL_SUBMISSION, + axis2_endpoint_ref_get_address(ctx_epr, env)) && axutil_strcmp(AXIS2_WSA_ANONYMOUS_URL, + axis2_endpoint_ref_get_address(ctx_epr, env)) && !(axutil_strstr( + axis2_endpoint_ref_get_address(ctx_epr, env), AXIS2_WS_RM_ANONYMOUS_URL))) + { + epr = ctx_epr; + } + } + + soap_data_out = axis2_msg_ctx_get_soap_envelope(msg_ctx, env); + if(!soap_data_out) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_SOAP_ENVELOPE_IN_MSG_CTX, AXIS2_FAILURE); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "%s", AXIS2_ERROR_GET_MESSAGE(env->error)); + return AXIS2_SUCCESS; + } + + xml_writer = axiom_xml_writer_create_for_memory(env, NULL, AXIS2_TRUE, 0, + AXIS2_XML_PARSER_TYPE_BUFFER); + if(!xml_writer) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Could not create xml_writer for \ +AXIS2_XML_PARSER_TYPE_BUFFER"); + return AXIS2_FAILURE; + } + + om_output = axiom_output_create(env, xml_writer); + if(!om_output) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Could not create om_output for xml writer of \ +AXIS2_XML_PARSER_TYPE_BUFFER"); + axiom_xml_writer_free(xml_writer, env); + xml_writer = NULL; + return AXIS2_FAILURE; + } + + /* setting SOAP version for OM_OUTPUT. */ + axiom_output_set_soap11(om_output, env, axis2_msg_ctx_get_is_soap_11(msg_ctx, env)); + + /* This is the case where normal client send the requet using a http_client*/ + + if(epr) + { + if(axutil_strcmp(AXIS2_WSA_NONE_URL_SUBMISSION, axis2_endpoint_ref_get_address(epr, env)) + == 0 || axutil_strcmp(AXIS2_WSA_NONE_URL, axis2_endpoint_ref_get_address(epr, env)) + == 0) + { + epr = NULL; + } + else + { + status = axis2_http_transport_sender_write_message(transport_sender, env, msg_ctx, epr, + soap_data_out, om_output); + } + } + + /* If no endpoint reference could be derived from the the message context. It could well be the + * single channel two way scenario in the application server side send. + */ + if(!epr) + { + axutil_stream_t *out_stream = axis2_msg_ctx_get_transport_out_stream(msg_ctx, env); + + if(AXIS2_TRUE == axis2_msg_ctx_get_server_side(msg_ctx, env)) + { + axis2_http_out_transport_info_t *out_info = NULL; + axis2_bool_t is_soap11 = AXIS2_FALSE; + axis2_op_ctx_t *op_ctx = NULL; + /*axis2_char_t *header_value = NULL;*/ + + out_info = (axis2_http_out_transport_info_t *)axis2_msg_ctx_get_out_transport_info( + msg_ctx, env); + + if(!out_info) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_OUT_TRNSPORT_INFO_NULL, AXIS2_FAILURE); + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + return AXIS2_FAILURE; + } + /*header_value = axis2_http_transport_utils_get_session(env, msg_ctx); + if(header_value) + { + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_COOKIE_HEADER(out_info, env, header_value); + }*/ + + is_soap11 = axis2_msg_ctx_get_is_soap_11(msg_ctx, env); + + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CHAR_ENCODING(out_info, env, char_set_enc); + if(AXIS2_TRUE == is_soap11) + { + /* SOAP1.1 */ + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(out_info, env, + AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML); + } + else + { + /* SOAP1.2 */ + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(out_info, env, + AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP); + } + + 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) + { + /* get access to HTTP transport for sending */ + trans_desc = axis2_conf_get_transport_out(conf, env, AXIS2_TRANSPORT_ENUM_HTTP); + } + + if(trans_desc) + { + + /* accessing parameter in axis2.xml which set to have + * an ability to send xml versoin processing + * instruction */ + 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) + { + /* Accessing attribute values */ + 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(AXIS2_TRUE == axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + axiom_node_t *body_node = NULL; + /* axis2_bool_t fault = AXIS2_FALSE;*/ + axiom_soap_fault_t *soap_fault; + axiom_soap_body_t *soap_body = axiom_soap_envelope_get_body(soap_data_out, env); + axiom_soap_fault_detail_t *soap_fault_detial; + + if(!soap_body) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL, + AXIS2_FAILURE); + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + return AXIS2_FAILURE; + } + + fault = axiom_soap_body_has_fault(soap_body, env); + + if(fault == AXIS2_TRUE) + { + soap_fault = axiom_soap_body_get_fault(soap_body, env); + + if(!soap_fault) + { + + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Rest fault has occur, error described below"); + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + return AXIS2_FAILURE; + } + + soap_fault_detial = axiom_soap_fault_get_detail(soap_fault, env); + + if(!soap_fault_detial) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "Returning failure to obtain soap_fault_detail from soap_fault"); + return AXIS2_FAILURE; + } + + body_node = axiom_soap_fault_detail_get_base_node(soap_fault_detial, env); + if(!body_node) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "failure to get base node from soap_fault_detail."); + return AXIS2_FAILURE; + } + + } + else + { + + body_node = axiom_soap_body_get_base_node(soap_body, env); + if(!body_node) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "failure to get base node from soap_body."); + return AXIS2_FAILURE; + } + } + + data_out = axiom_node_get_first_element(body_node, env); + + if(!data_out || axiom_node_get_node_type(data_out, env) != AXIOM_ELEMENT) + { + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "unable to get first element from soap_body, base node."); + return AXIS2_FAILURE; + } + + axiom_node_serialize(data_out, env, om_output); + buffer = (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env); + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + axutil_stream_write(out_stream, env, buffer, buffer_size); + /* Finish Rest Processing */ + + } + else + { + axiom_soap_body_t *body = NULL; + + body = axiom_soap_envelope_get_body(soap_data_out, env); + fault = axiom_soap_body_has_fault(body, env); + + /* SOAP Processing */ + axiom_output_set_do_optimize(om_output, env, do_mtom); + axiom_soap_envelope_serialize(soap_data_out, env, om_output, AXIS2_FALSE); + if(do_mtom && !fault) + { + axis2_status_t mtom_status = AXIS2_FAILURE; + axis2_char_t *content_type = NULL; + axutil_array_list_t *mime_parts = NULL; + + /*Create the attachment related data and put them to an + *array_list */ + mtom_status = axiom_output_flush(om_output, env); + if(mtom_status == AXIS2_SUCCESS) + { + mime_parts = axiom_output_get_mime_parts(om_output, env); + if(!mime_parts) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Unable to create the mime_part list from om_output"); + return AXIS2_FAILURE; + } + else + { + axis2_msg_ctx_set_mime_parts(msg_ctx, env, mime_parts); + } + } + /*om_out put has the details of content_type */ + content_type = (axis2_char_t *)axiom_output_get_content_type(om_output, env); + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_CONTENT_TYPE(out_info, env, content_type); + } + else + { + buffer = (axis2_char_t *)axiom_xml_writer_get_xml(xml_writer, env); + buffer_size = axiom_xml_writer_get_xml_size(xml_writer, env); + + /* This is where it actually fill the buffer in out_stream. In application server + * side this is the out_stream passed to the in message context from http_worker + * function and then copied to the out message context. + */ + axutil_stream_write(out_stream, env, buffer, buffer_size); + } + } + + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + axis2_op_ctx_set_response_written(op_ctx, env, AXIS2_TRUE); + } + } + + axiom_output_free(om_output, env); + om_output = NULL; + xml_writer = NULL; + + if(transport_url) + { + if(epr) + { + axis2_endpoint_ref_free(epr, env); + epr = NULL; + } + } + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_transport_sender_invoke"); + return status; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_clean_up( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, transport_sender, AXIS2_FAILURE); + /* + * Clean up is not used. If the http sender needs + * to be cleaned up it should be done here. + */ + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_init( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_transport_out_desc_t * out_desc) +{ + axutil_param_t *version_param = NULL; + axis2_char_t *version = NULL; + axis2_char_t *temp = NULL; + axutil_param_t *temp_param = NULL; + + AXIS2_PARAM_CHECK(env->error, conf_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out_desc, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, transport_sender, AXIS2_FAILURE); + + /* Getting HTTP version from axis2.xml */ + version_param = axutil_param_container_get_param(axis2_transport_out_desc_param_container( + out_desc, env), env, AXIS2_HTTP_PROTOCOL_VERSION); + + if(version_param) + { + version = axutil_param_get_value(version_param, env); + } + + if(version) + { + /* handling HTTP 1.1 */ + if(0 == axutil_strcmp(version, AXIS2_HTTP_HEADER_PROTOCOL_11)) + { + axis2_char_t *encoding = NULL; + axutil_param_t *encoding_param = NULL; + if(AXIS2_INTF_TO_IMPL(transport_sender)->http_version) + { + AXIS2_FREE(env->allocator, AXIS2_INTF_TO_IMPL(transport_sender)->http_version); + } + + AXIS2_INTF_TO_IMPL(transport_sender)->http_version = axutil_strdup(env, version); + AXIS2_INTF_TO_IMPL(transport_sender)->keep_alive = AXIS2_TRUE; + encoding_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(out_desc, env), env, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING); + + if(encoding_param) + { + encoding = axutil_param_get_value(encoding_param, env); + } + + if(encoding && 0 + == axutil_strcmp(encoding, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + AXIS2_INTF_TO_IMPL(transport_sender)->chunked = AXIS2_TRUE; + } + else + { + AXIS2_INTF_TO_IMPL(transport_sender)->chunked = AXIS2_FALSE; + } + + } + else if(0 == axutil_strcmp(version, AXIS2_HTTP_HEADER_PROTOCOL_10)) + { + axutil_param_t *keepalive_param = NULL; + + /* Handling HTTP 1.0 */ + if(AXIS2_INTF_TO_IMPL(transport_sender)->http_version) + { + AXIS2_FREE(env->allocator, AXIS2_INTF_TO_IMPL(transport_sender)->http_version); + } + AXIS2_INTF_TO_IMPL(transport_sender)->http_version = axutil_strdup(env, version); + AXIS2_INTF_TO_IMPL(transport_sender)->chunked = AXIS2_FALSE; + keepalive_param = axutil_param_container_get_param( + axis2_transport_out_desc_param_container(out_desc, env), env, + AXIS2_HTTP_HEADER_CONNECTION_KEEPALIVE); + if(keepalive_param) + { + axis2_char_t *keepalive_value = NULL; + keepalive_value = axutil_param_get_value(keepalive_param, env); + if(!axutil_strcmp(keepalive_value, AXIS2_VALUE_FALSE)) + { + AXIS2_INTF_TO_IMPL(transport_sender)->keep_alive = AXIS2_FALSE; + } + } + } + } + else + { + /* HTTP version is not available in axis2.xml */ + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_HTTP_VERSION, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + /* Getting HTTP_SO_TIMEOUT value from axis2.xml */ + temp_param = axutil_param_container_get_param(axis2_transport_out_desc_param_container( + out_desc, env), env, AXIS2_HTTP_SO_TIMEOUT); + + if(temp_param) + { + temp = axutil_param_get_value(temp_param, env); + } + + if(temp) + { + AXIS2_INTF_TO_IMPL(transport_sender)->so_timeout = AXIS2_ATOI(temp); + } + + /* Getting HTTP_CONNECTION_TIMEOUT from axis2.xml */ + temp + = (axis2_char_t *)axutil_param_container_get_param( + axis2_transport_out_desc_param_container(out_desc, env), env, + AXIS2_HTTP_CONNECTION_TIMEOUT); + if(temp_param) + { + temp = axutil_param_get_value(temp_param, env); + } + + /* set axis2.xml connection timeout value to http_sender */ + if(temp) + { + AXIS2_INTF_TO_IMPL(transport_sender)->connection_timeout = AXIS2_ATOI(temp); + } + + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_http_transport_sender_write_message( + axis2_transport_sender_t * transport_sender, + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axis2_endpoint_ref_t * epr, + axiom_soap_envelope_t * out, + axiom_output_t * om_output) +{ + const axis2_char_t *soap_action = NULL; + const axis2_char_t *url = NULL; + axis2_http_sender_t *sender = NULL; + axis2_status_t status = AXIS2_FAILURE; + const axis2_char_t *soap_ns_uri = NULL; + axiom_soap_envelope_t *response_envelope = NULL; + axis2_op_t *op = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, epr, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, om_output, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, transport_sender, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out, AXIS2_FAILURE); + + /* epr is already passed NULL checking */ + url = axis2_endpoint_ref_get_address(epr, env); + + soap_action = axutil_string_get_buffer(axis2_msg_ctx_get_soap_action(msg_ctx, env), env); + + if(!soap_action) + { + soap_action = ""; + } + + sender = axis2_http_sender_create(env); + + if(!sender) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "http sender creation failed"); + return AXIS2_FAILURE; + } + axis2_http_sender_set_keep_alive(sender, env, AXIS2_INTF_TO_IMPL(transport_sender)->keep_alive); + + /* For the MTOM case we should on chunking. And for chunking to work the + * protocol should be http 1.1*/ + + if(axis2_msg_ctx_get_doing_mtom(msg_ctx, env)) + { + AXIS2_HTTP_SENDER_SET_CHUNKED(sender, env, AXIS2_TRUE); + AXIS2_HTTP_SENDER_SET_HTTP_VERSION(sender, env, AXIS2_HTTP_HEADER_PROTOCOL_11); + } + else + { + AXIS2_HTTP_SENDER_SET_CHUNKED(sender, env, AXIS2_INTF_TO_IMPL(transport_sender)->chunked); + AXIS2_HTTP_SENDER_SET_HTTP_VERSION(sender, env, + AXIS2_INTF_TO_IMPL(transport_sender)->http_version); + } + AXIS2_HTTP_SENDER_SET_OM_OUTPUT(sender, env, om_output); + +#ifdef AXIS2_LIBCURL_ENABLED + AXIS2_LOG_DEBUG (env->log, AXIS2_LOG_SI, "using axis2 libcurl http sender."); + status = + axis2_libcurl_http_send(AXIS2_INTF_TO_IMPL(transport_sender)->libcurl, + sender, env, msg_ctx, out, url, soap_action); +#else + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "using axis2 native http sender."); + status = AXIS2_HTTP_SENDER_SEND(sender, env, msg_ctx, out, url, soap_action); +#endif + + AXIS2_HTTP_SENDER_FREE(sender, env); + sender = NULL; + + /* if the send was not successful, do not process any response */ + if(status != AXIS2_SUCCESS) + return status; + + op = axis2_msg_ctx_get_op(msg_ctx, env); + if(op) + { + /* handle one way case */ + const axis2_char_t *mep = axis2_op_get_msg_exchange_pattern(op, env); + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "OP name axutil_qname_get_localpart = %s", mep); + if(axutil_strcmp(mep, AXIS2_MEP_URI_OUT_ONLY) == 0 || axutil_strcmp(mep, + AXIS2_MEP_URI_ROBUST_OUT_ONLY) == 0 || axutil_strcmp(mep, AXIS2_MEP_URI_IN_ONLY) == 0) + { + return status; + } + else + { + /* AXIS2_MEP_URI_IN_OUT case , we have a response this + * time */ + soap_ns_uri + = axis2_msg_ctx_get_is_soap_11(msg_ctx, env) ? AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI + : AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI; + response_envelope = axis2_http_transport_utils_create_soap_msg(env, msg_ctx, + soap_ns_uri); + if(response_envelope) + { + axis2_msg_ctx_set_response_soap_envelope(msg_ctx, env, response_envelope); + } + } + } + + return status; +} + +/** + * Following block distinguish the exposed part of the dll. + */ + +/* When building for static deployment, give the get and remove methods + * unique names. This avoids having the linker fail with duplicate symbol + * errors. + */ + +AXIS2_EXPORT int +#ifndef AXIS2_STATIC_DEPLOY +axis2_get_instance( +#else + axis2_http_transport_sender_get_instance( +#endif + struct axis2_transport_sender **inst, + const axutil_env_t * env) +{ + *inst = axis2_http_transport_sender_create(env); + if(!(*inst)) + { + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXPORT int +#ifndef AXIS2_STATIC_DEPLOY +axis2_remove_instance( +#else + axis2_http_transport_sender_remove_instance( +#endif + axis2_transport_sender_t * inst, + const axutil_env_t * env) +{ + if(inst) + { + AXIS2_TRANSPORT_SENDER_FREE(inst, env); + } + return AXIS2_SUCCESS; +} + diff --git a/src/core/transport/http/sender/libcurl/Makefile.am b/src/core/transport/http/sender/libcurl/Makefile.am new file mode 100644 index 0000000..90e5ce6 --- /dev/null +++ b/src/core/transport/http/sender/libcurl/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST= axis2_libcurl.h axis2_libcurl.c libcurl_stream.h libcurl_stream.c + 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 +#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; + { + 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 */ + diff --git a/src/core/transport/http/sender/libcurl/axis2_libcurl.h b/src/core/transport/http/sender/libcurl/axis2_libcurl.h new file mode 100644 index 0000000..f2971e5 --- /dev/null +++ b/src/core/transport/http/sender/libcurl/axis2_libcurl.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef AXIS2_LIBCURL_H +#define AXIS2_LIBCURL_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* typedef struct axis2_libcurl axis2_libcurl_t; */ +/* actually defined in axis2_http_sender.h as it is part of axis2/include */ + +AXIS2_EXTERN axis2_libcurl_t *AXIS2_CALL +axis2_libcurl_create( + const axutil_env_t * env); + +AXIS2_EXTERN void AXIS2_CALL +axis2_libcurl_free( + axis2_libcurl_t *data, + const axutil_env_t * env); + +AXIS2_EXTERN 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); + +#endif /* AXIS2_LIBCURL_H */ diff --git a/src/core/transport/http/sender/libcurl/libcurl_stream.c b/src/core/transport/http/sender/libcurl/libcurl_stream.c new file mode 100644 index 0000000..0c9126d --- /dev/null +++ b/src/core/transport/http/sender/libcurl/libcurl_stream.c @@ -0,0 +1,192 @@ +/* + * 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 "libcurl_stream.h" +#include + +typedef struct libcurl_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + axis2_char_t *buffer; + int size; + int read_len; +} +libcurl_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((libcurl_stream_impl_t *)(stream)) + +/********************************Function headers******************************/ +axutil_stream_type_t AXIS2_CALL libcurl_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL libcurl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL libcurl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL libcurl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL libcurl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +/************************* End of function headers ****************************/ + +/* + * Internal function. Not exposed to outside + */ +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axutil_stream_create_libcurl( + const axutil_env_t * env, + axis2_char_t * buffer, + unsigned int size) +{ + libcurl_stream_impl_t *stream_impl = NULL; + + AXIS2_PARAM_CHECK(env->error, buffer, NULL); + + stream_impl = + (libcurl_stream_impl_t *) AXIS2_MALLOC(env->allocator, + sizeof(libcurl_stream_impl_t)); + + if (!stream_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + stream_impl->buffer = buffer; + stream_impl->size = size; + stream_impl->read_len = 0; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, libcurl_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, libcurl_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, libcurl_stream_skip); + + return &(stream_impl->stream); +} + +void AXIS2_CALL +libcurl_stream_free( + void * stream, + const axutil_env_t * env) +{ + libcurl_stream_impl_t *stream_impl = NULL; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + AXIS2_FREE(env->allocator, stream_impl); + + return; +} + +int AXIS2_CALL +libcurl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + libcurl_stream_impl_t *stream_impl = NULL; + int read = 0; + int unread = 0; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + if (stream_impl->size >= (int)count) + /* We are sure that the difference lies within the int range */ + { + if (buffer && (stream_impl->size > stream_impl->read_len)) + { + unread = (stream_impl->size - stream_impl->read_len); + if (unread > (int)count) + /* We are sure that the difference lies within the int range */ + { + memcpy(buffer, &stream_impl->buffer[stream_impl->read_len], + count); + read = (int)count; + /* We are sure that the difference lies within the int range */ + stream_impl->read_len += read; + } + else + { + memcpy(buffer, &stream_impl->buffer[stream_impl->read_len], + unread); + read = unread; + stream_impl->read_len += read; + } + } + else + read = 0; + } + else + { + if (buffer && (stream_impl->size > stream_impl->read_len)) + { + memcpy(buffer, &stream_impl->buffer[stream_impl->read_len], + stream_impl->size - stream_impl->read_len); + read = stream_impl->size - stream_impl->read_len; + stream_impl->read_len += read; + } + else + read = 0; + } + return read; +} + +int AXIS2_CALL +libcurl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count) +{ + return (int)count; + /* We are sure that the difference lies within the int range */ +} + +int AXIS2_CALL +libcurl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + return 0; +} + +int AXIS2_CALL +libcurl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + return 0; +} + +#endif /* AXIS2_LIBCURL_ENABLED */ + diff --git a/src/core/transport/http/sender/libcurl/libcurl_stream.h b/src/core/transport/http/sender/libcurl/libcurl_stream.h new file mode 100644 index 0000000..8a24fcc --- /dev/null +++ b/src/core/transport/http/sender/libcurl/libcurl_stream.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef LIBCURL_STREAM_H +#define LIBCURL_STREAM_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** brief Constructor for creating apche2 stream + * @return axutil_stream (libcurl) + */ + AXIS2_EXTERN axutil_stream_t *AXIS2_CALL + axutil_stream_create_libcurl( + const axutil_env_t * env, + axis2_char_t * buffer, + unsigned int size); + + /** @} */ + + void AXIS2_CALL libcurl_stream_free( + void * stream, + const axutil_env_t * env); + + +#ifdef __cplusplus +} +#endif + +#endif /* LIBCURL_STREAM_H */ diff --git a/src/core/transport/http/sender/ssl/Makefile.am b/src/core/transport/http/sender/ssl/Makefile.am new file mode 100644 index 0000000..3e457e5 --- /dev/null +++ b/src/core/transport/http/sender/ssl/Makefile.am @@ -0,0 +1,2 @@ +EXTRA_DIST= ssl_stream.c ssl_stream.h ssl_utils.c ssl_utils.h + diff --git a/src/core/transport/http/sender/ssl/ssl_stream.c b/src/core/transport/http/sender/ssl/ssl_stream.c new file mode 100644 index 0000000..9360f1a --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_stream.c @@ -0,0 +1,239 @@ +/* + * 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_SSL_ENABLED + +#include +#include +#include "ssl_stream.h" +#include "ssl_utils.h" + +/** + * @brief Stream struct impl + * Streaming mechanisms for SSL + */ +typedef struct ssl_stream_impl ssl_stream_impl_t; + +struct ssl_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + SSL *ssl; + SSL_CTX *ctx; + axis2_socket_t socket; +}; + +#define AXIS2_INTF_TO_IMPL(stream) ((ssl_stream_impl_t *)(stream)) + +void AXIS2_CALL axis2_ssl_stream_free( + axutil_stream_t * stream, + const axutil_env_t * env); + +axutil_stream_type_t AXIS2_CALL axis2_ssl_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL axis2_ssl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL axis2_ssl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL axis2_ssl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL axis2_ssl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axutil_stream_create_ssl( + const axutil_env_t * env, + axis2_socket_t socket, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp) +{ + ssl_stream_impl_t *stream_impl = NULL; + + stream_impl = + (ssl_stream_impl_t *) AXIS2_MALLOC(env->allocator, + sizeof(ssl_stream_impl_t)); + + if (!stream_impl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + memset ((void *)stream_impl, 0, sizeof (ssl_stream_impl_t)); + stream_impl->socket = socket; + stream_impl->ctx = NULL; + stream_impl->ssl = NULL; + + stream_impl->ctx = axis2_ssl_utils_initialize_ctx(env, server_cert, + key_file, ssl_pp); + if (!stream_impl->ctx) + { + axis2_ssl_stream_free((axutil_stream_t *) stream_impl, env); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE); + return NULL; + } + stream_impl->ssl = axis2_ssl_utils_initialize_ssl(env, stream_impl->ctx, + stream_impl->socket); + if (!stream_impl->ssl) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE); + return NULL; + } + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, axis2_ssl_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, + axis2_ssl_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, axis2_ssl_stream_skip); + + return &(stream_impl->stream); +} + +void AXIS2_CALL +axis2_ssl_stream_free( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + ssl_stream_impl_t *stream_impl = NULL; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + axis2_ssl_utils_cleanup_ssl(env, stream_impl->ctx, stream_impl->ssl); + AXIS2_FREE(env->allocator, stream_impl); + + return; +} + +int AXIS2_CALL +axis2_ssl_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + ssl_stream_impl_t *stream_impl = NULL; + int read = -1; + int len = -1; + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + SSL_set_mode(stream_impl->ssl, SSL_MODE_AUTO_RETRY); + + read = SSL_read(stream_impl->ssl, buffer, (int)count); + /* We are sure that the difference lies within the int range */ + switch (SSL_get_error(stream_impl->ssl, read)) + { + case SSL_ERROR_NONE: + len = read; + break; + case SSL_ERROR_ZERO_RETURN: + len = -1; + break; + case SSL_ERROR_SYSCALL: + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "SSL Error: Premature close"); + len = -1; + break; + default: + len = -1; + break; + } + return len; +} + +int AXIS2_CALL +axis2_ssl_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + ssl_stream_impl_t *stream_impl = NULL; + int write = -1; + + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + write = SSL_write(stream_impl->ssl, buf, (int)count); + /* We are sure that the difference lies within the int range */ + + switch (SSL_get_error(stream_impl->ssl, write)) + { + case SSL_ERROR_NONE: + if ((int)count != write) + /* We are sure that the difference lies within the int range */ + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Incomplete SSL write!"); + break; + default: + return -1; + } + return write; +} + +int AXIS2_CALL +axis2_ssl_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + ssl_stream_impl_t *stream_impl = NULL; + axis2_char_t *tmp_buffer = NULL; + int len = -1; + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + tmp_buffer = AXIS2_MALLOC(env->allocator, count * sizeof(axis2_char_t)); + if (tmp_buffer == NULL) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return -1; + } + len = SSL_read(stream_impl->ssl, tmp_buffer, count); + AXIS2_FREE(env->allocator, tmp_buffer); + return len; + +} + +int AXIS2_CALL +axis2_ssl_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +axis2_ssl_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} + +#endif + diff --git a/src/core/transport/http/sender/ssl/ssl_stream.h b/src/core/transport/http/sender/ssl/ssl_stream.h new file mode 100644 index 0000000..396da5d --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_stream.h @@ -0,0 +1,50 @@ + +/* + * Copyright 2004,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain count 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. + */ + +#ifndef AXIS2_SSL_STREAM_H +#define AXIS2_SSL_STREAM_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** \brief Constructor for creating ssl stream + * @return axutil_stream (ssl) + */ + AXIS2_EXTERN axutil_stream_t *AXIS2_CALL + axutil_stream_create_ssl( + const axutil_env_t * env, + axis2_socket_t socket, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* AXIS2_SSL_STREAM_H */ diff --git a/src/core/transport/http/sender/ssl/ssl_utils.c b/src/core/transport/http/sender/ssl/ssl_utils.c new file mode 100644 index 0000000..d565555 --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_utils.c @@ -0,0 +1,227 @@ +/* + * 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_SSL_ENABLED + +#include "ssl_utils.h" +#include +BIO *bio_err = 0; + +static int +password_cb( + char *buf, + int size, + int rwflag, + void *passwd) +{ + strncpy(buf, (char *) passwd, size); + buf[size - 1] = '\0'; + return (int)(strlen(buf)); + /* We are sure that the difference lies within the int range */ +} + +AXIS2_EXTERN SSL_CTX *AXIS2_CALL +axis2_ssl_utils_initialize_ctx( + const axutil_env_t * env, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp) +{ + SSL_METHOD *meth = NULL; + SSL_CTX *ctx = NULL; + axis2_char_t *ca_file = server_cert; + + if (!ca_file) + { + AXIS2_LOG_INFO(env->log, "[ssl client] CA certificate not specified"); + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_NO_CA_FILE, AXIS2_FAILURE); + return NULL; + } + + if (!bio_err) + { + /* Global system initialization */ + SSL_library_init(); + SSL_load_error_strings(); + + /* An error write context */ + bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); + } + + /* Create our context */ + meth = SSLv23_method(); + ctx = SSL_CTX_new(meth); + + /* Load our keys and certificates + * If we need client certificates it has to be done here + */ + if (key_file) /*can we check if the server needs client auth? */ + { + if (!ssl_pp) + { + AXIS2_LOG_INFO(env->log, + "[ssl client] No passphrase specified for \ +key file %s and server cert %s", key_file, server_cert); + } + + SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) ssl_pp); + SSL_CTX_set_default_passwd_cb(ctx, password_cb); + + if (!(SSL_CTX_use_certificate_chain_file(ctx, key_file))) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] Loading client certificate failed \ +, key file %s", key_file); + SSL_CTX_free(ctx); + return NULL; + } + + if (!(SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM))) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] Loading client key failed, key file \ +%s", key_file); + SSL_CTX_free(ctx); + return NULL; + } + } + else + { + AXIS2_LOG_INFO(env->log, + "[ssl client] Client certificate chain file" + "not specified"); + } + + /* Load the CAs we trust */ + if (!(SSL_CTX_load_verify_locations(ctx, ca_file, 0))) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] Loading CA certificate failed, \ +ca_file is %s", ca_file); + SSL_CTX_free(ctx); + return NULL; + } + + return ctx; +} + +AXIS2_EXTERN SSL *AXIS2_CALL +axis2_ssl_utils_initialize_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + axis2_socket_t socket) +{ + SSL *ssl = NULL; + BIO *sbio = NULL; + + AXIS2_PARAM_CHECK(env->error, ctx, NULL); + + ssl = SSL_new(ctx); + if (!ssl) + { + AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, + "[ssl]unable to create new ssl context"); + return NULL; + } + + sbio = BIO_new_socket((int)socket, BIO_NOCLOSE); + if (!sbio) + { + AXIS2_LOG_ERROR (env->log, AXIS2_LOG_SI, + "[ssl]unable to create BIO new socket for socket %d", + (int)socket); + return NULL; + } + + SSL_set_bio(ssl, sbio, sbio); + if (SSL_connect(ssl) <= 0) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SSL_ENGINE, AXIS2_FAILURE); + return NULL; + } + + if (SSL_get_verify_result(ssl) != X509_V_OK) + { + char sslerror[128]; /** error buffer must be at least 120 bytes long */ + X509 *peer_cert = NULL; + X509_STORE *cert_store = NULL; + X509_NAME *peer_name = NULL; + X509_OBJECT *client_object = NULL; + X509 *client_cert = NULL; + + peer_cert = SSL_get_peer_certificate(ssl); + if (peer_cert && peer_cert->cert_info) + { + peer_name = (peer_cert->cert_info)->subject; + } + + cert_store = SSL_CTX_get_cert_store(ctx); + if (peer_name && cert_store) + { + client_object = X509_OBJECT_retrieve_by_subject(cert_store->objs, + X509_LU_X509, + peer_name); + } + if (client_object) + { + client_cert = (client_object->data).x509; + if (client_cert && + (M_ASN1_BIT_STRING_cmp(client_cert->signature, + peer_cert->signature) == 0)) + { + if (peer_cert) + { + X509_free(peer_cert); + } + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "[ssl client] SSL certificate verified against peer"); + return ssl; + } + } + if (peer_cert) + { + X509_free(peer_cert); + } + ERR_error_string(SSL_get_verify_result(ssl), sslerror); + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "[ssl client] SSL certificate verification failed (%s)", + sslerror); + return NULL; + } + + return ssl; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_ssl_utils_cleanup_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + SSL * ssl) +{ + + if (ssl) + { + SSL_shutdown(ssl); + } + if (ctx) + { + SSL_CTX_free(ctx); + } + return AXIS2_SUCCESS; +} + +#endif + diff --git a/src/core/transport/http/sender/ssl/ssl_utils.h b/src/core/transport/http/sender/ssl/ssl_utils.h new file mode 100644 index 0000000..26dc16b --- /dev/null +++ b/src/core/transport/http/sender/ssl/ssl_utils.h @@ -0,0 +1,56 @@ + +/* + * 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. + */ + +#ifndef AXIS2_SSL_UTILS_H +#define AXIS2_SSL_UTILS_H + + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + AXIS2_EXTERN SSL_CTX *AXIS2_CALL + axis2_ssl_utils_initialize_ctx( + const axutil_env_t * env, + axis2_char_t * server_cert, + axis2_char_t * key_file, + axis2_char_t * ssl_pp); + + AXIS2_EXTERN SSL *AXIS2_CALL + axis2_ssl_utils_initialize_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + axis2_socket_t socket); + + AXIS2_EXTERN axis2_status_t AXIS2_CALL + axis2_ssl_utils_cleanup_ssl( + const axutil_env_t * env, + SSL_CTX * ctx, + SSL * ssl); + +#ifdef __cplusplus +} +#endif + +#endif /* AXIS2_SSL_UTILS_H */ diff --git a/src/core/transport/http/server/CGI/Makefile.am b/src/core/transport/http/server/CGI/Makefile.am new file mode 100644 index 0000000..fafb8bf --- /dev/null +++ b/src/core/transport/http/server/CGI/Makefile.am @@ -0,0 +1,31 @@ +prgbindir=$(bindir) +prgbin_PROGRAMS = axis2.cgi +SUBDIRS = +AM_CFLAGS = -g -pthread +axis2_cgi_SOURCES = axis2_cgi_main.c \ + axis2_cgi_out_transport_info.c \ + axis2_cgi_stream.c + +axis2_cgi_LDADD = $(LDFLAGS) \ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la \ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la \ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la \ + $(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/axiom/src/parser/$(WRAPPER_DIR)/libaxis2_parser.la \ + $(top_builddir)/src/core/description/libaxis2_description.la \ + $(top_builddir)/src/core/deployment/libaxis2_deployment.la \ + $(top_builddir)/src/core/context/libaxis2_context.la \ + $(top_builddir)/src/core/clientapi/libaxis2_clientapi.la \ + $(top_builddir)/src/core/engine/libaxis2_engine.la \ + $(top_builddir)/src/core/transport/http/sender/libaxis2_http_sender.la \ + $(top_builddir)/src/core/transport/http/receiver/libaxis2_http_receiver.la \ + -lpthread + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/description\ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/deployment\ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/server/CGI/axis2_cgi_main.c b/src/core/transport/http/server/CGI/axis2_cgi_main.c new file mode 100644 index 0000000..6f9a59d --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_main.c @@ -0,0 +1,280 @@ +/* + * 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. + */ + +#include "axis2_cgi_out_transport_info.h" +#include "axis2_cgi_stream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +axis2_char_t *axis2_cgi_default_url_prefix = "/cgi-bin/axis2.cgi/"; + +/***************************** Function headers *******************************/ + +void +axis2_cgi_system_exit( + axutil_env_t * env, + int status); + +void +axis2_cgi_set_request_vars( + axis2_cgi_request_t *cgi_request); + +axis2_status_t +axis2_cgi_write_response( + const void *buffer, + unsigned int length); + +/***************************** End of function headers ************************/ + +int +main( + int argc, + char *argv[]) +{ + axutil_allocator_t *allocator = NULL; + axutil_env_t *env = NULL; + const axis2_char_t *repo_path; + axis2_conf_ctx_t *conf_ctx; + axis2_cgi_request_t *cgi_request = NULL; + int content_length = 0; + axis2_char_t *request_url = NULL; + /* axutil_stream_t *request_body_stream = NULL; */ + axutil_stream_t *out_stream = NULL; + axis2_transport_in_desc_t *in_desc = NULL; + axis2_transport_out_desc_t *out_desc = NULL; + /* axis2_msg_ctx_t *msg_ctx = NULL; */ + /* axis2_bool_t processed = AXIS2_FALSE; */ + axis2_http_transport_in_t request; + axis2_http_transport_out_t response; + /*axis2_http_header_t* http_header = NULL; */ + /*axutil_hash_t *headers = NULL; */ + /* axis2_char_t *axis2_cgi_url_prefix = NULL; */ + + if(!(repo_path = AXIS2_GETENV("AXIS2C_HOME"))) + { + fprintf(stderr, "Error: AXIS2C_HOME environment variable not set!"); + axis2_cgi_system_exit(env, -1); + } + + allocator = axutil_allocator_init(NULL); + env = axutil_env_create(allocator); + + if(axutil_file_handler_access(repo_path, AXIS2_R_OK) != AXIS2_SUCCESS) + { + fprintf(stderr, "Error reading repository: %s\nPlease check AXIS2C_HOME var", repo_path); + axis2_cgi_system_exit(env, -1); + } + + /* Set configuration */ + + conf_ctx = axis2_build_conf_ctx(env, repo_path); + if(!conf_ctx) + { + fprintf(stderr, "Error: Configuration not builded propertly\n"); + axis2_cgi_system_exit(env, -1); + } + + axis2_http_transport_utils_transport_out_init(&response, env); + axis2_http_transport_utils_transport_in_init(&request, env); + + /* Get input info */ + + cgi_request = AXIS2_MALLOC(allocator, sizeof(axis2_cgi_request_t)); + axis2_cgi_set_request_vars(cgi_request); + + request_url = (axis2_char_t *)AXIS2_MALLOC(allocator, (7 + /* "http:" */ + strlen(cgi_request->server_name) + ((strlen(cgi_request->server_port)) ? 1 : 0) + /* ":"*/ + strlen(cgi_request->server_port) + strlen(cgi_request->script_name) + strlen( + cgi_request->path_info) + ((strlen(cgi_request->path_info)) ? 1 : 0) + /* "?" */ + strlen(cgi_request->query_string)) * sizeof(axis2_char_t)); + + request_url[0] = '\0'; + + strcat(request_url, "http://"); + strcat(request_url, cgi_request->server_name); + if(strlen(cgi_request->server_port)) + strcat(request_url, ":"); + strcat(request_url, cgi_request->server_port); + strcat(request_url, cgi_request->script_name); + strcat(request_url, cgi_request->path_info); + if(strlen(cgi_request->query_string)) + strcat(request_url, "?"); + strcat(request_url, cgi_request->query_string); + + if(cgi_request->content_length) + content_length = axutil_atoi(cgi_request->content_length); + else + content_length = 0; + + /* Set streams */ + + out_stream = axutil_stream_create_basic(env); + + /* Set message contexts */ + + out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + + request.msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc); + + axis2_msg_ctx_set_server_side(request.msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_transport_out_stream(request.msg_ctx, env, out_stream); + axis2_msg_ctx_set_transport_headers(request.msg_ctx, env, NULL); + + /* Set request parameters */ + + request.soap_action = cgi_request->soap_action; + request.in_stream = axutil_stream_create_cgi(env, content_length); + request.remote_ip = cgi_request->remote_addr; + request.content_length = content_length; + request.content_type = cgi_request->content_type; + request.request_uri = request_url; + request.svr_port = cgi_request->server_port; + request.accept_header = AXIS2_GETENV("HTTP_ACCEPT"); + request.accept_language_header = AXIS2_GETENV("HTTP_ACCEPT_LANGUAGE"); + request.accept_charset_header = AXIS2_GETENV("HTTP_ACCEPT_CHARSET"); + request.request_url_prefix = (AXIS2_GETENV("AXIS2C_URL_PREFIX")) ? AXIS2_GETENV( + "AXIS2C_URL_PREFIX") : axis2_cgi_default_url_prefix; + + if(axutil_strcasecmp(cgi_request->request_method, "POST") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_POST; + } + else if(axutil_strcasecmp(cgi_request->request_method, "GET") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_GET; + } + else if(axutil_strcasecmp(cgi_request->request_method, "HEAD") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_HEAD; + } + else if(axutil_strcasecmp(cgi_request->request_method, "PUT") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_PUT; + } + else if(axutil_strcasecmp(cgi_request->request_method, "DELETE") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_DELETE; + } + + request.out_transport_info = axis2_cgi_out_transport_info_create(env, cgi_request); + + /*Process request */ + fprintf(stderr, "ok\n"); + axis2_http_transport_utils_process_request(env, conf_ctx, &request, &response); + fprintf(stderr, "ok\n"); + /*Send status */ + + fprintf(stdout, "Status: %d %s \r\n", response.http_status_code, response.http_status_code_name); + + if(response.content_type) + { + fprintf(stdout, "Content-type: %s \r\n", response.content_type); + } + else if(strlen(axis2_cgi_out_transport_get_content(request.out_transport_info)) + && axis2_cgi_out_transport_get_content(request.out_transport_info)) + { + fprintf(stdout, "Content-type: %s \r\n", axis2_cgi_out_transport_get_content( + request.out_transport_info)); + } + + fprintf(stdout, "\r\n"); /* End of headers for server */ + + /* Write data body */ + if(!axis2_cgi_write_response(response.response_data, response.response_data_length)) + { + fprintf(stderr, "Error writing output data\n"); + } + + axis2_http_transport_utils_transport_in_uninit(&request, env); + axis2_http_transport_utils_transport_out_uninit(&response, env); + + return 0; +} + +axis2_status_t +axis2_cgi_write_response( + const void *buffer, + unsigned int length) +{ + if(buffer && length) + { + unsigned int completed = 0; + unsigned int written = 0; + + while(completed < length) + { + written = fwrite(buffer, sizeof(char), length - completed, stdout); + if(written < 0) + return AXIS2_FALSE; + completed += written; + } + } + return AXIS2_TRUE; +} + +void +axis2_cgi_set_request_vars( + axis2_cgi_request_t *cgi_request) +{ + cgi_request->server_name = (AXIS2_GETENV("SERVER_NAME")) ? AXIS2_GETENV("SERVER_NAME") : ""; + cgi_request->script_name = (AXIS2_GETENV("SCRIPT_NAME")) ? AXIS2_GETENV("SCRIPT_NAME") : ""; + cgi_request->path_info = (AXIS2_GETENV("PATH_INFO")) ? AXIS2_GETENV("PATH_INFO") : ""; + cgi_request->server_port = (AXIS2_GETENV("SERVER_PORT")) ? AXIS2_GETENV("SERVER_PORT") : ""; + cgi_request->server_protocol = (AXIS2_GETENV("SERVER_PROTOCOL")) ? AXIS2_GETENV( + "SERVER_PROTOCOL") : ""; + cgi_request->content_length = (AXIS2_GETENV("CONTENT_LENGTH")) ? AXIS2_GETENV("CONTENT_LENGTH") + : ""; + cgi_request->content_type = (AXIS2_GETENV("CONTENT_TYPE")) ? AXIS2_GETENV("CONTENT_TYPE") : ""; + cgi_request->request_method = (AXIS2_GETENV("REQUEST_METHOD")) ? AXIS2_GETENV("REQUEST_METHOD") + : ""; + cgi_request->remote_addr = (AXIS2_GETENV("REMOTE_ADDR")) ? AXIS2_GETENV("REMOTE_ADDR") : ""; + cgi_request->soap_action = (AXIS2_GETENV("HTTP_SOAPACTION")) ? AXIS2_GETENV("HTTP_SOAPACTION") + : NULL; + cgi_request->query_string = (AXIS2_GETENV("QUERY_STRING")) ? AXIS2_GETENV("QUERY_STRING") : ""; +} + +void +axis2_cgi_system_exit( + axutil_env_t * env, + int status) +{ + axutil_allocator_t *allocator = NULL; + + if(env) + { + allocator = env->allocator; + axutil_env_free(env); + } + exit(status); +} diff --git a/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c new file mode 100644 index 0000000..59e6820 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.c @@ -0,0 +1,160 @@ +/* + * 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. + */ + +#include "axis2_cgi_out_transport_info.h" +#include +#include + +/** + * @brief CIG Out transport info impl structure + * Axis2 cgi_out_transport_info_impl + */ + +typedef struct axis2_cgi_out_transport_info_s +{ + axis2_http_out_transport_info_t out_transport_info; + axis2_cgi_request_t *request; + axis2_char_t *encoding; +} axis2_cgi_out_transport_info_t; + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_cgi_out_transport_info_t *)(out_transport_info)) + +void AXIS2_CALL +axis2_cgi_out_transport_info_free( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + AXIS2_ENV_CHECK(env, void); + + info_impl = AXIS2_INTF_TO_IMPL(info); + + info_impl->request = NULL; /* doesn't belong here so no need to free it here */ + if(info_impl->encoding) + { + AXIS2_FREE(env->allocator, info_impl->encoding); + info_impl->encoding = NULL; + } + + AXIS2_FREE(env->allocator, info_impl); + return; +} + +void AXIS2_CALL +axis2_cgi_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + AXIS2_ENV_CHECK(env, void); + transport_info_l = (axis2_http_out_transport_info_t *)transport_info; + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +axis2_status_t AXIS2_CALL +axis2_cgi_out_transport_info_set_content_type( + axis2_http_out_transport_info_t *info, + const axutil_env_t *env, + const axis2_char_t *content_type) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + + axis2_char_t *temp1 = NULL; + axis2_char_t *temp2 = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + info_impl = AXIS2_INTF_TO_IMPL(info); + if(info_impl->encoding) + { + temp1 = axutil_stracat(env, content_type, ";charset="); + temp2 = axutil_stracat(env, temp1, info_impl->encoding); + info_impl->request->content_type = axutil_strdup(env, temp2); + AXIS2_FREE(env->allocator, temp1); + AXIS2_FREE(env->allocator, temp2); + } + else + { + info_impl->request->content_type = axutil_strdup(env, content_type); + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_cgi_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + + info_impl = AXIS2_INTF_TO_IMPL(info); + + if(info_impl->encoding) + { + AXIS2_FREE(env->allocator, info_impl->encoding); + } + info_impl->encoding = axutil_strdup(env, encoding); + + return AXIS2_SUCCESS; +} + +axis2_http_out_transport_info_t *AXIS2_CALL +axis2_cgi_out_transport_info_create( + const axutil_env_t * env, + axis2_cgi_request_t * request) +{ + axis2_cgi_out_transport_info_t *info = NULL; + axis2_http_out_transport_info_t *out_transport_info = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + info = (axis2_cgi_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_cgi_out_transport_info_t)); + + if(!info) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + info->request = request; + info->encoding = NULL; + + out_transport_info = &(info->out_transport_info); + + axis2_http_out_transport_info_set_char_encoding_func(out_transport_info, env, + axis2_cgi_out_transport_info_set_char_encoding); + axis2_http_out_transport_info_set_content_type_func(out_transport_info, env, + axis2_cgi_out_transport_info_set_content_type); + + return out_transport_info; +} + +axis2_char_t * +axis2_cgi_out_transport_get_content( + axis2_http_out_transport_info_t * info) +{ + axis2_cgi_out_transport_info_t *info_impl = NULL; + info_impl = AXIS2_INTF_TO_IMPL(info); + return info_impl->request->content_type; +} + diff --git a/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h new file mode 100644 index 0000000..bc0f526 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_out_transport_info.h @@ -0,0 +1,62 @@ + +/* + * 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. + */ + +#ifndef AXIS2_CGI_OUT_TRANSPORT_INFO_H +#define AXIS2_CGI_OUT_TRANSPORT_INFO_H + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_cgi_out_transport_info.h + * @brief axis2 CGI Out Transport Info + */ + +#include "axis2_cgi_types.h" +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + axis2_http_out_transport_info_t *AXIS2_CALL + + axis2_cgi_out_transport_info_create( + const axutil_env_t * env, + axis2_cgi_request_t * request); + + /** + * Free http_out_transport_info passed as void pointer. This will be + * cast into appropriate type and then pass the cast object + * into the http_out_transport_info structure's free method + */ + void AXIS2_CALL + axis2_cgi_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env); + + axis2_char_t *axis2_cgi_out_transport_get_content( + axis2_http_out_transport_info_t * out_transport_info); + +#ifdef __cplusplus +} +#endif +#endif /* AXIS2_SGI_OUT_TRANSPORT_INFO_H */ diff --git a/src/core/transport/http/server/CGI/axis2_cgi_stream.c b/src/core/transport/http/server/CGI/axis2_cgi_stream.c new file mode 100644 index 0000000..68ad19f --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_stream.c @@ -0,0 +1,164 @@ +/* + * 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. + */ + +#include +#include +#include "axis2_cgi_stream.h" + +/** + * @brief Stream struct impl + * Streaming mechanisms for cgi + */ + +typedef struct cgi_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + unsigned int cur_pos; + unsigned int content_length; +} cgi_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((cgi_stream_impl_t *)(stream)) + +axutil_stream_type_t AXIS2_CALL +cgi_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL cgi_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL cgi_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL cgi_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL cgi_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +axutil_stream_t *AXIS2_CALL +axutil_stream_create_cgi( + const axutil_env_t * env, + unsigned int content_length) +{ + cgi_stream_impl_t *stream_impl = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, content_length, NULL); + + stream_impl = (cgi_stream_impl_t *)AXIS2_MALLOC(env->allocator, sizeof(cgi_stream_impl_t)); + + if(!stream_impl) + { + return NULL; + } + stream_impl->cur_pos = 0; + stream_impl->content_length = content_length; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, cgi_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, cgi_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, cgi_stream_skip); + + return &(stream_impl->stream); +} +int AXIS2_CALL +cgi_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + /*void *temp_buff = NULL;*/ + /*unsigned int data_to_read = 0;*/ + unsigned int read_bytes = 0; + /*axis2_bool_t ret_ok = AXIS2_TRUE;*/ + + cgi_stream_impl_t *stream_impl = NULL; + /*char *temp = NULL;*/ + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = (cgi_stream_impl_t *)stream; + + if(count < stream_impl->content_length) + { + read_bytes = fread(buffer, sizeof(char), count, stdin); + } + else + { + read_bytes = fread(buffer, sizeof(char), stream_impl->content_length, stdin); + } + + return read_bytes; +} + +int AXIS2_CALL +cgi_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + /* Cannot write on cgi stdin, explicitly an input stream */ + + return -1; +} + +int AXIS2_CALL +cgi_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + cgi_stream_impl_t *stream_impl = NULL; + int skipped = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + if(fseek(stdin, count, SEEK_CUR) == 0) + skipped = count; + return skipped; +} + +int AXIS2_CALL +cgi_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +cgi_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} diff --git a/src/core/transport/http/server/CGI/axis2_cgi_stream.h b/src/core/transport/http/server/CGI/axis2_cgi_stream.h new file mode 100644 index 0000000..9a6af34 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_stream.h @@ -0,0 +1,44 @@ + +/* + * 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. + */ + +#ifndef CGI_STREAM_H +#define CGI_STREAM_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** brief Constructor for creating CGI stream + * @return axutil_stream (CGI) + */ + axutil_stream_t *AXIS2_CALL + axutil_stream_create_cgi( + const axutil_env_t * env, + unsigned int content_length); + +#ifdef __cplusplus +} +#endif + +#endif /* CGI_STREAM_H */ diff --git a/src/core/transport/http/server/CGI/axis2_cgi_types.h b/src/core/transport/http/server/CGI/axis2_cgi_types.h new file mode 100644 index 0000000..af184a1 --- /dev/null +++ b/src/core/transport/http/server/CGI/axis2_cgi_types.h @@ -0,0 +1,34 @@ + +/* + * 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. + */ + +#include + +typedef struct axis2_cgi_request +{ + axis2_char_t *server_name; + axis2_char_t *server_port; + axis2_char_t *script_name; + axis2_char_t *path_info; + axis2_char_t *server_protocol; + axis2_char_t *content_length; + axis2_char_t *content_type; + axis2_char_t *request_method; + axis2_char_t *remote_addr; + axis2_char_t *soap_action; + axis2_char_t *query_string; +} axis2_cgi_request_t; diff --git a/src/core/transport/http/server/IIS/README b/src/core/transport/http/server/IIS/README new file mode 100644 index 0000000..1a47cc4 --- /dev/null +++ b/src/core/transport/http/server/IIS/README @@ -0,0 +1,61 @@ +How to Configure IIS Module for Axis2C +________________________________________ + +Use the Axis2/C VC project or makefile to build the component. + +In this document it is assumed that the mod_axis2_IIS.dll is in the directory +c:\axis2c\lib\mod_axis2_IIS.dll and axis2c_home is c:\axis2c + +Add the following key to the registry. + +HKEY_LOCAL_MACHINE\SOFTWARE\Apache Axis2c\IIS ISAPI Redirector + +Add a string value with the name axis2c_home and a value of c:\axis2c + +Add a string value with the name log_file and a value of c:\axis2c\logs\axis2.log + +Add a string value with the name log_level. The value can be one of trace, error, info, critical, debug, warning + +You can add a string value with the name services_url_prefix. This is optional and defaults to "/services". +As an example, if you have "/web_services" as the prefix, then all the services hosted would have the endpoint prefix of : +http://localhost/axis2/web_services. +Note: don't forget the / at the begining. + +If you wish, you can also change the location as well by adding a string value with the name axis2_location. +This is also optional and defaults to /axis2. If you have /myserser as the value you can access your web +services with a url like http://localhost/myserver/services. +Note: Don't forget the / at the beginning. + +Now you can do all the registry editing using the JScript file axis2_iis_regedit.js +provided with the distribution. When you build axis2/C with the IIS module the file +is copied to the root directory of the binary distribution. Just double click it and +everything will be set to the defaults. The axis2c_home is taken as the current directory, +so make sure you run the file in the Axis2/C repository location (or root of the binary distribution). +If you want to change the values you can manually edit the the .js file or give it as command line arguments +to the script when running the script. To run the jscript from the command line use the command +:\cscript axis2_iis_regedit.js optional arguments. +We recomend the manual editing as it is the easiest way to specify the values + +IIS 5.1 or Below + +Using the IIS management console, add a new virtual directory to your IIS/PWS Web site. +The name of the virtual directory must be axis2. Its physical path should be the directory +where you placed mod_axis2_IIS.dll (in our example it is c:\axis2c\lib). When creating this new +virtual directory, assign execute access to it. + +By Using the IIS management console, add mod_axis2_IIS.dll as a filter in your IIS/PWS web site and restart the IIS admin service. + + +IIS 6 & 7 + +Using the IIS management console, add the mod_axis2_IIS.dll as a Wildcard Script Map. + Executable should be the complete path to the mod_axis2_IIS.dll + You can put any name as the name of the Wildcard Script Map + +Please don't add the mod_axis2_IIS.dll as a filter to IIS as in the IIS 5.1 case. + +Note: If the Axis2/C failed to load, verify that Axis2/C and its dependent DLLs are in the System Path (not the user path). + + + + diff --git a/src/core/transport/http/server/IIS/axis2_iis_constants.h b/src/core/transport/http/server/IIS/axis2_iis_constants.h new file mode 100644 index 0000000..fb6929b --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_constants.h @@ -0,0 +1,51 @@ + +/* + * 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. + */ + +#ifndef AXIS2_IIS_CONSTANTS_H +#define AXIS2_IIS_CONSTANTS_H + +#define INTERNET_MAX_PATH_LENGTH 2048 +#define INTERNET_MAX_SCHEME_LENGTH 32 /* longest protocol name length */ +#define INTERNET_MAX_URL_LENGTH (INTERNET_MAX_SCHEME_LENGTH +sizeof("://") +INTERNET_MAX_PATH_LENGTH) + +#define URI_MATCHED 1 +#define URI_UN_MATCHED 2 + +#define EXTENSION_URL "/axis2/mod_axis2_IIS.dll\? " +#define EXTENSION_URL_AXIS2 "/axis2/" +#define EXTENSION_URL_MODIIS "mod_axis2_IIS.dll\? " + + +#define MAX_SERVERNAME 128 +#define MAX_PORT_LEN 8 + +#define MAX_HTTP_VERSION_LEN 16 +#define MAX_HTTP_CONTENT_TYPE_LEN 2048 +#define MAX_CONTENT_ENCODING_LEN 16 +#define MAX_HTTP_METHOD_LEN 8 +#define MAX_TCP_PORT_LEN 8 +#define MAX_CONTENT_LEN 16 + +#define OK 200 +#define HTTP_INTERNAL_SERVER_ERROR 500 +#define HTTP_ACCEPTED 202 + +#define AXIS2_STRICMP _stricmp + +#endif /*AXIS2_IIS_CONSTANTS_H*/ + diff --git a/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c new file mode 100644 index 0000000..fb7693b --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.c @@ -0,0 +1,153 @@ +/* + * 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. + */ + +#include "axis2_iis_out_transport_info.h" +#include +#include +#include + +#include "axis2_iis_constants.h" + +/** + * @brief IIS Out transport info impl structure + * Axis2 iis_out_transport_info_impl + */ + +typedef struct axis2_iis_out_transport_info_s +{ + axis2_http_out_transport_info_t out_transport_info; + axis2_char_t *encoding; + axis2_char_t content_type[MAX_HTTP_CONTENT_TYPE_LEN]; +} axis2_iis_out_transport_info_t; + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_iis_out_transport_info_t *)(out_transport_info)) + +void AXIS2_CALL +axis2_iis_out_transport_info_free( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env) +{ + axis2_iis_out_transport_info_t *info = NULL; + AXIS2_ENV_CHECK(env, void); + + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + if(info->encoding) + { + AXIS2_FREE(env->allocator, info->encoding); + info->encoding = NULL; + } + + AXIS2_FREE(env->allocator, info); + return; +} + +void AXIS2_CALL +axis2_iis_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + AXIS2_ENV_CHECK(env, void); + transport_info_l = (axis2_http_out_transport_info_t *)transport_info; + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +axis2_status_t AXIS2_CALL +axis2_iis_out_transport_info_set_content_type( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_iis_out_transport_info_t *info_impl = NULL; + + info_impl = AXIS2_INTF_TO_IMPL(info); + info_impl->content_type[0] = '\0'; + if(info_impl->encoding) + { + sprintf(info_impl->content_type, "%s%s%s", content_type, ";charser:", info_impl->encoding); + } + else + { + strcat(info_impl->content_type, content_type); + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_iis_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + axis2_iis_out_transport_info_t *info_impl = NULL; + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + + info_impl = AXIS2_INTF_TO_IMPL(info); + + if(info_impl->encoding) + { + AXIS2_FREE(env->allocator, info_impl->encoding); + } + info_impl->encoding = axutil_strdup(env, encoding); + + return AXIS2_SUCCESS; +} + +axis2_http_out_transport_info_t *AXIS2_CALL +axis2_iis_out_transport_info_create( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + axis2_iis_out_transport_info_t *info = NULL; + axis2_http_out_transport_info_t *http_out_info = NULL; + AXIS2_ENV_CHECK(env, NULL); + + info = (axis2_iis_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_iis_out_transport_info_t)); + + if(!info) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + info->encoding = NULL; + + http_out_info = &(info->out_transport_info); + + axis2_http_out_transport_info_set_content_type_func(http_out_info, env, + axis2_iis_out_transport_info_set_content_type); + axis2_http_out_transport_info_set_char_encoding_func(http_out_info, env, + axis2_iis_out_transport_info_set_char_encoding); + axis2_http_out_transport_info_set_free_func(http_out_info, env, + axis2_iis_out_transport_info_free); + + return http_out_info; +} + +axis2_char_t * +axis2_iis_out_transport_get_content( + axis2_http_out_transport_info_t * info) +{ + axis2_iis_out_transport_info_t *info_impl = NULL; + info_impl = AXIS2_INTF_TO_IMPL(info); + return info_impl->content_type; +} diff --git a/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h new file mode 100644 index 0000000..893ffdf --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_out_transport_info.h @@ -0,0 +1,61 @@ + +/* + * 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. + */ + +#ifndef AXIS2_IIS_OUT_TRANSPORT_INFO_H +#define AXIS2_IIS_OUT_TRANSPORT_INFO_H + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_iis_out_transport_info.h + * @brief axis2 IIS Out Transport Info + */ + +#include +#include +#ifdef __cplusplus +extern "C" +{ +#endif + + axis2_http_out_transport_info_t *AXIS2_CALL + + axis2_iis_out_transport_info_create( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB); + + /** + * Free http_out_transport_info passed as void pointer. This will be + * cast into appropriate type and then pass the cast object + * into the http_out_transport_info structure's free method + */ + void AXIS2_CALL + axis2_iis_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env); + + axis2_char_t *axis2_iis_out_transport_get_content( + axis2_http_out_transport_info_t * out_transport_info); + +#ifdef __cplusplus +} +#endif +#endif /* AXIS2_IIS_OUT_TRANSPORT_INFO_H */ diff --git a/src/core/transport/http/server/IIS/axis2_iis_regedit.js b/src/core/transport/http/server/IIS/axis2_iis_regedit.js new file mode 100644 index 0000000..3889c1e --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_regedit.js @@ -0,0 +1,84 @@ +var WshShell = WScript.CreateObject("WScript.Shell"); + +/* You can change the following values to suite your requirements */ +/* Axis2/C repo location. axis2.xml, modules folder and services folder should be in this dir */ +var axis2c_home = WshShell.CurrentDirectory; +/* Log level. Possible values are trace, error, info, critical, user, debug and warning */ +var log_level = "debug"; +/* Full path to the log file */ +var log_file = axis2c_home + "/logs/axis2.log"; +/* Services URL prefix. This is the folder where services are hosted. Optional */ +var services_url_prefix; +/* Max log file size */ +var max_log_file_size; +/* Axis2 location */ +var axis2_location; + +/* Don't change anything below */ +var axis2c_home_str = "axis2c_home"; +var log_level_str = "log_level"; +var log_file_str = "log_file"; +var services_url_prefix_str = "services_url_prefix"; +var max_log_file_size_str = "max_log_file_size"; +var axis2_location_str = "axis2_location" + +var reg_location = "HKLM\\Software\\Apache Axis2C\\IIS ISAPI Redirector\\" +/* If specified get the values from the command prompt */ +var args = WScript.Arguments; +if (args.length > 0) { + axis2c_home = args.Item(0); + if (axis2c_home) { + log_file = axis2c_home + "/logs/axis2.log"; + } +} +if (args.length > 1) { + log_level = args.Item(1); +} +if (args.length > 2) { + log_file = args.Item(2); +} +if (args.length > 3) { + services_url_prefix = args.Item(3); +} +if (args.length > 4) { + max_log_file_size = args.Item(4); +} +if (args.length > 5) { + axis2_location = args.Item(5); +} +/* Write the axis2c_home entry. This is used by Axis2/C to find the repo location */ +WshShell.RegWrite (reg_location + axis2c_home_str, axis2c_home, "REG_SZ"); +/* Write the log_level registry entry */ +WshShell.RegWrite (reg_location + log_level_str, log_level, "REG_SZ"); +/* Write the log file name */ +WshShell.RegWrite (reg_location + log_file_str, log_file, "REG_SZ"); +/* Write the services url prefix. We write this only if specified */ +try { + var services_url_prefix_key = WshShell.RegRead (reg_location + services_url_prefix_str); + if (services_url_prefix_key) { + WshShell.RegDelete (reg_location + services_url_prefix_str); + } +} catch (e) {} +if (services_url_prefix) { + WshShell.RegWrite (reg_location + services_url_prefix_str, services_url_prefix, "REG_SZ"); +} +/* We write max_log_file_size only if specified */ +try { + var max_log_file_size_key = WshShell.RegRead (reg_location + max_log_file_size_str); + if (max_log_file_size_key) { + WshShell.RegDelete (reg_location + max_log_file_size_str); + } +} catch (e) {} +if (max_log_file_size) { + WshShell.RegWrite (reg_location + max_log_file_size_str, max_log_file_size, "REG_SZ"); +} + +try{ + var axis2_location_key = WshShell.RegRead (reg_location + axis2_location_str); + if (axis2_location_key) { + WshShell.RegDelete (reg_location + axis2_location_str); + } +} catch (e) {} +if (axis2_location) { + WshShell.RegWrite (reg_location + axis2_location_str, axis2_location, "REG_SZ"); +} \ No newline at end of file diff --git a/src/core/transport/http/server/IIS/axis2_iis_stream.c b/src/core/transport/http/server/IIS/axis2_iis_stream.c new file mode 100644 index 0000000..90fc8ba --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_stream.c @@ -0,0 +1,313 @@ +/* + * 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. + */ + +#include +#include +#include "axis2_iis_stream.h" +#include + +/** + * @brief Stream struct impl + * Streaming mechanisms for iis web server + */ + +typedef struct iis_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + LPEXTENSION_CONTROL_BLOCK lpECB; + unsigned int cur_pos; + void *cur_position; +} iis_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((iis_stream_impl_t *)(stream)) + +axutil_stream_type_t AXIS2_CALL +iis_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL iis_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL iis_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +int AXIS2_CALL iis_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL iis_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +axutil_stream_t *AXIS2_CALL +axutil_stream_create_iis( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + iis_stream_impl_t *stream_impl = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, lpECB, NULL); + + stream_impl = (iis_stream_impl_t *)AXIS2_MALLOC(env->allocator, sizeof(iis_stream_impl_t)); + + if(!stream_impl) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + stream_impl->cur_pos = 0; + stream_impl->cur_position = NULL; + stream_impl->lpECB = lpECB; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, iis_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, iis_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, iis_stream_skip); + + return &(stream_impl->stream); +} + +int AXIS2_CALL +iis_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + void *temp_buff = NULL; + unsigned int data_to_read = 0; + DWORD ret_val = TRUE; + DWORD read_bytes = (DWORD)count; + iis_stream_impl_t *stream_impl = NULL; + char *temp = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = (iis_stream_impl_t *)stream; + + if(stream_impl->cur_pos == 0) + stream_impl->cur_position = stream_impl->lpECB->lpbData; + + /* If this is the case all the bytes are in the lpECB->lpbData buffer*/ + if(stream_impl->lpECB->cbAvailable == stream_impl->lpECB->cbTotalBytes) + { + /* Cannot read more than in the buffer.*/ + if(count + stream_impl->cur_pos <= stream_impl->lpECB->cbAvailable) + data_to_read = (unsigned)count; + else + data_to_read = stream_impl->lpECB->cbTotalBytes - stream_impl->cur_pos; + + memcpy(buffer, stream_impl->cur_position, data_to_read); + temp = (char *)(stream_impl->cur_position); + temp += data_to_read; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += data_to_read; + read_bytes = data_to_read; + } + else if(stream_impl->lpECB->cbAvailable == -1) + { + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, buffer, &read_bytes); + } + else if(stream_impl->lpECB->cbAvailable < stream_impl->lpECB->cbTotalBytes) + { + if(stream_impl->cur_pos > stream_impl->lpECB->cbAvailable) + { + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, buffer, + &read_bytes); + } + else if(stream_impl->cur_pos + count > stream_impl->lpECB->cbAvailable + && stream_impl->cur_pos < stream_impl->lpECB->cbAvailable) + { + int read_length = 0; + if(count + stream_impl->cur_pos <= stream_impl->lpECB->cbAvailable) + read_length = (unsigned)count; + else + read_length = stream_impl->lpECB->cbTotalBytes - stream_impl->cur_pos; + data_to_read = stream_impl->lpECB->cbAvailable - stream_impl->cur_pos; + memcpy(buffer, stream_impl->cur_position, data_to_read); + + read_bytes = stream_impl->cur_pos + read_length - stream_impl->lpECB->cbAvailable; + temp_buff = malloc(read_bytes); + + if(temp_buff == NULL) + return data_to_read; + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, + &read_bytes); + memcpy(((char *)buffer + data_to_read), temp_buff, read_bytes); + read_bytes += data_to_read; + temp = (char *)(stream_impl->cur_position); + temp += read_bytes; + stream_impl->cur_position = temp; + stream_impl->cur_pos += (unsigned)read_bytes; + } + else + { + memcpy(buffer, stream_impl->cur_position, count); + temp = (char *)(stream_impl->cur_position); + temp += count; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += (unsigned)count; + read_bytes = (int)count; + } + } + if(ret_val == TRUE) + return read_bytes; + else + return -1; +} + +int AXIS2_CALL +iis_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + DWORD ret_val = NO_ERROR; + unsigned long bytes_sent = 0; + iis_stream_impl_t *stream_impl = NULL; + axis2_char_t *buffer = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + buffer = (axis2_char_t *)buf; + bytes_sent = (unsigned)strlen(buffer); + + if(count <= 0) + { + return (int)count; + } + /* assume that buffer is not null terminated */ + ret_val = stream_impl->lpECB->WriteClient(stream_impl->lpECB->ConnID, buffer, &bytes_sent, + HSE_IO_SYNC); + if(ret_val == TRUE) + return (int)bytes_sent; + else + return -1; +} + +int AXIS2_CALL +iis_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + DWORD ret_val = TRUE; + iis_stream_impl_t *stream_impl = NULL; + void *temp_buff = NULL; + int data_to_read = 0; + DWORD read_bytes = (DWORD)count; + char *temp = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = (iis_stream_impl_t *)stream; + + if(stream_impl->cur_pos == 0) + stream_impl->cur_position = stream_impl->lpECB->lpbData; + + if(stream_impl->lpECB->cbAvailable == stream_impl->lpECB->cbTotalBytes) + { + if(count + stream_impl->cur_pos <= stream_impl->lpECB->cbAvailable) + data_to_read = count; + else + data_to_read = stream_impl->lpECB->cbAvailable - stream_impl->cur_pos; + + temp = (char *)(stream_impl->cur_position); + temp += data_to_read; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += data_to_read; + read_bytes = data_to_read; + } + else if(stream_impl->lpECB->cbAvailable == -1) + { + temp_buff = malloc(read_bytes); + ret_val + = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, &read_bytes); + free(temp_buff); + } + else if(stream_impl->lpECB->cbAvailable < stream_impl->lpECB->cbTotalBytes) + { + if(stream_impl->cur_pos > stream_impl->lpECB->cbAvailable) + { + temp_buff = malloc(read_bytes); + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, + &read_bytes); + free(temp_buff); + } + else if(stream_impl->cur_pos + count > stream_impl->lpECB->cbAvailable + && stream_impl->cur_pos < stream_impl->lpECB->cbAvailable) + { + data_to_read = stream_impl->lpECB->cbAvailable - stream_impl->cur_pos; + read_bytes = stream_impl->cur_pos + count - stream_impl->lpECB->cbAvailable; + temp_buff = malloc(read_bytes); + + if(temp_buff == NULL) + return data_to_read; + + ret_val = stream_impl->lpECB->ReadClient(stream_impl->lpECB->ConnID, temp_buff, + &read_bytes); + read_bytes += data_to_read; + free(temp_buff); + } + else + { + temp = (char *)(stream_impl->cur_position); + temp += count; + stream_impl->cur_position = temp; + temp = NULL; + stream_impl->cur_pos += count; + read_bytes = count; + } + } + if(ret_val == FALSE) + { + return -1; + } + return read_bytes; +} + +int AXIS2_CALL +iis_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +iis_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} diff --git a/src/core/transport/http/server/IIS/axis2_iis_stream.h b/src/core/transport/http/server/IIS/axis2_iis_stream.h new file mode 100644 index 0000000..091edb0 --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_stream.h @@ -0,0 +1,45 @@ + +/* + * 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. + */ + +#ifndef IIS_STREAM_H +#define IIS_STREAM_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** brief Constructor for creating IIS stream + * @return axutil_stream (IIS) + */ + axutil_stream_t *AXIS2_CALL + axutil_stream_create_iis( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB); + +#ifdef __cplusplus +} +#endif + +#endif /* IIS_STREAM_H */ diff --git a/src/core/transport/http/server/IIS/axis2_iis_worker.c b/src/core/transport/http/server/IIS/axis2_iis_worker.c new file mode 100644 index 0000000..51a6cc8 --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_worker.c @@ -0,0 +1,607 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "axis2_iis_out_transport_info.h" +#include "axis2_iis_stream.h" +#include "axis2_iis_worker.h" + +/* Files from iis */ +#include +#include + +#include "axis2_iis_constants.h" + +#define READ_SIZE 2048 + +axis2_status_t AXIS2_CALL +axis2_worker_get_original_url( + char url[], + char ret_url[]); + +axis2_char_t * AXIS2_CALL +axis2_iis_worker_get_bytes( + const axutil_env_t * env, + axutil_stream_t * stream); + +axis2_status_t AXIS2_CALL +start_response( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB, + int status, + const char *reason, + axutil_array_list_t *headers); + +axis2_status_t +write_response( + LPEXTENSION_CONTROL_BLOCK lpECB, + const void *b, + unsigned int l); + +axutil_hash_t * +axis2_iis_worker_read_http_headers( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB); + +AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + +static struct reasons +{ + axis2_char_t * status_code; + int status_len; +} reasons[] = { { "200 OK", 6 }, { "202 Accepted", 12 }, { "500 Internal Server Error", 25 } }; + +struct axis2_iis_worker +{ + axis2_conf_ctx_t * conf_ctx; +}; + +char * +status_reason( + int status); + +axis2_iis_worker_t * AXIS2_CALL +axis2_iis_worker_create( + const axutil_env_t * env, + axis2_char_t * repo_path) +{ + axis2_iis_worker_t * iis_worker = NULL; + + iis_worker = (axis2_iis_worker_t *)AXIS2_MALLOC(env->allocator, sizeof(axis2_iis_worker_t)); + if(!iis_worker) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + iis_worker->conf_ctx = axis2_build_conf_ctx(env, repo_path); + if(!iis_worker->conf_ctx) + { + axis2_iis_worker_free((axis2_iis_worker_t *)iis_worker, env); + return NULL; + } + return iis_worker; +} + +void AXIS2_CALL +axis2_iis_worker_free( + axis2_iis_worker_t * iis_worker, + const axutil_env_t * env) +{ + if(iis_worker->conf_ctx) + { + axis2_conf_ctx_free(iis_worker->conf_ctx, env); + iis_worker->conf_ctx = NULL; + } + AXIS2_FREE(env->allocator, iis_worker); + return; +} + +int AXIS2_CALL +axis2_iis_worker_process_request( + axis2_iis_worker_t * iis_worker, + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + axis2_conf_ctx_t * conf_ctx = NULL; + axutil_stream_t * out_stream = NULL; + axis2_transport_out_desc_t * out_desc = NULL; + axis2_transport_in_desc_t * in_desc = NULL; + axis2_char_t soap_action[INTERNET_MAX_URL_LENGTH]; + axis2_char_t original_url[INTERNET_MAX_URL_LENGTH]; + axis2_char_t req_url[INTERNET_MAX_URL_LENGTH]; + DWORD cbSize = 0; + CHAR server_name[MAX_SERVERNAME]; + axis2_char_t port[MAX_TCP_PORT_LEN]; + axis2_char_t redirect_url[INTERNET_MAX_PATH_LENGTH]; + axis2_char_t accept_language[INTERNET_MAX_PATH_LENGTH]; + axutil_hash_t *headers = NULL; + axis2_char_t peer_ip[50]; + axis2_char_t accept_header[INTERNET_MAX_URL_LENGTH]; + axis2_char_t accept_charset[INTERNET_MAX_URL_LENGTH]; + /*axutil_property_t *peer_property = NULL;*/ + + axis2_http_header_t *content_type_header = NULL; + axis2_http_header_t *content_length_header = NULL; + + /* New Code variables */ + axis2_http_transport_in_t request; + axis2_http_transport_out_t response; + + /* initialize tranport in structure */ + axis2_http_transport_utils_transport_in_init(&request, env); + + /* initialize tranport out structure */ + axis2_http_transport_utils_transport_out_init(&response, env); + + soap_action[0] = '\0'; + + /*Check the parameters*/ + if(!lpECB) + { + AXIS2_ERROR_SET_ERROR_NUMBER(env->error, AXIS2_ERROR_INVALID_NULL_PARAM); + return AXIS2_FAILURE; + } + conf_ctx = iis_worker->conf_ctx; + if(!conf_ctx) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_CONFIGURATION_CONTEXT, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "SERVER_NAME", server_name, &cbSize) == FALSE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get server name from IIS."); + return AXIS2_FAILURE; + } + cbSize = MAX_TCP_PORT_LEN; + if(lpECB->GetServerVariable(lpECB->ConnID, "SERVER_PORT", port, &cbSize) == FALSE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get server port from IIS."); + return AXIS2_FAILURE; + } + request.svr_port = port; + + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_URL", redirect_url, &cbSize) == FALSE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Cannot get server port from IIS."); + return AXIS2_FAILURE; + } + + /* We have a mapped URL only when the server version is 5 or less than that. */ + if(server_version <= 5) + { + axis2_worker_get_original_url(redirect_url, original_url); + /* create the url using the above variables */ + sprintf(req_url, "%s%s%s%s%s", "http://", server_name, ":", port, original_url); + } + else + { + sprintf(req_url, "%s%s%s%s%s", "http://", server_name, ":", port, redirect_url); + } + /* Set the request url */ + request.request_uri = req_url; + + out_stream = axutil_stream_create_basic(env); + out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(iis_worker->conf_ctx, env), + env, AXIS2_TRANSPORT_ENUM_HTTP); + in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(iis_worker->conf_ctx, env), env, + AXIS2_TRANSPORT_ENUM_HTTP); + + /* Create the in message context */ + request.msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc); + axis2_msg_ctx_set_server_side(request.msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_transport_out_stream(request.msg_ctx, env, out_stream); + + /* Get the SOAPAction Header */ + cbSize = INTERNET_MAX_URL_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_SOAPAction", soap_action, &cbSize)) + { + request.soap_action = soap_action; + } + + /* Create the in stream */ + request.in_stream = axutil_stream_create_iis(env, lpECB); + if(!request.in_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occured in creating input stream."); + return AXIS2_FAILURE; + } + + /* Get the Remote Adrress */ + if(lpECB->GetServerVariable(lpECB->ConnID, "REMOTE_ADDR", peer_ip, &cbSize)) + { + request.remote_ip = peer_ip; + } + + /* Set the http headers into the message context */ + headers = axis2_iis_worker_read_http_headers(env, lpECB); + if(axis2_msg_ctx_set_transport_headers(request.msg_ctx, env, headers) == AXIS2_FAILURE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "IIS: Error occured in setting transport headers."); + } + /* Set the content length */ + request.content_length = lpECB->cbTotalBytes; + /* Set the HTTP method */ + if(axutil_strcasecmp(lpECB->lpszMethod, "POST") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_POST; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "GET") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_GET; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "HEAD") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_HEAD; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "PUT") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_PUT; + } + else if(axutil_strcasecmp(lpECB->lpszMethod, "DELETE") == 0) + { + request.request_method = AXIS2_HTTP_METHOD_DELETE; + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "IIS: Unsupported HTTP Method."); + return AXIS2_FAILURE; + } + /* Set the URL prefix. axis2_request_url_prefix is a global variable set at the init time */ + request.request_url_prefix = axis2_request_url_prefix; + /* Create the transport out info */ + request.out_transport_info = axis2_iis_out_transport_info_create(env, lpECB); + /* Set the content type */ + request.content_type = lpECB->lpszContentType; + + /* Get accept headaer */ + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_Accept", accept_header, &cbSize)) + { + request.accept_header = accept_header; + } + + /* Get the accept langauge */ + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_Accept-Language", accept_language, &cbSize)) + { + request.accept_language_header = accept_language; + } + + cbSize = INTERNET_MAX_PATH_LENGTH; + if(lpECB->GetServerVariable(lpECB->ConnID, "HTTP_Accept-Charset", accept_charset, &cbSize)) + { + request.accept_charset_header = accept_charset; + } + + /* Now we have set everything. We can call process method to process the request */ + if(axis2_http_transport_utils_process_request(env, conf_ctx, &request, &response) + == AXIS2_FAILURE) + { + return AXIS2_FAILURE; + } + + /* Write the response */ + if(response.response_data && response.response_data_length > 0) + { + axis2_char_t content_length_str[16] = { 0 }; + axis2_bool_t is_out_headers_created = AXIS2_FALSE; + if(!response.output_headers) + { + response.output_headers = axutil_array_list_create(env, 2); + is_out_headers_created = AXIS2_TRUE; + } + sprintf(content_length_str, "%d", response.response_data_length); + if(!response.content_type) + { + content_type_header = axis2_http_header_create(env, "Content-Type", + axis2_iis_out_transport_get_content(request.out_transport_info)); + } + else + { + content_type_header = axis2_http_header_create(env, "Content-Type", + response.content_type); + } + content_length_header = axis2_http_header_create(env, "Content-Length", content_length_str); + axutil_array_list_add(response.output_headers, env, content_length_header); + axutil_array_list_add(response.output_headers, env, content_type_header); + /* Write the headers */ + start_response(env, lpECB, response.http_status_code, response.http_status_code_name, + response.output_headers); + /* Write the response body */ + if(write_response(lpECB, response.response_data, response.response_data_length) + == AXIS2_FAILURE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "IIS: Writing data to IIS"); + return AXIS2_FAILURE; + } + if(is_out_headers_created) + { + if(content_length_header) + { + axis2_http_header_free(content_length_header, env); + } + if(content_type_header) + { + axis2_http_header_free(content_type_header, env); + } + axutil_array_list_free(response.output_headers, env); + } + } + else + { + /* If we don't have a body we should write the HTTP headers */ + start_response(env, lpECB, response.http_status_code, response.http_status_code_name, + response.output_headers); + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Response is NULL"); + } + + /* Do some cleaning */ + axis2_http_transport_utils_transport_in_uninit(&request, env); + axis2_http_transport_utils_transport_out_uninit(&response, env); + return AXIS2_SUCCESS; +} + +axis2_status_t +write_response( + LPEXTENSION_CONTROL_BLOCK lpECB, + const void *b, + unsigned int l) +{ + if(lpECB && b) + { + if(l) + { + unsigned int written = 0; + char *buf = (char *)b; + /* If couldn't write the data at onece try again until all the data is written.*/ + while(written < l) + { + DWORD try_to_write = l - written; + if(!lpECB-> WriteClient(lpECB->ConnID, buf + written, &try_to_write, 0)) + { + return AXIS2_FAILURE; + } + written += try_to_write; + } + } + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +axis2_status_t AXIS2_CALL +start_response( + const axutil_env_t *env, + LPEXTENSION_CONTROL_BLOCK lpECB, + int status, + const char *reason, + axutil_array_list_t *headers) +{ + static char crlf[3] = { (char)13, (char)10, '\0' }; + unsigned int num_of_headers = 0; + + if(status < 100 || status > 1000) + { + return AXIS2_FAILURE; + } + if(lpECB) + { + size_t len_of_status; + char *status_str; + char *headers_str; + + /* + * Create the status line + */ + if(reason) + { + status_str = (char *)_alloca((6 + strlen(reason)) * sizeof(char)); + sprintf(status_str, "%d %s", status, reason); + len_of_status = strlen(status_str); + } + else + { + switch(status) + { + case 200: + status_str = reasons[0].status_code; + len_of_status = reasons[0].status_len; + break; + case 202: + status_str = reasons[1].status_code; + len_of_status = reasons[1].status_len; + break; + case 500: + status_str = reasons[2].status_code; + len_of_status = reasons[2].status_len; + break; + default: + status_str = reasons[0].status_code; + len_of_status = reasons[0].status_len; + break; + } + } + /* + * Create response headers string + */ + if(headers && (num_of_headers = axutil_array_list_size(headers, env)) > 0) + { + size_t i, len_of_headers; + axis2_http_header_t *header = NULL; + for(i = 0, len_of_headers = 0; i < num_of_headers; i++) + { + header = axutil_array_list_get(headers, env, (int)i); + len_of_headers += strlen(axis2_http_header_get_name(header, env)); + len_of_headers += strlen(axis2_http_header_get_value(header, env)); + len_of_headers += 4; /* extra for colon, space and crlf */ + } + len_of_headers += 3; /* crlf and terminating null char */ + headers_str = (char *)_alloca(len_of_headers * sizeof(char)); + headers_str[0] = '\0'; + for(i = 0; i < num_of_headers; i++) + { + header = axutil_array_list_get(headers, env, (int)i); + strcat(headers_str, axis2_http_header_get_name(header, env)); + strcat(headers_str, ": "); + strcat(headers_str, axis2_http_header_get_value(header, env)); + strcat(headers_str, "\r\n"); + } + strcat(headers_str, "\r\n"); + } + else + { + headers_str = crlf; + } + if(!lpECB-> ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, status_str, + (LPDWORD) & len_of_status, (LPDWORD)headers_str)) + { + return AXIS2_FAILURE; + } + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} + +axis2_status_t AXIS2_CALL +axis2_worker_get_original_url( + char url[], + char ret_url[]) +{ + extern axis2_char_t *axis2_location; + strcpy(ret_url, axis2_location); + strcat(ret_url, &url[25]); + return URI_MATCHED; +} + +axis2_char_t * AXIS2_CALL +axis2_iis_worker_get_bytes( + const axutil_env_t * env, + axutil_stream_t * stream) +{ + axutil_stream_t * tmp_stream = NULL; + int return_size = -1; + axis2_char_t * buffer = NULL; + axis2_bool_t loop_state = AXIS2_TRUE; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, stream, NULL); + + tmp_stream = axutil_stream_create_basic(env); + while(loop_state) + { + int read = 0; + int write = 0; + char buf[READ_SIZE]; + + read = axutil_stream_read(stream, env, buf, READ_SIZE); + if(read < 0) + { + break; + } + write = axutil_stream_write(tmp_stream, env, buf, read); + if(read < (READ_SIZE - 1)) + { + break; + } + } + return_size = axutil_stream_get_len(tmp_stream, env); + if(return_size > 0) + { + buffer = (char *)AXIS2_MALLOC(env->allocator, sizeof(char) * (return_size + 2)); + return_size = axutil_stream_read(tmp_stream, env, buffer, return_size + 1); + buffer[return_size + 1] = '\0'; + } + axutil_stream_free(tmp_stream, env); + return buffer; +} + +/** Read all HTTP headers. + */ +axutil_hash_t * +axis2_iis_worker_read_http_headers( + const axutil_env_t * env, + LPEXTENSION_CONTROL_BLOCK lpECB) +{ + const char szHTTP_[] = "HTTP_"; + char szBuffer[4096]; + DWORD dwBufferSize = sizeof szBuffer; + axutil_hash_t *headers = NULL; + axis2_http_header_t* http_header = NULL; + + BOOL bGet = lpECB->GetServerVariable(lpECB->ConnID, "ALL_HTTP", szBuffer, &dwBufferSize); + if(bGet) + { + /* Find lines, split key/data pair and write them as output */ + LPTSTR pOpts = NULL; + LPTSTR pEnd = NULL; + LPTSTR pChar = NULL; + char szTmpBuf[512]; + char szTmpName[256]; + + headers = axutil_hash_make(env); + szTmpBuf[0] = 0; + for(pChar = szBuffer; '\0' != *pChar;) + { + if(*pChar == '\r' || *pChar == '\n') + { + pChar++; + continue; + } + pOpts = strchr(pChar, ':');/* findseparator */ + if(pOpts && *pOpts) + { + pEnd = pOpts; + while(*pEnd && *pEnd != '\r' && *pEnd != '\n') + { + pEnd++; + } + *pOpts = '\0'; /* split the strings */ + *pEnd = '\0'; + if(0 == strncmp(pChar, szHTTP_, strlen(szHTTP_))) + { + pChar += strlen(szHTTP_); + } + strcpy(szTmpName, pChar); + axutil_string_replace(szTmpName, '_', '-'); + http_header = axis2_http_header_create(env, szTmpName, pOpts + 1); + axutil_hash_set(headers, axutil_strdup(env, szTmpName), AXIS2_HASH_KEY_STRING, + http_header); + pChar = pEnd + 1; + } + } + } + else + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "axis2_iis_worker_read_http_headers: no http headers"); + } + return headers; +} + diff --git a/src/core/transport/http/server/IIS/axis2_iis_worker.h b/src/core/transport/http/server/IIS/axis2_iis_worker.h new file mode 100644 index 0000000..f9b6292 --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_iis_worker.h @@ -0,0 +1,62 @@ + +/* + * 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. + */ + +#ifndef AXIS2_APACHE2_WORKER_H +#define AXIS2_APACHE2_WORKER_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ + +#endif /* + */ + +typedef struct axis2_iis_worker axis2_iis_worker_t; + +int server_version; + +int AXIS2_CALL + axis2_iis_worker_process_request( + axis2_iis_worker_t * iis_worker, + const axutil_env_t * env, + void *r); + + +void AXIS2_CALL + axis2_iis_worker_free( + axis2_iis_worker_t * iis_worker, + const axutil_env_t * env); + + +axis2_iis_worker_t * AXIS2_CALL + axis2_iis_worker_create( + const axutil_env_t * env, + axis2_char_t * repo_path); + + +#ifdef __cplusplus +} +#endif /* + */ + +#endif /* AXIS2_IIS_WORKER_H */ diff --git a/src/core/transport/http/server/IIS/axis2_isapi_plugin.c b/src/core/transport/http/server/IIS/axis2_isapi_plugin.c new file mode 100644 index 0000000..eccfd1c --- /dev/null +++ b/src/core/transport/http/server/IIS/axis2_isapi_plugin.c @@ -0,0 +1,476 @@ + +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "axis2_iis_constants.h" +#include "axis2_iis_worker.h" + +/* Axis headers */ +#include +#include +#include +#include +#include + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#define AXIS2_IIS_LOG_FILE_TAG "log_file" +#define AXIS2_IIS_LOG_LEVEL_TAG "log_level" +#define AXIS2_IIS_REPO_PATH_TAG "axis2c_home" +#define AXIS2_IIS_EXTENSION_URI_TAG "extension_uri" +#define AXIS2_IIS_REDIRECT_WORD_TAG "redirect_uri" +#define AXIS2_IIS_AXIS2_LOCATION "axis2_location" +#define AXIS2_IIS_SERVICE_URL_PREFIX "services_url_prefix" + +#define AXIS2_IIS_LOG_TRACE_VERB "trace" +#define AXIS2_IIS_LOG_ERROR_VERB "error" +#define AXIS2_IIS_LOG_INFO_VERB "info" +#define AXIS2_IIS_LOG_USER_VERB "user" +#define AXIS2_IIS_LOG_CRITICAL_VERB "critical" +#define AXIS2_IIS_LOG_WARN_VERB "warning" +#define AXIS2_IIS_LOG_DEBUG_VERB "debug" + +#define MAX_FILE_PATH 256 +#define REGISTRY_LOCATION "Software\\Apache Axis2c\\IIS ISAPI Redirector" + +static int is_inited = FALSE; +static axis2_iis_worker_t *axis2_worker = NULL; +static const axutil_env_t *axutil_env = NULL; + +/* Configuration parameters */ +axis2_char_t *axis2_location = "/axis2"; +static axis2_char_t *axis2_service_url_prefix= "/services"; +static axis2_char_t repo_path[MAX_FILE_PATH]; +static axis2_char_t log_file[MAX_FILE_PATH]; +static axutil_log_levels_t log_level = AXIS2_LOG_LEVEL_CRITICAL; + +/* Path variables */ +static char szOriginalPath[_MAX_PATH + 1]; +static char szPath[_MAX_PATH + 1]; + +axis2_char_t general_error[] = "\r\n" + " An IIS server error occurred. \r\n" + "

An IIS server error occurred

\r\n" + "
\r\n" + "An error occurred in IIS while processing this request."; + +axis2_char_t initializing_error[] = "\r\n" + " An IIS server error occurred. \r\n" + "

An IIS server error occurred

\r\n" + "
\r\n" + "An error occurred while initilizing Axis2/C."; + + +/* + * This is a utility functipn for reading configuration data from the registery. + */ +static axis2_status_t AXIS2_CALL +read_registery_init_data(); + +/* + * Utility function for reading + */ +static axis2_status_t AXIS2_CALL get_registry_config_parameter( + HKEY hkey, + const char *tag, + char *b, + DWORD sz); + +/* + * Parse the given string and return the corresponding log_level + */ +axutil_log_levels_t AXIS2_CALL axis2_iis_parse_log_level(char level[]); + +/* + * Initialize axis. This function is called in the begining of the module loading. + * It initializes the axis by reading values from the configuration and creating the + * required structures for the axis2c +*/ +axis2_status_t AXIS2_CALL init_axis2(); + +/* + * This is the function to be called after the processing + * is over for non Axis2 requets + */ +VOID +WINAPI +ExecUrlCompletion ( + EXTENSION_CONTROL_BLOCK * pecb, + PVOID pContext, + DWORD cbIO, + DWORD dwError + ); + +/* + * If somethign went wrong in the IIS server when + * we are proccessing we send this + */ +BOOL +send_error( + EXTENSION_CONTROL_BLOCK * pecb, + CHAR error[]); + +axis2_status_t AXIS2_CALL init_axis2(); + +BOOL +WINAPI +GetExtensionVersion(HSE_VERSION_INFO * pVer) +{ + pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, + HSE_VERSION_MAJOR); + strncpy( pVer->lpszExtensionDesc, + "WildCardMap Sample ISAPI Extension", HSE_MAX_EXT_DLL_NAME_LEN ); + + pVer->lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN-1] = '\0'; + server_version = 5; + return TRUE; +} + +DWORD +WINAPI +HttpExtensionProc(EXTENSION_CONTROL_BLOCK * pecb) + +{ + HSE_EXEC_URL_INFO ExecUrlInfo; + DWORD cbData = INTERNET_MAX_URL_LENGTH; + char url[INTERNET_MAX_URL_LENGTH]; + axis2_bool_t is_for_us = AXIS2_TRUE; + + /* Get the URL */ + if ( pecb->GetServerVariable( pecb->ConnID, + "URL", + url, + &cbData ) == FALSE ) + { + return HSE_STATUS_ERROR; + } + + if (!is_inited) + { + DWORD dwBufferSize = 0; + axis2_char_t server_software[256]; + axis2_char_t *version = NULL; + + ZeroMemory(szOriginalPath, sizeof szOriginalPath); + dwBufferSize = sizeof szOriginalPath; + +#if _WIN32_WINNT >= 0x0502 + GetDllDirectory( dwBufferSize, szOriginalPath ); +#else + GetCurrentDirectory( dwBufferSize, szOriginalPath ); +#endif + ZeroMemory(szPath, sizeof szPath); + dwBufferSize = sizeof szPath; + /* Get the current physical paht */ + if (pecb->GetServerVariable(pecb->ConnID, "APPL_PHYSICAL_PATH", szPath, &dwBufferSize) == FALSE) + { + send_error(pecb, initializing_error); + return HSE_STATUS_ERROR; + } + /* Retrieve the server version */ + dwBufferSize = 32; + if (pecb->GetServerVariable(pecb->ConnID, "SERVER_SOFTWARE", server_software, &dwBufferSize) == FALSE) + { + send_error(pecb, initializing_error); + return HSE_STATUS_ERROR; + } + version = axutil_strchr(server_software, '/'); + if (version) + { + server_version = atoi(version + 1); + } +#if _WIN32_WINNT >= 0x0502 + SetDllDirectory( szPath ); +#else + SetCurrentDirectory( szPath ); +#endif + /* If we haven't initialized axis2/c before initialization failed */ + if (AXIS2_FAILURE == init_axis2()) + { + send_error(pecb, initializing_error); + return HSE_STATUS_ERROR; + } +#if _WIN32_WINNT >= 0x0502 + SetDllDirectory( szOriginalPath ); +#else + SetCurrentDirectory( szOriginalPath ); +#endif + } + + /* Check weather we have a request for Axis2/C */ + if (server_version >= 6 && strlen(url) >= strlen(axis2_location)) + { + int i = 0; + is_for_us = AXIS2_TRUE; + while (axis2_location[i] != '\0') + { + if (axis2_location[i] != (url)[i]) { + is_for_us = AXIS2_FALSE; + break; + } + i++; + } + if (url[i] != '/' && url[i] != '\0') + { + is_for_us = AXIS2_FALSE; + } + } + + if (is_for_us) + { + /* Windows cannot find the correct dlls unless the path is set*/ +#if _WIN32_WINNT >= 0x0502 + SetDllDirectory( szPath ); +#else + SetCurrentDirectory( szPath ); +#endif + pecb->dwHttpStatusCode = HTTP_INTERNAL_SERVER_ERROR; + /* We are sure that worker is not NULL since it is NULL init_axis2 would have failed */ + axis2_iis_worker_process_request(axis2_worker, axutil_env, pecb); + + /* Windows cannot find the correct dlls unless the dir is set + but we want to reset to previous dir after the load */ +#if _WIN32_WINNT >= 0x0502 + SetDllDirectory( szOriginalPath ); +#else + SetCurrentDirectory( szOriginalPath ); +#endif + return HSE_STATUS_SUCCESS; + } + else if (server_version >= 6) + { + /* For IIS 5.1 or earlier this code is never executed. Since the URL is + redirected to Axis2/C by the Filter */ + + /* If not for Axis2/C let the request go to who ever wants it */ + ExecUrlInfo.pszUrl = NULL; /* Use original request URL */ + ExecUrlInfo.pszMethod = NULL; /* Use original request method */ + ExecUrlInfo.pszChildHeaders = NULL; /* Use original request headers */ + ExecUrlInfo.pUserInfo = NULL; /* Use original request user info */ + ExecUrlInfo.pEntity = NULL; /* Use original request entity */ + + /* Provent recursion */ + ExecUrlInfo.dwExecUrlFlags = HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR; + + /* Associate the completion routine and the current URL with this request. */ + if ( pecb->ServerSupportFunction( pecb->ConnID, + HSE_REQ_IO_COMPLETION, + ExecUrlCompletion, + NULL, + NULL) == FALSE ) + { + return HSE_STATUS_ERROR; + } + + /* Ok, now that everything is set up, let's call the child request */ + if ( pecb->ServerSupportFunction( pecb->ConnID, + HSE_REQ_EXEC_URL, + &ExecUrlInfo, + NULL, + NULL ) == FALSE ) + { + return HSE_STATUS_ERROR; + } + /* Return pending and let the completion clean up */ + return HSE_STATUS_PENDING; + } + return HSE_STATUS_ERROR; +} + +VOID +WINAPI +ExecUrlCompletion ( + EXTENSION_CONTROL_BLOCK * pecb, + PVOID pContext, + DWORD cbIO, + DWORD dwError + ) +{ + /* We are done so notify */ + pecb->ServerSupportFunction( + pecb->ConnID, + HSE_REQ_DONE_WITH_SESSION, + NULL, + NULL, + NULL); +} + + +BOOL +send_error( + EXTENSION_CONTROL_BLOCK * pecb, + axis2_char_t error[]) +{ + DWORD cbData; + pecb->dwHttpStatusCode = 500; + /* Send headers and response */ + pecb->ServerSupportFunction( pecb->ConnID, + HSE_REQ_SEND_RESPONSE_HEADER, + "500 Server Error", + NULL, + (LPDWORD)"Content-Type: text/html\r\n\r\n" ); + + cbData = axutil_strlen( error ); + return pecb->WriteClient( pecb->ConnID, + error, + &cbData, + HSE_IO_SYNC ); +} + +axis2_status_t AXIS2_CALL read_registery_init_data() +{ + long rc = 0; + axis2_status_t ok = TRUE; + char tmpbuf[INTERNET_MAX_URL_LENGTH]; + HKEY hkey; + AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + + rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD) 0, KEY_READ, &hkey); + if (ERROR_SUCCESS != rc) + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_REPO_PATH_TAG, tmpbuf, sizeof(repo_path))) + { + strcpy(repo_path, tmpbuf); + } + else + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_LOG_FILE_TAG, tmpbuf, sizeof(log_file))) + { + strcpy(log_file, tmpbuf); + } + else + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_LOG_LEVEL_TAG, tmpbuf, sizeof(tmpbuf))) + { + log_level = axis2_iis_parse_log_level(tmpbuf); + } + else + { + return AXIS2_FAILURE; + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_SERVICE_URL_PREFIX, tmpbuf, sizeof(tmpbuf))) + { + axis2_request_url_prefix = _strdup(tmpbuf); + } + if (get_registry_config_parameter(hkey, AXIS2_IIS_AXIS2_LOCATION, tmpbuf, sizeof(tmpbuf))) + { + axis2_location = _strdup(tmpbuf); + } + RegCloseKey(hkey); + return ok; +} + +axutil_log_levels_t AXIS2_CALL +axis2_iis_parse_log_level(char level[]) +{ + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_TRACE_VERB)) + { + return AXIS2_LOG_LEVEL_TRACE; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_DEBUG_VERB)) + { + return AXIS2_LOG_LEVEL_DEBUG; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_INFO_VERB)) + { + return AXIS2_LOG_LEVEL_INFO; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_USER_VERB)) + { + return AXIS2_LOG_LEVEL_USER; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_WARN_VERB)) + { + return AXIS2_LOG_LEVEL_WARNING; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_ERROR_VERB)) + { + return AXIS2_LOG_LEVEL_ERROR; + } + if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_CRITICAL_VERB)) + { + return AXIS2_LOG_LEVEL_CRITICAL; + } + return AXIS2_LOG_LEVEL_DEBUG; +} + +axis2_status_t AXIS2_CALL +get_registry_config_parameter(HKEY hkey, const char *tag, char *b, DWORD sz) +{ + DWORD type = 0; + LONG lrc; + + lrc = RegQueryValueEx(hkey, tag, (LPDWORD) 0, &type, (LPBYTE) b, &sz); + if ((ERROR_SUCCESS != lrc) || (type != REG_SZ)) + { + return FALSE; + } + b[sz] = '\0'; + return TRUE; +} + +/** + * This method initializes the axis2 engine. All the required variables are set to + * their initial values in this method. +*/ +axis2_status_t AXIS2_CALL init_axis2() +{ + /* + * These are the varibles required to initialize axis. + */ + axis2_status_t status = FALSE; + /* We need to init xml readers before we go into threaded env */ + if (!is_inited) + { + axiom_xml_reader_init(); + status = read_registery_init_data(); + if (status == AXIS2_FAILURE) + { + return AXIS2_FAILURE; + } + axutil_error_init(); + /* Initialize the environement */ + axutil_env = axutil_env_create_all(log_file, log_level); + if (!axutil_env) + { + return AXIS2_FAILURE; + } + axis2_worker = axis2_iis_worker_create(axutil_env, repo_path); + if (!axis2_worker) + { + return AXIS2_FAILURE; + } + is_inited = AXIS2_TRUE; + return AXIS2_SUCCESS; + } + return AXIS2_FAILURE; +} diff --git a/src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c b/src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c new file mode 100644 index 0000000..49cd6d9 --- /dev/null +++ b/src/core/transport/http/server/IIS/iis_iaspi_plugin_51/axis2_isapi_51.c @@ -0,0 +1,153 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "..\\axis2_iis_constants.h" + +#define REGISTRY_LOC "Software\\Apache Axis2c\\IIS ISAPI Redirector" +#define AXIS2_IIS_AXIS2_LOC "axis2_location" +static char *axis2_loc = "/axis2"; + +static axis2_char_t redirect_word[INTERNET_MAX_URL_LENGTH] = "/axis2/mod_axis2_IIS.dll\?"; +/* + * Search a given uri to find weather it matches a uri for the axis2 + * The uri format for axis2 is of the form + * scheme://server:port/axis2/other_parts + * This function search a give uri for the /axis2/. If a match + * is found it will replace the /axis2 part of the url with /axis2/mod_iis.dll? + */ +axis2_bool_t AXIS2_CALL +get_extension_url( + char url[], + char ret_url[]); + +/* + * This function is called by the IIS server at the server + * initialization. So this is the ideal plcae for initializing + * axis2c. + */ +BOOL WINAPI +GetFilterVersion( + PHTTP_FILTER_VERSION pVer) +{ + DWORD type = 0, size = 0; + LONG lrc = 0; + char tmpbuf[INTERNET_MAX_URL_LENGTH]; + HKEY hkey; + ULONG http_filter_revision = HTTP_FILTER_REVISION; + pVer->dwFilterVersion = pVer->dwServerFilterVersion; + if(pVer->dwFilterVersion > http_filter_revision) + { + pVer->dwFilterVersion = http_filter_revision; + } + + /* + Receive notifictions when + 1. Server preprocessed the headers. + 2. Log + 3. All the request coming in secure and none secure ports. + */ + pVer->dwFlags = (SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_PREPROC_HEADERS | SF_NOTIFY_SECURE_PORT + | SF_NOTIFY_NONSECURE_PORT | SF_NOTIFY_AUTH_COMPLETE); + + /* Give a short discription about the module.*/ + strcpy(pVer->lpszFilterDesc, "axis2c filter"); + /* Get the axis2 location from the registry configuration */ + lrc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOC, (DWORD)0, KEY_READ, &hkey); + if(ERROR_SUCCESS != lrc) + { + return FALSE; + } + size = INTERNET_MAX_URL_LENGTH; + lrc = RegQueryValueEx(hkey, AXIS2_IIS_AXIS2_LOC, (LPDWORD)0, &type, (LPBYTE)tmpbuf, &size); + if((ERROR_SUCCESS == lrc) && (type == REG_SZ)) + { + tmpbuf[size] = '\0'; + axis2_loc = _strdup(tmpbuf); + } + RegCloseKey(hkey); + return TRUE; +} + +/* + When a notification happens this function is called by the IIS. + */ +DWORD WINAPI +HttpFilterProc( + PHTTP_FILTER_CONTEXT pfc, + DWORD notificationType, + LPVOID pvNotification) +{ + DWORD bufferLength = INTERNET_MAX_URL_LENGTH; + char url[INTERNET_MAX_URL_LENGTH]; + char modified_url[INTERNET_MAX_URL_LENGTH]; + + if(notificationType == SF_NOTIFY_PREPROC_HEADERS) + { + pfc->GetServerVariable(pfc, "HTTP_URL", url, &bufferLength); + if(get_extension_url(url, modified_url)) + { + ((PHTTP_FILTER_PREPROC_HEADERS)pvNotification)->SetHeader(pfc, "url", modified_url); + return SF_STATUS_REQ_HANDLED_NOTIFICATION; + } + } + return SF_STATUS_REQ_NEXT_NOTIFICATION; +} + +axis2_bool_t AXIS2_CALL +get_extension_url( + char url[], + char ret_url[]) +{ + axis2_bool_t is_for_us = AXIS2_FALSE; + int i = 0; + /* Should contain "/axis2/"*/ + ret_url[0] = '\0'; + if(strlen(url) >= strlen(axis2_loc)) + { + is_for_us = AXIS2_TRUE; + while(axis2_loc[i] != '\0') + { + if(axis2_loc[i] != (url)[i]) + { + is_for_us = AXIS2_FALSE; + break; + } + i++; + } + if(url[i] != '/' && url[i] != '\0') + { + is_for_us = AXIS2_FALSE; + } + } + if(is_for_us) + { + strcpy(ret_url, redirect_word); + strcat(ret_url, &url[i]); + } + return is_for_us; +} diff --git a/src/core/transport/http/server/IIS/mod_axis2.def b/src/core/transport/http/server/IIS/mod_axis2.def new file mode 100644 index 0000000..22205e7 --- /dev/null +++ b/src/core/transport/http/server/IIS/mod_axis2.def @@ -0,0 +1,7 @@ +LIBRARY "mod_axis2_IIS" + +EXPORTS + GetExtensionVersion + HttpExtensionProc + GetFilterVersion + HttpFilterProc \ No newline at end of file diff --git a/src/core/transport/http/server/Makefile.am b/src/core/transport/http/server/Makefile.am new file mode 100644 index 0000000..07cf1e9 --- /dev/null +++ b/src/core/transport/http/server/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS=@APACHE2BUILD@ simple_axis2_server ${CGI_DIR} +EXTRA_DIST=IIS CGI diff --git a/src/core/transport/http/server/apache2/Makefile.am b/src/core/transport/http/server/apache2/Makefile.am new file mode 100644 index 0000000..d5f6bd8 --- /dev/null +++ b/src/core/transport/http/server/apache2/Makefile.am @@ -0,0 +1,40 @@ +lib_LTLIBRARIES = libmod_axis2.la +libmod_axis2_la_SOURCES = mod_axis2.c\ + apache2_stream.c\ + apache2_out_transport_info.c\ + apache2_worker.c + +AM_CFLAGS = -DLINUX=2 -D_REENTRANT -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -D_SVID_SOURCE -D_GNU_SOURCE + +libmod_axis2_la_LIBADD = $(LDFLAGS) \ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la \ + $(top_builddir)/src/core/engine/libaxis2_engine.la\ + $(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la\ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la\ + $(top_builddir)/axiom/src/parser/$(WRAPPER_DIR)/libaxis2_parser.la\ + -lpthread + +libmod_axis2_la_LDFLAGS = -version-info $(VERSION_NO) + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/transport/http \ + -I$(top_builddir)/src/core/description \ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/src/core/deployment \ + -I$(top_builddir)/axiom/include\ + -I$(top_builddir)/util/include\ + @APACHE2INC@ \ + @APRINC@ + +EXTRA_DIST=axis2_apache2_worker.h apache2_stream.h axis2_apache2_out_transport_info.h + + + + + + + + diff --git a/src/core/transport/http/server/apache2/apache2_out_transport_info.c b/src/core/transport/http/server/apache2/apache2_out_transport_info.c new file mode 100644 index 0000000..9deaa56 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_out_transport_info.c @@ -0,0 +1,191 @@ +/* + * 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. + */ + +#include "axis2_apache2_out_transport_info.h" +#include +#include +#include +#include + +typedef struct axis2_apache2_out_transport_info +{ + axis2_http_out_transport_info_t out_transport_info; + request_rec *request; + axis2_char_t *encoding; +} axis2_apache2_out_transport_info_t; + +#define AXIS2_INTF_TO_IMPL(out_transport_info) \ + ((axis2_apache2_out_transport_info_t *)(out_transport_info)) + +void AXIS2_CALL +axis2_apache2_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env) +{ + axis2_http_out_transport_info_t *transport_info_l = NULL; + + AXIS2_ENV_CHECK(env, void); + transport_info_l = (axis2_http_out_transport_info_t *)transport_info; + axis2_http_out_transport_info_free(transport_info_l, env); + return; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_free( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env) +{ + axis2_apache2_out_transport_info_t *info = NULL; + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + info->request = NULL; /* request doesn't belong to info */ + if(info->encoding) + { + AXIS2_FREE(env->allocator, info->encoding); + info->encoding = NULL; + } + + AXIS2_FREE(env->allocator, info); + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_content_type( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_apache2_out_transport_info_t *info = NULL; + + axis2_char_t *tmp1 = NULL; + axis2_char_t *tmp2 = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + if(info->encoding) + { + + tmp1 = axutil_stracat(env, content_type, ";charset="); + tmp2 = axutil_stracat(env, tmp1, info->encoding); + info->request->content_type = apr_pstrdup(info->request->pool, tmp2); + AXIS2_FREE(env->allocator, tmp1); + AXIS2_FREE(env->allocator, tmp2); + } + else + { + info->request->content_type = apr_pstrdup(info->request->pool, content_type); + } + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_char_encoding( + axis2_http_out_transport_info_t * info, + const axutil_env_t * env, + const axis2_char_t * encoding) +{ + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, encoding, AXIS2_FAILURE); + + if(info->encoding) + { + AXIS2_FREE(env->allocator, info->encoding); + } + info->encoding = axutil_strdup(env, encoding); + + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_cookie_header( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * cookie_header) +{ + axis2_apache2_out_transport_info_t *info = NULL; + + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, cookie_header, AXIS2_FAILURE); + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + apr_table_set(info->request->headers_out, AXIS2_HTTP_HEADER_SET_COOKIE, cookie_header); + return AXIS2_SUCCESS; +} + +axis2_status_t AXIS2_CALL +axis2_apache_out_transport_info_set_session( + axis2_http_out_transport_info_t * out_transport_info, + const axutil_env_t * env, + const axis2_char_t * session_id, + const axis2_char_t * session_value) +{ + axis2_apache2_out_transport_info_t *info = NULL; + axis2_status_t status = AXIS2_SUCCESS; + + AXIS2_ENV_CHECK(env, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, session_id, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, session_value, AXIS2_FAILURE); + info = AXIS2_INTF_TO_IMPL(out_transport_info); + + status = env->set_session_fn(info->request, session_id, session_value); + + return status; +} + +axis2_http_out_transport_info_t *AXIS2_CALL +axis2_apache2_out_transport_info_create( + const axutil_env_t * env, + request_rec * request) +{ + axis2_apache2_out_transport_info_t *info = NULL; + axis2_http_out_transport_info_t *out_transport_info = NULL; + + AXIS2_ENV_CHECK(env, NULL); + + info = (axis2_apache2_out_transport_info_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_apache2_out_transport_info_t)); + + if(!info) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + info->request = request; + info->encoding = NULL; + + out_transport_info = &(info->out_transport_info); + out_transport_info->encoding = NULL; + out_transport_info->response = NULL; + + axis2_http_out_transport_info_set_char_encoding_func(out_transport_info, env, + axis2_apache_out_transport_info_set_char_encoding); + axis2_http_out_transport_info_set_content_type_func(out_transport_info, env, + axis2_apache_out_transport_info_set_content_type); + axis2_http_out_transport_info_set_cookie_header_func(out_transport_info, env, + axis2_apache_out_transport_info_set_cookie_header); + axis2_http_out_transport_info_set_session_func(out_transport_info, env, + axis2_apache_out_transport_info_set_session); + + return out_transport_info; +} + + diff --git a/src/core/transport/http/server/apache2/apache2_stream.c b/src/core/transport/http/server/apache2/apache2_stream.c new file mode 100644 index 0000000..5e189a7 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_stream.c @@ -0,0 +1,292 @@ +/* + * 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. + */ + +#include +#include +#include "apache2_stream.h" +#include + +typedef struct apache2_stream_impl +{ + axutil_stream_t stream; + axutil_stream_type_t stream_type; + request_rec *request; +} apache2_stream_impl_t; + +#define AXIS2_INTF_TO_IMPL(stream) ((apache2_stream_impl_t *)(stream)) + +axutil_stream_type_t AXIS2_CALL +apache2_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env); + +int AXIS2_CALL apache2_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buffer, + size_t count); + +int AXIS2_CALL apache2_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count); + +static int AXIS2_CALL +apache2_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count); + +int AXIS2_CALL apache2_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env); + +static apr_size_t +apache2_ap_get_client_block( + request_rec *r, + char* buffer, + apr_size_t bufsiz); + +AXIS2_EXTERN axutil_stream_t *AXIS2_CALL +axutil_stream_create_apache2( + const axutil_env_t * env, + request_rec * request) +{ + apache2_stream_impl_t *stream_impl = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, request, NULL); + + stream_impl = (apache2_stream_impl_t *)AXIS2_MALLOC(env->allocator, + sizeof(apache2_stream_impl_t)); + + if(!stream_impl) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + + memset(&(stream_impl->stream), 0, sizeof(axutil_stream_t)); + + stream_impl->request = request; + stream_impl->stream_type = AXIS2_STREAM_MANAGED; + + axutil_stream_set_read(&(stream_impl->stream), env, apache2_stream_read); + axutil_stream_set_write(&(stream_impl->stream), env, apache2_stream_write); + axutil_stream_set_skip(&(stream_impl->stream), env, apache2_stream_skip); + + return &(stream_impl->stream); +} + +int AXIS2_CALL +apache2_stream_read( + axutil_stream_t * stream, + const axutil_env_t * env, + void *buffer, + size_t count) +{ + apache2_stream_impl_t *stream_impl = NULL; + size_t read = 0; + size_t len = 0; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + while(count - len > 0) + { + read = apache2_ap_get_client_block(stream_impl->request, (char *) buffer + len, + count - len); + if(read > 0) + { + len += read; + } + else + { + break; + } + } + + return (int)len; + /* We are sure that the difference lies within the int range */ +} + +int AXIS2_CALL +apache2_stream_write( + axutil_stream_t * stream, + const axutil_env_t * env, + const void *buf, + size_t count) +{ + apache2_stream_impl_t *stream_impl = NULL; + axis2_char_t *buffer = NULL; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, buf, AXIS2_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + buffer = (axis2_char_t *)buf; + if(count <= 0) + { + return (int)count; + /* We are sure that the difference lies within the int range */ + } + /* assume that buffer is not null terminated */ + return ap_rwrite(buffer, (int)count, stream_impl->request); + /* We are sure that the difference lies within the int range */ +} + +static int AXIS2_CALL +apache2_stream_skip( + axutil_stream_t * stream, + const axutil_env_t * env, + int count) +{ + apache2_stream_impl_t *stream_impl = NULL; + axis2_char_t *tmp_buffer = NULL; + apr_size_t len = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + stream_impl = AXIS2_INTF_TO_IMPL(stream); + + tmp_buffer = AXIS2_MALLOC(env->allocator, count * sizeof(axis2_char_t)); + if(tmp_buffer == NULL) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return -1; + } + len = apache2_ap_get_client_block(stream_impl->request, tmp_buffer, count); + AXIS2_FREE(env->allocator, tmp_buffer); + return (int)len; + +} + +int AXIS2_CALL +apache2_stream_get_char( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + int ret = -1; + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + + return ret; +} + +axutil_stream_type_t AXIS2_CALL +apache2_stream_get_type( + axutil_stream_t * stream, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + return AXIS2_INTF_TO_IMPL(stream)->stream_type; +} + +/* + * This is a re-write of get_client_block found in http_filters.c in httpd + * which does not work when dealing with compressed payloads (or any other input + * filters that could potentially return 0 bytes of filtered data and not be at + * the end of the stream). + * get_client_block is called in a loop to get the request message body. + * This is quite simple if the client includes a content-length + * (the normal case), but gets messy if the body is chunked. Note that + * r->remaining is used to maintain state across calls and that + * r->read_length is the total number of bytes given to the caller + * across all invocations. It is messy because we have to be careful not + * to read past the data provided by the client, since these reads block. + * Returns 0 on End-of-body, -1 on error or premature chunk end. + * + */ +static apr_size_t +apache2_ap_get_client_block( + request_rec *r, + char *buffer, + apr_size_t bufsiz) +{ + apr_status_t rv; + apr_bucket_brigade *bb; + int loop = 1; + apr_size_t origBufSize = bufsiz; + + if (r->remaining < 0 || (!r->read_chunked && r->remaining == 0)) { + return 0; + } + + bb = apr_brigade_create(r->pool, r->connection->bucket_alloc); + if (bb == NULL) { + r->connection->keepalive = AP_CONN_CLOSE; + return -1; + } + + /* we need to loop until the input filters (if any) give us data */ + while (loop) { + rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES, + APR_BLOCK_READ, bufsiz); + + /* We lose the failure code here. This is why ap_get_client_block should + * not be used. + */ + if (rv != APR_SUCCESS) { + /* if we actually fail here, we want to just return and + * stop trying to read data from the client. + */ + r->connection->keepalive = AP_CONN_CLOSE; + apr_brigade_destroy(bb); + return -1; + } + + /* If this fails, it means that a filter is written incorrectly and that + * it needs to learn how to properly handle APR_BLOCK_READ requests by + * returning data when requested. + */ + AP_DEBUG_ASSERT(!APR_BRIGADE_EMPTY(bb)); + + /* Check to see if EOS in the brigade. + * + * If so, we have to leave a nugget for the *next* ap_get_client_block + * call to return 0. + */ + if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { + if (r->read_chunked) { + r->remaining = -1; + } else { + r->remaining = 0; + } + } + + rv = apr_brigade_flatten(bb, buffer, &bufsiz); + if (rv != APR_SUCCESS) { + apr_brigade_destroy(bb); + return -1; + } + + /* XXX yank me? */ + r->read_length += bufsiz; + + /* it is possible that the entire bucket brigade is exhausted, but no data + * has been produced by the input filter (mod_deflate, for example).... + * in this scenario, we really need to keep looping + */ + if (bufsiz != 0 || r->remaining <= 0) { + loop = 0; + apr_brigade_destroy(bb); + } else { + if (bufsiz == 0) { + bufsiz = origBufSize; + } + } + + } + + return (long)bufsiz; +} diff --git a/src/core/transport/http/server/apache2/apache2_stream.h b/src/core/transport/http/server/apache2/apache2_stream.h new file mode 100644 index 0000000..abbea45 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_stream.h @@ -0,0 +1,46 @@ + +/* + * Copyright 2004,2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain count 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. + */ + +#ifndef APACHE2_STREAM_H +#define APACHE2_STREAM_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /** \brief Constructor for creating apche2 stream + * @return axutil_stream (apache2) + */ + AXIS2_EXTERN axutil_stream_t *AXIS2_CALL + axutil_stream_create_apache2( + const axutil_env_t * env, + request_rec * req); + + /** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APACHE2_STREAM_H */ diff --git a/src/core/transport/http/server/apache2/apache2_worker.c b/src/core/transport/http/server/apache2/apache2_worker.c new file mode 100644 index 0000000..12b05b2 --- /dev/null +++ b/src/core/transport/http/server/apache2/apache2_worker.c @@ -0,0 +1,1687 @@ +/* + * 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. + */ + +#include "axis2_apache2_worker.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "axis2_apache2_out_transport_info.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#define READ_SIZE 2048 + +static axis2_status_t +apache2_worker_send_mtom_message( + request_rec *request, + const axutil_env_t * env, + axutil_array_list_t *mime_parts, + axis2_char_t *mtom_sending_callback_name); + +static axis2_status_t +apache2_worker_send_attachment_using_file( + const axutil_env_t * env, + request_rec *request, + FILE *fp, + axis2_byte_t *buffer, + int buffer_size); + +static axis2_status_t +apache2_worker_send_attachment_using_callback( + const axutil_env_t * env, + request_rec *request, + axiom_mtom_sending_callback_t *callback, + void *handler, + void *user_param); + +static axutil_hash_t* +axis2_apache_worker_get_headers( + const axutil_env_t *env, + request_rec *request); + + +struct axis2_apache2_worker +{ + axis2_conf_ctx_t *conf_ctx; +}; + +AXIS2_EXTERN axis2_apache2_worker_t *AXIS2_CALL +axis2_apache2_worker_create( + const axutil_env_t * env, + axis2_char_t * repo_path) +{ + axis2_apache2_worker_t *apache2_worker = NULL; + axutil_hash_t* svc_map = NULL; + axis2_conf_t* conf = NULL; + axutil_hash_index_t *hi = NULL; + void* svc = NULL; + AXIS2_ENV_CHECK(env, NULL); + AXIS2_LOG_INFO(env->log, "[Axis2] Axis2 worker created"); + apache2_worker = (axis2_apache2_worker_t *)AXIS2_MALLOC(env->allocator, + sizeof(axis2_apache2_worker_t)); + + if(!apache2_worker) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + apache2_worker->conf_ctx = axis2_build_conf_ctx(env, repo_path); + + if(!apache2_worker->conf_ctx) + { + axis2_apache2_worker_free((axis2_apache2_worker_t *)apache2_worker, env); + return NULL; + } + + /* + * we have to load all the services. This is because, before the fork (in linux) + * we should have a full code segment. Otherwise, we can't share function pointers of services + * between processed. In fork, the code segment will be duplicated across processes + */ + conf = axis2_conf_ctx_get_conf(apache2_worker->conf_ctx, env); + if(!conf) + { + axis2_apache2_worker_free((axis2_apache2_worker_t *)apache2_worker, env); + return NULL; + } + + svc_map = axis2_conf_get_all_svcs(conf, env); + if(!svc_map) + { + axis2_apache2_worker_free((axis2_apache2_worker_t *)apache2_worker, env); + return NULL; + } + + for(hi = axutil_hash_first(svc_map, env); hi; hi = axutil_hash_next(env, hi)) + { + void *impl_class = NULL; + axis2_msg_recv_t *msg_recv = NULL; + axutil_hash_t *ops_hash = NULL; + + axutil_hash_this(hi, NULL, NULL, &svc); + if(!svc) + continue; + impl_class = axis2_svc_get_impl_class(svc, env); + if(impl_class) + continue; + ops_hash = axis2_svc_get_all_ops(svc, env); + if(ops_hash) + { + axutil_hash_index_t *op_hi = NULL; + void *op = NULL; + op_hi = axutil_hash_first(ops_hash, env); + if(op_hi) + { + axutil_hash_this(op_hi, NULL, NULL, &op); + if(op) + { + msg_recv = axis2_op_get_msg_recv(op, env); + if(msg_recv) + { + axis2_msg_recv_set_conf_ctx(msg_recv, env, apache2_worker->conf_ctx); + axis2_msg_recv_load_and_init_svc(msg_recv, env, svc); + } + } + } + + } + } + + AXIS2_LOG_INFO(env->log, "[Axis2] Axis2 worker created"); + + return apache2_worker; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_apache2_worker_free( + axis2_apache2_worker_t * apache2_worker, + const axutil_env_t * env) +{ + AXIS2_ENV_CHECK(env, void); + + if(apache2_worker->conf_ctx) + { + axis2_conf_ctx_free(apache2_worker->conf_ctx, env); + apache2_worker->conf_ctx = NULL; + } + + AXIS2_FREE(env->allocator, apache2_worker); + + return; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_apache2_worker_process_request( + axis2_apache2_worker_t * apache2_worker, + const axutil_env_t * env, + request_rec * request) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_msg_ctx_t *msg_ctx = NULL; + axutil_stream_t *request_body = NULL; + axutil_stream_t *out_stream = NULL; + axis2_transport_out_desc_t *out_desc = NULL; + axis2_transport_in_desc_t *in_desc = NULL; + axis2_char_t *http_version = NULL; + axutil_string_t *soap_action = NULL; + axis2_char_t *soap_action_header_txt = NULL; + axis2_bool_t processed = AXIS2_FALSE; + int content_length = -1; + axis2_char_t *url_external_form = NULL; + axis2_char_t *body_string = NULL; + unsigned int body_string_len = 0; + int send_status = DECLINED; + axis2_char_t *content_type = NULL; + axis2_http_out_transport_info_t *apache2_out_transport_info = NULL; + axis2_char_t *ctx_uuid = NULL; + axis2_op_ctx_t *op_ctx = NULL; + axis2_char_t *peer_ip = NULL; + axutil_property_t *peer_property = NULL; + axutil_url_t *request_url = NULL; + axis2_char_t *accept_header_value = NULL; + axis2_char_t *accept_charset_header_value = NULL; + axis2_char_t *accept_language_header_value = NULL; + axis2_char_t *content_language_header_value = NULL; + axis2_bool_t do_mtom = AXIS2_FALSE; + axutil_array_list_t *mime_parts = NULL; + axutil_param_t *callback_name_param = NULL; + axis2_char_t *mtom_sending_callback_name = NULL; + axis2_char_t *cookie = NULL; + axis2_char_t *header_value = NULL; + axis2_status_t status = AXIS2_FAILURE; + axutil_hash_t *headers = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, request, AXIS2_CRITICAL_FAILURE); + + conf_ctx = apache2_worker->conf_ctx; + + if(!conf_ctx) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_CONFIGURATION_CONTEXT, AXIS2_FAILURE); + return AXIS2_CRITICAL_FAILURE; + } + content_length = (int)request->remaining; + /* We are sure that the difference lies within the int range */ + http_version = request->protocol; + + request_url = axutil_url_create(env, "http", request->hostname, request->parsed_uri.port, + request->unparsed_uri); + if(request_url) + { + url_external_form = axutil_url_to_external_form(request_url, env); + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, url_external_form); + axutil_url_free(request_url, env); + request_url = NULL; + } + else + { + send_status = OK; + request->status = HTTP_BAD_REQUEST; + return send_status; + } + + content_type = (axis2_char_t *)apr_table_get(request->headers_in, + AXIS2_HTTP_HEADER_CONTENT_TYPE); + if(!content_type) + { + content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN; + } + request->content_type = content_type; + + out_desc = axis2_conf_get_transport_out(axis2_conf_ctx_get_conf(apache2_worker->conf_ctx, env), + env, AXIS2_TRANSPORT_ENUM_HTTP); + in_desc = axis2_conf_get_transport_in(axis2_conf_ctx_get_conf(apache2_worker->conf_ctx, env), + env, AXIS2_TRANSPORT_ENUM_HTTP); + { + axis2_transport_receiver_t *receiver = NULL; + receiver = axis2_transport_in_desc_get_recv(in_desc, env); + if(receiver) + axis2_transport_receiver_set_server_ip(receiver, env, request->connection->local_ip); + } + + msg_ctx = axis2_msg_ctx_create(env, conf_ctx, in_desc, out_desc); + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + + cookie = (axis2_char_t *)apr_table_get(request->headers_in, + AXIS2_HTTP_HEADER_COOKIE); + if(cookie) + { + char *session_str = NULL; + axis2_char_t *session_id = NULL; + + session_id = axis2_http_transport_utils_get_session_id_from_cookie(env, cookie); + if(session_id) + session_str = env->get_session_fn((void *) request, session_id); + if(session_str) + axis2_http_transport_utils_set_session(env, msg_ctx, session_str); + } + + if(request->read_chunked == AXIS2_TRUE && 0 == content_length) + { + content_length = -1; + request->chunked = 1; + } + if(!http_version) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_HTTP_VERSION, AXIS2_FAILURE); + return AXIS2_CRITICAL_FAILURE; + } + out_stream = axutil_stream_create_basic(env); + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Client HTTP version %s", http_version); + + peer_ip = request->connection->remote_ip; + + if(peer_ip) + { + peer_property = axutil_property_create(env); + axutil_property_set_value(peer_property, env, axutil_strdup(env, peer_ip)); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_SVR_PEER_IP_ADDR, peer_property); + } + + axis2_msg_ctx_set_transport_out_stream(msg_ctx, env, out_stream); + + ctx_uuid = axutil_uuid_gen(env); + if(ctx_uuid) + { + axutil_string_t *uuid_str = axutil_string_create_assume_ownership(env, &ctx_uuid); + axis2_msg_ctx_set_svc_grp_ctx_id(msg_ctx, env, uuid_str); + axutil_string_free(uuid_str, env); + } + + apache2_out_transport_info = axis2_apache2_out_transport_info_create(env, request); + axis2_msg_ctx_set_out_transport_info(msg_ctx, env, &(apache2_out_transport_info->out_transport)); + + accept_header_value = (axis2_char_t *)apr_table_get(request->headers_in, + AXIS2_HTTP_HEADER_ACCEPT); + if(accept_header_value) + { + axutil_array_list_t *accept_header_field_list = NULL; + axutil_array_list_t *accept_record_list = NULL; + accept_header_field_list = axutil_tokenize(env, accept_header_value, ','); + if(accept_header_field_list && axutil_array_list_size(accept_header_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_header_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_record_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_header_field_list, env, 0); + } + while(token); + } + if(accept_record_list && axutil_array_list_size(accept_record_list, env) > 0) + { + axis2_msg_ctx_set_http_accept_record_list(msg_ctx, env, accept_record_list); + } + } + + accept_charset_header_value = (axis2_char_t *)apr_table_get(request->headers_in, + AXIS2_HTTP_HEADER_ACCEPT_CHARSET); + if(accept_charset_header_value) + { + axutil_array_list_t *accept_charset_header_field_list = NULL; + axutil_array_list_t *accept_charset_record_list = NULL; + accept_charset_header_field_list = axutil_tokenize(env, accept_charset_header_value, ','); + if(accept_charset_header_field_list && axutil_array_list_size( + accept_charset_header_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_charset_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_charset_header_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_charset_record_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_charset_header_field_list, + env, 0); + } + while(token); + } + if(accept_charset_record_list && axutil_array_list_size(accept_charset_record_list, env) + > 0) + { + axis2_msg_ctx_set_http_accept_charset_record_list(msg_ctx, env, + accept_charset_record_list); + } + } + + accept_language_header_value = (axis2_char_t *)apr_table_get(request->headers_in, + AXIS2_HTTP_HEADER_ACCEPT_LANGUAGE); + if(accept_language_header_value) + { + axutil_array_list_t *accept_language_header_field_list = NULL; + axutil_array_list_t *accept_language_record_list = NULL; + accept_language_header_field_list = axutil_tokenize(env, accept_language_header_value, ','); + if(accept_language_header_field_list && axutil_array_list_size( + accept_language_header_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_language_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_language_header_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_language_record_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_language_header_field_list, + env, 0); + } + while(token); + } + if(accept_language_record_list && axutil_array_list_size(accept_language_record_list, env) + > 0) + { + axis2_msg_ctx_set_http_accept_language_record_list(msg_ctx, env, + accept_language_record_list); + } + } + + soap_action_header_txt = (axis2_char_t *)apr_table_get(request->headers_in, + AXIS2_HTTP_HEADER_SOAP_ACTION); + + if(soap_action_header_txt) + { + soap_action = axutil_string_create(env, soap_action_header_txt); + } + + headers = axis2_apache_worker_get_headers(env, request); + axis2_msg_ctx_set_transport_headers(msg_ctx, env, headers); + + request_body = axutil_stream_create_apache2(env, request); + if(!request_body) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occured in" + " creating input stream."); + return AXIS2_CRITICAL_FAILURE; + } + if(M_GET == request->method_number || M_DELETE == request->method_number) + { + if(M_DELETE == request->method_number) + { + processed = axis2_http_transport_utils_process_http_delete_request(env, msg_ctx, + request_body, out_stream, content_type, soap_action, url_external_form, conf_ctx, + axis2_http_transport_utils_get_request_params(env, + (axis2_char_t *)url_external_form)); + } + else if(request->header_only) + { + processed = axis2_http_transport_utils_process_http_head_request(env, msg_ctx, + request_body, out_stream, content_type, soap_action, url_external_form, conf_ctx, + axis2_http_transport_utils_get_request_params(env, + (axis2_char_t *)url_external_form)); + } + else + { + processed = axis2_http_transport_utils_process_http_get_request(env, msg_ctx, + request_body, out_stream, content_type, soap_action, url_external_form, conf_ctx, + axis2_http_transport_utils_get_request_params(env, + (axis2_char_t *)url_external_form)); + } + if(AXIS2_FALSE == processed) + { + axis2_char_t *wsdl = NULL; + axis2_bool_t is_services_path = AXIS2_FALSE; + if(M_DELETE != request->method_number) + { + axis2_char_t *temp = NULL; + temp = strstr(url_external_form, AXIS2_REQUEST_URL_PREFIX); + if(temp) + { + temp += strlen(AXIS2_REQUEST_URL_PREFIX); + if(*temp == '/') + { + temp++; + } + if(!*temp || *temp == '?' || *temp == '#') + { + is_services_path = AXIS2_TRUE; + } + } + } + wsdl = strstr(url_external_form, AXIS2_REQUEST_WSDL); + if(is_services_path) + { + body_string = axis2_http_transport_utils_get_services_html(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + } + else if(M_DELETE != request->method_number && wsdl) + { + body_string = axis2_http_transport_utils_get_services_static_wsdl(env, conf_ctx, + (axis2_char_t *)url_external_form); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML; + + } + else if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND) + { + axutil_array_list_t *method_list = NULL; + int size = 0; + method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env); + size = axutil_array_list_size(method_list, env); + if(method_list && size) + { + axis2_char_t *method_list_str = NULL; + axis2_char_t *temp; + int i = 0; + method_list_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 29); + temp = method_list_str; + request->allowed_methods->method_mask = 0; + for(i = 0; i < size; i++) + { + if(i) + { + sprintf(temp, ", "); + temp += 2; + } + sprintf(temp, "%s", (axis2_char_t *)axutil_array_list_get(method_list, env, + i)); + temp += strlen(temp); + /* Conditions below is to assist down-stream modules */ + if(!strcasecmp(AXIS2_HTTP_PUT, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_PUT; + } + else if(!strcasecmp(AXIS2_HTTP_POST, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_POST; + } + else if(!strcasecmp(AXIS2_HTTP_GET, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET; + } + else if(!strcasecmp(AXIS2_HTTP_HEAD, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + /* Apache Can't differentiate between HEAD and GET */ + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET; + } + else if(!strcasecmp(AXIS2_HTTP_DELETE, + (axis2_char_t *)axutil_array_list_get(method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_DELETE; + } + } + *temp = '\0'; + apr_table_set(request->err_headers_out, AXIS2_HTTP_HEADER_ALLOW, + method_list_str); + AXIS2_FREE(env->allocator, method_list_str); + body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx); + request->status = HTTP_METHOD_NOT_ALLOWED; + } + else + { + body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx); + request->status = HTTP_NOT_FOUND; + } + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_bad_request(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_BAD_REQUEST; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_request_timeout(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_REQUEST_TIME_OUT; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_conflict(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_CONFLICT; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_GONE_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_gone(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_GONE; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_precondition_failed(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_PRECONDITION_FAILED; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_request_entity_too_large(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_REQUEST_ENTITY_TOO_LARGE; + } + else if(axis2_msg_ctx_get_status_code(msg_ctx, env) + == AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL) + { + body_string = axis2_http_transport_utils_get_service_unavailable(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_SERVICE_UNAVAILABLE; + } + else + { + body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_INTERNAL_SERVER_ERROR; + } + + if(body_string) + { + body_string_len = axutil_strlen(body_string); + } + send_status = OK; + } + } + else if(M_POST == request->method_number || M_PUT == request->method_number) + { + /*axis2_status_t status = AXIS2_FAILURE;*/ + if(M_POST == request->method_number) + { + status = axis2_http_transport_utils_process_http_post_request(env, msg_ctx, + request_body, out_stream, content_type, content_length, soap_action, + (axis2_char_t *)url_external_form); + } + else + { + status = axis2_http_transport_utils_process_http_put_request(env, msg_ctx, + request_body, out_stream, content_type, content_length, soap_action, + (axis2_char_t *)url_external_form); + } + if(AXIS2_FAILURE == status && (M_PUT == request->method_number + || axis2_msg_ctx_get_doing_rest(msg_ctx, env))) + { + if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND) + { + axutil_array_list_t *method_list = NULL; + int size = 0; + method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env); + size = axutil_array_list_size(method_list, env); + if(method_list && size) + { + axis2_char_t *method_list_str = NULL; + axis2_char_t *temp; + int i = 0; + method_list_str = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * 29); + temp = method_list_str; + request->allowed_methods->method_mask = 0; + for(i = 0; i < size; i++) + { + if(i) + { + sprintf(temp, ", "); + temp += 2; + } + sprintf(temp, "%s", (axis2_char_t *)axutil_array_list_get(method_list, env, + i)); + temp += strlen(temp); + /* Conditions below is to assist down-stream modules */ + if(!strcasecmp(AXIS2_HTTP_PUT, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_PUT; + } + else if(!strcasecmp(AXIS2_HTTP_POST, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_POST; + } + else if(!strcasecmp(AXIS2_HTTP_GET, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET; + } + else if(!strcasecmp(AXIS2_HTTP_HEAD, (axis2_char_t *)axutil_array_list_get( + method_list, env, i))) + { + /* Apache Can't differentiate between HEAD and GET */ + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_GET; + } + else if(!strcasecmp(AXIS2_HTTP_DELETE, + (axis2_char_t *)axutil_array_list_get(method_list, env, i))) + { + request->allowed_methods->method_mask |= AP_METHOD_BIT << M_DELETE; + } + } + *temp = '\0'; + apr_table_set(request->err_headers_out, AXIS2_HTTP_HEADER_ALLOW, + method_list_str); + AXIS2_FREE(env->allocator, method_list_str); + body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx); + request->status = HTTP_METHOD_NOT_ALLOWED; + } + else + { + body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx); + request->status = HTTP_NOT_FOUND; + } + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + } + else + { + body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + request->status = HTTP_INTERNAL_SERVER_ERROR; + } + + if(body_string) + { + body_string_len = axutil_strlen(body_string); + } + send_status = OK; + } + else if(status == AXIS2_FAILURE) + { + axis2_msg_ctx_t *fault_ctx = NULL; + axis2_char_t *fault_code = NULL; + axis2_engine_t *engine = axis2_engine_create(env, conf_ctx); + if(!engine) + { + /* Critical error, cannot proceed, Apache will send default + document for 500 + */ + return AXIS2_CRITICAL_FAILURE; + } + if(axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX ":" + AXIOM_SOAP11_FAULT_CODE_SENDER; + } + else + { + fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX ":" + AXIOM_SOAP12_SOAP_FAULT_VALUE_SENDER; + } + fault_ctx = axis2_engine_create_fault_msg_ctx(engine, env, msg_ctx, + fault_code, + axutil_error_get_message + (env->error)); + axis2_engine_send_fault(engine, env, fault_ctx); + if (out_stream) + { + body_string = axutil_stream_get_buffer(out_stream, env); + body_string_len = axutil_stream_get_len(out_stream, env); + } + + /* In case of a SOAP Fault, we have to set the status to 500, + but still return OK because the module has handled the error + */ + send_status = OK; + request->status = HTTP_INTERNAL_SERVER_ERROR; + } + } + else + { + body_string = + axis2_http_transport_utils_get_not_implemented(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + + if (body_string) + { + body_string_len = axutil_strlen(body_string); + } + send_status = OK; + request->status = HTTP_NOT_IMPLEMENTED; + } + + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + + if (op_ctx) + { + axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + if (out_msg_ctx) + { + content_language_header_value = axis2_msg_ctx_get_content_language(out_msg_ctx, env); + } + } + + if (send_status == DECLINED) + { + axis2_bool_t do_rest = AXIS2_FALSE; + if (M_POST != request->method_number || + axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + do_rest = AXIS2_TRUE; + } + if ((accept_header_value || accept_charset_header_value || + accept_language_header_value) && do_rest) + { + axis2_char_t *content_type_header_value = NULL; + axis2_char_t *temp = NULL; + axis2_char_t *language_header_value = NULL; + + content_type_header_value = (axis2_char_t *) request->content_type; + language_header_value = content_language_header_value; + if (content_type_header_value) + { + temp = axutil_strdup(env, content_type_header_value); + } + if (temp) + { + axis2_char_t *content_type = NULL; + axis2_char_t *char_set = NULL; + axis2_char_t *temp2 = NULL; + + temp2 = strchr(temp, ';'); + if (temp2) + { + *temp2 = '\0'; + temp2++; + char_set = axutil_strcasestr(temp2, AXIS2_HTTP_CHAR_SET_ENCODING); + } + if (char_set) + { + char_set = axutil_strltrim(env, char_set, " \t="); + } + if (char_set) + { + temp2 = strchr(char_set, ';'); + } + if (temp2) + { + *temp2 = '\0'; + } + content_type = axutil_strtrim(env, temp, NULL); + + if (temp) + { + AXIS2_FREE(env->allocator, temp); + temp = NULL; + } + if (content_type && accept_header_value && + !axutil_strcasestr(accept_header_value, content_type)) + { + temp2 = strchr(content_type, '/'); + if (temp2) + { + *temp2 = '\0'; + temp = AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * ((int)strlen(content_type) + 3)); + if (!temp) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return AXIS2_FALSE; + } + sprintf(temp, "%s/*", content_type); + if (!axutil_strcasestr(accept_header_value, temp) && + !strstr(accept_header_value, AXIS2_HTTP_HEADER_ACCEPT_ALL)) + { + body_string = + axis2_http_transport_utils_get_not_acceptable(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + + if (body_string) + { + body_string_len = axutil_strlen(body_string); + } + send_status = OK; + request->status = HTTP_NOT_ACCEPTABLE; + } + AXIS2_FREE(env->allocator, temp); + } + } + if (content_type) + { + AXIS2_FREE(env->allocator, content_type); + } + if (char_set && accept_charset_header_value && + !axutil_strcasestr(accept_charset_header_value, char_set)) + { + body_string = + axis2_http_transport_utils_get_not_acceptable(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + + if (body_string) + { + body_string_len = axutil_strlen(body_string); + } + send_status = OK; + request->status = HTTP_NOT_ACCEPTABLE; + } + if (char_set) + { + AXIS2_FREE(env->allocator, char_set); + } + } + if (language_header_value) + { + if (accept_language_header_value && + !axutil_strcasestr(accept_language_header_value, language_header_value)) + { + body_string = + axis2_http_transport_utils_get_not_acceptable(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + + if (body_string) + { + body_string_len = axutil_strlen(body_string); + } + send_status = OK; + request->status = HTTP_NOT_ACCEPTABLE; + } + } + } + } + + header_value = axis2_http_transport_utils_get_session(env, msg_ctx); + if(header_value) + { + axis2_http_out_transport_info_t *out_info = NULL; + out_info = (axis2_http_out_transport_info_t *)axis2_msg_ctx_get_out_transport_info(msg_ctx, env); + AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_COOKIE_HEADER(out_info, env, header_value); + } + if (send_status == DECLINED) + { + axis2_bool_t do_rest = AXIS2_FALSE; + if (M_POST != request->method_number || + axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + do_rest = AXIS2_TRUE; + } + if (op_ctx && axis2_op_ctx_get_response_written(op_ctx, env)) + { + if (do_rest) + { + axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + if (in_msg_ctx) + { + /* TODO: Add necessary handling */ + } + if (out_msg_ctx) + { + int size = 0; + axutil_array_list_t *output_header_list = NULL; + output_header_list = axis2_msg_ctx_get_http_output_headers(out_msg_ctx, env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, env); + } + while (size) + { + axis2_http_header_t *output_header = NULL; + size--; + output_header = (axis2_http_header_t *) + axutil_array_list_get(output_header_list, env, size); + apr_table_set(request->err_headers_out, + axis2_http_header_get_name(output_header, env), + axis2_http_header_get_value(output_header, env)); + } + if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL: + request->status = HTTP_CONTINUE; + break; + case AXIS2_HTTP_RESPONSE_ACK_CODE_VAL: + request->status = HTTP_ACCEPTED; + break; + case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL: + request->status = HTTP_MULTIPLE_CHOICES; + break; + case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL: + request->status = HTTP_MOVED_PERMANENTLY; + break; + case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL: + request->status = HTTP_SEE_OTHER; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + request->status = HTTP_NOT_MODIFIED; + break; + case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL: + request->status = HTTP_TEMPORARY_REDIRECT; + break; + case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL: + request->status = HTTP_BAD_REQUEST; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL: + request->status = HTTP_REQUEST_TIME_OUT; + break; + case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL: + request->status = HTTP_CONFLICT; + break; + case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL: + request->status = HTTP_GONE; + break; + case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL: + request->status = HTTP_PRECONDITION_FAILED; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL: + request->status = HTTP_REQUEST_ENTITY_TOO_LARGE; + break; + case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL: + request->status = HTTP_SERVICE_UNAVAILABLE; + break; + default: + request->status = HTTP_OK; + break; + } + send_status = DONE; + } + } + } + if (send_status == DECLINED) + { + send_status = OK; + if (out_stream) + { + body_string = axutil_stream_get_buffer(out_stream, env); + body_string_len = axutil_stream_get_len(out_stream, env); + } + } + } + else if (op_ctx) + { + if (do_rest) + { + axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + if (in_msg_ctx) + { + /* TODO: Add necessary handling */ + } + if (out_msg_ctx) + { + int size = 0; + axutil_array_list_t *output_header_list = NULL; + output_header_list = axis2_msg_ctx_get_http_output_headers(out_msg_ctx, env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, env); + } + while (size) + { + axis2_http_header_t *output_header = NULL; + size--; + output_header = (axis2_http_header_t *) + axutil_array_list_get(output_header_list, env, size); + apr_table_set(request->err_headers_out, + axis2_http_header_get_name(output_header, env), + axis2_http_header_get_value(output_header, env)); + } + if (axis2_msg_ctx_get_no_content(out_msg_ctx, env)) + { + if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_RESET_CONTENT_CODE_VAL: + request->status = HTTP_RESET_CONTENT; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + request->status = HTTP_NOT_MODIFIED; + break; + default: + request->status = HTTP_NO_CONTENT; + break; + } + } + else + { + request->status = HTTP_NO_CONTENT; + } + send_status = DONE; + } + else if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL: + request->status = HTTP_CONTINUE; + break; + case AXIS2_HTTP_RESPONSE_OK_CODE_VAL: + request->status = HTTP_OK; + break; + case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL: + request->status = HTTP_MULTIPLE_CHOICES; + break; + case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL: + request->status = HTTP_MOVED_PERMANENTLY; + break; + case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL: + request->status = HTTP_SEE_OTHER; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + request->status = HTTP_NOT_MODIFIED; + break; + case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL: + request->status = HTTP_TEMPORARY_REDIRECT; + break; + case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL: + request->status = HTTP_BAD_REQUEST; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL: + request->status = HTTP_REQUEST_TIME_OUT; + break; + case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL: + request->status = HTTP_CONFLICT; + break; + case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL: + request->status = HTTP_GONE; + break; + case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL: + request->status = HTTP_PRECONDITION_FAILED; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL: + request->status = HTTP_REQUEST_ENTITY_TOO_LARGE; + break; + case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL: + request->status = HTTP_SERVICE_UNAVAILABLE; + break; + default: + request->status = HTTP_ACCEPTED; + break; + } + send_status = DONE; + } + } + } + if (send_status == DECLINED) + { + if (msg_ctx) + { + int size = 0; + int status_code; + axutil_array_list_t *output_header_list = NULL; + output_header_list = axis2_msg_ctx_get_http_output_headers(msg_ctx, env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, env); + } + while (size) + { + axis2_http_header_t *output_header = NULL; + size--; + output_header = (axis2_http_header_t *) + axutil_array_list_get(output_header_list, env, size); + apr_table_set(request->err_headers_out, + axis2_http_header_get_name(output_header, env), + axis2_http_header_get_value(output_header, env)); + } + + status_code = axis2_msg_ctx_get_status_code(msg_ctx, env); + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL: + request->status = HTTP_CONTINUE; + break; + case AXIS2_HTTP_RESPONSE_OK_CODE_VAL: + request->status = HTTP_OK; + break; + case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL: + request->status = HTTP_MULTIPLE_CHOICES; + break; + case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL: + request->status = HTTP_MOVED_PERMANENTLY; + break; + case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL: + request->status = HTTP_SEE_OTHER; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + request->status = HTTP_NOT_MODIFIED; + break; + case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL: + request->status = HTTP_TEMPORARY_REDIRECT; + break; + case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL: + request->status = HTTP_BAD_REQUEST; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL: + request->status = HTTP_REQUEST_TIME_OUT; + break; + case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL: + request->status = HTTP_CONFLICT; + break; + case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL: + request->status = HTTP_GONE; + break; + case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL: + request->status = HTTP_PRECONDITION_FAILED; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL: + request->status = HTTP_REQUEST_ENTITY_TOO_LARGE; + break; + case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL: + request->status = HTTP_SERVICE_UNAVAILABLE; + break; + case AXIS2_HTTP_RESPONSE_FORBIDDEN_CODE_VAL: + request->status = HTTP_FORBIDDEN; + break; + case AXIS2_HTTP_RESPONSE_HTTP_UNAUTHORIZED_CODE_VAL: + request->status = HTTP_UNAUTHORIZED; + break; + default: + request->status = HTTP_ACCEPTED; + break; + } + + out_stream = axis2_msg_ctx_get_transport_out_stream(msg_ctx, env); + if (out_stream) + { + body_string = axutil_stream_get_buffer(out_stream, env); + body_string_len = axutil_stream_get_len(out_stream, env); + } + send_status = DONE; + } + else + { + request->status = HTTP_ACCEPTED; + send_status = DONE; + } + } + } + else + { + send_status = DONE; + request->status = HTTP_ACCEPTED; + } + } + + if (content_language_header_value) + { + apr_table_set(request->err_headers_out, AXIS2_HTTP_HEADER_CONTENT_LANGUAGE, + content_language_header_value); + } + + if (op_ctx) + { + axis2_msg_ctx_t *out_msg_ctx = NULL, + *in_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + axis2_char_t *msg_id = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + in_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN]; + + /* In mtom case we send the attachment differently */ + + /* status = AXIS2_FAILURE means fault scenario. We are not + * doing MTOM for fault cases. */ + + if(status != AXIS2_FAILURE) + { + do_mtom = axis2_msg_ctx_get_doing_mtom(out_msg_ctx, env); + if(do_mtom) + { + mime_parts = axis2_msg_ctx_get_mime_parts(out_msg_ctx, env); + if(!mime_parts) + { + return AXIS2_FAILURE; + } + callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env , + AXIS2_MTOM_SENDING_CALLBACK); + if(callback_name_param) + { + mtom_sending_callback_name = + (axis2_char_t *) axutil_param_get_value (callback_name_param, env); + } + } + } + + if (out_msg_ctx) + { + axis2_msg_ctx_free(out_msg_ctx, env); + out_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT] = NULL; + } + + if (in_msg_ctx) + { + msg_id = + axutil_strdup(env, axis2_msg_ctx_get_msg_id(in_msg_ctx, env)); + conf_ctx = axis2_msg_ctx_get_conf_ctx(in_msg_ctx, env); + axis2_msg_ctx_reset_out_transport_info(in_msg_ctx, env); + axis2_msg_ctx_free(in_msg_ctx, env); + in_msg_ctx = NULL; + msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_IN] = NULL; + } + + if (!axis2_op_ctx_is_in_use(op_ctx, env)) + { + axis2_op_ctx_destroy_mutex(op_ctx, env); + if (conf_ctx && msg_id) + { + axis2_conf_ctx_register_op_ctx(conf_ctx, env, msg_id, NULL); + AXIS2_FREE(env->allocator, msg_id); + } + axis2_op_ctx_free(op_ctx, env); + } + + } /* Done freeing message contexts */ + + /* We send the message in parts when doing MTOM */ + + if(do_mtom) + { + axis2_status_t mtom_status = AXIS2_FAILURE; + + if(!mtom_sending_callback_name) + { + /* If the callback name is not there, then we will check whether there + * is any mime_parts which has type callback. If we found then no point + * of continuing we should return a failure */ + + if(!mtom_sending_callback_name) + { + if(axis2_http_transport_utils_is_callback_required( + env, mime_parts)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Sender callback not specified"); + return AXIS2_FAILURE; + } + } + } + + mtom_status = apache2_worker_send_mtom_message(request, env, mime_parts, + mtom_sending_callback_name); + if(mtom_status == AXIS2_SUCCESS) + { + send_status = DONE; + } + else + { + send_status = DECLINED; + } + + axis2_http_transport_utils_destroy_mime_parts(mime_parts, env); + mime_parts = NULL; + } + + else if (body_string) + { + ap_rwrite(body_string, body_string_len, request); + body_string = NULL; + } + + if (request_body) + { + axutil_stream_free(request_body, env); + request_body = NULL; + } + + axutil_string_free(soap_action, env); + + msg_ctx = NULL; + return send_status; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_apache2_worker_get_bytes( + const axutil_env_t * env, + axutil_stream_t * stream) +{ + + axutil_stream_t *tmp_stream = NULL; + int return_size = -1; + axis2_char_t *buffer = NULL; + axis2_bool_t loop_status = AXIS2_TRUE; + + AXIS2_ENV_CHECK(env, NULL); + AXIS2_PARAM_CHECK(env->error, stream, NULL); + + tmp_stream = axutil_stream_create_basic(env); + while(loop_status) + { + int read = 0; + int write = 0; + + char buf[READ_SIZE]; + read = axutil_stream_read(stream, env, buf, READ_SIZE); + if(read < 0) + { + break; + } + write = axutil_stream_write(tmp_stream, env, buf, read); + if(read < (READ_SIZE - 1)) + { + break; + } + } + return_size = axutil_stream_get_len(tmp_stream, env); + + if(return_size > 0) + { + buffer = (char *)AXIS2_MALLOC(env->allocator, sizeof(char) * (return_size + 2)); + return_size = axutil_stream_read(tmp_stream, env, buffer, return_size + 1); + buffer[return_size + 1] = '\0'; + } + axutil_stream_free(tmp_stream, env); + return buffer; +} + +static axis2_status_t +apache2_worker_send_mtom_message( + request_rec *request, + const axutil_env_t * env, + axutil_array_list_t *mime_parts, + axis2_char_t *mtom_sending_callback_name) +{ + int i = 0; + axiom_mime_part_t *mime_part = NULL; + axis2_status_t status = AXIS2_SUCCESS; + /*int written = 0;*/ + int len = 0; + + if(mime_parts) + { + for(i = 0; i < axutil_array_list_size(mime_parts, env); i++) + { + mime_part = (axiom_mime_part_t *)axutil_array_list_get(mime_parts, env, i); + if((mime_part->type) == AXIOM_MIME_PART_BUFFER) + { + len = 0; + len = ap_rwrite(mime_part->part, (int)mime_part->part_size, request); + ap_rflush(request); + if(len == -1) + { + status = AXIS2_FAILURE; + break; + } + } + else if((mime_part->type) == AXIOM_MIME_PART_FILE) + { + FILE *f = NULL; + axis2_byte_t *output_buffer = NULL; + int output_buffer_size = 0; + + f = fopen(mime_part->file_name, "rb"); + if(!f) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for reading", + mime_part->file_name); + return AXIS2_FAILURE; + } + if(mime_part->part_size > AXIS2_MTOM_OUTPUT_BUFFER_SIZE) + { + output_buffer_size = AXIS2_MTOM_OUTPUT_BUFFER_SIZE; + } + else + { + output_buffer_size = (int)mime_part->part_size; + } + + output_buffer = AXIS2_MALLOC(env->allocator, (output_buffer_size + 1) + * sizeof(axis2_char_t)); + + status = apache2_worker_send_attachment_using_file(env, request, f, output_buffer, + output_buffer_size); + if(status == AXIS2_FAILURE) + { + return status; + } + } + else if((mime_part->type) == AXIOM_MIME_PART_CALLBACK) + { + void *handler = NULL; + axiom_mtom_sending_callback_t *callback = NULL; + + handler = axis2_http_transport_utils_initiate_callback(env, + mtom_sending_callback_name, mime_part->user_param, &callback); + + if(handler) + { + status = apache2_worker_send_attachment_using_callback(env, request, callback, + handler, mime_part->user_param); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "MTOM Sending Callback loading failed"); + status = AXIS2_FAILURE; + } + if(callback) + { + axutil_param_t *param = NULL; + + param = callback->param; + + AXIOM_MTOM_SENDING_CALLBACK_FREE(callback, env); + callback = NULL; + + if(param) + { + axutil_param_free(param, env); + param = NULL; + } + + } + + if(status == AXIS2_FAILURE) + { + return status; + } + } + else + { + return AXIS2_FAILURE; + } + if(status == AXIS2_FAILURE) + { + break; + } + } + return status; + } + else + { + return AXIS2_FAILURE; + } +} + +static axis2_status_t +apache2_worker_send_attachment_using_file( + const axutil_env_t * env, + request_rec *request, + FILE *fp, + axis2_byte_t *buffer, + int buffer_size) +{ + + int count = 0; + int len = 0; + /*int written = 0;*/ + axis2_status_t status = AXIS2_SUCCESS; + + do + { + count = (int)fread(buffer, 1, buffer_size + 1, fp); + if(ferror(fp)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in reading file containg the attachment"); + if(buffer) + { + AXIS2_FREE(env->allocator, buffer); + buffer = NULL; + } + fclose(fp); + return AXIS2_FAILURE; + } + + if(count > 0) + { + len = 0; + len = ap_rwrite(buffer, count, request); + ap_rflush(request); + if(len == -1) + { + status = AXIS2_FAILURE; + break; + } + } + else + { + if(buffer) + { + AXIS2_FREE(env->allocator, buffer); + buffer = NULL; + } + fclose(fp); + return AXIS2_FAILURE; + } + memset(buffer, 0, buffer_size); + if(status == AXIS2_FAILURE) + { + if(buffer) + { + AXIS2_FREE(env->allocator, buffer); + buffer = NULL; + } + fclose(fp); + return AXIS2_FAILURE; + } + } + while(!feof(fp)); + + fclose(fp); + AXIS2_FREE(env->allocator, buffer); + buffer = NULL; + return AXIS2_SUCCESS; +} + +static axis2_status_t +apache2_worker_send_attachment_using_callback( + const axutil_env_t * env, + request_rec *request, + axiom_mtom_sending_callback_t *callback, + void *handler, + void *user_param) +{ + int count = 0; + int len = 0; + axis2_status_t status = AXIS2_SUCCESS; + axis2_char_t *buffer = NULL; + + /* Keep on loading the data in a loop until + * all the data is sent */ + + while((count = AXIOM_MTOM_SENDING_CALLBACK_LOAD_DATA(callback, env, handler, &buffer)) > 0) + { + len = 0; + len = ap_rwrite(buffer, count, request); + ap_rflush(request); + if(len == -1) + { + status = AXIS2_FAILURE; + break; + } + } + + if(status == AXIS2_FAILURE) + { + AXIOM_MTOM_SENDING_CALLBACK_CLOSE_HANDLER(callback, env, handler); + return status; + } + + status = AXIOM_MTOM_SENDING_CALLBACK_CLOSE_HANDLER(callback, env, handler); + return status; +} + + +static axutil_hash_t* +axis2_apache_worker_get_headers( + const axutil_env_t *env, + request_rec *request) +{ + int i = 0; + axutil_hash_t *header_map = NULL; + const apr_array_header_t *tarr; + const apr_table_entry_t *telts; + axis2_http_header_t * tmp_http_header = NULL; + + + header_map = axutil_hash_make(env); + tarr = apr_table_elts(request->headers_in); + telts = (const apr_table_entry_t*)tarr->elts; + + for (i = 0; i < tarr->nelts; i++) + { + axis2_char_t* tmp_key = (axis2_char_t*) telts[i].key; + axis2_char_t* tmp_value = (axis2_char_t*) telts[i].val; + tmp_http_header = axis2_http_header_create(env, tmp_key, tmp_value); + axutil_hash_set(header_map, tmp_key, AXIS2_HASH_KEY_STRING, tmp_http_header); + } + + return header_map; + + +} diff --git a/src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h b/src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h new file mode 100644 index 0000000..9ab9250 --- /dev/null +++ b/src/core/transport/http/server/apache2/axis2_apache2_out_transport_info.h @@ -0,0 +1,61 @@ + +/* + * 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. + */ + +#ifndef AXIS2_APACHE2_OUT_TRANSPORT_INFO_H +#define AXIS2_APACHE2_OUT_TRANSPORT_INFO_H + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_apache2_out_transport_info.h + * @brief axis2 Apache2 Out Transport Info + */ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + AXIS2_EXTERN axis2_http_out_transport_info_t *AXIS2_CALL + + axis2_apache2_out_transport_info_create( + const axutil_env_t * env, + request_rec * r); + + /** + * Free http_out_transport_info passed as void pointer. This will be + * cast into appropriate type and then pass the cast object + * into the http_out_transport_info structure's free method + */ + AXIS2_EXTERN void AXIS2_CALL + + axis2_apache2_out_transport_info_free_void_arg( + void *transport_info, + const axutil_env_t * env); + + /** @} */ +#ifdef __cplusplus +} +#endif +#endif /* AXIS2_APACHE2_OUT_TRANSPORT_INFO_H */ diff --git a/src/core/transport/http/server/apache2/axis2_apache2_worker.h b/src/core/transport/http/server/apache2/axis2_apache2_worker.h new file mode 100644 index 0000000..eea4033 --- /dev/null +++ b/src/core/transport/http/server/apache2/axis2_apache2_worker.h @@ -0,0 +1,78 @@ + +/* + * 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. + */ + +#ifndef AXIS2_APACHE2_WORKER_H +#define AXIS2_APACHE2_WORKER_H + +/** + * @brief Apache2 Worker ops struct + * Encapsulator struct for ops of axis2_apache2_worker + */ + +/** + * @ingroup axis2_core_transport_http + * @{ + */ + +/** + * @file axis2_apache2_worker.h + * @brief axis2 Apache2 Worker + */ + +#include +#include +#include +#include +#include "apache2_stream.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct axis2_apache2_worker axis2_apache2_worker_t; + + AXIS2_EXTERN int AXIS2_CALL + axis2_apache2_worker_process_request( + axis2_apache2_worker_t * apache2_worker, + const axutil_env_t * env, + request_rec * r); + + AXIS2_EXTERN void AXIS2_CALL + axis2_apache2_worker_free( + axis2_apache2_worker_t * apache2_worker, + const axutil_env_t * env); + + AXIS2_EXTERN axis2_apache2_worker_t *AXIS2_CALL + + axis2_apache2_worker_create( + const axutil_env_t * env, + axis2_char_t * repo_path); + +#define AXIS2_APACHE2_WORKER_PROCESS_REQUEST(apache2_worker, env, request) \ + axis2_apache2_worker_process_request(\ + apache2_worker, env, request) +#define AXIS2_APACHE2_WORKER_FREE(apache2_worker, env) \ + axis2_apache2_worker_free(apache2_worker, env) + + /** @} */ +#ifdef __cplusplus +} +#endif + +#endif /* AXIS2_APACHE2_WORKER_H */ diff --git a/src/core/transport/http/server/apache2/mod_axis2.c b/src/core/transport/http/server/apache2/mod_axis2.c new file mode 100644 index 0000000..a9431eb --- /dev/null +++ b/src/core/transport/http/server/apache2/mod_axis2.c @@ -0,0 +1,844 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include "axis2_apache2_worker.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Configuration structure populated by apache2.conf */ +typedef struct axis2_config_rec +{ + char *axutil_log_file; + char *axis2_repo_path; + axutil_log_levels_t log_level; + int max_log_file_size; + int axis2_global_pool_size; +} axis2_config_rec_t; + +axis2_apache2_worker_t *axis2_worker = NULL; +axutil_env_t *axutil_env = NULL; +apr_rmm_t* rmm = NULL; +apr_global_mutex_t *global_mutex = NULL; + +/******************************Function Headers********************************/ +static void * +axis2_create_svr( + apr_pool_t * p, + server_rec * s); + +static const char * +axis2_set_repo_path( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_log_file( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_max_log_file_size( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_global_pool_size( + cmd_parms * cmd, + void * dummy, + const char *arg); + +static const char * +axis2_set_log_level( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static const char * +axis2_set_svc_url_prefix( + cmd_parms * cmd, + void *dummy, + const char *arg); + +static int +axis2_handler( + request_rec * req); + +/* Shutdown Axis2 */ +apr_status_t +axis2_shutdown( + void *tmp); + +void *AXIS2_CALL axis2_module_malloc( + axutil_allocator_t * allocator, + size_t size); + +void *AXIS2_CALL axis2_module_realloc( + axutil_allocator_t * allocator, + void *ptr, + size_t size); + +void AXIS2_CALL axis2_module_free( + axutil_allocator_t * allocator, + void *ptr); + +static void +axis2_module_init( + apr_pool_t * p, + server_rec * svr_rec); + +static void +axis2_register_hooks( + apr_pool_t * p); + +char * +axis2_get_session( + void *req, + const char *id); + +axis2_status_t +axis2_set_session( + void *req, + const char *id, + const char *session); + +/***************************End of Function Headers****************************/ + +static const command_rec axis2_cmds[] = { AP_INIT_TAKE1("Axis2RepoPath", axis2_set_repo_path, NULL, + RSRC_CONF, "Axis2/C repository path"), AP_INIT_TAKE1("Axis2LogFile", axis2_set_log_file, NULL, + RSRC_CONF, "Axis2/C log file name"), AP_INIT_TAKE1("Axis2LogLevel", axis2_set_log_level, NULL, + RSRC_CONF, "Axis2/C log level"), AP_INIT_TAKE1("Axis2MaxLogFileSize", + axis2_set_max_log_file_size, NULL, RSRC_CONF, "Axis2/C maximum log file size"), + AP_INIT_TAKE1("Axis2GlobalPoolSize", axis2_set_global_pool_size, NULL, RSRC_CONF, + "Axis2/C global pool size"), AP_INIT_TAKE1("Axis2ServiceURLPrefix", + axis2_set_svc_url_prefix, NULL, RSRC_CONF, "Axis2/C service URL prifix"), + { NULL } }; + +/* Dispatch list for API hooks */ +module AP_MODULE_DECLARE_DATA axis2_module = { STANDARD20_MODULE_STUFF, NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + axis2_create_svr, /* create per-server config structures */ + NULL, /* merge per-server config structures */ + axis2_cmds, /* table of config file commands */ + axis2_register_hooks /* register hooks */ + }; + +static void * +axis2_create_svr( + apr_pool_t * p, + server_rec * s) +{ + axis2_config_rec_t *conf = apr_palloc(p, sizeof(*conf)); + conf->axutil_log_file = NULL; + conf->axis2_repo_path = NULL; + conf->log_level = AXIS2_LOG_LEVEL_DEBUG; + conf->axis2_global_pool_size = 0; + conf->max_log_file_size = 1; + return conf; +} + +static const char * +axis2_set_repo_path( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->axis2_repo_path = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +static const char * +axis2_set_log_file( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->axutil_log_file = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +static const char * +axis2_set_max_log_file_size( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->max_log_file_size = 1024 * 1024 * atoi(arg); + return NULL; +} + +static const char * +axis2_set_global_pool_size( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + conf->axis2_global_pool_size = 1024 * 1024 * atoi(arg); + return NULL; +} + +static const char * +axis2_set_log_level( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + char *str; + axutil_log_levels_t level = AXIS2_LOG_LEVEL_DEBUG; + axis2_config_rec_t *conf = NULL; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if(err != NULL) + { + return err; + } + + conf = (axis2_config_rec_t *)ap_get_module_config(cmd->server->module_config, &axis2_module); + + str = ap_getword_conf(cmd->pool, &arg); + if(str) + { + if(!strcasecmp(str, "crit")) + { + level = AXIS2_LOG_LEVEL_CRITICAL; + } + else if(!strcasecmp(str, "error")) + { + level = AXIS2_LOG_LEVEL_ERROR; + } + else if(!strcasecmp(str, "warn")) + { + level = AXIS2_LOG_LEVEL_WARNING; + } + else if(!strcasecmp(str, "info")) + { + level = AXIS2_LOG_LEVEL_INFO; + } + else if(!strcasecmp(str, "debug")) + { + level = AXIS2_LOG_LEVEL_DEBUG; + } + else if(!strcasecmp(str, "user")) + { + level = AXIS2_LOG_LEVEL_USER; + } + else if(!strcasecmp(str, "trace")) + { + level = AXIS2_LOG_LEVEL_TRACE; + } + } + conf->log_level = level; + return NULL; +} + +static const char * +axis2_set_svc_url_prefix( + cmd_parms * cmd, + void *dummy, + const char *arg) +{ + AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + + axis2_request_url_prefix = AXIS2_REQUEST_URL_PREFIX; + if(!err) + { + axis2_char_t *prefix = apr_pstrdup(cmd->pool, arg); + if(prefix) + axis2_request_url_prefix = prefix; + } + + return NULL; +} + +/* The sample content handler */ +static int +axis2_handler( + request_rec * req) +{ + int rv = 0; + axutil_env_t *thread_env = NULL; + axutil_allocator_t *allocator = NULL; + axutil_error_t *error = NULL; + + apr_allocator_t *local_allocator = NULL; + apr_pool_t *local_pool = NULL; + + if(strcmp(req->handler, "axis2_module")) + { + return DECLINED; + } + + /* Set up the read policy from the client. */ + if((rv = ap_setup_client_block(req, REQUEST_CHUNKED_DECHUNK)) != OK) + { + return rv; + } + ap_should_client_block(req); + + apr_allocator_create(&local_allocator); + apr_pool_create_ex(&local_pool, NULL, NULL, local_allocator); + + /*thread_env = axutil_init_thread_env(axutil_env);*/ + + /*axutil_env->allocator->current_pool = (void *) req->pool; + rv = AXIS2_APACHE2_WORKER_PROCESS_REQUEST(axis2_worker, axutil_env, req);*/ + + /* create new allocator for this request */ + /*allocator = (axutil_allocator_t *) apr_palloc(req->pool, + sizeof(axutil_allocator_t));*/ + + allocator = (axutil_allocator_t *)apr_palloc(local_pool, sizeof(axutil_allocator_t)); + + if(!allocator) + { + return HTTP_INTERNAL_SERVER_ERROR; + } + allocator->malloc_fn = axis2_module_malloc; + allocator->realloc = axis2_module_realloc; + allocator->free_fn = axis2_module_free; + allocator->global_pool_ref = 0; + allocator->local_pool = (void *)local_pool; + allocator->current_pool = (void *)local_pool; + allocator->global_pool = axutil_env->allocator->global_pool; + + error = axutil_error_create(allocator); + thread_env = axutil_env_create_with_error_log_thread_pool(allocator, error, axutil_env->log, + axutil_env-> thread_pool); + thread_env->allocator = allocator; + thread_env->set_session_fn = axis2_set_session; + thread_env->get_session_fn = axis2_get_session; + + rv = AXIS2_APACHE2_WORKER_PROCESS_REQUEST(axis2_worker, thread_env, req); + if(AXIS2_CRITICAL_FAILURE == rv) + { + return HTTP_INTERNAL_SERVER_ERROR; + } + + apr_pool_destroy(local_pool); + apr_allocator_destroy(local_allocator); + + return rv; +} + +void *AXIS2_CALL +axis2_module_malloc( + axutil_allocator_t * allocator, + size_t size) +{ +#if APR_HAS_SHARED_MEMORY + if (rmm == allocator->current_pool) + { + + void* ptr = NULL; + apr_rmm_off_t offset; + apr_global_mutex_lock(global_mutex); + offset = apr_rmm_malloc(rmm, size); + if (offset) + ptr = apr_rmm_addr_get(rmm, offset); + apr_global_mutex_unlock(global_mutex); + return ptr; + } +#endif + return apr_palloc((apr_pool_t *)(allocator->current_pool), size); +} + +void *AXIS2_CALL +axis2_module_realloc( + axutil_allocator_t * allocator, + void *ptr, + size_t size) +{ +#if APR_HAS_SHARED_MEMORY + if (rmm == allocator->current_pool) + { + void* ptr = NULL; + apr_rmm_off_t offset; + apr_global_mutex_lock(global_mutex); + offset = apr_rmm_realloc(rmm, ptr, size); + if (offset) + ptr = apr_rmm_addr_get(rmm, offset); + apr_global_mutex_unlock(global_mutex); + return ptr; + } +#endif + /* can't be easily implemented */ + return NULL; +} + +void AXIS2_CALL +axis2_module_free( + axutil_allocator_t * allocator, + void *ptr) +{ +#if APR_HAS_SHARED_MEMORY + if (rmm == allocator->current_pool) + { + apr_rmm_off_t offset; + apr_global_mutex_lock(global_mutex); + offset = apr_rmm_offset_get(rmm, ptr); + apr_rmm_free(rmm, offset); + apr_global_mutex_unlock(global_mutex); + } +#endif +} + +static int +axis2_post_config( + apr_pool_t *pconf, + apr_pool_t *plog, + apr_pool_t *ptemp, + server_rec *svr_rec) +{ + apr_status_t status = APR_SUCCESS; + axutil_allocator_t *allocator = NULL; + axutil_error_t *error = NULL; + axutil_log_t *axutil_logger = NULL; + axutil_thread_pool_t *thread_pool = NULL; + void *data = NULL; + const char *userdata_key = "axis2_init"; + axis2_config_rec_t *conf = (axis2_config_rec_t *)ap_get_module_config(svr_rec->module_config, + &axis2_module); + + /* axis2_post_config() will be called twice. Don't bother + * going through all of the initialization on the first call + * because it will just be thrown away.*/ + + ap_add_version_component(pconf, AXIS2_HTTP_HEADER_SERVER_AXIS2C); + + apr_pool_userdata_get(&data, userdata_key, svr_rec->process->pool); + if(!data) + { + apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, + svr_rec->process->pool); + return OK; + } + +#if APR_HAS_SHARED_MEMORY + if (conf->axis2_global_pool_size > 0) + { + apr_shm_t *shm; + apr_rmm_off_t offset; + + status = apr_shm_create(&shm, conf->axis2_global_pool_size, NULL, pconf); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error creating shared memory pool"); + exit(APEXIT_INIT); + } + + status = apr_rmm_init(&rmm, NULL, apr_shm_baseaddr_get(shm), conf->axis2_global_pool_size, + pconf); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error creating relocatable memory pool"); + exit(APEXIT_INIT); + } + + status = apr_global_mutex_create(&global_mutex, NULL, + APR_LOCK_DEFAULT, pconf); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error creating global mutex"); + exit(APEXIT_INIT); + } + + /*status = unixd_set_global_mutex_perms(global_mutex); + if (status != APR_SUCCESS) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Permision cannot be set to global mutex"); + exit(APEXIT_INIT); + } + */ + + offset = apr_rmm_malloc(rmm, sizeof(axutil_allocator_t)); + if (!offset) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error in creating allocator in global pool"); + exit(APEXIT_INIT); + } + allocator = apr_rmm_addr_get(rmm, offset); + allocator->malloc_fn = axis2_module_malloc; + allocator->realloc = axis2_module_realloc; + allocator->free_fn = axis2_module_free; + allocator->global_pool_ref = 0; + allocator->local_pool = (void *) rmm; + allocator->current_pool = (void *) rmm; + allocator->global_pool = (void *) rmm; + + /* We need to init xml readers before we go into threaded env + */ + axiom_xml_reader_init(); + axutil_error_init(); + + error = axutil_error_create(allocator); + if (!error) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 error structure"); + exit(APEXIT_CHILDFATAL); + } + + axutil_logger = axutil_log_create(allocator, NULL, conf->axutil_log_file); + if (!axutil_logger) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 log structure"); + exit(APEXIT_CHILDFATAL); + } + thread_pool = axutil_thread_pool_init(allocator); + if (!thread_pool) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error initializing mod_axis2 thread pool"); + exit(APEXIT_CHILDFATAL); + } + axutil_env = axutil_env_create_with_error_log_thread_pool(allocator, error, + axutil_logger, + thread_pool); + if (!axutil_env) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 environment"); + exit(APEXIT_CHILDFATAL); + } + if (axutil_logger) + { + axutil_logger->level = conf->log_level; + axutil_logger->size = conf->max_log_file_size; + AXIS2_LOG_INFO(axutil_env->log, "Apache Axis2/C version in use : %s", + axis2_version_string()); + AXIS2_LOG_INFO(axutil_env->log, + "Starting log with log level %d and max log file size %d", + conf->log_level, conf->max_log_file_size); + } + axutil_env->set_session_fn = axis2_set_session; + axutil_env->get_session_fn = axis2_get_session; + + axis2_worker = axis2_apache2_worker_create(axutil_env, + conf->axis2_repo_path); + if (!axis2_worker) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 apache2 worker"); + exit(APEXIT_CHILDFATAL); + } + } + +#endif + + return OK; +} + +static void +axis2_module_init( + apr_pool_t * p, + server_rec * svr_rec) +{ + apr_pool_t *pool; + apr_status_t status; + axutil_allocator_t *allocator = NULL; + axutil_error_t *error = NULL; + axutil_log_t *axutil_logger = NULL; + axutil_thread_pool_t *thread_pool = NULL; + axis2_config_rec_t *conf = (axis2_config_rec_t*)ap_get_module_config(svr_rec->module_config, + &axis2_module); + + if(conf->axis2_global_pool_size > 0) + { + /* + If we are using shared memory, no need to init the child, as the + worker has been created in post config. + */ + return; + } + + /* We need to init xml readers before we go into threaded env + */ + axiom_xml_reader_init(); + + /* create an allocator that uses APR memory pools and lasts the + * lifetime of the httpd server child process + */ + status = apr_pool_create(&pool, p); + if(status) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, svr_rec, + "[Axis2] Error allocating mod_axis2 memory pool"); + exit(APEXIT_CHILDFATAL); + } + allocator = (axutil_allocator_t*)apr_palloc(pool, sizeof(axutil_allocator_t)); + if(!allocator) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_ENOMEM, svr_rec, + "[Axis2] Error allocating mod_axis2 allocator"); + exit(APEXIT_CHILDFATAL); + } + allocator->malloc_fn = axis2_module_malloc; + allocator->realloc = axis2_module_realloc; + allocator->free_fn = axis2_module_free; + allocator->global_pool_ref = 0; + allocator->local_pool = (void*)pool; + allocator->current_pool = (void*)pool; + allocator->global_pool = (void*)pool; + + if(!allocator) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error initializing mod_axis2 allocator"); + exit(APEXIT_CHILDFATAL); + } + + axutil_error_init(); + + error = axutil_error_create(allocator); + if(!error) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 error structure"); + exit(APEXIT_CHILDFATAL); + } + axutil_logger = axutil_log_create(allocator, NULL, conf->axutil_log_file); + if(!axutil_logger) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 log structure"); + exit(APEXIT_CHILDFATAL); + } + thread_pool = axutil_thread_pool_init(allocator); + if(!thread_pool) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error initializing mod_axis2 thread pool"); + exit(APEXIT_CHILDFATAL); + } + axutil_env = axutil_env_create_with_error_log_thread_pool(allocator, error, axutil_logger, + thread_pool); + if(!axutil_env) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 environment"); + exit(APEXIT_CHILDFATAL); + } + if(axutil_logger) + { + + axutil_logger->level = conf->log_level; + AXIS2_LOG_INFO(axutil_env->log, "Apache Axis2/C version in use : %s", + axis2_version_string()); + AXIS2_LOG_INFO(axutil_env->log, "Starting log with log level %d", conf->log_level); + } + axutil_env->set_session_fn = axis2_set_session; + axutil_env->get_session_fn = axis2_get_session; + axis2_worker = axis2_apache2_worker_create(axutil_env, conf->axis2_repo_path); + if(!axis2_worker) + { + ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, svr_rec, + "[Axis2] Error creating mod_axis2 apache2 worker"); + exit(APEXIT_CHILDFATAL); + } + + /*ap_dbd_prepare(svr_rec, "SELECT value FROM session WHERE id = %s", "retrieve_session"); + ap_dbd_prepare(svr_rec, "INSERT INTO session VALUES(?,?)", "insert_session");*/ + + + /* If we are initialized we register a clean up as well */ + /* apr_pool_cleanup_register(p, NULL, axis2_shutdown, apr_pool_cleanup_null);*/ +} + +static void +axis2_register_hooks( + apr_pool_t * p) +{ + ap_hook_post_config(axis2_post_config, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_handler(axis2_handler, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_child_init(axis2_module_init, NULL, NULL, APR_HOOK_MIDDLE); +} + +apr_status_t +axis2_shutdown( + void *tmp) +{ + if(axis2_worker) + { + axis2_apache2_worker_free(axis2_worker, axutil_env); + } + return APR_SUCCESS; +} + +char * +axis2_get_session( + void *req, + const char *id) +{ + request_rec *request = NULL; + apr_status_t rv; + const char *dbd_session = NULL; + apr_dbd_prepared_t *statement; + apr_dbd_results_t *res = NULL; + apr_dbd_row_t *row = NULL; + ap_dbd_t *dbd = NULL; + ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL; + request = (request_rec *) req; + + authn_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); + dbd = authn_dbd_acquire_fn(request); + if (!dbd) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Failed to acquire database connection to look up " + "id '%s'", id); + return NULL; + } + + statement = apr_hash_get(dbd->prepared, "retrieve_session", APR_HASH_KEY_STRING); + if (!statement) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "A prepared statement could not be found for " + "the key '%s'", "retrieve_session"); + return NULL; + } + if (apr_dbd_pvselect(dbd->driver, request->pool, dbd->handle, &res, statement, + 0, id, NULL) != 0) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Query execution error looking up '%s' " + "in database", id); + return NULL; + } + for (rv = apr_dbd_get_row(dbd->driver, request->pool, res, &row, -1); rv != -1; + rv = apr_dbd_get_row(dbd->driver, request->pool, res, &row, -1)) + { + if (rv != 0) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, request, + "Error retrieving results while looking up '%s' " + "in database", id); + return NULL; + } + if (!dbd_session) + { + dbd_session = apr_dbd_get_entry(dbd->driver, row, 0); + } + /* we can't break out here or row won't get cleaned up */ + } + + if (!dbd_session) + { + return NULL; + } + + return (char *) dbd_session; +} + +axis2_status_t +axis2_set_session( + void *req, + const char *id, + const char *session) +{ + request_rec *request = NULL; + apr_dbd_prepared_t *statement; + int affected_rows = -1; + ap_dbd_t *dbd = NULL; + ap_dbd_t *(*authn_dbd_acquire_fn)(request_rec*) = NULL; + request = (request_rec *) req; + + authn_dbd_acquire_fn = APR_RETRIEVE_OPTIONAL_FN(ap_dbd_acquire); + dbd = authn_dbd_acquire_fn(request); + if (!dbd) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Failed to acquire database connection to insert session for " + "id '%s'", id); + return AXIS2_FAILURE; + } + + statement = apr_hash_get(dbd->prepared, "insert_session", APR_HASH_KEY_STRING); + if (!statement) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "A prepared statement could not be found for " + "the key '%s'", "insert_session"); + return AXIS2_FAILURE; + } + if (apr_dbd_pvquery(dbd->driver, request->pool, dbd->handle, &affected_rows, statement, id, + session, NULL) != 0) + { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, request, + "Query execution error inserting session for '%s' " + "in database", id); + return AXIS2_FAILURE; + } + + return AXIS2_SUCCESS; +} + + diff --git a/src/core/transport/http/server/simple_axis2_server/Makefile.am b/src/core/transport/http/server/simple_axis2_server/Makefile.am new file mode 100644 index 0000000..604851d --- /dev/null +++ b/src/core/transport/http/server/simple_axis2_server/Makefile.am @@ -0,0 +1,30 @@ +prgbindir=$(bindir) +prgbin_PROGRAMS = axis2_http_server +SUBDIRS = +AM_CFLAGS = -g -pthread +axis2_http_server_SOURCES = http_server_main.c + +axis2_http_server_LDADD = $(LDFLAGS) \ + $(top_builddir)/src/core/transport/http/util/libaxis2_http_util.la \ + $(top_builddir)/src/core/transport/http/common/libaxis2_http_common.la \ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la \ + $(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/axiom/src/parser/$(WRAPPER_DIR)/libaxis2_parser.la \ + $(top_builddir)/src/core/description/libaxis2_description.la \ + $(top_builddir)/src/core/deployment/libaxis2_deployment.la \ + $(top_builddir)/src/core/context/libaxis2_context.la \ + $(top_builddir)/src/core/clientapi/libaxis2_clientapi.la \ + $(top_builddir)/src/core/engine/libaxis2_engine.la \ + $(top_builddir)/src/core/transport/http/sender/libaxis2_http_sender.la \ + $(top_builddir)/src/core/transport/http/receiver/libaxis2_http_receiver.la \ + $(top_builddir)/neethi/src/libneethi.la \ + -lpthread + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/description\ + -I$(top_builddir)/src/core/context \ + -I$(top_builddir)/src/core/deployment\ + -I$(top_builddir)/src/core/phaseresolver \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/server/simple_axis2_server/http_server_main.c b/src/core/transport/http/server/simple_axis2_server/http_server_main.c new file mode 100644 index 0000000..cfbcda4 --- /dev/null +++ b/src/core/transport/http/server/simple_axis2_server/http_server_main.c @@ -0,0 +1,310 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +axutil_env_t *system_env = NULL; +axis2_transport_receiver_t *server = NULL; +AXIS2_IMPORT extern int axis2_http_socket_read_timeout; +AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix; + +#define DEFAULT_REPO_PATH "../" + +/***************************** Function headers *******************************/ +axutil_env_t * +init_syetem_env( + axutil_allocator_t * allocator, + const axis2_char_t * log_file); + +void +system_exit( + axutil_env_t * env, + int status); + +void +usage( + axis2_char_t * prog_name); + +void +sig_handler( + int signal); + +/***************************** End of function headers ************************/ +axutil_env_t * +init_syetem_env( + axutil_allocator_t * allocator, + const axis2_char_t * log_file) +{ + axutil_error_t *error = axutil_error_create(allocator); + axutil_log_t *log = axutil_log_create(allocator, NULL, log_file); + /* if (!log) */ + + /* log = axutil_log_create_default (allocator); */ + axutil_thread_pool_t *thread_pool = axutil_thread_pool_init(allocator); + /* We need to init the parser in main thread before spawning child + * threads + */ + axiom_xml_reader_init(); + return axutil_env_create_with_error_log_thread_pool(allocator, error, log, thread_pool); +} + +void +system_exit( + axutil_env_t * env, + int status) +{ + axutil_allocator_t *allocator = NULL; + if(server) + { + axis2_transport_receiver_free(server, system_env); + } + if(env) + { + allocator = env->allocator; + axutil_env_free(env); + } + /*axutil_allocator_free(allocator); */ + axiom_xml_reader_cleanup(); + exit(status); +} + +int +main( + int argc, + char *argv[]) +{ + axutil_allocator_t *allocator = NULL; + axutil_env_t *env = NULL; + extern char *optarg; + extern int optopt; + int c; + unsigned int len; + int log_file_size = AXUTIL_LOG_FILE_SIZE; + unsigned int file_flag = 0; + axutil_log_levels_t log_level = AXIS2_LOG_LEVEL_DEBUG; + const axis2_char_t *log_file = "axis2.log"; + const axis2_char_t *repo_path = DEFAULT_REPO_PATH; + int port = 9090; + axis2_status_t status; + + /* Set the service URL prefix to be used. This could default to services if not + set with AXIS2_REQUEST_URL_PREFIX macro at compile time */ + axis2_request_url_prefix = AXIS2_REQUEST_URL_PREFIX; + + while((c = AXIS2_GETOPT(argc, argv, ":p:r:ht:l:s:f:")) != -1) + { + + switch(c) + { + case 'p': + port = AXIS2_ATOI(optarg); + break; + case 'r': + repo_path = optarg; + break; + case 't': + axis2_http_socket_read_timeout = AXIS2_ATOI(optarg) * 1000; + break; + case 'l': + log_level = AXIS2_ATOI(optarg); + if(log_level < AXIS2_LOG_LEVEL_CRITICAL) + log_level = AXIS2_LOG_LEVEL_CRITICAL; + if(log_level > AXIS2_LOG_LEVEL_TRACE) + log_level = AXIS2_LOG_LEVEL_TRACE; + break; + case 's': + log_file_size = 1024 * 1024 * AXIS2_ATOI(optarg); + break; + case 'f': + log_file = optarg; + break; + case 'h': + usage(argv[0]); + return 0; + case ':': + fprintf(stderr, "\nOption -%c requires an operand\n", optopt); + usage(argv[0]); + return -1; + case '?': + if(isprint(optopt)) + fprintf(stderr, "\nUnknown option `-%c'.\n", optopt); + usage(argv[0]); + return -1; + } + } + + allocator = axutil_allocator_init(NULL); + + if(!allocator) + { + system_exit(NULL, -1); + } + + env = init_syetem_env(allocator, log_file); + env->log->level = log_level; + env->log->size = log_file_size; + + axutil_error_init(); + system_env = env; + + signal(SIGINT, sig_handler); +#ifndef WIN32 + signal(SIGPIPE, sig_handler); +#endif + + AXIS2_LOG_INFO(env->log, "Starting Axis2 HTTP server...."); + AXIS2_LOG_INFO(env->log, "Apache Axis2/C version in use : %s", axis2_version_string()); + AXIS2_LOG_INFO(env->log, "Server port : %d", port); + AXIS2_LOG_INFO(env->log, "Repo location : %s", repo_path); + AXIS2_LOG_INFO(env->log, "Read Timeout : %d ms", axis2_http_socket_read_timeout); + + status = axutil_file_handler_access(repo_path, AXIS2_R_OK); + if(status == AXIS2_SUCCESS) + { + len = (unsigned int)strlen(repo_path); + /* We are sure that the difference lies within the unsigned int range */ + if((len >= 9) && !strcmp((repo_path + (len - 9)), "axis2.xml")) + { + file_flag = 1; + } + } + else + { + AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "provided repo path %s does " + "not exist or no permissions to read, set " + "repo_path to DEFAULT_REPO_PATH", repo_path); + repo_path = DEFAULT_REPO_PATH; + } + + if(!file_flag) + server = axis2_http_server_create(env, repo_path, port); + else + server = axis2_http_server_create_with_file(env, repo_path, port); + + if(!server) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Server creation failed: Error code:" " %d :: %s", + env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); + system_exit(env, -1); + + } + printf("Started Simple Axis2 HTTP Server ...\n"); + if(axis2_transport_receiver_start(server, env) == AXIS2_FAILURE) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Server start failed: Error code:" " %d :: %s", + env->error->error_number, AXIS2_ERROR_GET_MESSAGE(env->error)); + system_exit(env, -1); + } + return 0; +} + +void +usage( + axis2_char_t * prog_name) +{ + fprintf(stdout, "\n Usage : %s", prog_name); + fprintf(stdout, " [-p PORT]"); + fprintf(stdout, " [-t TIMEOUT]"); + fprintf(stdout, " [-r REPO_PATH]"); + fprintf(stdout, " [-l LOG_LEVEL]"); + fprintf(stdout, " [-f LOG_FILE]\n"); + fprintf(stdout, " [-s LOG_FILE_SIZE]\n"); + fprintf(stdout, " Options :\n"); + fprintf(stdout, "\t-p PORT \t port number to use, default port is 9090\n"); + fprintf(stdout, "\t-r REPO_PATH \t repository path, default is ../\n"); + fprintf(stdout, "\t-t TIMEOUT\t socket read timeout, default is 30 seconds\n"); + fprintf(stdout, "\t-l LOG_LEVEL\t log level, available log levels:" + "\n\t\t\t 0 - critical 1 - errors 2 - warnings" + "\n\t\t\t 3 - information 4 - debug 5- user 6- trace" + "\n\t\t\t Default log level is 4(debug).\n"); +#ifndef WIN32 + fprintf(stdout, "\t-f LOG_FILE\t log file, default is $AXIS2C_HOME/logs/axis2.log" + "\n\t\t\t or axis2.log in current folder if AXIS2C_HOME not set\n"); +#else + fprintf(stdout, + "\t-f LOG_FILE\t log file, default is %%AXIS2C_HOME%%\\logs\\axis2.log" + "\n\t\t\t or axis2.log in current folder if AXIS2C_HOME not set\n"); +#endif + fprintf(stdout, + "\t-s LOG_FILE_SIZE\t Maximum log file size in mega bytes, default maximum size is 1MB.\n"); + fprintf(stdout, " Help :\n\t-h \t display this help screen.\n\n"); +} + +/** + * Signal handler + */ +void +sig_handler( + int signal) +{ + + if(!system_env) + { + AXIS2_LOG_ERROR( + system_env->log, + AXIS2_LOG_SI, + "Received signal %d, unable to proceed system_env is NULL ,\ + system exit with -1", + signal); + _exit(-1); + } + + switch(signal) + { + case SIGINT: + { + /* Use of SIGINT in Windows is valid, since we have a console application + * Thus, eventhough this may a single threaded application, it does work. + */ + AXIS2_LOG_INFO(system_env->log, "Received signal SIGINT. Server " + "shutting down"); + if(server) + { + axis2_http_server_stop(server, system_env); + } + + AXIS2_LOG_INFO(system_env->log, "Shutdown complete ..."); + system_exit(system_env, 0); + } +#ifndef WIN32 + case SIGPIPE: + { + AXIS2_LOG_INFO(system_env->log, "Received signal SIGPIPE. Client " + "request serve aborted"); + return; + } +#endif + case SIGSEGV: + { + fprintf(stderr, "Received deadly signal SIGSEGV. Terminating\n"); + _exit(-1); + } + } +} diff --git a/src/core/transport/http/util/Makefile.am b/src/core/transport/http/util/Makefile.am new file mode 100644 index 0000000..eff6c0e --- /dev/null +++ b/src/core/transport/http/util/Makefile.am @@ -0,0 +1,14 @@ +NSUBDIRS = +noinst_LTLIBRARIES = libaxis2_http_util.la + +libaxis2_http_util_la_SOURCES = http_transport_utils.c + +libaxis2_http_util_la_LIBADD=$(top_builddir)/util/src/libaxutil.la \ + $(top_builddir)/axiom/src/parser/${WRAPPER_DIR}/libaxis2_parser.la\ + $(top_builddir)/axiom/src/om/libaxis2_axiom.la + + +INCLUDES = -I$(top_builddir)/include \ + -I$(top_builddir)/src/core/engine \ + -I$(top_builddir)/util/include \ + -I$(top_builddir)/axiom/include diff --git a/src/core/transport/http/util/http_transport_utils.c b/src/core/transport/http/util/http_transport_utils.c new file mode 100644 index 0000000..97d1510 --- /dev/null +++ b/src/core/transport/http/util/http_transport_utils.c @@ -0,0 +1,3885 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AXIOM_MIME_BOUNDARY_BYTE 45 + +/** Size of the buffer to be used when reading a file */ +#ifndef AXIS2_FILE_READ_SIZE +#define AXIS2_FILE_READ_SIZE 2048 +#endif + +/** Content length value to be used in case of chunked content */ +#ifndef AXIS2_CHUNKED_CONTENT_LENGTH +#define AXIS2_CHUNKED_CONTENT_LENGTH 100000000 +#endif + +const axis2_char_t *AXIS2_TRANS_UTIL_DEFAULT_CHAR_ENCODING = + AXIS2_HTTP_HEADER_DEFAULT_CHAR_ENCODING; + +/***************************** Function headers *******************************/ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_process_http_post_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + const int content_length, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri); + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_process_http_put_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + const int content_length, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri); + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_process_http_get_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri, + axis2_conf_ctx_t * conf_ctx, + axutil_hash_t * request_params); + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_process_http_head_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri, + axis2_conf_ctx_t * conf_ctx, + axutil_hash_t * request_params); + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_process_http_delete_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri, + axis2_conf_ctx_t * conf_ctx, + axutil_hash_t * request_params); + +AXIS2_EXTERN axiom_stax_builder_t *AXIS2_CALL +axis2_http_transport_utils_select_builder_for_mime( + const axutil_env_t * env, + axis2_char_t * request_uri, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axis2_char_t * content_type); + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_is_optimized( + const axutil_env_t * env, + axiom_element_t * om_element); + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_do_write_mtom( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_strdecode( + const axutil_env_t * env, + axis2_char_t * dest, + axis2_char_t * src); + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_transport_utils_hexit( + axis2_char_t c); + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_services_html( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx); + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_services_static_wsdl( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_char_t * request_url); + +AXIS2_EXTERN axutil_string_t *AXIS2_CALL +axis2_http_transport_utils_get_charset_enc( + const axutil_env_t * env, + const axis2_char_t * content_type); + +int AXIS2_CALL +axis2_http_transport_utils_on_data_request( + char *buffer, + int size, + void *ctx); + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_http_transport_utils_create_soap_msg( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + const axis2_char_t * soap_ns_uri); + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_value_from_content_type( + const axutil_env_t * env, + const axis2_char_t * content_type, + const axis2_char_t * key); + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_dispatch_and_verify( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx); + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_http_transport_utils_handle_media_type_url_encoded( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_hash_t * param_map, + axis2_char_t * method); + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_transport_utils_session_map_free_void_arg( + void *sm_void, + const axutil_env_t *env); + +static axis2_status_t +axis2_http_transport_utils_send_attachment_using_file( + const axutil_env_t * env, + axutil_http_chunked_stream_t *chunked_stream, + FILE *fp, + axis2_byte_t *buffer, + int buffer_size); + +static axis2_status_t +axis2_http_transport_utils_send_attachment_using_callback( + const axutil_env_t * env, + axutil_http_chunked_stream_t *chunked_stream, + axiom_mtom_sending_callback_t *callback, + void *handler, + void *user_param); + +static axis2_char_t * +axis2_http_transport_utils_copy_key( + const axutil_env_t *env, + axis2_char_t *); + +static axis2_char_t * +axis2_http_transport_utils_copy_value( + const axutil_env_t *env, + axis2_char_t *pair); + +static void +axis2_http_transport_utils_parse_session_str( + const axutil_env_t *env, + axis2_char_t *str, + axutil_hash_t *ht); +/***************************** End of function headers ************************/ + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_transport_out_init( + axis2_http_transport_out_t *response, + const axutil_env_t *env) +{ + response->http_status_code_name = NULL; + response->http_status_code = 0; + response->msg_ctx = NULL; + response->response_data = NULL; + response->content_type = NULL; + response->response_data_length = 0; + response->content_language = NULL; + response->output_headers = NULL; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_transport_out_uninit( + axis2_http_transport_out_t *response, + const axutil_env_t *env) +{ + if(response->msg_ctx) + { + axis2_msg_ctx_free(response->msg_ctx, env); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_transport_in_init( + axis2_http_transport_in_t *request, + const axutil_env_t *env) +{ + request->content_type = NULL; + request->content_length = 0; + request->msg_ctx = NULL; + request->soap_action = NULL; + request->request_uri = NULL; + request->in_stream = NULL; + request->remote_ip = NULL; + request->svr_port = NULL; + request->transfer_encoding = NULL; + request->accept_header = NULL; + request->accept_language_header = NULL; + request->accept_charset_header = NULL; + request->request_method = 0; + request->out_transport_info = NULL; + request->request_url_prefix = NULL; + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_transport_in_uninit( + axis2_http_transport_in_t *request, + const axutil_env_t *env) +{ + if(request->msg_ctx) + { + axis2_msg_ctx_reset_out_transport_info(request->msg_ctx, env); + axis2_msg_ctx_free(request->msg_ctx, env); + } + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_process_http_post_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + const int content_length, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri) +{ + axiom_soap_envelope_t *soap_envelope = NULL; + axiom_soap_builder_t *soap_builder = NULL; + axiom_stax_builder_t *om_builder = NULL; + axis2_bool_t is_soap11 = AXIS2_FALSE; + axiom_xml_reader_t *xml_reader = NULL; + axutil_string_t *char_set_str = NULL; + + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_callback_info_t *callback_ctx = NULL; + axis2_callback_info_t *mime_cb_ctx = NULL; + axutil_hash_t *headers = NULL; + axis2_engine_t *engine = NULL; + axiom_soap_body_t *soap_body = NULL; + axis2_status_t status = AXIS2_FAILURE; + axutil_hash_t *binary_data_map = NULL; + axis2_char_t *soap_body_str = NULL; + axutil_stream_t *stream = NULL; + axis2_bool_t do_rest = AXIS2_FALSE; + axis2_bool_t run_as_get = AXIS2_FALSE; + axis2_char_t *soap_action = NULL; + unsigned int soap_action_len = 0; + axutil_property_t *http_error_property = NULL; + axiom_mime_parser_t *mime_parser = NULL; + axis2_bool_t is_svc_callback = AXIS2_FALSE; + axutil_property_t *is_client_property = NULL; + axis2_bool_t is_application_client_side = AXIS2_FALSE; + axis2_char_t *mime_boundary = NULL; + axis2_bool_t check_for_fault = AXIS2_FALSE; + axis2_bool_t has_fault = AXIS2_FALSE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, in_stream, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out_stream, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, request_uri, AXIS2_FAILURE); + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + + callback_ctx = AXIS2_MALLOC(env->allocator, sizeof(axis2_callback_info_t)); + /* Note: the memory created above is freed in xml reader free function + as this is passed on to the reader */ + callback_ctx->in_stream = in_stream; + callback_ctx->env = env; + callback_ctx->content_length = content_length; + callback_ctx->unread_len = content_length; + callback_ctx->chunked_stream = NULL; + + soap_action = (axis2_char_t *)axutil_string_get_buffer(soap_action_header, env); + soap_action_len = axutil_string_get_length(soap_action_header, env); + + if(soap_action && (soap_action_len > 0)) + { + /* remove leading and trailing " s */ + if(AXIS2_DOUBLE_QUOTE == soap_action[0]) + { + memmove(soap_action, soap_action + sizeof(char), soap_action_len - 1 + sizeof(char)); + } + if(AXIS2_DOUBLE_QUOTE == soap_action[soap_action_len - 2]) + { + soap_action[soap_action_len - 2] = AXIS2_ESC_NULL; + } + } + else + { + /** soap action is null, check whether soap action is in content_type header */ + soap_action = axis2_http_transport_utils_get_value_from_content_type(env, content_type, + AXIS2_ACTION); + } + + headers = axis2_msg_ctx_get_transport_headers(msg_ctx, env); + if(headers) + { + axis2_http_header_t *encoding_header = NULL; + encoding_header = (axis2_http_header_t *)axutil_hash_get(headers, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING, AXIS2_HASH_KEY_STRING); + + if(encoding_header) + { + axis2_char_t *encoding_value = NULL; + encoding_value = axis2_http_header_get_value(encoding_header, env); + if(encoding_value && 0 == axutil_strcasecmp(encoding_value, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + callback_ctx->chunked_stream = axutil_http_chunked_stream_create(env, in_stream); + + if(!callback_ctx->chunked_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occurred in" + " creating in chunked stream."); + return AXIS2_FAILURE; + } + + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "HTTP" + " stream chunked"); + } + } + } + else + { + /* Encoding header is not available */ + /* check content encoding from msg ctx property */ + axis2_char_t *value = axis2_msg_ctx_get_transfer_encoding(msg_ctx, env); + + if(value && axutil_strstr(value, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + /* In case Transfer encoding is set to message context, some streams strip chunking meta + data, so chunked streams should not be created */ + + callback_ctx->content_length = -1; + callback_ctx->unread_len = -1; + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "[chunked ] setting length to -1"); + } + } + + /* when the message contains does not contain pure XML we can't send it + * directly to the parser, First we need to separate the SOAP part from + * the attachment */ + + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED)) + { + /* get mime boundary */ + mime_boundary = axis2_http_transport_utils_get_value_from_content_type(env, + content_type, AXIS2_HTTP_HEADER_CONTENT_TYPE_MIME_BOUNDARY); + + if(mime_boundary) + { + /*axiom_mime_parser_t *mime_parser = NULL;*/ + int soap_body_len = 0; + axutil_param_t *buffer_size_param = NULL; + axutil_param_t *max_buffers_param = NULL; + axutil_param_t *attachment_dir_param = NULL; + axutil_param_t *callback_name_param = NULL; + axutil_param_t *enable_service_callback_param = NULL; + axis2_char_t *value_size = NULL; + axis2_char_t *value_num = NULL; + axis2_char_t *value_dir = NULL; + axis2_char_t *value_callback = NULL; + axis2_char_t *value_enable_service_callback = NULL; + int size = 0; + int num = 0; + + mime_parser = axiom_mime_parser_create(env); + /* This is the size of the buffer we keep inside mime_parser + * when parsing. */ + + enable_service_callback_param = axis2_msg_ctx_get_parameter(msg_ctx, env, + AXIS2_ENABLE_MTOM_SERVICE_CALLBACK); + if(enable_service_callback_param) + { + value_enable_service_callback = (axis2_char_t *)axutil_param_get_value( + enable_service_callback_param, env); + if(value_enable_service_callback) + { + if(!axutil_strcmp(value_enable_service_callback, AXIS2_VALUE_TRUE)) + { + is_svc_callback = AXIS2_TRUE; + } + } + } + + buffer_size_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_MTOM_BUFFER_SIZE); + if(buffer_size_param) + { + value_size = (axis2_char_t *)axutil_param_get_value(buffer_size_param, env); + if(value_size) + { + size = atoi(value_size); + axiom_mime_parser_set_buffer_size(mime_parser, env, size); + } + } + + /* We create an array of buffers in order to conatin SOAP data inside + * mime_parser. This is the number of sucj buffers */ + max_buffers_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_MTOM_MAX_BUFFERS); + if(max_buffers_param) + { + value_num = (axis2_char_t *)axutil_param_get_value(max_buffers_param, env); + if(value_num) + { + num = atoi(value_num); + axiom_mime_parser_set_max_buffers(mime_parser, env, num); + } + } + /* If this paramter is there mime_parser will cached the attachment + * using to the directory for large attachments. */ + + callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env, + AXIS2_MTOM_CACHING_CALLBACK); + if(callback_name_param) + { + value_callback = (axis2_char_t *)axutil_param_get_value(callback_name_param, env); + if(value_callback) + { + axiom_mime_parser_set_caching_callback_name(mime_parser, env, value_callback); + } + } + + attachment_dir_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_ATTACHMENT_DIR); + + if(attachment_dir_param) + { + value_dir = (axis2_char_t *)axutil_param_get_value(attachment_dir_param, env); + if(value_dir) + { + axiom_mime_parser_set_attachment_dir(mime_parser, env, value_dir); + } + } + + axiom_mime_parser_set_mime_boundary(mime_parser, env, mime_boundary); + + if(axiom_mime_parser_parse_for_soap(mime_parser, env, + axis2_http_transport_utils_on_data_request, (void *)callback_ctx, mime_boundary) + == AXIS2_FAILURE) + { + return AXIS2_FAILURE; + } + + if(!is_svc_callback) + { + binary_data_map = axiom_mime_parser_parse_for_attachments(mime_parser, env, + axis2_http_transport_utils_on_data_request, (void *)callback_ctx, + mime_boundary, NULL); + if(!binary_data_map) + { + return AXIS2_FAILURE; + } + } + soap_body_len = (int)axiom_mime_parser_get_soap_body_len(mime_parser, env); + soap_body_str = axiom_mime_parser_get_soap_body_str(mime_parser, env); + + if(!is_svc_callback) + { + if(callback_ctx->chunked_stream) + { + axutil_http_chunked_stream_free(callback_ctx->chunked_stream, env); + callback_ctx->chunked_stream = NULL; + } + } + else + { + mime_cb_ctx = AXIS2_MALLOC(env->allocator, sizeof(axis2_callback_info_t)); + if(mime_cb_ctx) + { + mime_cb_ctx->in_stream = callback_ctx->in_stream; + mime_cb_ctx->env = callback_ctx->env; + mime_cb_ctx->content_length = callback_ctx->content_length; + mime_cb_ctx->unread_len = callback_ctx->unread_len; + mime_cb_ctx->chunked_stream = callback_ctx->chunked_stream; + } + } + + stream = axutil_stream_create_basic(env); + if(stream) + { + axutil_stream_write(stream, env, soap_body_str, soap_body_len); + callback_ctx->in_stream = stream; + callback_ctx->chunked_stream = NULL; + callback_ctx->content_length = soap_body_len; + callback_ctx->unread_len = soap_body_len; + } + /*axiom_mime_parser_free(mime_parser, env); + mime_parser = NULL;*/ + + /*AXIS2_FREE(env->allocator, mime_boundary);*/ + } + /*AXIS2_FREE(env->allocator, mime_boundary);*/ + } + + if(soap_action_header) + { + axis2_msg_ctx_set_soap_action(msg_ctx, env, soap_action_header); + + } + else if(soap_action) + { + axutil_string_t *soap_action_str = NULL; + soap_action_str = axutil_string_create(env, soap_action); + axis2_msg_ctx_set_soap_action(msg_ctx, env, soap_action_str); + axutil_string_free(soap_action_str, env); + } + axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri)); + + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + + char_set_str = axis2_http_transport_utils_get_charset_enc(env, content_type); + xml_reader = axiom_xml_reader_create_for_io(env, axis2_http_transport_utils_on_data_request, + NULL, (void *)callback_ctx, axutil_string_get_buffer(char_set_str, env)); + + if(!xml_reader) + { + return AXIS2_FAILURE; + } + + axis2_msg_ctx_set_charset_encoding(msg_ctx, env, char_set_str); + + om_builder = axiom_stax_builder_create(env, xml_reader); + if(!om_builder) + { + axiom_xml_reader_free(xml_reader, env); + xml_reader = NULL; + return AXIS2_FAILURE; + } + + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP)) + { + is_soap11 = AXIS2_FALSE; + soap_builder = axiom_soap_builder_create(env, om_builder, + AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI); + if(!soap_builder) + { + /* We should not be freeing om_builder here as it is done by + axiom_soap_builder_create in case of error - Samisa */ + om_builder = NULL; + xml_reader = NULL; + axis2_msg_ctx_set_is_soap_11(msg_ctx, env, is_soap11); + return AXIS2_FAILURE; + } + + soap_envelope = axiom_soap_builder_get_soap_envelope(soap_builder, env); + if(!soap_envelope) + { + axiom_stax_builder_free(om_builder, env); + om_builder = NULL; + xml_reader = NULL; + axiom_soap_builder_free(soap_builder, env); + soap_builder = NULL; + axis2_msg_ctx_set_is_soap_11(msg_ctx, env, is_soap11); + return AXIS2_FAILURE; + } + } + else if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML)) + { + is_soap11 = AXIS2_TRUE; + if(soap_action_header) + { + soap_builder = axiom_soap_builder_create(env, om_builder, + AXIOM_SOAP11_SOAP_ENVELOPE_NAMESPACE_URI); + if(!soap_builder) + { + /* We should not be freeing om_builder here as it is done by + axiom_soap_builder_create in case of error - Samisa */ + om_builder = NULL; + xml_reader = NULL; + axis2_msg_ctx_set_is_soap_11(msg_ctx, env, is_soap11); + return AXIS2_FAILURE; + } + soap_envelope = axiom_soap_builder_get_soap_envelope(soap_builder, env); + if(!soap_envelope) + { + axiom_soap_builder_free(soap_builder, env); + om_builder = NULL; + xml_reader = NULL; + soap_builder = NULL; + axis2_msg_ctx_set_is_soap_11(msg_ctx, env, is_soap11); + return AXIS2_FAILURE; + } + } + else + { + /* REST support */ + do_rest = AXIS2_TRUE; + } + } + + else if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_X_WWW_FORM_URLENCODED)) + { + /* REST support */ + do_rest = AXIS2_TRUE; + run_as_get = AXIS2_TRUE; + } + else + { + http_error_property = axutil_property_create(env); + axutil_property_set_value(http_error_property, env, AXIS2_HTTP_UNSUPPORTED_MEDIA_TYPE); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_TRANSPORT_ERROR, http_error_property); + } + + if(soap_builder) + { + if(mime_parser) + { + axiom_soap_builder_set_mime_parser(soap_builder, env, mime_parser); + if(mime_cb_ctx) + { + axiom_soap_builder_set_callback_ctx(soap_builder, env, mime_cb_ctx); + axiom_soap_builder_set_callback_function(soap_builder, env, + axis2_http_transport_utils_on_data_request); + } + else if(is_svc_callback) + { + return AXIS2_FAILURE; + } + } + } + + if(do_rest) + { + /* REST support */ + axutil_param_t *rest_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_ENABLE_REST); + if(rest_param && 0 == axutil_strcmp(AXIS2_VALUE_TRUE, axutil_param_get_value(rest_param, + env))) + { + axiom_soap_body_t *def_body = NULL; + axiom_document_t *om_doc = NULL; + axiom_node_t *root_node = NULL; + if(!run_as_get) + { + soap_envelope = axiom_soap_envelope_create_default_soap_envelope(env, AXIOM_SOAP11); + def_body = axiom_soap_envelope_get_body(soap_envelope, env); + om_doc = axiom_stax_builder_get_document(om_builder, env); + root_node = axiom_document_build_all(om_doc, env); + axiom_soap_body_add_child(def_body, env, root_node); + } + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_POST); + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + } + else + { + return AXIS2_FAILURE; + } + if(AXIS2_SUCCESS != axis2_http_transport_utils_dispatch_and_verify(env, msg_ctx)) + { + return AXIS2_FAILURE; + } + } + + if(run_as_get) + { + axis2_char_t *buffer = NULL; + axis2_char_t *new_url = NULL; + buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (content_length + 1)); + if(!buffer) + { + return AXIS2_FAILURE; + } + axis2_http_transport_utils_on_data_request(buffer, content_length, (void *)callback_ctx); + + new_url = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * ((int)(strlen(request_uri) + + strlen(buffer)) + 2)); + if(!new_url) + { + return AXIS2_FAILURE; + } + sprintf(new_url, "%s?%s", request_uri, buffer); + AXIS2_FREE(env->allocator, buffer); + + soap_envelope = axis2_http_transport_utils_handle_media_type_url_encoded(env, msg_ctx, + axis2_http_transport_utils_get_request_params(env, new_url), AXIS2_HTTP_POST); + } + + if(binary_data_map) + { + axiom_soap_builder_set_mime_body_parts(soap_builder, env, binary_data_map); + } + + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + + engine = axis2_engine_create(env, conf_ctx); + + if(!soap_envelope) + return AXIS2_FAILURE; + + soap_body = axiom_soap_envelope_get_body(soap_envelope, env); + + if(!soap_body) + return AXIS2_FAILURE; + + if(!is_svc_callback) + { + is_client_property = axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_TRANPORT_IS_APPLICATION_CLIENT_SIDE); + if(is_client_property) + { + axis2_char_t *prop_value = NULL; + prop_value = axutil_property_get_value(is_client_property, env); + if(prop_value && !axutil_strcmp(prop_value , AXIS2_VALUE_TRUE)) + { + is_application_client_side = AXIS2_TRUE; + } + } + if(mime_boundary || is_application_client_side) + { + check_for_fault = AXIS2_TRUE; + } + if(check_for_fault) + { + has_fault = axiom_soap_body_has_fault(soap_body, env); + } + if(has_fault) + { + status = axis2_engine_receive_fault(engine, env, msg_ctx); + } + else + { + status = axis2_engine_receive(engine, env, msg_ctx); + } + } + else + { + status = axis2_engine_receive(engine, env, msg_ctx); + } + + if(!axis2_msg_ctx_get_soap_envelope(msg_ctx, env) && AXIS2_FALSE == is_soap11) + { + axiom_soap_envelope_t *def_envelope = axiom_soap_envelope_create_default_soap_envelope(env, + AXIOM_SOAP12); + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, def_envelope); + } + + if(engine) + { + axis2_engine_free(engine, env); + } + + if(soap_body_str) + { + AXIS2_FREE(env->allocator, soap_body_str); + } + + if(stream) + { + axutil_stream_free(stream, env); + } + + if(char_set_str) + { + axutil_string_free(char_set_str, env); + } + if(!soap_builder && om_builder) + { + axiom_stax_builder_free_self(om_builder, env); + om_builder = NULL; + } + if(!axutil_string_get_buffer(soap_action_header, env) && soap_action) + { + AXIS2_FREE(env->allocator, soap_action); + soap_action = NULL; + } + return status; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_process_http_put_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + const int content_length, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri) +{ + axiom_soap_envelope_t *soap_envelope = NULL; + axiom_soap_builder_t *soap_builder = NULL; + axiom_stax_builder_t *om_builder = NULL; + axis2_bool_t is_soap11 = AXIS2_FALSE; + axiom_xml_reader_t *xml_reader = NULL; + axutil_string_t *char_set_str = NULL; + + axis2_conf_ctx_t *conf_ctx = NULL; + axis2_callback_info_t *callback_ctx; + axutil_hash_t *headers = NULL; + axis2_engine_t *engine = NULL; + axiom_soap_body_t *soap_body = NULL; + axis2_status_t status = AXIS2_FAILURE; + axutil_hash_t *binary_data_map = NULL; + axis2_char_t *soap_body_str = NULL; + axutil_stream_t *stream = NULL; + axis2_bool_t do_rest = AXIS2_FALSE; + axis2_bool_t run_as_get = AXIS2_FALSE; + axutil_property_t *http_error_property = NULL; + axutil_property_t *is_client_property = NULL; + axis2_bool_t is_application_client_side = AXIS2_FALSE; + axis2_char_t *mime_boundary = NULL; + axis2_bool_t check_for_fault = AXIS2_FALSE; + axis2_bool_t has_fault = AXIS2_FALSE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, in_stream, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, out_stream, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, content_type, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, request_uri, AXIS2_FAILURE); + + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + + callback_ctx = AXIS2_MALLOC(env->allocator, sizeof(axis2_callback_info_t)); + /* Note: the memory created above is freed in xml reader free function + as this is passed on to the reader */ + callback_ctx->in_stream = in_stream; + callback_ctx->env = env; + callback_ctx->content_length = content_length; + callback_ctx->unread_len = content_length; + callback_ctx->chunked_stream = NULL; + + headers = axis2_msg_ctx_get_transport_headers(msg_ctx, env); + if(headers) + { + axis2_http_header_t *encoding_header = NULL; + encoding_header = (axis2_http_header_t *)axutil_hash_get(headers, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING, AXIS2_HASH_KEY_STRING); + + if(encoding_header) + { + axis2_char_t *encoding_value = NULL; + encoding_value = axis2_http_header_get_value(encoding_header, env); + if(encoding_value && 0 == axutil_strcasecmp(encoding_value, + AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + callback_ctx->chunked_stream = axutil_http_chunked_stream_create(env, in_stream); + if(!callback_ctx->chunked_stream) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error occured in" + " creating in chunked stream."); + return AXIS2_FAILURE; + } + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "HTTP" + " stream chunked"); + } + } + } + else + { + /* check content encoding from msg ctx property */ + axis2_char_t *value = axis2_msg_ctx_get_transfer_encoding(msg_ctx, env); + + if(value && axutil_strstr(value, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + /* this is an UGLY hack to get some of the transports working + e.g. PHP transport where it strips the chunking info in case of chunking + and also gives out a content lenght of 0. + We need to fix the transport design to fix sutuations like this. + */ + callback_ctx->content_length = AXIS2_CHUNKED_CONTENT_LENGTH; + callback_ctx->unread_len = callback_ctx->content_length; + } + } + + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_MULTIPART_RELATED)) + { + /* get mime boundry */ + mime_boundary = axis2_http_transport_utils_get_value_from_content_type(env, + content_type, AXIS2_HTTP_HEADER_CONTENT_TYPE_MIME_BOUNDARY); + + if(mime_boundary) + { + axiom_mime_parser_t *mime_parser = NULL; + int soap_body_len = 0; + axutil_param_t *buffer_size_param = NULL; + axutil_param_t *max_buffers_param = NULL; + axutil_param_t *attachment_dir_param = NULL; + axutil_param_t *callback_name_param = NULL; + axis2_char_t *value_size = NULL; + axis2_char_t *value_num = NULL; + axis2_char_t *value_dir = NULL; + axis2_char_t *value_callback = NULL; + int size = 0; + int num = 0; + + mime_parser = axiom_mime_parser_create(env); + + buffer_size_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_MTOM_BUFFER_SIZE); + if(buffer_size_param) + { + value_size = (axis2_char_t *)axutil_param_get_value(buffer_size_param, env); + if(value_size) + { + size = atoi(value_size); + axiom_mime_parser_set_buffer_size(mime_parser, env, size); + } + } + + max_buffers_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_MTOM_MAX_BUFFERS); + if(max_buffers_param) + { + value_num = (axis2_char_t *)axutil_param_get_value(max_buffers_param, env); + if(value_num) + { + num = atoi(value_num); + axiom_mime_parser_set_max_buffers(mime_parser, env, num); + } + } + + callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env, + AXIS2_MTOM_CACHING_CALLBACK); + if(callback_name_param) + { + value_callback = (axis2_char_t *)axutil_param_get_value(callback_name_param, env); + if(value_callback) + { + axiom_mime_parser_set_caching_callback_name(mime_parser, env, value_callback); + } + } + + attachment_dir_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_ATTACHMENT_DIR); + + if(attachment_dir_param) + { + value_dir = (axis2_char_t *)axutil_param_get_value(attachment_dir_param, env); + if(value_dir) + { + axiom_mime_parser_set_attachment_dir(mime_parser, env, value_dir); + } + } + + if(mime_parser) + { + /*binary_data_map = + axiom_mime_parser_parse(mime_parser, env, + axis2_http_transport_utils_on_data_request, + (void *) callback_ctx, + mime_boundary);*/ + if(!binary_data_map) + { + return AXIS2_FAILURE; + } + soap_body_len = (int)axiom_mime_parser_get_soap_body_len(mime_parser, env); + soap_body_str = axiom_mime_parser_get_soap_body_str(mime_parser, env); + } + + stream = axutil_stream_create_basic(env); + if(stream) + { + axutil_stream_write(stream, env, soap_body_str, soap_body_len); + callback_ctx->in_stream = stream; + callback_ctx->chunked_stream = NULL; + callback_ctx->content_length = soap_body_len; + callback_ctx->unread_len = soap_body_len; + } + axiom_mime_parser_free(mime_parser, env); + mime_parser = NULL; + } + /*AXIS2_FREE(env->allocator, mime_boundary);*/ + } + + axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri)); + + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + + char_set_str = axis2_http_transport_utils_get_charset_enc(env, content_type); + xml_reader = axiom_xml_reader_create_for_io(env, axis2_http_transport_utils_on_data_request, + NULL, (void *)callback_ctx, axutil_string_get_buffer(char_set_str, env)); + + if(!xml_reader) + { + return AXIS2_FAILURE; + } + + axis2_msg_ctx_set_charset_encoding(msg_ctx, env, char_set_str); + + om_builder = axiom_stax_builder_create(env, xml_reader); + if(!om_builder) + { + axiom_xml_reader_free(xml_reader, env); + xml_reader = NULL; + return AXIS2_FAILURE; + } + + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP)) + { + is_soap11 = AXIS2_FALSE; + soap_builder = axiom_soap_builder_create(env, om_builder, + AXIOM_SOAP12_SOAP_ENVELOPE_NAMESPACE_URI); + if(!soap_builder) + { + /* We should not be freeing om_builder here as it is done by + axiom_soap_builder_create in case of error - Samisa */ + om_builder = NULL; + xml_reader = NULL; + axis2_msg_ctx_set_is_soap_11(msg_ctx, env, is_soap11); + return AXIS2_FAILURE; + } + + soap_envelope = axiom_soap_builder_get_soap_envelope(soap_builder, env); + if(!soap_envelope) + { + axiom_stax_builder_free(om_builder, env); + om_builder = NULL; + xml_reader = NULL; + axiom_soap_builder_free(soap_builder, env); + soap_builder = NULL; + axis2_msg_ctx_set_is_soap_11(msg_ctx, env, is_soap11); + return AXIS2_FAILURE; + } + } + else if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML)) + { + do_rest = AXIS2_TRUE; + if(soap_action_header) + { + return AXIS2_FAILURE; + } + else + { + /* REST support */ + do_rest = AXIS2_TRUE; + } + } + else if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_X_WWW_FORM_URLENCODED)) + { + /* REST support */ + do_rest = AXIS2_TRUE; + run_as_get = AXIS2_TRUE; + } + else + { + http_error_property = axutil_property_create(env); + axutil_property_set_value(http_error_property, env, AXIS2_HTTP_UNSUPPORTED_MEDIA_TYPE); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_HTTP_TRANSPORT_ERROR, http_error_property); + } + + if(do_rest) + { + /* REST support */ + axutil_param_t *rest_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_ENABLE_REST); + if(rest_param && 0 == axutil_strcmp(AXIS2_VALUE_TRUE, axutil_param_get_value(rest_param, + env))) + { + axiom_soap_body_t *def_body = NULL; + axiom_document_t *om_doc = NULL; + axiom_node_t *root_node = NULL; + if(!run_as_get) + { + soap_envelope = axiom_soap_envelope_create_default_soap_envelope(env, AXIOM_SOAP11); + def_body = axiom_soap_envelope_get_body(soap_envelope, env); + om_doc = axiom_stax_builder_get_document(om_builder, env); + root_node = axiom_document_build_all(om_doc, env); + axiom_soap_body_add_child(def_body, env, root_node); + } + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_PUT); + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + } + else + { + return AXIS2_FAILURE; + } + if(AXIS2_SUCCESS != axis2_http_transport_utils_dispatch_and_verify(env, msg_ctx)) + { + return AXIS2_FAILURE; + } + } + + if(run_as_get) + { + axis2_char_t *buffer = NULL; + axis2_char_t *new_url = NULL; + buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (content_length + 1)); + if(!buffer) + { + return AXIS2_FAILURE; + } + axis2_http_transport_utils_on_data_request(buffer, content_length, (void *)callback_ctx); + + new_url = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * ((int)(strlen(request_uri) + + strlen(buffer)) + 2)); + if(!new_url) + { + return AXIS2_FAILURE; + } + sprintf(new_url, "%s?%s", request_uri, buffer); + AXIS2_FREE(env->allocator, buffer); + + soap_envelope = axis2_http_transport_utils_handle_media_type_url_encoded(env, msg_ctx, + axis2_http_transport_utils_get_request_params(env, new_url), AXIS2_HTTP_POST); + } + + if(binary_data_map) + { + axiom_soap_builder_set_mime_body_parts(soap_builder, env, binary_data_map); + } + + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + + engine = axis2_engine_create(env, conf_ctx); + + if(!soap_envelope) + return AXIS2_FAILURE; + + soap_body = axiom_soap_envelope_get_body(soap_envelope, env); + + if(!soap_body) + return AXIS2_FAILURE; + + is_client_property = axis2_msg_ctx_get_property(msg_ctx, env, + AXIS2_TRANPORT_IS_APPLICATION_CLIENT_SIDE); + if(is_client_property) + { + axis2_char_t *prop_value = NULL; + prop_value = axutil_property_get_value(is_client_property, env); + if(prop_value && !axutil_strcmp(prop_value , AXIS2_VALUE_TRUE)) + { + is_application_client_side = AXIS2_TRUE; + } + } + if(mime_boundary || is_application_client_side) + { + check_for_fault = AXIS2_TRUE; + } + if(check_for_fault) + { + has_fault = axiom_soap_body_has_fault(soap_body, env); + } + if(has_fault) + { + status = axis2_engine_receive_fault(engine, env, msg_ctx); + } + else + { + status = axis2_engine_receive(engine, env, msg_ctx); + } + if(mime_boundary) + { + AXIS2_FREE(env->allocator, mime_boundary); + } + if(!axis2_msg_ctx_get_soap_envelope(msg_ctx, env) && AXIS2_FALSE == is_soap11) + { + axiom_soap_envelope_t *def_envelope = axiom_soap_envelope_create_default_soap_envelope(env, + AXIOM_SOAP12); + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, def_envelope); + } + + if(engine) + { + axis2_engine_free(engine, env); + } + + if(soap_body_str) + { + AXIS2_FREE(env->allocator, soap_body_str); + } + + if(stream) + { + axutil_stream_free(stream, env); + } + + if(char_set_str) + { + axutil_string_free(char_set_str, env); + } + if(!soap_builder && om_builder) + { + axiom_stax_builder_free_self(om_builder, env); + om_builder = NULL; + } + return status; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_process_http_head_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri, + axis2_conf_ctx_t * conf_ctx, + axutil_hash_t * request_params) +{ + axiom_soap_envelope_t *soap_envelope = NULL; + axis2_engine_t *engine = NULL; + axis2_bool_t do_rest = AXIS2_TRUE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, in_stream, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, out_stream, AXIS2_FALSE); + + AXIS2_PARAM_CHECK(env->error, request_uri, AXIS2_FALSE); + + axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri)); + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML)) + { + if(soap_action_header) + { + do_rest = AXIS2_FALSE; + } + } + else if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP)) + { + do_rest = AXIS2_FALSE; + } + + if(do_rest) + { + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_HEAD); + } + else + { + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_FALSE); + } + if(AXIS2_SUCCESS != axis2_http_transport_utils_dispatch_and_verify(env, msg_ctx)) + { + return AXIS2_FALSE; + } + + soap_envelope = axis2_http_transport_utils_handle_media_type_url_encoded(env, msg_ctx, + request_params, AXIS2_HTTP_HEAD); + if(!soap_envelope) + { + return AXIS2_FALSE; + } + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + engine = axis2_engine_create(env, conf_ctx); + axis2_engine_receive(engine, env, msg_ctx); + return AXIS2_TRUE; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_process_http_get_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri, + axis2_conf_ctx_t * conf_ctx, + axutil_hash_t * request_params) +{ + axiom_soap_envelope_t *soap_envelope = NULL; + axis2_engine_t *engine = NULL; + axis2_bool_t do_rest = AXIS2_TRUE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, in_stream, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, out_stream, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, request_uri, AXIS2_FALSE); + + axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri)); + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + if(content_type && strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML)) + { + if(soap_action_header) + { + do_rest = AXIS2_FALSE; + } + } + else if(content_type && strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP)) + { + do_rest = AXIS2_FALSE; + } + + if(do_rest) + { + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_GET); + } + else + { + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_FALSE); + } + + if(AXIS2_SUCCESS != axis2_http_transport_utils_dispatch_and_verify(env, msg_ctx)) + { + return AXIS2_FALSE; + } + soap_envelope = axis2_http_transport_utils_handle_media_type_url_encoded(env, msg_ctx, + request_params, AXIS2_HTTP_GET); + if(!soap_envelope) + { + return AXIS2_FALSE; + } + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + + engine = axis2_engine_create(env, conf_ctx); + axis2_engine_receive(engine, env, msg_ctx); + return AXIS2_TRUE; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_process_http_delete_request( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_stream_t * in_stream, + axutil_stream_t * out_stream, + const axis2_char_t * content_type, + axutil_string_t * soap_action_header, + const axis2_char_t * request_uri, + axis2_conf_ctx_t * conf_ctx, + axutil_hash_t * request_params) +{ + axiom_soap_envelope_t *soap_envelope = NULL; + axis2_engine_t *engine = NULL; + axis2_bool_t do_rest = AXIS2_TRUE; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, in_stream, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, out_stream, AXIS2_FALSE); + AXIS2_PARAM_CHECK(env->error, request_uri, AXIS2_FALSE); + + axis2_msg_ctx_set_to(msg_ctx, env, axis2_endpoint_ref_create(env, request_uri)); + axis2_msg_ctx_set_server_side(msg_ctx, env, AXIS2_TRUE); + if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML)) + { + if(soap_action_header) + { + do_rest = AXIS2_FALSE; + } + } + else if(strstr(content_type, AXIS2_HTTP_HEADER_ACCEPT_APPL_SOAP)) + { + do_rest = AXIS2_FALSE; + } + + if(do_rest) + { + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_TRUE); + axis2_msg_ctx_set_rest_http_method(msg_ctx, env, AXIS2_HTTP_DELETE); + } + else + { + axis2_msg_ctx_set_doing_rest(msg_ctx, env, AXIS2_FALSE); + } + + soap_envelope = axis2_http_transport_utils_handle_media_type_url_encoded(env, msg_ctx, + request_params, AXIS2_HTTP_DELETE); + if(!soap_envelope) + { + return AXIS2_FALSE; + } + + axis2_msg_ctx_set_soap_envelope(msg_ctx, env, soap_envelope); + + if(AXIS2_SUCCESS != axis2_http_transport_utils_dispatch_and_verify(env, msg_ctx)) + { + return AXIS2_FALSE; + } + engine = axis2_engine_create(env, conf_ctx); + axis2_engine_receive(engine, env, msg_ctx); + return AXIS2_TRUE; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_do_write_mtom( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + return (axis2_msg_ctx_get_doing_mtom(msg_ctx, env)); +} + +AXIS2_EXTERN axutil_hash_t *AXIS2_CALL +axis2_http_transport_utils_get_request_params( + const axutil_env_t * env, + axis2_char_t * request_uri) +{ + + axis2_char_t *query_str = NULL; + axis2_char_t *tmp = strchr(request_uri, AXIS2_Q_MARK); + axis2_char_t *tmp2 = NULL; + axis2_char_t *tmp_name = NULL; + axis2_char_t *tmp_value = NULL; + axutil_hash_t *ret = NULL; + + AXIS2_PARAM_CHECK(env->error, request_uri, NULL); + + if(!tmp || AXIS2_ESC_NULL == *(tmp + 1)) + { + return NULL; + } + query_str = axutil_strdup(env, tmp + 1); + + for(tmp2 = tmp = query_str; *tmp != AXIS2_ESC_NULL; ++tmp) + { + if(AXIS2_EQ == *tmp) + { + *tmp = AXIS2_ESC_NULL; + tmp_name = axutil_strdup(env, tmp2); + axis2_http_transport_utils_strdecode(env, tmp_name, tmp_name); + tmp2 = tmp + 1; + } + if(AXIS2_AND == *tmp) + { + *tmp = AXIS2_ESC_NULL; + tmp_value = axutil_strdup(env, tmp2); + axis2_http_transport_utils_strdecode(env, tmp_value, tmp_value); + tmp2 = tmp + 1; + } + if(tmp_name && NULL != tmp_value) + { + if(!ret) + { + ret = axutil_hash_make(env); + } + axutil_hash_set(ret, tmp_name, AXIS2_HASH_KEY_STRING, tmp_value); + tmp_name = NULL; + tmp_value = NULL; + } + } + if(tmp_name && AXIS2_ESC_NULL != *tmp2) + { + if(!ret) + { + ret = axutil_hash_make(env); + } + tmp_value = axutil_strdup(env, tmp2); + axis2_http_transport_utils_strdecode(env, tmp_value, tmp_value); + axutil_hash_set(ret, tmp_name, AXIS2_HASH_KEY_STRING, tmp_value); + } + + return ret; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_strdecode( + const axutil_env_t * env, + axis2_char_t * dest, + axis2_char_t * src) +{ + AXIS2_PARAM_CHECK(env->error, dest, AXIS2_FAILURE); + AXIS2_PARAM_CHECK(env->error, src, AXIS2_FAILURE); + + for(; *src != AXIS2_ESC_NULL; ++dest, ++src) + { + if(src[0] == AXIS2_PERCENT && isxdigit((int)src[1]) && isxdigit((int)src[2])) + { + *dest = (axis2_char_t)(axis2_http_transport_utils_hexit(src[1]) * 16 + + axis2_http_transport_utils_hexit(src[2])); + /* We are sure that the conversion is valid */ + src += 2; + } + else + { + *dest = *src; + } + } + *dest = AXIS2_ESC_NULL; + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN int AXIS2_CALL +axis2_http_transport_utils_hexit( + axis2_char_t c) +{ + if(c >= '0' && c <= '9') + { + return c - '0'; + } + if(c >= 'a' && c <= 'f') + { + return c - 'a' + 10; + } + if(c >= 'A' && c <= 'F') + { + return c - 'A' + 10; + } + return 0; /* shouldn't happen, we're guarded by isxdigit() */ +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_not_found( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_NOT_FOUND; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_not_implemented( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_NOT_IMPLEMENTED; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_internal_server_error( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_INTERNAL_SERVER_ERROR; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_method_not_allowed( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_METHOD_NOT_ALLOWED; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_not_acceptable( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_NOT_ACCEPTABLE; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_bad_request( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_BAD_REQUEST; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_request_timeout( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_REQUEST_TIMEOUT; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_conflict( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_CONFLICT; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_gone( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_GONE; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_precondition_failed( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_PRECONDITION_FAILED; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_request_entity_too_large( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_TOO_LARGE; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_service_unavailable( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + return AXIS2_HTTP_SERVICE_UNAVILABLE; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_services_html( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx) +{ + axutil_hash_t *services_map = NULL; + axutil_hash_t *errorneous_svc_map = NULL; + axis2_char_t *ret = NULL; + axis2_char_t *tmp2 = (axis2_char_t *)"

Deployed Services

"; + axutil_hash_index_t *hi = NULL; + axis2_bool_t svcs_exists = AXIS2_FALSE; + axis2_conf_t *conf = NULL; + AXIS2_PARAM_CHECK(env->error, conf_ctx, NULL); + + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + services_map = axis2_conf_get_all_svcs(conf, env); + errorneous_svc_map = axis2_conf_get_all_faulty_svcs(conf, env); + if(services_map && 0 != axutil_hash_count(services_map)) + { + void *service = NULL; + axis2_char_t *sname = NULL; + axutil_hash_t *ops = NULL; + svcs_exists = AXIS2_TRUE; + + for(hi = axutil_hash_first(services_map, env); hi; hi = axutil_hash_next(env, hi)) + { + axutil_hash_this(hi, NULL, NULL, &service); + sname = axutil_qname_get_localpart(axis2_svc_get_qname(((axis2_svc_t *)service), env), + env); + ret = axutil_stracat(env, tmp2, "

"); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, sname); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, "

"); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, "

"); + tmp2 = ret; + + /** + *setting services description */ + ret = axutil_stracat(env, tmp2, axis2_svc_get_svc_desc((axis2_svc_t *)service, env)); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, "

"); + tmp2 = ret; + ops = axis2_svc_get_all_ops(((axis2_svc_t *)service), env); + if(ops && 0 != axutil_hash_count(ops)) + { + axutil_hash_index_t *hi2 = NULL; + void *op = NULL; + axis2_char_t *oname = NULL; + + ret = axutil_stracat(env, tmp2, "Available Operations
    "); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + for(hi2 = axutil_hash_first(ops, env); hi2; hi2 = axutil_hash_next(env, hi2)) + { + axutil_hash_this(hi2, NULL, NULL, &op); + oname = axutil_qname_get_localpart(axis2_op_get_qname(((axis2_op_t *)op), env), + env); + ret = axutil_stracat(env, tmp2, "
  • "); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + + ret = axutil_stracat(env, tmp2, oname); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, "
  • "); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + } + ret = axutil_stracat(env, tmp2, "
"); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + } + else + { + ret = axutil_stracat(env, tmp2, "No operations Available"); + tmp2 = ret; + } + } + } + + if(errorneous_svc_map && 0 != axutil_hash_count(errorneous_svc_map)) + { + void *fsname = NULL; + svcs_exists = AXIS2_TRUE; + ret = axutil_stracat(env, tmp2, + "

Faulty \ + Services

"); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + + for(hi = axutil_hash_first(errorneous_svc_map, env); hi; axutil_hash_next(env, hi)) + { + axutil_hash_this(hi, (const void **)&fsname, NULL, NULL); + ret = axutil_stracat(env, tmp2, "

"); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, (axis2_char_t *)fsname); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, "

"); + AXIS2_FREE(env->allocator, tmp2); + tmp2 = ret; + } + } + if(AXIS2_FALSE == svcs_exists) + { + ret = axutil_strdup(env, "

There are no services deployed

"); + } + ret = axutil_stracat(env, "Axis2C :: Services" + "", tmp2); + tmp2 = ret; + ret = axutil_stracat(env, tmp2, "\r\n"); + + return ret; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_services_static_wsdl( + const axutil_env_t * env, + axis2_conf_ctx_t * conf_ctx, + axis2_char_t * request_url) +{ + axis2_char_t *wsdl_string = NULL; + axis2_char_t *wsdl_path = NULL; + axis2_char_t **url_tok = NULL; + unsigned int len = 0; + axis2_char_t *svc_name = NULL; + axis2_conf_t *conf = NULL; + axutil_hash_t *services_map = NULL; + axutil_hash_index_t *hi = NULL; + + AXIS2_PARAM_CHECK(env->error, conf_ctx, NULL); + AXIS2_PARAM_CHECK(env->error, request_url, NULL); + + url_tok = axutil_parse_request_url_for_svc_and_op(env, request_url); + if(url_tok[0]) + { + len = (int)strlen(url_tok[0]); + /* We are sure that the difference lies within the int range */ + url_tok[0][len - 5] = 0; + svc_name = url_tok[0]; + } + + conf = axis2_conf_ctx_get_conf(conf_ctx, env); + services_map = axis2_conf_get_all_svcs(conf, env); + + if(services_map && 0 != axutil_hash_count(services_map)) + { + void *service = NULL; + axis2_char_t *sname = NULL; + + for(hi = axutil_hash_first(services_map, env); hi; hi = axutil_hash_next(env, hi)) + { + axutil_hash_this(hi, NULL, NULL, &service); + sname = axutil_qname_get_localpart(axis2_svc_get_qname(((axis2_svc_t *)service), env), + env); + if(!axutil_strcmp(svc_name, sname)) + { + wsdl_path = (axis2_char_t *)axutil_strdup(env, axis2_svc_get_svc_wsdl_path( + (axis2_svc_t *)service, env)); + if(!wsdl_path) + { + wsdl_path = axutil_strcat(env, axis2_svc_get_svc_folder_path( + (axis2_svc_t *)service, env), AXIS2_PATH_SEP_STR, svc_name, ".wsdl", NULL); + } + break; + } + + } + } + + if(wsdl_path) + { + FILE *wsdl_file = NULL; + axis2_char_t *content = NULL; + int c; + int size = AXIS2_FILE_READ_SIZE; + axis2_char_t *tmp; + int i = 0; + + content = (axis2_char_t *)AXIS2_MALLOC(env->allocator, size); + wsdl_file = fopen(wsdl_path, "r"); + if(wsdl_file) + { + c = fgetc(wsdl_file); + while(c != EOF) + { + if(i >= size) + { + size = size * 3; + tmp = (axis2_char_t *)AXIS2_MALLOC(env->allocator, size); + memcpy(tmp, content, i); + AXIS2_FREE(env->allocator, content); + content = tmp; + } + content[i++] = (axis2_char_t)c; + c = fgetc(wsdl_file); + } + content[i] = AXIS2_ESC_NULL; + wsdl_string = (axis2_char_t *)content; + fclose(wsdl_file); + } + + AXIS2_FREE(env->allocator, wsdl_path); + } + else + { + wsdl_string = axutil_strdup(env, "Unable to retrieve wsdl for this service"); + } + + return wsdl_string; +} + +AXIS2_EXTERN axutil_string_t *AXIS2_CALL +axis2_http_transport_utils_get_charset_enc( + const axutil_env_t * env, + const axis2_char_t * content_type) +{ + axis2_char_t *tmp = NULL; + axis2_char_t *tmp_content_type = NULL; + axis2_char_t *tmp2 = NULL; + axutil_string_t *str = NULL; + + AXIS2_PARAM_CHECK(env->error, content_type, NULL); + + tmp_content_type = (axis2_char_t *)content_type; + if(!tmp_content_type) + { + return axutil_string_create_const(env, + (axis2_char_t **)&AXIS2_TRANS_UTIL_DEFAULT_CHAR_ENCODING); + } + + tmp = strstr(tmp_content_type, AXIS2_HTTP_CHAR_SET_ENCODING); + + if(tmp) + { + tmp = strchr(tmp, AXIS2_EQ); + if(tmp) + { + tmp2 = strchr(tmp, AXIS2_SEMI_COLON); + if(!tmp2) + { + tmp2 = tmp + strlen(tmp); + } + } + + if(tmp2) + { + if('\'' == *(tmp2 - sizeof(axis2_char_t)) || '\"' == *(tmp2 - sizeof(axis2_char_t))) + { + tmp2 -= sizeof(axis2_char_t); + } + *tmp2 = AXIS2_ESC_NULL; + } + } + + if(tmp) + { + /* Following formats are acceptable + * charset="UTF-8" + * charser='UTF-8' + * charset=UTF-8 + * But for our requirements charset we get should be UTF-8 + */ + if(AXIS2_ESC_SINGLE_QUOTE == *(tmp + sizeof(axis2_char_t)) || AXIS2_ESC_DOUBLE_QUOTE + == *(tmp + sizeof(axis2_char_t))) + { + tmp += 2 * sizeof(axis2_char_t); + } + else + { + tmp += sizeof(axis2_char_t); + } + } + + if(tmp) + { + str = axutil_string_create(env, tmp); + } + else + { + str = axutil_string_create_const(env, + (axis2_char_t **)&AXIS2_TRANS_UTIL_DEFAULT_CHAR_ENCODING); + } + return str; +} + +int AXIS2_CALL +axis2_http_transport_utils_on_data_request( + char *buffer, + int size, + void *ctx) +{ + const axutil_env_t *env = NULL; + int len = -1; + axis2_callback_info_t *cb_ctx = (axis2_callback_info_t *)ctx; + + if(!buffer || !ctx) + { + return 0; + } + env = ((axis2_callback_info_t *)ctx)->env; + if(cb_ctx->unread_len <= 0 && -1 != cb_ctx->content_length) + { + return 0; + } + if(cb_ctx->chunked_stream) + { + --size; + /* reserve space to insert trailing null */ + len = axutil_http_chunked_stream_read(cb_ctx->chunked_stream, env, buffer, size); + if(len >= 0) + { + buffer[len] = AXIS2_ESC_NULL; + } + } + else + { + axutil_stream_t *in_stream = NULL; + in_stream = (axutil_stream_t *)((axis2_callback_info_t *)ctx)->in_stream; + --size; /* reserve space to insert trailing null */ + len = axutil_stream_read(in_stream, env, buffer, size); + if(len > 0) + { + buffer[len] = AXIS2_ESC_NULL; + ((axis2_callback_info_t *)ctx)->unread_len -= len; + } + else if(len == 0) + { + ((axis2_callback_info_t *)ctx)->unread_len = 0; + } + } + return len; +} + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_http_transport_utils_create_soap_msg( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + const axis2_char_t * soap_ns_uri) +{ + axis2_op_ctx_t *op_ctx = NULL; + const axis2_char_t *char_set_enc = NULL; + axis2_char_t *content_type = NULL; + axutil_stream_t *in_stream = NULL; + axis2_callback_info_t *callback_ctx = NULL; + axis2_char_t *trans_enc = NULL; + int *content_length = NULL; + axutil_property_t *property = NULL; + axutil_hash_t *binary_data_map = NULL; + axiom_soap_envelope_t *soap_envelope = NULL; + axutil_stream_t *stream = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, NULL); + AXIS2_PARAM_CHECK(env->error, soap_ns_uri, NULL); + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_TRANSPORT_IN); + if(property) + { + in_stream = axutil_property_get_value(property, env); + property = NULL; + } + callback_ctx = AXIS2_MALLOC(env->allocator, sizeof(axis2_callback_info_t)); + /* Note: the memory created above is freed in xml reader free function + as this is passed on to the reader */ + if(!callback_ctx) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return NULL; + } + callback_ctx->in_stream = in_stream; + callback_ctx->env = env; + callback_ctx->content_length = -1; + callback_ctx->unread_len = -1; + callback_ctx->chunked_stream = NULL; + + property = axis2_msg_ctx_get_property(msg_ctx, env, AXIS2_HTTP_HEADER_CONTENT_LENGTH); + if(property) + { + content_length = axutil_property_get_value(property, env); + property = NULL; + } + + if(content_length) + { + callback_ctx->content_length = *content_length; + callback_ctx->unread_len = *content_length; + } + + if(!in_stream) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NULL_IN_STREAM_IN_MSG_CTX, AXIS2_FAILURE); + AXIS2_FREE(env->allocator, callback_ctx); + return NULL; + } + + trans_enc = axis2_msg_ctx_get_transfer_encoding(msg_ctx, env); + + if(trans_enc && 0 == axutil_strcmp(trans_enc, AXIS2_HTTP_HEADER_TRANSFER_ENCODING_CHUNKED)) + { + callback_ctx->chunked_stream = axutil_http_chunked_stream_create(env, in_stream); + if(!callback_ctx->chunked_stream) + { + return NULL; + } + } + + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + if(op_ctx) + { + axis2_ctx_t *ctx = axis2_op_ctx_get_base(op_ctx, env); + if(ctx) + { + property = axis2_ctx_get_property(ctx, env, AXIS2_CHARACTER_SET_ENCODING); + if(property) + { + char_set_enc = axutil_property_get_value(property, env); + property = NULL; + } + property = axis2_ctx_get_property(ctx, env, MTOM_RECIVED_CONTENT_TYPE); + if(property) + { + content_type = axutil_property_get_value(property, env); + property = NULL; + } + + } + } + + if(!char_set_enc) + { + char_set_enc = AXIS2_DEFAULT_CHAR_SET_ENCODING; + } + if(content_type) + { + axis2_char_t *mime_boundary = NULL; + axis2_msg_ctx_set_doing_mtom(msg_ctx, env, AXIS2_TRUE); + /* get mime boundry */ + mime_boundary = axis2_http_transport_utils_get_value_from_content_type(env, content_type, + AXIS2_HTTP_HEADER_CONTENT_TYPE_MIME_BOUNDARY); + + if(mime_boundary) + { + axiom_mime_parser_t *mime_parser = NULL; + int soap_body_len = 0; + axis2_char_t *soap_body_str = NULL; + axutil_param_t *buffer_size_param = NULL; + axutil_param_t *max_buffers_param = NULL; + axutil_param_t *attachment_dir_param = NULL; + axutil_param_t *callback_name_param = NULL; + axis2_char_t *value_size = NULL; + axis2_char_t *value_num = NULL; + axis2_char_t *value_dir = NULL; + axis2_char_t *value_callback = NULL; + int size = 0; + int num = 0; + + mime_parser = axiom_mime_parser_create(env); + + /* Following are the parameters in the axis2.xml regarding MTOM */ + + buffer_size_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_MTOM_BUFFER_SIZE); + if(buffer_size_param) + { + value_size = (axis2_char_t *)axutil_param_get_value(buffer_size_param, env); + + if(value_size) + { + size = atoi(value_size); + axiom_mime_parser_set_buffer_size(mime_parser, env, size); + } + } + + max_buffers_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_MTOM_MAX_BUFFERS); + if(max_buffers_param) + { + value_num = (axis2_char_t *)axutil_param_get_value(max_buffers_param, env); + if(value_num) + { + num = atoi(value_num); + axiom_mime_parser_set_max_buffers(mime_parser, env, num); + } + } + + callback_name_param = axis2_msg_ctx_get_parameter(msg_ctx, env, + AXIS2_MTOM_CACHING_CALLBACK); + if(callback_name_param) + { + value_callback = (axis2_char_t *)axutil_param_get_value(callback_name_param, env); + if(value_callback) + { + axiom_mime_parser_set_caching_callback_name(mime_parser, env, value_callback); + } + } + + attachment_dir_param = axis2_msg_ctx_get_parameter(msg_ctx, env, AXIS2_ATTACHMENT_DIR); + if(attachment_dir_param) + { + value_dir = (axis2_char_t *)axutil_param_get_value(attachment_dir_param, env); + if(value_dir) + { + axiom_mime_parser_set_attachment_dir(mime_parser, env, value_dir); + } + } + + if(mime_parser) + { + if(axiom_mime_parser_parse_for_soap(mime_parser, env, + axis2_http_transport_utils_on_data_request, (void *)callback_ctx, mime_boundary) + == AXIS2_FAILURE) + { + return NULL; + } + + binary_data_map = axiom_mime_parser_parse_for_attachments(mime_parser, env, + axis2_http_transport_utils_on_data_request, (void *)callback_ctx, + mime_boundary, NULL); + if(!binary_data_map) + { + return NULL; + } + + if(!binary_data_map) + { + return NULL; + } + + soap_body_len = (int)axiom_mime_parser_get_soap_body_len(mime_parser, env); + soap_body_str = axiom_mime_parser_get_soap_body_str(mime_parser, env); + } + + if(callback_ctx->chunked_stream) + { + axutil_http_chunked_stream_free(callback_ctx->chunked_stream, env); + callback_ctx->chunked_stream = NULL; + } + + stream = axutil_stream_create_basic(env); + if(stream) + { + axutil_stream_write(stream, env, soap_body_str, soap_body_len); + callback_ctx->in_stream = stream; + callback_ctx->chunked_stream = NULL; + callback_ctx->content_length = soap_body_len; + callback_ctx->unread_len = soap_body_len; + } + + axiom_mime_parser_free(mime_parser, env); + mime_parser = NULL; + if(mime_boundary) + { + AXIS2_FREE(env->allocator, mime_boundary); + } + + if(soap_body_str) + { + AXIS2_FREE(env->allocator, soap_body_str); + } + } + } + + if(AXIS2_TRUE != axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + axiom_xml_reader_t *xml_reader = NULL; + axiom_stax_builder_t *om_builder = NULL; + axiom_soap_builder_t *soap_builder = NULL; + + xml_reader = axiom_xml_reader_create_for_io(env, + axis2_http_transport_utils_on_data_request, NULL, (void *)callback_ctx, char_set_enc); + if(!xml_reader) + { + return NULL; + } + om_builder = axiom_stax_builder_create(env, xml_reader); + if(!om_builder) + { + axiom_xml_reader_free(xml_reader, env); + xml_reader = NULL; + return NULL; + } + soap_builder = axiom_soap_builder_create(env, om_builder, soap_ns_uri); + if(!soap_builder) + { + /* We should not be freeing om_builder here as it is done by + axiom_soap_builder_create in case of error - Samisa */ + om_builder = NULL; + xml_reader = NULL; + return NULL; + } + + soap_envelope = axiom_soap_builder_get_soap_envelope(soap_builder, env); + + if(binary_data_map) + { + axiom_soap_builder_set_mime_body_parts(soap_builder, env, binary_data_map); + } + + if(soap_envelope) + { + /* hack to get around MTOM problem */ + axiom_soap_body_t *soap_body = axiom_soap_envelope_get_body(soap_envelope, env); + + if(soap_body) + { + axiom_soap_body_has_fault(soap_body, env); + } + } + if(stream) + { + axutil_stream_free(stream, env); + callback_ctx->in_stream = NULL; + } + if(callback_ctx->chunked_stream) + { + axutil_http_chunked_stream_free(callback_ctx->chunked_stream, env); + callback_ctx->chunked_stream = NULL; + } + + } + else + { + /* REST processing */ + axiom_xml_reader_t *xml_reader = NULL; + axiom_stax_builder_t *om_builder = NULL; + axiom_soap_body_t *def_body = NULL; + axiom_document_t *om_doc = NULL; + axiom_node_t *root_node = NULL; + + xml_reader = axiom_xml_reader_create_for_io(env, + axis2_http_transport_utils_on_data_request, NULL, (void *)callback_ctx, char_set_enc); + if(!xml_reader) + { + return NULL; + } + om_builder = axiom_stax_builder_create(env, xml_reader); + if(!om_builder) + { + axiom_xml_reader_free(xml_reader, env); + xml_reader = NULL; + return NULL; + } + soap_envelope = axiom_soap_envelope_create_default_soap_envelope(env, AXIOM_SOAP11); + def_body = axiom_soap_envelope_get_body(soap_envelope, env); + om_doc = axiom_stax_builder_get_document(om_builder, env); + root_node = axiom_document_build_all(om_doc, env); + axiom_soap_body_add_child(def_body, env, root_node); + axiom_stax_builder_free_self(om_builder, env); + } + + return soap_envelope; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_value_from_content_type( + const axutil_env_t * env, + const axis2_char_t * content_type, + const axis2_char_t * key) +{ + axis2_char_t *tmp = NULL; + axis2_char_t *tmp_content_type = NULL; + axis2_char_t *tmp2 = NULL; + + AXIS2_PARAM_CHECK(env->error, content_type, NULL); + AXIS2_PARAM_CHECK(env->error, key, NULL); + + tmp_content_type = axutil_strdup(env, content_type); + if(!tmp_content_type) + { + return NULL; + } + tmp = strstr(tmp_content_type, key); + if(!tmp) + { + AXIS2_FREE(env->allocator, tmp_content_type); + return NULL; + } + + tmp = strchr(tmp, AXIS2_EQ); + tmp2 = strchr(tmp, AXIS2_SEMI_COLON); + + if(tmp2) + { + *tmp2 = AXIS2_ESC_NULL; + } + if(!tmp) + { + AXIS2_FREE(env->allocator, tmp_content_type); + return NULL; + } + + tmp2 = axutil_strdup(env, tmp + 1); + + AXIS2_FREE(env->allocator, tmp_content_type); + if(*tmp2 == AXIS2_DOUBLE_QUOTE) + { + tmp = tmp2; + tmp2 = axutil_strdup(env, tmp + 1); + tmp2[strlen(tmp2) - 1] = AXIS2_ESC_NULL; + if(tmp) + { + AXIS2_FREE(env->allocator, tmp); + tmp = NULL; + } + + } + /* handle XOP */ + if(*tmp2 == AXIS2_B_SLASH && *(tmp2 + 1) == '\"') + { + tmp = tmp2; + tmp2 = axutil_strdup(env, tmp + 2); + tmp2[strlen(tmp2) - 3] = AXIS2_ESC_NULL; + if(tmp) + { + AXIS2_FREE(env->allocator, tmp); + tmp = NULL; + } + } + return tmp2; +} + +AXIS2_EXTERN axiom_soap_envelope_t *AXIS2_CALL +axis2_http_transport_utils_handle_media_type_url_encoded( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx, + axutil_hash_t * param_map, + axis2_char_t * method) +{ + axiom_soap_envelope_t *soap_env = NULL; + axiom_soap_body_t *soap_body = NULL; + axiom_element_t *body_child = NULL; + axiom_node_t *body_child_node = NULL; + axiom_node_t *body_element_node = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, NULL); + AXIS2_PARAM_CHECK(env->error, method, NULL); + + soap_env = axis2_msg_ctx_get_soap_envelope(msg_ctx, env); + + if(!soap_env) + { + soap_env = axiom_soap_envelope_create_default_soap_envelope(env, AXIOM_SOAP11); + } + soap_body = axiom_soap_envelope_get_body(soap_env, env); + if(!soap_body) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SOAP_ENVELOPE_OR_SOAP_BODY_NULL, AXIS2_FAILURE); + return NULL; + } + + body_element_node = axiom_soap_body_get_base_node(soap_body, env); + + if(body_element_node) + { + body_child_node = axiom_node_get_first_child(body_element_node, env); + } + + if(!body_child_node) + { + if(!axis2_msg_ctx_get_op(msg_ctx, env)) + { + return NULL; + } + body_child = axiom_element_create_with_qname(env, NULL, axis2_op_get_qname( + axis2_msg_ctx_get_op(msg_ctx, env), env), &body_child_node); + axiom_soap_body_add_child(soap_body, env, body_child_node); + } + if(param_map) + { + axutil_hash_index_t *hi = NULL; + for(hi = axutil_hash_first(param_map, env); hi; hi = axutil_hash_next(env, hi)) + { + void *name = NULL; + void *value = NULL; + axiom_node_t *node = NULL; + axiom_element_t *element = NULL; + + axutil_hash_this(hi, (const void **)&name, NULL, (void **)&value); + element = axiom_element_create(env, NULL, (axis2_char_t *)name, NULL, &node); + axiom_element_set_text(element, env, (axis2_char_t *)value, node); + axiom_node_add_child(body_child_node, env, node); + } + } + return soap_env; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_dispatch_and_verify( + const axutil_env_t * env, + axis2_msg_ctx_t * msg_ctx) +{ + axis2_disp_t *rest_disp = NULL; + axis2_handler_t *handler = NULL; + + AXIS2_PARAM_CHECK(env->error, msg_ctx, AXIS2_FAILURE); + + if(axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + rest_disp = axis2_rest_disp_create(env); + handler = axis2_disp_get_base(rest_disp, env); + axis2_handler_invoke(handler, env, msg_ctx); + + if(!axis2_msg_ctx_get_svc(msg_ctx, env) || !axis2_msg_ctx_get_op(msg_ctx, env)) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_SVC_OR_OP_NOT_FOUND, AXIS2_FAILURE); + return AXIS2_FAILURE; + } + } + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL +axis2_http_transport_utils_process_accept_headers( + const axutil_env_t *env, + axis2_char_t *accept_value) +{ + axutil_array_list_t *accept_field_list = NULL; + axutil_array_list_t *accept_record_list = NULL; + accept_field_list = axutil_tokenize(env, accept_value, ','); + if(accept_field_list && axutil_array_list_size(accept_field_list, env) > 0) + { + axis2_char_t *token = NULL; + accept_record_list = axutil_array_list_create(env, axutil_array_list_size( + accept_field_list, env)); + do + { + if(token) + { + axis2_http_accept_record_t *rec = NULL; + rec = axis2_http_accept_record_create(env, token); + if(rec) + { + axutil_array_list_add(accept_field_list, env, rec); + } + AXIS2_FREE(env->allocator, token); + } + token = (axis2_char_t *)axutil_array_list_remove(accept_field_list, env, 0); + } + while(token); + } + if(accept_record_list && axutil_array_list_size(accept_record_list, env) > 0) + { + return accept_record_list; + } + return NULL; +} + +int +axis2_http_transport_utils_check_status_code( + int status_code) +{ + int status = AXIS2_HTTP_RESPONSE_OK_CODE_VAL; + switch(status_code) + { + case AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_CONTINUE_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_ACK_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_ACK_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_MOVED_PERMANENTLY_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_MULTIPLE_CHOICES_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_SEE_OTHER_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_TEMPORARY_REDIRECT_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_GONE_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_GONE_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL: + status = AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL; + break; + } + return status; +} + +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_process_request( + const axutil_env_t *env, + axis2_conf_ctx_t *conf_ctx, + axis2_http_transport_in_t *request, + axis2_http_transport_out_t *response) +{ + axis2_status_t status = AXIS2_FAILURE; + axis2_msg_ctx_t *msg_ctx = NULL; + axutil_stream_t *out_stream = NULL; + axutil_string_t *soap_action = NULL; + axis2_bool_t processed = AXIS2_FALSE; + axis2_char_t *body_string = NULL; + axis2_char_t *ctx_uuid = NULL; + axis2_op_ctx_t *op_ctx = NULL; + axis2_char_t *peer_ip = NULL; + axutil_property_t *peer_property = NULL; + axis2_msg_ctx_t *out_msg_ctx = NULL; + axis2_msg_ctx_t **msg_ctx_map = NULL; + + AXIS2_ENV_CHECK(env, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, request, AXIS2_CRITICAL_FAILURE); + AXIS2_PARAM_CHECK(env->error, request->request_uri, AXIS2_FALSE); + + if(!conf_ctx) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NULL_CONFIGURATION_CONTEXT, AXIS2_FAILURE); + return AXIS2_CRITICAL_FAILURE; + } + + if(!request->content_type) + { + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_PLAIN; + } + + /** creating the out stream */ + out_stream = axutil_stream_create_basic(env); + + if(request->transfer_encoding) + axis2_msg_ctx_set_transfer_encoding(request->msg_ctx, env, request->transfer_encoding); + + axis2_msg_ctx_set_server_side(request->msg_ctx, env, AXIS2_TRUE); + msg_ctx = request->msg_ctx; + peer_ip = request->remote_ip; + + if(peer_ip) + { + peer_property = axutil_property_create(env); + axutil_property_set_value(peer_property, env, axutil_strdup(env, peer_ip)); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_SVR_PEER_IP_ADDR, peer_property); + } + + axis2_msg_ctx_set_transport_out_stream(msg_ctx, env, out_stream); + + ctx_uuid = axutil_uuid_gen(env); + if(ctx_uuid) + { + axutil_string_t *uuid_str = axutil_string_create_assume_ownership(env, &ctx_uuid); + axis2_msg_ctx_set_svc_grp_ctx_id(msg_ctx, env, uuid_str); + axutil_string_free(uuid_str, env); + } + + axis2_msg_ctx_set_out_transport_info(msg_ctx, env, + &(request->out_transport_info->out_transport)); + + if(request->accept_header) + { + axutil_array_list_t *accept_record_list = NULL; + accept_record_list = axis2_http_transport_utils_process_accept_headers(env, + request->accept_header); + if(accept_record_list && axutil_array_list_size(accept_record_list, env) > 0) + { + axis2_msg_ctx_set_http_accept_record_list(msg_ctx, env, accept_record_list); + } + } + if(request->accept_charset_header) + { + axutil_array_list_t *accept_charset_record_list = NULL; + accept_charset_record_list = axis2_http_transport_utils_process_accept_headers(env, + request->accept_charset_header); + if(accept_charset_record_list) + { + axis2_msg_ctx_set_http_accept_charset_record_list(msg_ctx, env, + accept_charset_record_list); + } + } + if(request->accept_language_header) + { + axutil_array_list_t *accept_language_record_list = NULL; + accept_language_record_list = axis2_http_transport_utils_process_accept_headers(env, + request->accept_language_header); + if(accept_language_record_list) + { + axis2_msg_ctx_set_http_accept_language_record_list(msg_ctx, env, + accept_language_record_list); + } + } + + if(request->soap_action) + { + soap_action = axutil_string_create(env, request->soap_action); + } + + if(request->request_method == AXIS2_HTTP_METHOD_GET || request->request_method + == AXIS2_HTTP_METHOD_DELETE || request->request_method == AXIS2_HTTP_METHOD_HEAD) + { + + if(request->request_method == AXIS2_HTTP_METHOD_DELETE) + { + processed = axis2_http_transport_utils_process_http_delete_request(env, + request->msg_ctx, request->in_stream, out_stream, request->content_type, + soap_action, request->request_uri, conf_ctx, + axis2_http_transport_utils_get_request_params(env, request->request_uri)); + } + else if(request->request_method == AXIS2_HTTP_METHOD_HEAD) + { + processed = axis2_http_transport_utils_process_http_head_request(env, request->msg_ctx, + request->in_stream, out_stream, request->content_type, soap_action, + request->request_uri, conf_ctx, axis2_http_transport_utils_get_request_params(env, + request->request_uri)); + } + else if(request->request_method == AXIS2_HTTP_METHOD_GET) + { + processed = axis2_http_transport_utils_process_http_get_request(env, request->msg_ctx, + request->in_stream, out_stream, request->content_type, soap_action, + request->request_uri, conf_ctx, axis2_http_transport_utils_get_request_params(env, + request->request_uri)); + } + if(AXIS2_FALSE == processed) + { + axis2_bool_t is_services_path = AXIS2_FALSE; + int msg_ctx_status_code = axis2_msg_ctx_get_status_code(msg_ctx, env); + if(request->request_method != AXIS2_HTTP_METHOD_DELETE && request->request_url_prefix) + { + axis2_char_t *temp = NULL; + temp = strstr(request->request_uri, request->request_url_prefix); + if(temp) + { + temp += strlen(request->request_url_prefix); + if(*temp == '/') + { + temp++; + } + if(!*temp || *temp == '?' || *temp == '#') + { + is_services_path = AXIS2_TRUE; + } + } + } + if(is_services_path) + { + body_string = axis2_http_transport_utils_get_services_html(env, conf_ctx); + response->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + response->http_status_code = AXIS2_HTTP_RESPONSE_OK_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_OK_CODE_NAME; + } + else if(AXIS2_HTTP_METHOD_DELETE != request->request_method) + { + axis2_char_t *wsdl = NULL; + wsdl = strstr(request->request_uri, AXIS2_REQUEST_WSDL); + if(wsdl) + { + body_string = axis2_http_transport_utils_get_services_static_wsdl(env, + conf_ctx, request->request_uri); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_XML; + response->http_status_code = AXIS2_HTTP_RESPONSE_OK_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_OK_CODE_NAME; + } + } + else if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND) + { + axutil_array_list_t *method_list = NULL; + int size = 0; + method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env); + size = axutil_array_list_size(method_list, env); + + if(method_list && size) + { + /** 405 */ + body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx); + + response->http_status_code = AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_VAL; + response->http_status_code_name + = AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_NAME; + } + else + { + /** 404 */ + body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_NAME; + } + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL) + { + /* 400, Bad Request */ + body_string = axis2_http_transport_utils_get_bad_request(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_BAD_REQUEST_CODE_NAME; + + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL) + { + /* 408, Request Timeout */ + body_string = axis2_http_transport_utils_get_request_timeout(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_REQUEST_TIMEOUT_CODE_NAME; + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL) + { + /* 409, Conflict Types */ + body_string = axis2_http_transport_utils_get_conflict(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_CONFLICT_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_CONFLICT_CODE_NAME; + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_GONE_CODE_VAL) + { + /* 410, Gone. Resource no longer available */ + body_string = axis2_http_transport_utils_get_gone(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_GONE_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_GONE_CODE_NAME; + + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL) + { + /*410, Precondition for the url failed */ + body_string = axis2_http_transport_utils_get_precondition_failed(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_PRECONDITION_FAILED_CODE_NAME; + + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL) + { + /* 413, Request entity too large */ + body_string + = axis2_http_transport_utils_get_request_entity_too_large(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_VAL; + response->http_status_code_name + = AXIS2_HTTP_RESPONSE_REQUEST_ENTITY_TOO_LARGE_CODE_NAME; + } + else if(msg_ctx_status_code == AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL) + { + /* 513, Service Unavailable */ + body_string = axis2_http_transport_utils_get_service_unavailable(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_SERVICE_UNAVAILABLE_CODE_NAME; + } + else + { + /* 500, Internal Server Error */ + body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL; + response->http_status_code_name + = AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_NAME; + } + + if(body_string) + { + response->response_data = body_string; + response->response_data_length = axutil_strlen(body_string); + } + status = AXIS2_SUCCESS; + } + } + else if(AXIS2_HTTP_METHOD_POST == request->request_method || AXIS2_HTTP_METHOD_PUT + == request->request_method) + { + if(AXIS2_HTTP_METHOD_POST == request->request_method) + { + processed = axis2_http_transport_utils_process_http_post_request(env, request->msg_ctx, + request->in_stream, out_stream, request->content_type, request->content_length, + soap_action, request->request_uri); + } + else + { + processed = axis2_http_transport_utils_process_http_put_request(env, request->msg_ctx, + request->in_stream, out_stream, request->content_type, request->content_length, + soap_action, request->request_uri); + } + if(AXIS2_FAILURE == processed && (AXIS2_HTTP_METHOD_PUT == request->request_method + || axis2_msg_ctx_get_doing_rest(msg_ctx, env))) + { + + if(env->error->error_number == AXIS2_ERROR_SVC_OR_OP_NOT_FOUND) + { + axutil_array_list_t *method_list = NULL; + int size = 0; + method_list = axis2_msg_ctx_get_supported_rest_http_methods(msg_ctx, env); + size = axutil_array_list_size(method_list, env); + if(method_list && size) + { + /** 405 */ + body_string = axis2_http_transport_utils_get_method_not_allowed(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_VAL; + response->http_status_code_name + = AXIS2_HTTP_RESPONSE_METHOD_NOT_ALLOWED_CODE_NAME; + } + else + { + /** 404 */ + body_string = axis2_http_transport_utils_get_not_found(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_NOT_FOUND_CODE_NAME; + } + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + } + else + { + /* 500, Internal Server Error */ + body_string = axis2_http_transport_utils_get_internal_server_error(env, conf_ctx); + response->http_status_code = AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL; + response->http_status_code_name + = AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_NAME; + + } + + if(body_string) + { + response->response_data = body_string; + response->response_data_length = axutil_strlen(body_string); + } + status = AXIS2_SUCCESS; + } + else if(processed == AXIS2_FAILURE) + { + axis2_msg_ctx_t *fault_ctx = NULL; + axis2_char_t *fault_code = NULL; + axis2_engine_t *engine = axis2_engine_create(env, conf_ctx); + if(!engine) + { + /* Critical error, cannot proceed, send defaults document for 500 */ + return AXIS2_CRITICAL_FAILURE; + } + if(axis2_msg_ctx_get_is_soap_11(msg_ctx, env)) + { + fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX ":" + AXIOM_SOAP11_FAULT_CODE_SENDER; + } + else + { + fault_code = AXIOM_SOAP_DEFAULT_NAMESPACE_PREFIX ":" + AXIOM_SOAP12_SOAP_FAULT_VALUE_SENDER; + } + fault_ctx = axis2_engine_create_fault_msg_ctx(engine, env, request->msg_ctx, + fault_code, axutil_error_get_message(env->error)); + + axis2_engine_send_fault(engine, env, fault_ctx); + if (out_stream) + { + response->response_data = axutil_stream_get_buffer(out_stream, env); + response->response_data_length = axutil_stream_get_len (out_stream, env); + } + /* In case of a SOAP Fault, we have to set the status to 500, but still return */ + status = AXIS2_SUCCESS; + response->http_status_code = AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_INTERNAL_SERVER_ERROR_CODE_NAME; + } + } + else + { + response->response_data = axis2_http_transport_utils_get_not_implemented(env, conf_ctx); + request->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + + if (response->response_data) + { + response->response_data_length = axutil_strlen(response->response_data); + } + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_IMPLEMENTED_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_NOT_IMPLEMENTED_CODE_NAME; + status = AXIS2_SUCCESS; + } + + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + + if (op_ctx) + { + msg_ctx_map = axis2_op_ctx_get_msg_ctx_map(op_ctx, env); + out_msg_ctx = msg_ctx_map[AXIS2_WSDL_MESSAGE_LABEL_OUT]; + response->msg_ctx = out_msg_ctx; + } + + if (status == AXIS2_FAILURE) + { + axis2_bool_t do_rest = AXIS2_FALSE; + if (AXIS2_HTTP_METHOD_POST != request->request_method || + axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + do_rest = AXIS2_TRUE; + } + if ((request->accept_header || request->accept_charset_header || + request->accept_language_header) && do_rest) + { + axis2_char_t *content_type_header_value = NULL; + axis2_char_t *temp = NULL; + axis2_char_t *language_header_value = NULL; + + content_type_header_value = (axis2_char_t *) request->content_type; + language_header_value = axis2_msg_ctx_get_content_language(out_msg_ctx,env); + if (content_type_header_value) + { + temp = axutil_strdup(env, content_type_header_value); + } + if (temp) + { + axis2_char_t *content_type = NULL; + axis2_char_t *char_set = NULL; + axis2_char_t *temp2 = NULL; + + temp2 = strchr(temp, ';'); + if (temp2) + { + *temp2 = '\0'; + temp2++; + char_set = axutil_strcasestr(temp2, AXIS2_HTTP_CHAR_SET_ENCODING); + } + if (char_set) + { + char_set = axutil_strltrim(env, char_set, " \t="); + } + if (char_set) + { + temp2 = strchr(char_set, ';'); + } + if (temp2) + { + *temp2 = '\0'; + } + content_type = axutil_strtrim(env, temp, NULL); + + if (temp) + { + AXIS2_FREE(env->allocator, temp); + temp = NULL; + } + if (content_type && request->accept_header && + !axutil_strcasestr(request->accept_header, content_type)) + { + temp2 = strchr(content_type, '/'); + if (temp2) + { + *temp2 = '\0'; + temp = AXIS2_MALLOC(env->allocator, + sizeof(axis2_char_t) * ((int)strlen(content_type) + 3)); + if (!temp) + { + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return AXIS2_FALSE; + } + sprintf(temp, "%s/*", content_type); + if (!axutil_strcasestr(request->accept_header, temp) && + !strstr(request->accept_header, AXIS2_HTTP_HEADER_ACCEPT_ALL)) + { + response->response_data = + axis2_http_transport_utils_get_not_acceptable(env, conf_ctx); + response->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + if (response->response_data) + { + response->response_data_length = axutil_strlen(response->response_data); + } + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_NOT_IMPLEMENTED_CODE_NAME; + status = AXIS2_TRUE; + } + AXIS2_FREE(env->allocator, temp); + } + } + if (content_type) + { + AXIS2_FREE(env->allocator, content_type); + } + if (char_set && request->accept_charset_header && + !axutil_strcasestr(request->accept_charset_header , char_set)) + { + response->response_data = + axis2_http_transport_utils_get_not_acceptable(env, conf_ctx); + response->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + + if (response->response_data) + { + response->response_data_length= axutil_strlen(response->response_data); + } + status = AXIS2_SUCCESS; + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_NAME; + } + if (char_set) + { + AXIS2_FREE(env->allocator, char_set); + } + } + if (language_header_value) + { + if (request->accept_language_header && + !axutil_strcasestr(request->accept_language_header , language_header_value)) + { + response->response_data = + axis2_http_transport_utils_get_not_acceptable(env, conf_ctx); + response->content_type = AXIS2_HTTP_HEADER_ACCEPT_TEXT_HTML; + if (response->response_data) + { + response->response_data_length = axutil_strlen(response->response_data); + } + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_NOT_ACCEPTABLE_CODE_NAME; + } + } + } + } + if (status == AXIS2_FAILURE) + { + axis2_bool_t do_rest = AXIS2_FALSE; + if (AXIS2_HTTP_METHOD_POST != request->request_method || + axis2_msg_ctx_get_doing_rest(msg_ctx, env)) + { + do_rest = AXIS2_TRUE; + } + if (op_ctx && axis2_op_ctx_get_response_written(op_ctx, env)) + { + if (do_rest) + { + if (out_msg_ctx) + { + int size = 0; + axutil_array_list_t *output_header_list = NULL; + output_header_list = axis2_msg_ctx_get_http_output_headers(out_msg_ctx, env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, env); + response->output_headers = output_header_list; + } + + if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + response->http_status_code = + axis2_http_transport_utils_check_status_code(status_code); + status = AXIS2_SUCCESS; + } + } + } + if (status == AXIS2_FAILURE) + { + status = AXIS2_SUCCESS; + if (out_stream) + { + response->response_data = axutil_stream_get_buffer(out_stream, env); + response->response_data_length = axutil_stream_get_len(out_stream, env); + response->http_status_code = AXIS2_HTTP_RESPONSE_OK_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_OK_CODE_NAME; + } + } + } + else if (op_ctx) + { + if (do_rest) + { + if (out_msg_ctx) + { + int size = 0; + axutil_array_list_t *output_header_list = NULL; + output_header_list = axis2_msg_ctx_get_http_output_headers(out_msg_ctx, env); + if (output_header_list) + { + size = axutil_array_list_size(output_header_list, env); + response->output_headers = output_header_list; + } + if (axis2_msg_ctx_get_no_content(out_msg_ctx, env)) + { + if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + switch (status_code) + { + case AXIS2_HTTP_RESPONSE_RESET_CONTENT_CODE_VAL: + response->http_status_code = AXIS2_HTTP_RESPONSE_RESET_CONTENT_CODE_VAL; + break; + case AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL: + response->http_status_code = AXIS2_HTTP_RESPONSE_NOT_MODIFIED_CODE_VAL; + break; + default: + response->http_status_code = AXIS2_HTTP_RESPONSE_NO_CONTENT_CODE_VAL; + break; + } + } + else + { + response->http_status_code = AXIS2_HTTP_RESPONSE_NO_CONTENT_CODE_VAL; + } + status = AXIS2_SUCCESS; + } + else if (axis2_msg_ctx_get_status_code(out_msg_ctx, env)) + { + int status_code = axis2_msg_ctx_get_status_code(out_msg_ctx, env); + response->http_status_code = + axis2_http_transport_utils_check_status_code(status_code); + status = AXIS2_SUCCESS; + } + } + } + if (status == AXIS2_FAILURE) + { + response->http_status_code = AXIS2_HTTP_RESPONSE_ACK_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_ACK_CODE_NAME; + status = AXIS2_SUCCESS; + } + } + else + { + status = AXIS2_SUCCESS; + response->http_status_code = AXIS2_HTTP_RESPONSE_ACK_CODE_VAL; + response->http_status_code_name = AXIS2_HTTP_RESPONSE_ACK_CODE_NAME; + } + } + axutil_string_free(soap_action, env); + msg_ctx = NULL; + + return status; +} + +/* This method takes an array_list as the input. It has items some + may be buffers and some may be files. This will send these part + one by one to the wire using the chunked stream.*/ +AXIS2_EXTERN axis2_status_t AXIS2_CALL +axis2_http_transport_utils_send_mtom_message( + axutil_http_chunked_stream_t * chunked_stream, + const axutil_env_t * env, + axutil_array_list_t *mime_parts, + axis2_char_t *sending_callback_name) +{ + int i = 0; + axis2_status_t status = AXIS2_SUCCESS; + + for(i = 0; i < axutil_array_list_size(mime_parts, env); i++) + { + axiom_mime_part_t *mime_part = NULL; + mime_part = (axiom_mime_part_t *)axutil_array_list_get(mime_parts, env, i); + + /* If it is a buffer just write it to the wire. This includes mime_bounadaries, + * mime_headers and SOAP */ + if(mime_part->type == AXIOM_MIME_PART_BUFFER) + { + size_t written = 0; + while(written < mime_part->part_size) + { + int len = 0; + len = axutil_http_chunked_stream_write(chunked_stream, env, + mime_part->part + written, mime_part->part_size - written); + if(len == -1) + { + status = AXIS2_FAILURE; + break; + } + else + { + written += len; + } + } + } + + /* If it is a file we load a very little portion to memory and send it as chunked , + * we keep on doing this until we find the end of the file */ + else if(mime_part->type == AXIOM_MIME_PART_FILE) + { + FILE *f = NULL; + axis2_byte_t *output_buffer = NULL; + int output_buffer_size = 0; + + f = fopen(mime_part->file_name, "rb"); + if(!f) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for reading", + mime_part->file_name); + return AXIS2_FAILURE; + } + + /* If the part_size is less than the defined buffer size then + * from the first write to the wire we can send the file */ + if(mime_part->part_size > AXIS2_MTOM_OUTPUT_BUFFER_SIZE) + { + output_buffer_size = AXIS2_MTOM_OUTPUT_BUFFER_SIZE; + } + else + { + output_buffer_size = (int)mime_part->part_size; + } + + output_buffer = AXIS2_MALLOC(env->allocator, output_buffer_size * sizeof(axis2_char_t)); + + /*This is the method responsible for writing to the wire */ + status = axis2_http_transport_utils_send_attachment_using_file(env, chunked_stream, + f, output_buffer, output_buffer_size); + AXIS2_FREE(env->allocator, output_buffer); + fclose(f); + } + + /* if the callback is given, send data using callback */ + else if((mime_part->type) == AXIOM_MIME_PART_CALLBACK) + { + void *handler = NULL; + axiom_mtom_sending_callback_t *callback = NULL; + + handler = axis2_http_transport_utils_initiate_callback(env, sending_callback_name, + mime_part->user_param, &callback); + if(handler) + { + status = axis2_http_transport_utils_send_attachment_using_callback(env, + chunked_stream, callback, handler, mime_part->user_param); + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "MTOM Sending Callback loading failed"); + status = AXIS2_FAILURE; + } + + if(callback) + { + axutil_param_t *param = NULL; + param = callback->param; + AXIOM_MTOM_SENDING_CALLBACK_FREE(callback, env); + if(param) + { + axutil_param_free(param, env); + } + } + } + else + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unknown mime_part."); + status = AXIS2_FAILURE; + } + + if(status != AXIS2_SUCCESS) + { + break; + } + } + + if(status == AXIS2_SUCCESS) + { + /* send the end of chunk */ + status = axutil_http_chunked_stream_write_last_chunk(chunked_stream, env); + } + + return status; +} + +static axis2_status_t +axis2_http_transport_utils_send_attachment_using_file( + const axutil_env_t * env, + axutil_http_chunked_stream_t *chunked_stream, + FILE *fp, + axis2_byte_t *buffer, + int buffer_size) +{ + /*We do not load the whole file to memory. Just load a buffer_size portion + *and send it. Keep on doing this until the end of file */ + do + { + int written = 0; + int count = (int)fread(buffer, 1, buffer_size, fp); + if(ferror(fp) || (count < 0)) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Error in reading file containing the attachment"); + return AXIS2_FAILURE; + } + + /* count == 0 is a valid case. If the file size is multiple of buffer_size, then last read + * will have count == 0 + */ + + /*Writing the part we loaded to memory to the wire*/ + while(written < count) + { + int len = axutil_http_chunked_stream_write(chunked_stream, env, + buffer + written, count - written); + if(len == -1) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "error in writing file to stream"); + return AXIS2_FAILURE; + } + + written += len; + } + } + while(!feof(fp)); + + return AXIS2_SUCCESS; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_transport_utils_destroy_mime_parts( + axutil_array_list_t *mime_parts, + const axutil_env_t *env) +{ + if (mime_parts) + { + int i = 0; + for (i = 0; i < axutil_array_list_size(mime_parts, env); i++) + { + axiom_mime_part_t *mime_part = NULL; + mime_part = (axiom_mime_part_t *) + axutil_array_list_get(mime_parts, env, i); + if (mime_part) + { + axiom_mime_part_free(mime_part, env); + } + } + axutil_array_list_free(mime_parts, env); + } +} + +AXIS2_EXTERN void *AXIS2_CALL +axis2_http_transport_utils_initiate_callback( + const axutil_env_t *env, + axis2_char_t *callback_name, + void *user_param, + axiom_mtom_sending_callback_t **callback) +{ + axutil_dll_desc_t *dll_desc = NULL; + axutil_param_t *impl_info_param = NULL; + void *ptr = NULL; + + if(!callback_name) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "invalid callback name given"); + return NULL; + } + + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Trying to load module = %s", callback_name); + + dll_desc = axutil_dll_desc_create(env); + axutil_dll_desc_set_name(dll_desc, env, callback_name); + impl_info_param = axutil_param_create(env, NULL, dll_desc); + axutil_param_set_value_free(impl_info_param, env, axutil_dll_desc_free_void_arg); + axutil_class_loader_init(env); + ptr = axutil_class_loader_create_dll(env, impl_info_param); + if (!ptr) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Unable to load the module %s.", callback_name); + return NULL; + } + + *callback = (axiom_mtom_sending_callback_t *)ptr; + (*callback)->param = impl_info_param; + + return AXIOM_MTOM_SENDING_CALLBACK_INIT_HANDLER(*callback, env, user_param); +} + +static axis2_status_t +axis2_http_transport_utils_send_attachment_using_callback( + const axutil_env_t * env, + axutil_http_chunked_stream_t *chunked_stream, + axiom_mtom_sending_callback_t *callback, + void *handler, + void *user_param) +{ + int count = 0; + axis2_status_t status = AXIS2_SUCCESS; + axis2_char_t *buffer = NULL; + + /* Keep on loading the data in a loop until all the data is sent */ + while((count = AXIOM_MTOM_SENDING_CALLBACK_LOAD_DATA(callback, env, handler, &buffer)) > 0) + { + int written = 0; + while(written < count) + { + int len = 0; + len = axutil_http_chunked_stream_write(chunked_stream, env, + buffer + written, count - written); + if(len == -1) + { + status = AXIS2_FAILURE; + break; + } + + written += len; + } + } + + status = AXIOM_MTOM_SENDING_CALLBACK_CLOSE_HANDLER(callback, env, handler) && status; + return status; +} + +AXIS2_EXTERN axis2_bool_t AXIS2_CALL +axis2_http_transport_utils_is_callback_required( + const axutil_env_t *env, + axutil_array_list_t *mime_parts) +{ + int size = 0; + int i = 0; + axis2_bool_t is_required = AXIS2_FALSE; + + size = axutil_array_list_size(mime_parts, env); + for(i = 0; i < size; i++) + { + axiom_mime_part_t *mime_part = NULL; + mime_part = (axiom_mime_part_t *)axutil_array_list_get(mime_parts, env, i); + if(mime_part) + { + if(mime_part->type == AXIOM_MIME_PART_CALLBACK) + { + is_required = AXIS2_TRUE; + break; + } + } + } + + return is_required; +} + +static void +axis2_http_transport_utils_parse_session_str(const axutil_env_t *env, axis2_char_t *str, + axutil_hash_t *ht) +{ + while (*str) + { + axis2_char_t *next = axutil_strstr(str, ";"); + if (next) + { + axis2_char_t *key = NULL; + axis2_char_t *val = NULL; + + + /* Get key and value pairs */ + key = axis2_http_transport_utils_copy_key(env, str); + val = axis2_http_transport_utils_copy_value(env, str); + axutil_hash_set(ht, key, AXIS2_HASH_KEY_STRING, val); + + /* find next token */ + str = next + 1; + } + + } +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_session( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx) +{ + axutil_hash_index_t *hi = NULL; + void *val = NULL; + const void *key = NULL; + axutil_hash_t *ht = NULL; + axis2_char_t *session_id = NULL; + axis2_char_t *time_str = NULL; + axis2_char_t *header_value = NULL; + axutil_date_time_t *expire_time = NULL; + axis2_char_t session_value[256]; + axis2_http_out_transport_info_t *out_info = NULL; + axis2_status_t status = AXIS2_SUCCESS; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_transport_utils_get_session"); + ht = axis2_msg_ctx_get_property_value(msg_ctx, env, AXIS2_TRANSPORT_SESSION_TABLE); + if(!ht) + { + axis2_op_ctx_t *op_ctx = NULL; + axis2_msg_ctx_t *in_msg_ctx = NULL; + op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env); + if(op_ctx) + { + in_msg_ctx = axis2_op_ctx_get_msg_ctx(op_ctx, env, AXIS2_WSDL_MESSAGE_LABEL_IN); + if(in_msg_ctx) + { + ht = axis2_msg_ctx_get_property_value(in_msg_ctx, env, + AXIS2_TRANSPORT_SESSION_TABLE); + } + } + if(!ht) + { + return NULL; + } + } + session_id = axutil_hash_get(ht, "id", AXIS2_HASH_KEY_STRING); + if(!session_id) + { + /* Generate session and set it in session table */ + session_id = axutil_uuid_gen(env); + axutil_hash_set(ht, axutil_strdup(env, "id"), AXIS2_HASH_KEY_STRING, axutil_strdup(env, + session_id)); + + /* Generate expire time and set it in session table */ + expire_time = axutil_date_time_create_with_offset(env, AXIS2_TRANSPORT_SESSION_EXPIRE_DURATION); + time_str = axutil_strdup(env, axutil_date_time_serialize_date_time(expire_time, env)); + axutil_date_time_free(expire_time, env); + axutil_hash_set(ht, axutil_strdup(env, "expires"), AXIS2_HASH_KEY_STRING, time_str); + + sprintf(session_value, "%s", ""); + + for(hi = axutil_hash_first(ht, env); hi; hi = axutil_hash_next(env, hi)) + { + axis2_char_t *name = NULL; + axis2_char_t *value = NULL; + int len = -1; + + axutil_hash_this(hi, &key, NULL, &val); + name = (axis2_char_t *) key; + value = (axis2_char_t *) val; + if(name) + { + len = axutil_strlen(session_value); + sprintf(session_value + len, "%s=", name); + AXIS2_FREE(env->allocator, name); + } + if(value) + { + len = axutil_strlen(session_value); + sprintf(session_value + len, "%s;", value); + AXIS2_FREE(env->allocator, value); + } + } + + out_info = (axis2_http_out_transport_info_t *)axis2_msg_ctx_get_out_transport_info( + msg_ctx, env); + if(!out_info) + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_OUT_TRNSPORT_INFO_NULL, AXIS2_FAILURE); + AXIS2_FREE(env->allocator, header_value); + return NULL; + } + status = AXIS2_HTTP_OUT_TRANSPORT_INFO_SET_SESSION(out_info, env, session_id, session_value); + if(status != AXIS2_SUCCESS) + { + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, + "Inserting session value failed for session id %s", session_id); + return NULL; + } + } + else + { + time_str = axutil_hash_get(ht, "expires", AXIS2_HASH_KEY_STRING); + } + header_value = AXIS2_MALLOC(env->allocator, 256 * sizeof(axis2_char_t)); + sprintf(header_value, "ID=%s; expires=%s;", session_id, time_str); + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_transport_utils_get_session"); + return header_value; +} + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_transport_utils_set_session( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_char_t *session_str) +{ + axutil_date_time_t *expire_time = NULL; + axutil_date_time_t *current_time = NULL; + axutil_date_time_comp_result_t result; + axis2_char_t *time_str = NULL; + axutil_hash_t *ht = NULL; + axutil_property_t *property = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_tranpsport_utils_set_session"); + + /* Check whether session has expired. If so set error and return */ + ht = axutil_hash_make(env); + axis2_http_transport_utils_parse_session_str(env, session_str, ht); + time_str = (axis2_char_t *) axutil_hash_get(ht, "time", AXIS2_HASH_KEY_STRING); + expire_time = axutil_date_time_create(env); + axutil_date_time_deserialize_date_time(expire_time, env, time_str); + current_time = axutil_date_time_create(env); + result = axutil_date_time_compare(current_time, env, expire_time); + axutil_date_time_free(current_time, env); + axutil_date_time_free(expire_time, env); + if(result == AXIS2_DATE_TIME_COMP_RES_EXPIRED) + { + axutil_hash_index_t *hi = NULL; + void *val = NULL; + const void *key = NULL; + + AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Session time out"); + AXIS2_ERROR_SET(env->error, AXIS2_ERROR_SESSION_TIMEOUT, AXIS2_FAILURE); + for(hi = axutil_hash_first(ht, env); hi; hi = axutil_hash_next(env, hi)) + { + axis2_char_t *name = NULL; + axis2_char_t *value = NULL; + + axutil_hash_this(hi, &key, NULL, &val); + name = (axis2_char_t *) key; + if(name) + { + AXIS2_FREE(env->allocator, name); + } + value = (axis2_char_t *) val; + if(value) + { + AXIS2_FREE(env->allocator, value); + } + } + axutil_hash_free(ht, env); + } + + property = axutil_property_create_with_args(env, 0, AXIS2_TRUE, 0, ht); + axis2_msg_ctx_set_property(msg_ctx, env, AXIS2_TRANSPORT_SESSION_TABLE, property); + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_tranpsport_utils_set_session"); +} + +/** + * After receiving Set-Cookie header store it + */ +AXIS2_EXTERN void AXIS2_CALL +axis2_http_transport_utils_store_cookie( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx, + axis2_char_t *cookie) +{ + axis2_conf_ctx_t *conf_ctx = NULL; + axutil_property_t *property = NULL; + axutil_hash_t *session_map = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + const axis2_char_t *address = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_transport_utils_store_cookie"); + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + property = axis2_conf_ctx_get_property(conf_ctx, env, AXIS2_TRANSPORT_SESSION_MAP); + if(property) + { + session_map = axutil_property_get_value(property, env); + } + if(!session_map) + { + if(!cookie) + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, + "No session map found and no cookie set. So return"); + return; + } + session_map = axutil_hash_make(env); + if(session_map) + { + property = axutil_property_create_with_args(env, AXIS2_SCOPE_APPLICATION, 1, + axis2_http_transport_utils_session_map_free_void_arg, session_map); + axis2_conf_ctx_set_property(conf_ctx, env, AXIS2_TRANSPORT_SESSION_MAP, property); + } + else + { + AXIS2_HANDLE_ERROR(env, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); + return; + } + } + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = NULL; + server = axutil_url_get_server(url, env); + if(server) + { + if(cookie) + { + axutil_hash_set(session_map, axutil_strdup(env, server), AXIS2_HASH_KEY_STRING, + axutil_strdup(env, cookie)); + } + else /* We remove any cookie set for this endpoint */ + { + cookie = axutil_hash_get(session_map, server, AXIS2_HASH_KEY_STRING); + if(cookie) + { + AXIS2_FREE(env->allocator, cookie); + } + axutil_hash_set(session_map, axutil_strdup(env, server), AXIS2_HASH_KEY_STRING, NULL); + } + } + axutil_url_free(url, env); + } + } + } + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_transport_utils_store_cookie"); +} + +/* Read from cookie store before sending */ +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_read_from_cookie_store( + const axutil_env_t *env, + axis2_msg_ctx_t *msg_ctx) +{ + axutil_property_t *property = NULL; + axutil_hash_t *session_map = NULL; + axis2_endpoint_ref_t *endpoint = NULL; + const axis2_char_t *address = NULL; + axis2_char_t *cookie = NULL; + axis2_conf_ctx_t *conf_ctx = NULL; + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Entry:axis2_http_transport_utils_read_from_cookie_store"); + conf_ctx = axis2_msg_ctx_get_conf_ctx(msg_ctx, env); + property = axis2_conf_ctx_get_property(conf_ctx, env, AXIS2_TRANSPORT_SESSION_MAP); + if(property) + { + session_map = axutil_property_get_value(property, env); + } + if(!session_map) + { + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "No session map stored"); + return NULL; + } + endpoint = axis2_msg_ctx_get_to(msg_ctx, env); + if(endpoint) + { + address = axis2_endpoint_ref_get_address(endpoint, env); + if(address) + { + axutil_url_t *url = NULL; + url = axutil_url_parse_string(env, address); + if(url) + { + axis2_char_t *server = NULL; + server = axutil_url_get_server(url, env); + if(server) + { + cookie = axutil_hash_get(session_map, server, AXIS2_HASH_KEY_STRING); + } + axutil_url_free(url, env); + } + AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "cookie:%s", cookie); + } + } + + AXIS2_LOG_TRACE(env->log, AXIS2_LOG_SI, "Exit:axis2_http_transport_utils_read_from_cookie_store"); + return cookie; +} + +AXIS2_EXTERN axis2_char_t *AXIS2_CALL +axis2_http_transport_utils_get_session_id_from_cookie( + const axutil_env_t *env, + axis2_char_t *cookie) +{ + axis2_char_t *next = NULL; + axis2_char_t *session_id = NULL; + + next = axutil_strstr(cookie, ";"); + if (next) + { + session_id = axis2_http_transport_utils_copy_value(env, cookie); + } + + return session_id; +} + +static axis2_char_t * +axis2_http_transport_utils_copy_key( + const axutil_env_t *env, + axis2_char_t *pair) +{ + axis2_char_t *p = axutil_strchr(pair, '='); + axis2_char_t *ret = NULL; + + if (p) + { + axis2_char_t c; + size_t len = p - pair; + c = pair[len]; + pair[len] = '\0'; + ret = axutil_strdup(env, pair); + pair[len] = c; + } + + return ret; +} + +static axis2_char_t * +axis2_http_transport_utils_copy_value( + const axutil_env_t *env, + axis2_char_t *pair) +{ + axis2_char_t *ret = NULL; + size_t len; + axis2_char_t c; + + pair = axutil_strchr(pair, '='); + if (pair) + { + pair++; + len = axutil_strchr(pair, ';') - pair; + c = pair[len]; + pair[len] = '\0'; + ret = axutil_strdup(env, pair); + pair[len] = c; + } + + return ret; +} + + +AXIS2_EXTERN void AXIS2_CALL +axis2_http_transport_utils_session_map_free_void_arg( + void *sm_void, + const axutil_env_t *env) +{ + void *val = NULL; + const void *key = NULL; + axutil_hash_index_t *hi = NULL; + axutil_hash_t *ht = (axutil_hash_t *)sm_void; + + for(hi = axutil_hash_first(ht, env); hi; hi = axutil_hash_next(env, hi)) + { + axis2_char_t *name = NULL; + axis2_char_t *value = NULL; + + axutil_hash_this(hi, &key, NULL, &val); + name = (axis2_char_t *) key; + if(name) + { + AXIS2_FREE(env->allocator, name); + } + value = (axis2_char_t *) val; + if(value) + { + AXIS2_FREE(env->allocator, value); + } + } + axutil_hash_free(ht, env); +} + + -- cgit v1.1-32-gdbae