summaryrefslogtreecommitdiffstats
path: root/axiom/src/attachments
diff options
context:
space:
mode:
Diffstat (limited to 'axiom/src/attachments')
-rw-r--r--axiom/src/attachments/Makefile.am15
-rw-r--r--axiom/src/attachments/axiom_mime_body_part.h121
-rw-r--r--axiom/src/attachments/data_handler.c572
-rw-r--r--axiom/src/attachments/mime_body_part.c284
-rw-r--r--axiom/src/attachments/mime_parser.c2304
-rw-r--r--axiom/src/attachments/mime_part.c535
6 files changed, 3831 insertions, 0 deletions
diff --git a/axiom/src/attachments/Makefile.am b/axiom/src/attachments/Makefile.am
new file mode 100644
index 0000000..e4ec8fd
--- /dev/null
+++ b/axiom/src/attachments/Makefile.am
@@ -0,0 +1,15 @@
+noinst_LTLIBRARIES = libaxis2_attachments.la
+AM_CPPFLAGS = $(CPPFLAGS)
+libaxis2_attachments_la_SOURCES = mime_part.c \
+ data_handler.c \
+ mime_body_part.c \
+ mime_parser.c
+
+libaxis2_attachments_la_LIBADD = ../../../util/src/libaxutil.la
+
+INCLUDES = -I$(top_builddir)/include \
+ -I$(top_builddir)/parser \
+ -I ../../../util/include
+
+EXTRA_DIST = axiom_mime_body_part.h
+
diff --git a/axiom/src/attachments/axiom_mime_body_part.h b/axiom/src/attachments/axiom_mime_body_part.h
new file mode 100644
index 0000000..a925679
--- /dev/null
+++ b/axiom/src/attachments/axiom_mime_body_part.h
@@ -0,0 +1,121 @@
+
+/*
+ * 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 AXIOM_MIME_BODY_PART_H
+#define AXIOM_MIME_BODY_PART_H
+
+/**
+ * @file axiom_mime_body_part.h
+ * @brief axis2 mime_body_part interface
+ */
+
+#include <axutil_utils.h>
+#include <axutil_error.h>
+#include <axutil_utils_defines.h>
+#include <axutil_env.h>
+#include <axutil_allocator.h>
+#include <axutil_string.h>
+#include <axutil_array_list.h>
+#include <axiom_data_handler.h>
+#include <axiom_text.h>
+#include <axiom_mime_const.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct axiom_mime_body_part axiom_mime_body_part_t;
+
+ /** @defgroup axiom_mime_body_part
+ * @ingroup axiom_mime_body_part
+ * @{
+ */
+
+ AXIS2_EXTERN axis2_status_t AXIS2_CALL
+ axiom_mime_body_part_add_header(
+ axiom_mime_body_part_t * mime_body_part,
+ const axutil_env_t * env,
+ const axis2_char_t * name,
+ const axis2_char_t * value);
+
+ AXIS2_EXTERN axis2_status_t AXIS2_CALL
+
+ axiom_mime_body_part_set_data_handler(
+ axiom_mime_body_part_t * mime_body_part,
+ const axutil_env_t * env,
+ axiom_data_handler_t * data_handler);
+
+ AXIS2_EXTERN axis2_status_t AXIS2_CALL
+ axiom_mime_body_part_write_to(
+ axiom_mime_body_part_t * mime_body_part,
+ const axutil_env_t * env,
+ axis2_byte_t ** output_stream,
+ int *output_stream_size);
+
+ /** Deallocate memory
+ * @return status code
+ */
+ AXIS2_EXTERN void AXIS2_CALL
+ axiom_mime_body_part_free(
+ axiom_mime_body_part_t * mime_body_part,
+ const axutil_env_t * env);
+
+ AXIS2_EXTERN axis2_status_t AXIS2_CALL
+ axiom_mime_body_part_write_to_list(
+ axiom_mime_body_part_t *mime_body_part,
+ const axutil_env_t *env,
+ axutil_array_list_t *list);
+
+ /**
+ * Creates mime_body_part struct
+ * @return pointer to newly created mime_body_part
+ */
+ AXIS2_EXTERN axiom_mime_body_part_t *AXIS2_CALL
+ axiom_mime_body_part_create(
+ const axutil_env_t * env);
+
+ /**
+ * Creates mime_body_part struct from a om_text
+ * @return pointer to newly created mime_body_part
+ */
+
+ AXIS2_EXTERN axiom_mime_body_part_t *AXIS2_CALL
+ axiom_mime_body_part_create_from_om_text(
+ const axutil_env_t *env,
+ axiom_text_t *text);
+
+
+#define AXIOM_MIME_BODY_PART_FREE(mime_body_part, env) \
+ axiom_mime_body_part_free (mime_body_part, env)
+
+#define AXIOM_MIME_BODY_PART_ADD_HEADER(mime_body_part, env, name, value) \
+ axiom_mime_body_part_add_header (mime_body_part, env, name, value)
+
+#define AXIOM_MIME_BODY_PART_SET_DATA_HANDLER(mime_body_part, env, data_handler) \
+ axiom_mime_body_part_set_data_handler (mime_body_part, env, data_handler)
+
+#define AXIOM_MIME_BODY_PART_WRITE_TO(mime_body_part, env, output_stream, output_stream_size) \
+ axiom_mime_body_part_write_to (mime_body_part, env, output_stream, output_stream_size)
+
+ /** @} */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* AXIOM_MIME_BODY_PART_H */
diff --git a/axiom/src/attachments/data_handler.c b/axiom/src/attachments/data_handler.c
new file mode 100644
index 0000000..3be8a9d
--- /dev/null
+++ b/axiom/src/attachments/data_handler.c
@@ -0,0 +1,572 @@
+/*
+ * 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 <axiom_data_handler.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <axiom_mime_part.h>
+
+struct axiom_data_handler
+{
+ /* The content type */
+ axis2_char_t *mime_type;
+
+ /* If in a file then the file name*/
+ axis2_char_t *file_name;
+
+ /* If it is in a buffer then the buffer */
+ axis2_byte_t *buffer;
+
+ /* The length of the buffer */
+ size_t buffer_len;
+
+ /* Is this a data_handler with a file name or a buffer*/
+ axiom_data_handler_type_t data_handler_type;
+
+ /* When parsing whether we have cached it or not */
+ axis2_bool_t cached;
+
+ /* The Content Id */
+ axis2_char_t *mime_id;
+
+ /* In the case of sending callback this is required */
+ void *user_param;
+
+};
+
+/* Creates the data_handler. The file name is not mandatory */
+
+AXIS2_EXTERN axiom_data_handler_t *AXIS2_CALL
+axiom_data_handler_create(
+ const axutil_env_t *env,
+ const axis2_char_t *file_name,
+ const axis2_char_t *mime_type)
+{
+ axiom_data_handler_t *data_handler = NULL;
+
+ AXIS2_ENV_CHECK(env, NULL);
+ data_handler = (axiom_data_handler_t *)AXIS2_MALLOC(env->allocator,
+ sizeof(axiom_data_handler_t));
+
+ if(!data_handler)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create data handler");
+ return NULL;
+ }
+
+ data_handler->mime_type = NULL;
+ data_handler->file_name = NULL;
+ data_handler->buffer = NULL;
+ data_handler->buffer_len = 0;
+ /* By default, a Data Handler is of type Buffer */
+ data_handler->data_handler_type = AXIOM_DATA_HANDLER_TYPE_BUFFER;
+ data_handler->cached = AXIS2_FALSE;
+ data_handler->mime_id = NULL;
+ data_handler->user_param = NULL;
+
+ if(mime_type)
+ {
+ data_handler->mime_type = axutil_strdup(env, mime_type);
+ if(!(data_handler->mime_type))
+ {
+ axiom_data_handler_free(data_handler, env);
+ return NULL;
+ }
+ }
+ if(file_name)
+ {
+ data_handler->file_name = axutil_strdup(env, file_name);
+ if(!(data_handler->file_name))
+ {
+ axiom_data_handler_free(data_handler, env);
+ return NULL;
+ }
+ data_handler->data_handler_type = AXIOM_DATA_HANDLER_TYPE_FILE;
+ }
+
+ return data_handler;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_data_handler_free(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ if(data_handler->file_name)
+ {
+ AXIS2_FREE(env->allocator, data_handler->file_name);
+ }
+
+ if(data_handler->mime_type)
+ {
+ AXIS2_FREE(env->allocator, data_handler->mime_type);
+ }
+
+ if(data_handler->buffer)
+ {
+ AXIS2_FREE(env->allocator, data_handler->buffer);
+ }
+
+ if(data_handler->mime_id)
+ {
+ AXIS2_FREE(env->allocator, data_handler->mime_id);
+ }
+
+ if(data_handler)
+ {
+ AXIS2_FREE(env->allocator, data_handler);
+ }
+
+ return;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axiom_data_handler_get_content_type(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->mime_type;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_set_content_type(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ const axis2_char_t *mime_type)
+{
+ if(data_handler->mime_type)
+ {
+ AXIS2_FREE(env->allocator, data_handler->mime_type);
+ }
+ data_handler->mime_type = axutil_strdup(env, mime_type);
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_bool_t AXIS2_CALL
+axiom_data_handler_get_cached(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->cached;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_data_handler_set_cached(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ axis2_bool_t cached)
+{
+ data_handler->cached = cached;
+}
+
+AXIS2_EXTERN axis2_byte_t *AXIS2_CALL
+axiom_data_handler_get_input_stream(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->buffer;
+}
+
+AXIS2_EXTERN size_t AXIS2_CALL
+axiom_data_handler_get_input_stream_len(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->buffer_len;
+}
+
+/* With MTOM caching support this function is no longer used
+ * Because this will load whole file in to buffer. So for large
+ * attachment this is not wise */
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_read_from(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ axis2_byte_t **output_stream,
+ size_t *output_stream_size)
+{
+ if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_BUFFER)
+ {
+ *output_stream = data_handler->buffer;
+ *output_stream_size = data_handler->buffer_len;
+ }
+ else if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_FILE
+ && data_handler->file_name)
+ {
+ FILE *f = NULL;
+ axis2_byte_t *byte_stream = NULL;
+ axis2_byte_t *temp_byte_stream = NULL;
+ axis2_byte_t *read_stream = NULL;
+ int byte_stream_size = 0;
+ int temp_byte_stream_size = 0;
+ int read_stream_size = 0;
+ int count = 0;
+ struct stat stat_p;
+
+ f = fopen(data_handler->file_name, "rb");
+ if(!f)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for reading",
+ data_handler->file_name);
+ return AXIS2_FAILURE;
+ }
+
+ if(stat(data_handler->file_name, &stat_p) == -1)
+ {
+ fclose(f);
+ return AXIS2_FAILURE;
+ }
+ else if(stat_p.st_size == 0)
+ {
+ fclose(f);
+ *output_stream = NULL;
+ *output_stream_size = 0;
+ return AXIS2_SUCCESS;
+ }
+
+ do
+ {
+ read_stream_size = stat_p.st_size;
+ read_stream = AXIS2_MALLOC(env->allocator, (read_stream_size) * sizeof(axis2_byte_t));
+ if(!read_stream)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create binary stream");
+ if(byte_stream)
+ {
+ AXIS2_FREE(env->allocator, byte_stream);
+ }
+ fclose(f);
+ return AXIS2_FAILURE;
+ }
+ count = (int)fread(read_stream, 1, read_stream_size, f);
+ /* The count lies within the int range */
+ if(ferror(f))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in reading file %s",
+ data_handler->file_name);
+ if(byte_stream)
+ {
+ AXIS2_FREE(env->allocator, byte_stream);
+ }
+ if(read_stream)
+ {
+ AXIS2_FREE(env->allocator, read_stream);
+ }
+ fclose(f);
+ return AXIS2_FAILURE;
+ }
+
+ /* copy the read bytes */
+ if(count > 0)
+ {
+ if(byte_stream)
+ {
+ temp_byte_stream = byte_stream;
+ temp_byte_stream_size = byte_stream_size;
+ byte_stream_size = temp_byte_stream_size + count;
+ byte_stream = AXIS2_MALLOC(env->allocator, (byte_stream_size)
+ * sizeof(axis2_byte_t));
+ if(!byte_stream)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Cannot create binary stream");
+ if(read_stream)
+ {
+ AXIS2_FREE(env->allocator, read_stream);
+ }
+ if(temp_byte_stream)
+ {
+ AXIS2_FREE(env->allocator, temp_byte_stream);
+ }
+ fclose(f);
+ return AXIS2_FAILURE;
+ }
+
+ memcpy(byte_stream, temp_byte_stream, temp_byte_stream_size);
+ memcpy(byte_stream + temp_byte_stream_size, read_stream, count);
+
+ if(read_stream)
+ {
+ AXIS2_FREE(env->allocator, read_stream);
+ read_stream_size = 0;
+ }
+ if(temp_byte_stream)
+ {
+ AXIS2_FREE(env->allocator, temp_byte_stream);
+ temp_byte_stream = NULL;
+ temp_byte_stream_size = 0;
+ }
+ }
+ else
+ {
+ byte_stream = read_stream;
+ byte_stream_size = read_stream_size;
+ read_stream = NULL;
+ read_stream_size = 0;
+ }
+ }
+ else if(read_stream)
+ {
+ AXIS2_FREE(env->allocator, read_stream);
+ }
+ }
+ while(!feof(f));
+
+ fclose(f);
+ data_handler->buffer = byte_stream;
+ data_handler->buffer_len = byte_stream_size;
+ *output_stream = byte_stream;
+ *output_stream_size = byte_stream_size;
+ }
+ else
+ {
+ /* Data Handler File Name is missing */
+ return AXIS2_FAILURE;
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_set_binary_data(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ axis2_byte_t *input_stream,
+ size_t input_stream_len)
+{
+ data_handler->buffer = input_stream;
+ data_handler->buffer_len = input_stream_len;
+ return AXIS2_SUCCESS;
+}
+
+/* This function will write the data in the buffer
+ * to a file. When caching is being used this will
+ * not be called , because the parser it self cache
+ * the attachment while parsing */
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_write_to(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ if(data_handler->file_name)
+ {
+ FILE *f = NULL;
+ int count = 0;
+
+ f = fopen(data_handler->file_name, "wb");
+ if(!f)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error opening file %s for writing",
+ data_handler->file_name);
+ return AXIS2_FAILURE;
+ }
+
+ count = (int)fwrite(data_handler->buffer, 1, data_handler->buffer_len, f);
+ /* The count lies within the int range */
+
+ if(ferror(f))
+ {
+ fclose(f);
+ return AXIS2_FAILURE;
+ }
+ fflush(f);
+ fclose(f);
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_set_file_name(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ axis2_char_t *file_name)
+{
+ if(data_handler->file_name)
+ {
+ AXIS2_FREE(env->allocator, data_handler->file_name);
+ data_handler->file_name = NULL;
+ }
+
+ if(file_name)
+ {
+ data_handler->file_name = axutil_strdup(env, file_name);
+ if(!(data_handler->file_name))
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axiom_data_handler_get_file_name(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ if(data_handler->file_name)
+ {
+ return data_handler->file_name;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/* This method will add the data_handler binary data to the array_list.
+ * If it is a buffer the part type is buffer. otherwise it is a file. In the
+ * case of file the array_list have just the file name and the size. The content
+ * is not loaded to the memory.
+ */
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_add_binary_data(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ axutil_array_list_t *list)
+
+{
+ axiom_mime_part_t *binary_part = NULL;
+
+ binary_part = axiom_mime_part_create(env);
+
+ if(!binary_part)
+ {
+ return AXIS2_FAILURE;
+ }
+
+ if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_BUFFER)
+ {
+ binary_part->part = (axis2_byte_t *)AXIS2_MALLOC(env->allocator, (data_handler->buffer_len)
+ * sizeof(axis2_byte_t));
+ memcpy(binary_part->part, data_handler->buffer, data_handler->buffer_len);
+
+ binary_part->part_size = data_handler->buffer_len;
+ binary_part->type = AXIOM_MIME_PART_BUFFER;
+ }
+
+ /* In the case of file we first calculate the file size
+ * and then add the file name */
+
+ else if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_FILE
+ && data_handler->file_name)
+ {
+ struct stat stat_p;
+
+ if(stat(data_handler->file_name, &stat_p) == -1)
+ {
+ return AXIS2_FAILURE;
+ }
+ else if(stat_p.st_size == 0)
+ {
+ return AXIS2_SUCCESS;
+ }
+ else
+ {
+ binary_part->file_name = (axis2_char_t *)axutil_strdup(env, data_handler->file_name);
+ binary_part->part_size = stat_p.st_size;
+ binary_part->type = AXIOM_MIME_PART_FILE;
+ }
+ }
+ /* In the case of Callback the user should specify the callback name in the
+ * configuration file. We just set the correct type. Inside the transport
+ * it will load the callback and send the attachment appropriately */
+
+ else if(data_handler->data_handler_type == AXIOM_DATA_HANDLER_TYPE_CALLBACK)
+ {
+ binary_part->type = AXIOM_MIME_PART_CALLBACK;
+ binary_part->user_param = data_handler->user_param;
+ }
+
+ else
+ {
+ /* Data Handler File Name is missing */
+ return AXIS2_FAILURE;
+ }
+
+ /* Finaly we add the binary details to the list */
+
+ axutil_array_list_add(list, env, binary_part);
+
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axiom_data_handler_get_mime_id(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->mime_id;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_data_handler_set_mime_id(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ const axis2_char_t *mime_id)
+{
+ if(data_handler->mime_id)
+ {
+ AXIS2_FREE(env->allocator, data_handler->mime_id);
+ }
+ data_handler->mime_id = axutil_strdup(env, mime_id);
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axiom_data_handler_type_t AXIS2_CALL
+axiom_data_handler_get_data_handler_type(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->data_handler_type;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_data_handler_set_data_handler_type(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ axiom_data_handler_type_t data_handler_type)
+{
+ data_handler->data_handler_type = data_handler_type;
+ return;
+}
+
+AXIS2_EXTERN void *AXIS2_CALL
+axiom_data_handler_get_user_param(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env)
+{
+ return data_handler->user_param;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_data_handler_set_user_param(
+ axiom_data_handler_t *data_handler,
+ const axutil_env_t *env,
+ void *user_param)
+{
+ data_handler->user_param = user_param;
+ return;
+}
+
diff --git a/axiom/src/attachments/mime_body_part.c b/axiom/src/attachments/mime_body_part.c
new file mode 100644
index 0000000..186acdb
--- /dev/null
+++ b/axiom/src/attachments/mime_body_part.c
@@ -0,0 +1,284 @@
+/*
+ * 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 "axiom_mime_body_part.h"
+#include <axiom_mime_part.h>
+#include <axiom_data_handler.h>
+#include <axutil_hash.h>
+
+struct axiom_mime_body_part
+{
+ /* hash map to hold header name, value pairs */
+ axutil_hash_t *header_map;
+ axiom_data_handler_t *data_handler;
+};
+
+/* This method just create a mime_body_part. It does not
+ * fill the header map.
+ */
+
+AXIS2_EXTERN axiom_mime_body_part_t *AXIS2_CALL
+axiom_mime_body_part_create(
+ const axutil_env_t *env)
+{
+ axiom_mime_body_part_t *mime_body_part = NULL;
+
+ AXIS2_ENV_CHECK(env, NULL);
+ mime_body_part = (axiom_mime_body_part_t *)AXIS2_MALLOC(env->allocator,
+ sizeof(axiom_mime_body_part_t));
+
+ if(!mime_body_part)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create MIME body part");
+ return NULL;
+ }
+
+ mime_body_part->header_map = NULL;
+ mime_body_part->data_handler = NULL;
+
+ mime_body_part->header_map = axutil_hash_make(env);
+ if(!(mime_body_part->header_map))
+ {
+ axiom_mime_body_part_free(mime_body_part, env);
+ return NULL;
+ }
+
+ return mime_body_part;
+}
+
+/* This method will create the mime_body_part and fill the header map with
+ * default information. Default information are for binary attachments.
+ * Attachment information is taken from the information in data_handler in passed
+ * om_text.
+ */
+
+AXIS2_EXTERN axiom_mime_body_part_t *AXIS2_CALL
+axiom_mime_body_part_create_from_om_text(
+ const axutil_env_t *env,
+ axiom_text_t *text)
+{
+ axiom_data_handler_t *data_handler = NULL;
+ axiom_mime_body_part_t *mime_body_part = NULL;
+ axis2_char_t *content_id = NULL;
+ axis2_char_t *temp_content_id = NULL;
+ const axis2_char_t *content_type = AXIOM_MIME_TYPE_OCTET_STREAM;
+
+ mime_body_part = axiom_mime_body_part_create(env);
+ if(!mime_body_part)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "MIME body part creation failed");
+ return NULL;
+ }
+
+ /* Take the data_handler which is set by the sending applocation. */
+
+ data_handler = axiom_text_get_data_handler(text, env);
+
+ if(data_handler)
+ {
+ content_type = axiom_data_handler_get_content_type(data_handler, env);
+ }
+
+ AXIOM_MIME_BODY_PART_SET_DATA_HANDLER(mime_body_part, env, data_handler);
+ content_id = (axis2_char_t *)"<";
+ content_id = axutil_stracat(env, content_id, axiom_text_get_content_id(text, env));
+ temp_content_id = axutil_stracat(env, content_id, ">");
+
+ AXIS2_FREE(env->allocator, content_id);
+ content_id = temp_content_id;
+
+ /* Adding the content-id */
+ AXIOM_MIME_BODY_PART_ADD_HEADER(mime_body_part, env, AXIOM_MIME_HEADER_CONTENT_ID, content_id);
+
+ /* Adding the content-type */
+ AXIOM_MIME_BODY_PART_ADD_HEADER(mime_body_part, env, AXIOM_MIME_HEADER_CONTENT_TYPE,
+ axutil_strdup(env, content_type));
+
+ /* Adding the content-transfer encoding */
+ AXIOM_MIME_BODY_PART_ADD_HEADER(mime_body_part, env,
+ AXIOM_MIME_HEADER_CONTENT_TRANSFER_ENCODING, axutil_strdup(env,
+ AXIOM_MIME_CONTENT_TRANSFER_ENCODING_BINARY));
+
+ return mime_body_part;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_body_part_free(
+ axiom_mime_body_part_t *mime_body_part,
+ const axutil_env_t *env)
+{
+ if(mime_body_part->header_map)
+ {
+ axutil_hash_index_t *hash_index = NULL;
+ const void *key = NULL;
+ void *value = NULL;
+ for(hash_index = axutil_hash_first(mime_body_part->header_map, env); hash_index; hash_index
+ = axutil_hash_next(env, hash_index))
+ {
+ axutil_hash_this(hash_index, &key, NULL, &value);
+ if(value)
+ {
+ AXIS2_FREE(env->allocator, value);
+ }
+ }
+
+ axutil_hash_free(mime_body_part->header_map, env);
+ mime_body_part->header_map = NULL;
+ }
+
+ if(mime_body_part)
+ {
+ AXIS2_FREE(env->allocator, mime_body_part);
+ }
+
+ return;
+}
+
+/* This method will add a mime_header to the hash */
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_mime_body_part_add_header(
+ axiom_mime_body_part_t *mime_body_part,
+ const axutil_env_t *env,
+ const axis2_char_t *name,
+ const axis2_char_t *value)
+{
+ AXIS2_PARAM_CHECK(env->error, name, AXIS2_FAILURE);
+
+ if(!mime_body_part->header_map)
+ {
+ return AXIS2_FAILURE;
+ }
+ axutil_hash_set(mime_body_part->header_map, name, AXIS2_HASH_KEY_STRING, value);
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_mime_body_part_set_data_handler(
+ axiom_mime_body_part_t *mime_body_part,
+ const axutil_env_t *env,
+ axiom_data_handler_t *data_handler)
+{
+ mime_body_part->data_handler = data_handler;
+ return AXIS2_SUCCESS;
+}
+
+/* This method will fill the array_list with binary and binary_beader information.
+ * If the binary is in a file this will not load the file to the memory. Because
+ * that will cause performance degradation when the file size is large. Instead
+ * this will add file information to the list so that when writing the message
+ * through transport_sender it can send the file by chunk.
+ */
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_mime_body_part_write_to_list(
+ axiom_mime_body_part_t *mime_body_part,
+ const axutil_env_t *env,
+ axutil_array_list_t *list)
+{
+ axutil_hash_index_t *hash_index = NULL;
+ const void *key = NULL;
+ void *value = NULL;
+ axis2_char_t *header_str = NULL;
+ axis2_char_t *temp_header_str = NULL;
+ int header_str_size = 0;
+ axis2_status_t status = AXIS2_FAILURE;
+ axiom_mime_part_t *mime_header_part = NULL;
+
+ /* We have the mime headers in the hash with thier keys
+ * So first concatenate them to a one string */
+
+ for(hash_index = axutil_hash_first(mime_body_part->header_map, env); hash_index; hash_index
+ = axutil_hash_next(env, hash_index))
+ {
+ axutil_hash_this(hash_index, &key, NULL, &value);
+ if(key && value)
+ {
+ /* First conactenate to the already conacatenated stuff */
+
+ temp_header_str = axutil_stracat(env, header_str, (axis2_char_t *)key);
+ if(header_str)
+ {
+ AXIS2_FREE(env->allocator, header_str);
+ }
+ header_str = temp_header_str;
+ temp_header_str = axutil_stracat(env, header_str, ": ");
+ AXIS2_FREE(env->allocator, header_str);
+ header_str = temp_header_str;
+
+ /* Add the new stuff */
+ temp_header_str = axutil_stracat(env, header_str, (axis2_char_t *)value);
+ AXIS2_FREE(env->allocator, header_str);
+ header_str = temp_header_str;
+
+ /* Next header will be in a new line. So lets add it */
+
+ temp_header_str = axutil_stracat(env, header_str, AXIS2_CRLF);
+ AXIS2_FREE(env->allocator, header_str);
+ header_str = temp_header_str;
+ }
+ }
+
+ /* If there is a data handler that's mean there is an attachment. Attachment
+ * will always start after an additional new line . So let's add it .*/
+
+ if(mime_body_part->data_handler)
+ {
+ temp_header_str = axutil_stracat(env, header_str, AXIS2_CRLF);
+ AXIS2_FREE(env->allocator, header_str);
+ header_str = temp_header_str;
+ }
+
+ if(header_str)
+ {
+ header_str_size = axutil_strlen(header_str);
+ }
+
+ /* Now we have the complete mime_headers string for a particular mime part.
+ * First wrap it as a mime_part_t .Then add it to the array list so
+ * later through the transport this can be written to the wire. */
+
+ mime_header_part = axiom_mime_part_create(env);
+
+ if(mime_header_part)
+ {
+ mime_header_part->part = (axis2_byte_t *)header_str;
+ mime_header_part->part_size = header_str_size;
+ mime_header_part->type = AXIOM_MIME_PART_BUFFER;
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+
+ axutil_array_list_add(list, env, mime_header_part);
+
+ /* Then if the data_handler is there let's add the binary data, may be
+ * buffer , may be file name and information.
+ */
+
+ if(mime_body_part->data_handler)
+ {
+ status = axiom_data_handler_add_binary_data(mime_body_part->data_handler, env, list);
+ if(status != AXIS2_SUCCESS)
+ {
+ return status;
+ }
+ }
+ return AXIS2_SUCCESS;
+}
diff --git a/axiom/src/attachments/mime_parser.c b/axiom/src/attachments/mime_parser.c
new file mode 100644
index 0000000..f36286c
--- /dev/null
+++ b/axiom/src/attachments/mime_parser.c
@@ -0,0 +1,2304 @@
+/*
+ * 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 <axiom_mime_parser.h>
+#include <axutil_string.h>
+#include <axiom_data_handler.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <axutil_http_chunked_stream.h>
+#include <axiom_mtom_caching_callback.h>
+#include <axutil_class_loader.h>
+#include <axutil_url.h>
+
+struct axiom_mime_parser
+{
+ /* This will keep the attachment and its info*/
+ axutil_hash_t *mime_parts_map;
+
+ /* This is the actual SOAP part len */
+ size_t soap_body_len;
+
+ /* The SOAP part of the message */
+ axis2_char_t *soap_body_str;
+
+ /* The size of the buffer we give to the callback to
+ * read data */
+ size_t buffer_size;
+
+ /* The number of buffers */
+ int max_buffers;
+
+ /* The attachment dir name, in the case of caching */
+ axis2_char_t *attachment_dir;
+
+ /*A pointer to the caching callback */
+ axiom_mtom_caching_callback_t *mtom_caching_callback;
+
+ /* The caching callback name specified */
+ axis2_char_t *callback_name;
+
+ axis2_char_t **buf_array;
+
+ size_t *len_array;
+
+ int current_buf_num;
+
+ axis2_bool_t end_of_mime;
+
+ axis2_char_t *mime_boundary;
+
+};
+
+struct axiom_search_info
+{
+ /*String need to be searched*/
+ const axis2_char_t *search_str;
+
+ /*The buffers and the lengths need to be searched*/
+ axis2_char_t *buffer1;
+ size_t len1;
+ axis2_char_t *buffer2;
+ size_t len2;
+
+ /*Flag to keep what type of search is this buffer has done*/
+ axis2_bool_t primary_search;
+
+ /*The offset where we found the pattern entirely in one buffer*/
+ size_t match_len1;
+
+ /*when pattern contains in two buffers the length of partial pattern
+ in buffer2 */
+ size_t match_len2;
+
+ /*Whether we need caching or not*/
+ axis2_bool_t cached;
+
+ /*A pointer to a user provided storage to which we cache the attachment*/
+ void *handler;
+
+ /* Size of the binary when writing to the buffer*/
+ size_t binary_size;
+};
+
+typedef struct axiom_search_info axiom_search_info_t;
+
+#define AXIOM_MIME_PARSER_CONTENT_ID "content-id"
+#define AXIOM_MIME_PARSER_CONTENT_TYPE "content-type"
+
+#define AXIOM_MIME_PARSER_END_OF_MIME_MAX_COUNT 100
+
+static axis2_char_t *
+axiom_mime_parser_search_for_soap(
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ int *buf_num,
+ size_t *len_array,
+ axis2_char_t **buf_array,
+ axiom_search_info_t *search_info,
+ size_t size,
+ axis2_char_t *mime_boundary,
+ axiom_mime_parser_t *mime_parser);
+
+static axis2_char_t *
+axiom_mime_parser_search_for_crlf(
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ int *buf_num,
+ size_t *len_array,
+ axis2_char_t **buf_array,
+ axiom_search_info_t *search_info,
+ size_t size,
+ axiom_mime_parser_t *mime_parser);
+
+static size_t
+axiom_mime_parser_calculate_part_len(
+ const axutil_env_t *env,
+ int buf_num,
+ size_t *len_list,
+ int maker,
+ axis2_char_t *pos,
+ axis2_char_t *buf);
+
+static axis2_char_t *
+axiom_mime_parser_create_part(
+ const axutil_env_t *env,
+ size_t part_len,
+ int buf_num,
+ size_t *len_list,
+ int marker,
+ axis2_char_t *pos,
+ axis2_char_t **buf_list,
+ axiom_mime_parser_t *mime_parser);
+
+static axis2_char_t *
+axiom_mime_parser_search_string(
+ axiom_search_info_t *search_info,
+ const axutil_env_t *env);
+
+static axis2_char_t *
+axiom_mime_parser_search_for_attachment(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ int *buf_num,
+ size_t *len_array,
+ axis2_char_t **buf_array,
+ axiom_search_info_t *search_info,
+ size_t size,
+ axis2_char_t *mime_boundary,
+ axis2_char_t *mime_id,
+ void *user_param);
+
+static axis2_status_t
+axiom_mime_parser_store_attachment(
+ const axutil_env_t *env,
+ axiom_mime_parser_t *mime_parser,
+ axis2_char_t *mime_id,
+ axis2_char_t *mime_type,
+ axis2_char_t *mime_binary,
+ size_t mime_binary_len,
+ axis2_bool_t cached);
+
+static void
+axiom_mime_parser_clear_buffers(
+ const axutil_env_t *env,
+ axis2_char_t **buf_list,
+ int free_from,
+ int free_to);
+
+static axis2_status_t
+axiom_mime_parser_cache_to_buffer(
+ const axutil_env_t *env,
+ axis2_char_t *buf,
+ size_t buf_len,
+ axiom_search_info_t *search_info,
+ axiom_mime_parser_t *mime_parser);
+
+static axis2_bool_t
+axiom_mime_parser_is_more_data(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_callback_info_t *callback_info);
+
+static axis2_char_t *
+axiom_mime_parser_process_mime_headers(
+ const axutil_env_t *env,
+ axiom_mime_parser_t *mime_parser,
+ axis2_char_t **mime_id,
+ axis2_char_t *mime_headers);
+
+static axis2_status_t
+axiom_mime_parser_cache_to_file(
+ const axutil_env_t* env,
+ axis2_char_t *buf,
+ size_t buf_len,
+ void *handler);
+
+static void*
+axiom_mime_parser_initiate_callback(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_char_t *mime_id,
+ void *user_param);
+
+AXIS2_EXTERN axiom_mime_parser_t *AXIS2_CALL
+axiom_mime_parser_create(
+ const axutil_env_t * env)
+{
+ axiom_mime_parser_t *mime_parser = NULL;
+
+ AXIS2_ENV_CHECK(env, NULL);
+ mime_parser = (axiom_mime_parser_t *)AXIS2_MALLOC(env->allocator, sizeof(axiom_mime_parser_t));
+
+ if(!mime_parser)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ return NULL;
+ }
+
+ mime_parser->mime_parts_map = NULL;
+ mime_parser->soap_body_len = 0;
+ mime_parser->soap_body_str = NULL; /* shallow copy */
+ mime_parser->buffer_size = 1;
+ mime_parser->max_buffers = AXIOM_MIME_PARSER_MAX_BUFFERS;
+ mime_parser->attachment_dir = NULL;
+ mime_parser->mtom_caching_callback = NULL;
+ mime_parser->callback_name = NULL;
+ mime_parser->buf_array = NULL;
+ mime_parser->len_array = NULL;
+ mime_parser->current_buf_num = 0;
+ mime_parser->end_of_mime = AXIS2_FALSE;
+ mime_parser->mime_boundary = NULL;
+
+ mime_parser->mime_parts_map = axutil_hash_make(env);
+ if(!(mime_parser->mime_parts_map))
+ {
+ axiom_mime_parser_free(mime_parser, env);
+ return NULL;
+ }
+
+ return mime_parser;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_parser_free(
+ axiom_mime_parser_t * mime_parser,
+ const axutil_env_t * env)
+{
+ AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
+
+ /* The map is passed on to SOAP builder, and SOAP builder take over the
+ ownership of the map */
+
+ /* We will unload the callback at the end */
+
+ if(mime_parser->mtom_caching_callback)
+ {
+ axutil_param_t *param = NULL;
+ param = mime_parser->mtom_caching_callback->param;
+
+ AXIOM_MTOM_CACHING_CALLBACK_FREE(mime_parser->mtom_caching_callback, env);
+ mime_parser->mtom_caching_callback = NULL;
+
+ if(param)
+ {
+ axutil_param_free(param, env);
+ param = NULL;
+ }
+ }
+
+ if(mime_parser->buf_array)
+ {
+ AXIS2_FREE(env->allocator, mime_parser->buf_array);
+ mime_parser->buf_array = NULL;
+ }
+
+ if(mime_parser->len_array)
+ {
+ AXIS2_FREE(env->allocator, mime_parser->len_array);
+ mime_parser->len_array = NULL;
+ }
+
+ if(mime_parser)
+ {
+ AXIS2_FREE(env->allocator, mime_parser);
+ }
+
+ return;
+}
+
+AXIS2_EXTERN axis2_status_t AXIS2_CALL
+axiom_mime_parser_parse_for_soap(
+ axiom_mime_parser_t * mime_parser,
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ axis2_char_t * mime_boundary)
+{
+ size_t size = 0;
+ axis2_char_t *soap_str = NULL;
+ size_t soap_len = 0;
+ size_t temp_mime_boundary_size = 0;
+ axis2_char_t *temp_mime_boundary = NULL;
+ axis2_char_t **buf_array = NULL;
+ size_t *len_array = NULL;
+ int buf_num = 0;
+ axis2_char_t *pos = NULL;
+ axiom_search_info_t *search_info = NULL;
+ int part_start = 0;
+ axis2_bool_t end_of_mime = AXIS2_FALSE;
+ size_t len = 0;
+ axis2_char_t *buffer = NULL;
+ size_t malloc_len = 0;
+ axis2_callback_info_t *callback_info = NULL;
+
+ callback_info = (axis2_callback_info_t *)callback_ctx;
+
+ /* The user will specify the mime_parser->buffer_size */
+
+ size = AXIOM_MIME_PARSER_BUFFER_SIZE * (mime_parser->buffer_size);
+
+ /*An array to keep the set of buffers*/
+
+ buf_array = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t *) * (mime_parser->max_buffers));
+
+ if(!buf_array)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Failed in creating buffer array");
+ return AXIS2_FAILURE;
+ }
+
+ /*Keeps the corresponding lengths of buffers in buf_array*/
+
+ len_array = AXIS2_MALLOC(env->allocator, sizeof(size_t) * (mime_parser->max_buffers));
+
+ if(!len_array)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Failed in creating length array");
+ return AXIS2_FAILURE;
+ }
+
+ mime_parser->buf_array = buf_array;
+ mime_parser->len_array = len_array;
+
+ temp_mime_boundary = axutil_stracat(env, "--", mime_boundary);
+ temp_mime_boundary_size = strlen(mime_boundary) + 2;
+
+ /*This struct keeps the pre-post search informations*/
+ search_info = AXIS2_MALLOC(env->allocator, sizeof(axiom_search_info_t));
+
+ /* The first buffer is created */
+ buf_array[buf_num] = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ /* The buffer is filled from the callback */
+
+ if(buf_array[buf_num])
+ {
+ len = callback(buf_array[buf_num], (int)size, (void *)callback_ctx);
+ }
+ if(len > 0)
+ {
+ len_array[buf_num] = len;
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error reading from the stream");
+ return AXIS2_FAILURE;
+ }
+
+ /*starting buffer for the current search*/
+ part_start = buf_num;
+
+ /*We are passing the address of the buf_num , beacause that value
+ is changing inside the method.*/
+
+ /* Following call to the method will search first \r\n\r\n */
+
+ pos = axiom_mime_parser_search_for_crlf(env, callback, callback_ctx, &buf_num, len_array,
+ buf_array, search_info, size, mime_parser);
+
+ if(!pos)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in the message.");
+ return AXIS2_FAILURE;
+ }
+
+ /* The patteren contains in one buffer */
+
+ if((search_info->match_len2 == 0))
+ {
+ /*Readjusting the buffers for the next search and discarding the prevoius
+ buffers*/
+
+ /* We need the remaining part in the buffer after the \r\n\r\n*/
+
+ malloc_len = buf_array[buf_num] + len_array[buf_num] - pos - 4;
+ if(malloc_len < 0)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing.");
+ return AXIS2_FAILURE;
+ }
+ else
+ {
+ /* Here we will create a new buffer of predefined size fill the
+ * first portion from the remaining part after previous search
+ * and then fill the remaining from the callback */
+
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, pos + 4, malloc_len);
+ }
+
+ /* Here we need to check for more data, because if the message is too small
+ * comapred to the reading size there may be no data in the stream , instead
+ * all the remaining data may be in the buffer.And if there are no more data
+ * we will set the len to be 0. Otherwise len_array will contain wrong lenghts.
+ */
+
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ /* There is more data so fill the remaining from the stream*/
+
+ len = callback(buffer + malloc_len, (int)(size - malloc_len), (void *)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+
+ /* We do not need the data in the previous buffers once we found a particular
+ * string and after worked with those buffers */
+
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+
+ /* Adding the new buffer to the buffer list */
+
+ if(len >= 0)
+ {
+ buf_array[buf_num] = buffer;
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ }
+
+ /*The pattern divides among two buffers*/
+
+ else if(search_info->match_len2 > 0)
+ {
+ malloc_len = len_array[buf_num] - search_info->match_len2;
+ if(malloc_len < 0)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing.");
+ return AXIS2_FAILURE;
+ }
+ else
+ {
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ /* Here the buf_num is the second buffer. We will copy the remaining data
+ * after the partial string in the second buffer */
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, buf_array[buf_num] + search_info->match_len2, malloc_len);
+ }
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len, (int)(size - malloc_len), (void *)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ if(len >= 0)
+ {
+ buf_array[buf_num] = buffer;
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing.");
+ return AXIS2_FAILURE;
+ }
+
+ /*Resetting the previous search data and getting ready
+ for the next search */
+
+ part_start = buf_num;
+ pos = NULL;
+ malloc_len = 0;
+
+ search_info->match_len1 = 0;
+ search_info->match_len2 = 0;
+
+ /*In order to extract the soap envelope we need to search for the first
+ --MIMEBOUNDARY */
+
+ pos = axiom_mime_parser_search_for_soap(env, callback, callback_ctx, &buf_num, len_array,
+ buf_array, search_info, size, temp_mime_boundary, mime_parser);
+
+ if(!pos)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error while searching for the SOAP part ");
+ return AXIS2_FAILURE;
+ }
+
+ if(search_info->match_len2 == 0)
+ {
+ /*Calculating the length of the SOAP str*/
+
+ soap_len = axiom_mime_parser_calculate_part_len(env, buf_num, len_array, part_start, pos,
+ buf_array[buf_num]);
+ if(soap_len > 0)
+ {
+ /* Get the SOAP string from the starting and end buffers containing
+ * the SOAP part */
+
+ soap_str = axiom_mime_parser_create_part(env, soap_len, buf_num, len_array, part_start,
+ pos, buf_array, mime_parser);
+ if(!soap_str)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Error while creating the SOAP part from the message ");
+ return AXIS2_FAILURE;
+ }
+
+ malloc_len = len_array[buf_num] - search_info->match_len1 - temp_mime_boundary_size;
+ if(malloc_len < 0)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing for mime.");
+ return AXIS2_FAILURE;
+ }
+ else
+ {
+ /* This will fill the new buffer with remaining data after the
+ * SOAP */
+
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ memset(buffer, 0, size + 1);
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, pos + temp_mime_boundary_size, malloc_len);
+ }
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len,(int)(size - malloc_len),(void *)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ if(len >= 0)
+ {
+ buf_array[buf_num] = buffer;
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+
+ /* This is the condition where the --MIMEBOUNDARY is divided among two
+ * buffers */
+
+ else if(search_info->match_len2 > 0)
+ {
+ soap_len = axiom_mime_parser_calculate_part_len(env, buf_num - 1, len_array, part_start,
+ pos, buf_array[buf_num - 1]);
+
+ if(soap_len > 0)
+ {
+ /* Here we pass buf_num-1 because buf_num does not have any thing we want to
+ * for this particular part. It begins with the latter part of the search string */
+
+ soap_str = axiom_mime_parser_create_part(env, soap_len, buf_num - 1, len_array,
+ part_start, pos, buf_array, mime_parser);
+ if(!soap_str)
+ {
+ return AXIS2_FAILURE;
+ }
+
+ malloc_len = len_array[buf_num] - search_info->match_len2;
+ if(malloc_len < 0)
+ {
+ return AXIS2_FAILURE;
+ }
+ else
+ {
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, buf_array[buf_num] + search_info->match_len2, malloc_len);
+ }
+
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len,(int)(size - malloc_len),(void *)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ if(len >= 0)
+ {
+ buf_array[buf_num] = buffer;
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+
+ mime_parser->soap_body_str = soap_str;
+ mime_parser->soap_body_len = soap_len;
+ mime_parser->current_buf_num = buf_num;
+
+ /* There are multipart/related messages which does not contain attachments
+ * The only mime_part is the soap envelope. So for those messages the mime
+ * boundary after the soap will end up with --
+ * So we will check that here and if we found then the logic inside the
+ * while loop will not be executed */
+
+ end_of_mime = (AXIOM_MIME_BOUNDARY_BYTE == *(buf_array[buf_num])) && (AXIOM_MIME_BOUNDARY_BYTE
+ == *(buf_array[buf_num] + 1));
+ if(end_of_mime)
+ {
+ AXIS2_FREE(env->allocator, buf_array[buf_num]);
+ buf_array[buf_num] = NULL;
+ }
+
+ if(temp_mime_boundary)
+ {
+ AXIS2_FREE(env->allocator, temp_mime_boundary);
+ temp_mime_boundary = NULL;
+ }
+
+ if(search_info)
+ {
+ AXIS2_FREE(env->allocator, search_info);
+ search_info = NULL;
+ }
+
+ mime_parser->end_of_mime = end_of_mime;
+
+ return AXIS2_SUCCESS;
+}
+
+AXIS2_EXTERN axutil_hash_t *AXIS2_CALL
+axiom_mime_parser_parse_for_attachments(
+ axiom_mime_parser_t * mime_parser,
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ axis2_char_t * mime_boundary,
+ void *user_param)
+{
+ int count = 0;
+ axiom_search_info_t *search_info = NULL;
+ axis2_char_t *pos = NULL;
+ int part_start = 0;
+ axis2_char_t **buf_array = NULL;
+ size_t *len_array = NULL;
+ int buf_num = 0;
+ size_t size = 0;
+ size_t malloc_len = 0;
+ axis2_callback_info_t *callback_info = NULL;
+ axis2_char_t *temp_mime_boundary = NULL;
+ size_t temp_mime_boundary_size = 0;
+ axis2_bool_t end_of_mime = AXIS2_FALSE;
+
+ callback_info = (axis2_callback_info_t *)callback_ctx;
+
+ search_info = AXIS2_MALLOC(env->allocator, sizeof(axiom_search_info_t));
+
+ size = AXIOM_MIME_PARSER_BUFFER_SIZE * (mime_parser->buffer_size);
+
+ buf_array = mime_parser->buf_array;
+ len_array = mime_parser->len_array;
+ buf_num = mime_parser->current_buf_num;
+
+ /*<SOAP></SOAP>--MIMEBOUNDARY
+ mime_headr1:.......
+ mime_headr2:....
+
+ Binarstart.................
+ ...............--MIMEBOUNDARY
+ */
+
+ /* This loop will extract all the attachments in the message. The condition
+ * with the count is needed because if the sender not marked the end of the
+ * attachment wiht -- then this loop may run infinitely. To prevent that
+ * this additional condition has been put */
+
+ temp_mime_boundary = axutil_stracat(env, "--", mime_boundary);
+ temp_mime_boundary_size = strlen(mime_boundary) + 2;
+
+ while((!(mime_parser->end_of_mime)) && count < AXIOM_MIME_PARSER_END_OF_MIME_MAX_COUNT)
+ {
+ /*First we will search for \r\n\r\n*/
+ axis2_char_t *mime_id = NULL;
+ axis2_char_t *mime_type = NULL;
+ size_t mime_headers_len = 0;
+ size_t mime_binary_len = 0;
+ axis2_char_t *mime_binary = NULL;
+ axis2_char_t *mime_headers = NULL;
+ axis2_char_t *buffer = NULL;
+ int len = 0;
+ axis2_status_t status = AXIS2_FAILURE;
+
+ search_info->match_len1 = 0;
+ search_info->match_len2 = 0;
+ pos = NULL;
+ part_start = buf_num;
+
+ malloc_len = 0;
+
+ count++;
+
+ pos = axiom_mime_parser_search_for_crlf(env, callback, callback_ctx, &buf_num, len_array,
+ buf_array, search_info, size, mime_parser);
+
+ if(!pos)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing for mime.");
+ return NULL;
+ }
+
+ /*The pattern contains in one buffer*/
+ if(search_info->match_len2 == 0)
+ {
+ /*We found it . so lets seperates the details of this binary into
+ mime headers.*/
+
+ mime_headers_len = axiom_mime_parser_calculate_part_len(env, buf_num, len_array,
+ part_start, pos, buf_array[buf_num]);
+ if(mime_headers_len > 0)
+ {
+ mime_headers = axiom_mime_parser_create_part(env, mime_headers_len, buf_num,
+ len_array, part_start, pos, buf_array, mime_parser);
+
+ if(!mime_headers)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing for mime headers.");
+ return NULL;
+ }
+ malloc_len = buf_array[buf_num] + len_array[buf_num] - pos - 4;
+
+ /*This should be > 0 , > 0 means there is some part to copy = 0 means
+ there is nothing to copy*/
+ if(malloc_len < 0)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing for mime headers");
+ return NULL;
+ }
+
+ else
+ {
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, pos + 4, malloc_len);
+ }
+
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len,(int)(size - malloc_len),(void *)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ if(len >= 0)
+ {
+ buf_array[buf_num] = buffer;
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Error in parsing for mime headers.");
+ return NULL;
+ }
+ }
+
+ else if(search_info->match_len2 > 0)
+ {
+ /*Now we extract the mime headers */
+
+ mime_headers_len = axiom_mime_parser_calculate_part_len(env, buf_num - 1, len_array,
+ part_start, pos, buf_array[buf_num - 1]);
+
+ if(mime_headers_len > 0)
+ {
+ mime_headers = axiom_mime_parser_create_part(env, mime_headers_len, buf_num - 1,
+ len_array, part_start, pos, buf_array, mime_parser);
+ if(!mime_headers)
+ {
+ return NULL;
+ }
+
+ malloc_len = len_array[buf_num] - search_info->match_len2;
+ if(malloc_len < 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, buf_array[buf_num] + search_info->match_len2, malloc_len);
+ }
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len,(int)(size - malloc_len),(void*)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ if(len >= 0)
+ {
+ buf_array[buf_num] = buffer;
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ pos = NULL;
+
+ search_info->match_len1 = 0;
+ search_info->match_len2 = 0;
+
+ part_start = buf_num;
+ malloc_len = 0;
+
+ mime_type
+ = axiom_mime_parser_process_mime_headers(env, mime_parser, &mime_id, mime_headers);
+
+ if(!mime_id)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Error in parsing for mime headers.Mime id did not find");
+ return NULL;
+ }
+
+ if(!mime_type)
+ {
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Mime type did not find");
+ }
+
+ /*We extract the mime headers. So lets search for the attachment.*/
+
+ pos = axiom_mime_parser_search_for_attachment(mime_parser, env, callback, callback_ctx,
+ &buf_num, len_array, buf_array, search_info, size, temp_mime_boundary, mime_id,
+ user_param);
+
+ if(pos)
+ {
+ /*If it is small we are not caching. Hence the attachment
+ is in memory. So store it in a buffer. */
+
+ if(!search_info->cached)
+ {
+ if(search_info->match_len2 == 0)
+ {
+ /* mime_binary contains the attachment when it does not
+ * cached */
+
+ mime_binary_len = axiom_mime_parser_calculate_part_len(env, buf_num, len_array,
+ part_start, pos, buf_array[buf_num]);
+ if(mime_binary_len > 0)
+ {
+ mime_binary = axiom_mime_parser_create_part(env, mime_binary_len, buf_num,
+ len_array, part_start, pos, buf_array, mime_parser);
+ if(!mime_binary)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ else if(search_info->match_len2 > 0)
+ {
+ mime_binary_len = axiom_mime_parser_calculate_part_len(env, buf_num - 1,
+ len_array, part_start, pos, buf_array[buf_num - 1]);
+
+ if(mime_binary_len > 0)
+ {
+ mime_binary = axiom_mime_parser_create_part(env, mime_binary_len, buf_num
+ - 1, len_array, part_start, pos, buf_array, mime_parser);
+ if(!mime_binary)
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ }
+
+ /* The functionality below is common when it is cached or not. It deals with remaining
+ * after a particualr attachment, Those may be related to a end of mime_boundary or
+ * another attachment */
+
+ if(search_info->match_len2 == 0)
+ {
+ malloc_len = len_array[buf_num] - search_info->match_len1 - temp_mime_boundary_size;
+ if(malloc_len < 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, pos + temp_mime_boundary_size, malloc_len);
+ }
+
+ /*When the last buffer only containing -- we know this is the end
+ of the attachments. Hence we don't need to read again*/
+
+ if(malloc_len != 2)
+ {
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len,(int)(size - malloc_len),(void*)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ if(len >= 0)
+ {
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+
+ /* This means there is another attachment */
+ else
+ {
+ len_array[buf_num] = malloc_len;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ buf_array[buf_num] = buffer;
+ }
+ }
+ else if(search_info->match_len2 > 0)
+ {
+ malloc_len = len_array[buf_num] - search_info->match_len2;
+
+ if(malloc_len < 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(malloc_len > 0)
+ {
+ memcpy(buffer, buf_array[buf_num] + search_info->match_len2, malloc_len);
+ }
+ if(malloc_len != 2)
+ {
+ if(axiom_mime_parser_is_more_data(mime_parser, env, callback_info))
+ {
+ len = callback(buffer + malloc_len,(int)(size - malloc_len),(void *)callback_ctx);
+ }
+ else
+ {
+ len = 0;
+ }
+ if(len >= 0)
+ {
+ len_array[buf_num] = malloc_len + len;
+ }
+ }
+ else
+ {
+ len_array[buf_num] = malloc_len;
+ }
+ axiom_mime_parser_clear_buffers(env, buf_array, part_start, buf_num);
+ buf_array[buf_num] = buffer;
+ }
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ /*We have the attachment now either cached or not. So lets put it in the mime_parts
+ * hash map with the mime_id. Remember at this moment we have already processed the
+ * mime_headers and mime_id is already there */
+
+ /* In the case user has not specified the callback or the attachment dir . So we cached it to a memory
+ * buffer. Hence the data_handler type we need to create is different */
+
+ if((search_info->cached) && (!mime_parser->attachment_dir) && (!mime_parser->callback_name))
+ {
+ mime_binary = (axis2_char_t *)search_info->handler;
+ mime_binary_len = search_info->binary_size;
+ }
+
+ /* Storing the attachment in the hash map with the id*/
+
+ status = axiom_mime_parser_store_attachment(env, mime_parser, mime_id, mime_type,
+ mime_binary, mime_binary_len, search_info->cached);
+
+ /*Check wether we encounter --MIMEBOUNDARY-- to find the end of mime*/
+
+ if(buf_array[buf_num])
+ {
+ /* Here we check for the end of mime */
+
+ end_of_mime = (AXIOM_MIME_BOUNDARY_BYTE == *(buf_array[buf_num]))
+ && (AXIOM_MIME_BOUNDARY_BYTE == *(buf_array[buf_num] + 1));
+ if(end_of_mime)
+ {
+ AXIS2_FREE(env->allocator, buf_array[buf_num]);
+ buf_array[buf_num] = NULL;
+ }
+ mime_parser->end_of_mime = end_of_mime;
+ }
+
+ if(mime_headers)
+ {
+ AXIS2_FREE(env->allocator, mime_headers);
+ mime_headers = NULL;
+ }
+
+ if(status != AXIS2_SUCCESS)
+ {
+ return NULL;
+ }
+ }
+
+ /*Do the necessary cleaning */
+
+ /*if (buf_array)
+ {
+ AXIS2_FREE(env->allocator, buf_array);
+ buf_array = NULL;
+ }
+
+ if (len_array)
+ {
+ AXIS2_FREE(env->allocator, len_array);
+ len_array = NULL;
+ }*/
+
+ if(temp_mime_boundary)
+ {
+ AXIS2_FREE(env->allocator, temp_mime_boundary);
+ temp_mime_boundary = NULL;
+ }
+
+ if(search_info)
+ {
+ AXIS2_FREE(env->allocator, search_info);
+ search_info = NULL;
+ }
+
+ return mime_parser->mime_parts_map;
+
+}
+
+/*This method will search for \r\n\r\n */
+
+static axis2_char_t *
+axiom_mime_parser_search_for_crlf(
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ int *buf_num,
+ size_t *len_array,
+ axis2_char_t **buf_array,
+ axiom_search_info_t *search_info,
+ size_t size,
+ axiom_mime_parser_t *mime_parser)
+{
+ axis2_char_t *found = NULL;
+ int len = 0;
+
+ search_info->search_str = "\r\n\r\n";
+ search_info->buffer1 = NULL;
+ search_info->buffer2 = NULL;
+ search_info->len1 = 0;
+ search_info->len2 = 0;
+ search_info->match_len1 = 0;
+ search_info->match_len2 = 0;
+ search_info->primary_search = AXIS2_FALSE;
+ search_info->cached = AXIS2_FALSE;
+ search_info->handler = NULL;
+ search_info->binary_size = 0;
+
+ /*First do a search in the first buffer*/
+
+ if(buf_array[*buf_num])
+ {
+ search_info->buffer1 = buf_array[*buf_num];
+ search_info->len1 = len_array[*buf_num];
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+
+ while(!found)
+ {
+ /*Let's read another buffer and do a boundary search in both*/
+
+ *buf_num = *buf_num + 1;
+ buf_array[*buf_num] = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(buf_array[*buf_num])
+ {
+ len = callback(buf_array[*buf_num], (int)size, (void *)callback_ctx);
+ }
+ if(len > 0)
+ {
+ len_array[*buf_num] = len;
+ search_info->buffer2 = buf_array[*buf_num];
+ search_info->len2 = len;
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+ else
+ {
+ break;
+ }
+ if(!found)
+ {
+ /*Let's do a full search in the second buffer*/
+
+ search_info->buffer1 = buf_array[*buf_num];
+ search_info->len1 = len_array[*buf_num];
+ search_info->primary_search = AXIS2_FALSE;
+ search_info->buffer2 = NULL;
+ search_info->len2 = 0;
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+ }
+
+ return found;
+}
+
+/* This method will search for the mime_boundary after the SOAP part
+ * of the message */
+
+static axis2_char_t *
+axiom_mime_parser_search_for_soap(
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ int *buf_num,
+ size_t *len_array,
+ axis2_char_t **buf_array,
+ axiom_search_info_t *search_info,
+ size_t size,
+ axis2_char_t *mime_boundary,
+ axiom_mime_parser_t *mime_parser)
+{
+ axis2_char_t *found = NULL;
+ int len = 0;
+
+ /* What we need to search is the mime_boundary */
+
+ search_info->search_str = mime_boundary;
+ search_info->buffer1 = NULL;
+ search_info->buffer2 = NULL;
+ search_info->len1 = 0;
+ search_info->len2 = 0;
+ search_info->match_len1 = 0;
+ search_info->match_len2 = 0;
+ search_info->primary_search = AXIS2_FALSE;
+
+ if(buf_array[*buf_num])
+ {
+ search_info->buffer1 = buf_array[*buf_num];
+ search_info->len1 = len_array[*buf_num];
+ found = axiom_mime_parser_search_string(search_info, env);
+
+ /* Inside this search primary_search flag will be set to TRUE */
+ }
+
+ while(!found)
+ {
+ /* We need to create the second buffer and do the search for the
+ * mime_boundary in the both the buffers */
+
+ *buf_num = *buf_num + 1;
+ buf_array[*buf_num] = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(buf_array[*buf_num])
+ {
+ len = callback(buf_array[*buf_num], (int)size, (void *)callback_ctx);
+ }
+ if(len > 0)
+ {
+ /* In this search we are matching end part of the first
+ * buffer and starting part of the previous buffer */
+ len_array[*buf_num] = len;
+ search_info->buffer2 = buf_array[*buf_num];
+ search_info->len2 = len;
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+ else
+ {
+ break;
+ }
+ if(!found)
+ {
+ search_info->buffer1 = buf_array[*buf_num];
+ search_info->len1 = len_array[*buf_num];
+ search_info->primary_search = AXIS2_FALSE;
+ search_info->buffer2 = NULL;
+ search_info->len2 = 0;
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+ }
+
+ return found;
+}
+
+/*The caching is done in this function. Caching happens when we did not
+ find the mime_boundary in initial two buffers. So the maximum size
+ that we are keeping in memory is 2 * size. This size can be configurable from
+ the aixs.xml. The caching may starts when the search failed with the
+ second buffer.
+ In this logic first we will search for a callback to cache. If it is not
+ there then we will search for a directory to save the file. If it is also
+ not there then the attachment will be in memory.
+ */
+
+static axis2_char_t *
+axiom_mime_parser_search_for_attachment(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t * env,
+ AXIS2_READ_INPUT_CALLBACK callback,
+ void *callback_ctx,
+ int *buf_num,
+ size_t *len_array,
+ axis2_char_t **buf_array,
+ axiom_search_info_t *search_info,
+ size_t size,
+ axis2_char_t *mime_boundary,
+ axis2_char_t *mime_id,
+ void *user_param)
+{
+ axis2_char_t *found = NULL;
+ int len = 0;
+ axis2_status_t status = AXIS2_FAILURE;
+ axis2_char_t *temp = NULL;
+ size_t temp_length = 0;
+ axis2_char_t *file_name = NULL;
+
+ search_info->search_str = mime_boundary;
+ search_info->buffer1 = NULL;
+ search_info->buffer2 = NULL;
+ search_info->len1 = 0;
+ search_info->len2 = 0;
+ search_info->match_len1 = 0;
+ search_info->match_len2 = 0;
+ search_info->primary_search = AXIS2_FALSE;
+ search_info->cached = AXIS2_FALSE;
+ search_info->handler = NULL;
+
+ /*First search in the incoming buffer*/
+
+ if(buf_array[*buf_num])
+ {
+ search_info->buffer1 = buf_array[*buf_num];
+ search_info->len1 = len_array[*buf_num];
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+
+ while(!found)
+ {
+ if(search_info->cached)
+ {
+ if(mime_parser->callback_name)
+ {
+ if(!(search_info->handler))
+ {
+ /* If the callback is not loaded yet then we load it*/
+ if(!mime_parser->mtom_caching_callback)
+ {
+ search_info->handler = axiom_mime_parser_initiate_callback(mime_parser,
+ env, mime_id, user_param);
+ if(!(search_info->handler))
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "Caching Callback is not loaded");
+ return NULL;
+ }
+ }
+ }
+ /*So lets cache the previous buffer which has undergone the
+ full search and the partial search. */
+
+ if(mime_parser->mtom_caching_callback)
+ {
+ /* Caching callback is loaded. So we can cache the previous buffer */
+ status
+ = AXIOM_MTOM_CACHING_CALLBACK_CACHE(mime_parser->mtom_caching_callback,
+ env, buf_array[*buf_num - 1], (int)len_array[*buf_num - 1],
+ search_info->handler);
+ }
+ }
+
+ else if(mime_parser->attachment_dir)
+ {
+ if(!(search_info->handler))
+ {
+ /* If the File is not opened yet we will open it*/
+
+ axis2_char_t *encoded_mime_id = NULL;
+
+ /* Some times content-ids urls, hence we need to encode them
+ * becasue we can't create files with / */
+
+ encoded_mime_id = AXIS2_MALLOC(env->allocator, (sizeof(axis2_char_t))
+ * (strlen(mime_id)));
+ memset(encoded_mime_id, 0, strlen(mime_id));
+ encoded_mime_id = axutil_url_encode(env, encoded_mime_id, mime_id, (int)strlen(
+ mime_id));
+ if(!encoded_mime_id)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Mime Id encoding failed");
+ return NULL;
+ }
+
+ file_name = axutil_stracat(env, mime_parser->attachment_dir, encoded_mime_id);
+ AXIS2_FREE(env->allocator, encoded_mime_id);
+ encoded_mime_id = NULL;
+
+ if(!file_name)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Caching file name creation error");
+ return NULL;
+ }
+ search_info->handler = (void *)fopen(file_name, "ab+");
+ if(!(search_info->handler))
+ {
+ return NULL;
+ }
+ }
+
+ /*So lets cache the previous buffer which has undergone the
+ full search and the partial search. */
+
+ status = axiom_mime_parser_cache_to_file(env, buf_array[*buf_num - 1],
+ len_array[*buf_num - 1], search_info->handler);
+ }
+
+ else
+ {
+ /* Here the user has not specified the caching File location. So we are
+ * not going to cache. Instead we store the attachment in the buffer */
+ status = axiom_mime_parser_cache_to_buffer(env, buf_array[*buf_num - 1],
+ len_array[*buf_num - 1], search_info, mime_parser);
+ }
+
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+ /*Here we interchange the buffers.*/
+
+ temp = buf_array[*buf_num - 1];
+ buf_array[*buf_num - 1] = buf_array[*buf_num];
+ buf_array[*buf_num] = temp;
+ temp_length = len_array[*buf_num - 1];
+ len_array[*buf_num - 1] = len_array[*buf_num];
+ len_array[*buf_num] = temp_length;
+ if(buf_array[*buf_num])
+ {
+ /*The cached buffer is the one which get filled.*/
+ len = callback(buf_array[*buf_num], (int)size, (void *)callback_ctx);
+ }
+ }
+
+ /*Size of the data in memory not yet risen to the caching threasold
+ *So we can create the second buffer */
+ else
+ {
+ *buf_num = *buf_num + 1;
+ buf_array[*buf_num] = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (size + 1));
+
+ if(buf_array[*buf_num])
+ {
+ len = callback(buf_array[*buf_num], (int)size, (void *)callback_ctx);
+ }
+ }
+
+ /*Doing a complete search in newly cretaed buffer*/
+
+ if(len > 0)
+ {
+ len_array[*buf_num] = len;
+ search_info->buffer2 = buf_array[*buf_num];
+ search_info->len2 = len;
+ found = axiom_mime_parser_search_string(search_info, env);
+ }
+ else
+ {
+ break;
+ }
+
+ /* Now there are two buffers. If the searching string is not
+ * here then we must cache the first buffer */
+
+ if(!found)
+ {
+ /*So now we must start caching*/
+ search_info->buffer1 = buf_array[*buf_num];
+ search_info->len1 = len_array[*buf_num];
+ search_info->primary_search = AXIS2_FALSE;
+ search_info->buffer2 = NULL;
+ search_info->len2 = 0;
+ found = axiom_mime_parser_search_string(search_info, env);
+ if(!found)
+ {
+ /* So at the begining of the next search we start
+ * that only after caching this data */
+ search_info->cached = AXIS2_TRUE;
+ }
+ }
+ }
+
+ /* Here we are out of the loop. If there is no error then this means
+ * the searching string is found */
+ if(search_info->cached && found)
+ {
+ /* If the attachment is cached then we need to cache the
+ * final buffer */
+
+ if(search_info->match_len2 == 0)
+ {
+ /* This is the case where we found the whole string in one buffer
+ * So we need to cache previous buffer and the data up to the starting
+ * point of the search string in the current buffer */
+
+ /* deduct last 2 CRLF character.
+ * For buffering case, it will be done when creating datahandler.*/
+
+ if(mime_parser->mtom_caching_callback)
+ {
+ status = AXIOM_MTOM_CACHING_CALLBACK_CACHE(mime_parser->mtom_caching_callback, env,
+ buf_array[*buf_num - 1], (int)len_array[*buf_num - 1], search_info->handler);
+ if(status == AXIS2_SUCCESS)
+ {
+ status
+ = AXIOM_MTOM_CACHING_CALLBACK_CACHE(mime_parser->mtom_caching_callback,
+ env, buf_array[*buf_num], (int)(found - buf_array[*buf_num] - 2),
+ search_info->handler);
+ }
+ }
+
+ else if(mime_parser->attachment_dir)
+ {
+ status = axiom_mime_parser_cache_to_file(env, buf_array[*buf_num - 1],
+ len_array[*buf_num - 1], search_info->handler);
+ if(status == AXIS2_SUCCESS)
+ {
+ status = axiom_mime_parser_cache_to_file(env, buf_array[*buf_num], found
+ - buf_array[*buf_num] - 2, search_info->handler);
+ }
+ }
+
+ /* If the callback or a file is not there then the data is appended to the buffer */
+
+ else
+ {
+ status = axiom_mime_parser_cache_to_buffer(env, buf_array[*buf_num - 1],
+ len_array[*buf_num - 1], search_info, mime_parser);
+ if(status == AXIS2_SUCCESS)
+ {
+ status = axiom_mime_parser_cache_to_buffer(env, buf_array[*buf_num], found
+ - buf_array[*buf_num], search_info, mime_parser);
+ }
+ }
+ }
+ else if(search_info->match_len2 > 0)
+ {
+ /*Here the curent buffer has partial mime boundary. So we need
+ to cache only the previous buffer. */
+
+ if(mime_parser->mtom_caching_callback)
+ {
+ status = AXIOM_MTOM_CACHING_CALLBACK_CACHE(mime_parser->mtom_caching_callback, env,
+ buf_array[*buf_num - 1], (int)(search_info->match_len1 - 2), search_info->handler);
+ }
+
+ else if(mime_parser->attachment_dir)
+ {
+ status = axiom_mime_parser_cache_to_file(env, buf_array[*buf_num - 1],
+ search_info->match_len1 - 2, search_info->handler);
+ }
+ else
+ {
+ status = axiom_mime_parser_cache_to_buffer(env, buf_array[*buf_num - 1],
+ search_info->match_len1, search_info, mime_parser);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+ }
+
+ /* Parsing is done so lets close the relative handlers */
+
+ if(search_info->handler)
+ {
+ if(mime_parser->mtom_caching_callback)
+ {
+ status = AXIOM_MTOM_CACHING_CALLBACK_CLOSE_HANDLER(mime_parser->mtom_caching_callback,
+ env, search_info->handler);
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+ }
+
+ else if(mime_parser->attachment_dir)
+ {
+ if(fclose((FILE *)(search_info->handler)) == 0)
+ {
+ status = AXIS2_SUCCESS;
+ }
+ else
+ {
+ status = AXIS2_FAILURE;
+ }
+
+ AXIS2_FREE(env->allocator, file_name);
+ file_name = NULL;
+
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+ }
+ }
+ return found;
+}
+
+/*following two functions are used to extract important information
+ from the buffer list. eg: SOAP, MIME_HEADERS*/
+
+/*marker is the starting buffer of the required
+ part and pos is the end point of that part */
+
+static size_t
+axiom_mime_parser_calculate_part_len(
+ const axutil_env_t *env,
+ int buf_num,
+ size_t *len_list,
+ int marker,
+ axis2_char_t *pos,
+ axis2_char_t *buf)
+{
+ size_t part_len = 0;
+ int i = 0;
+
+ for(i = marker; i < buf_num; i++)
+ {
+ part_len += len_list[i];
+ }
+
+ part_len = part_len + (pos - buf);
+
+ return part_len;
+}
+
+static axis2_char_t *
+axiom_mime_parser_create_part(
+ const axutil_env_t *env,
+ size_t part_len,
+ int buf_num,
+ size_t *len_list,
+ int marker,
+ axis2_char_t *pos,
+ axis2_char_t **buf_list,
+ axiom_mime_parser_t *mime_parser)
+{
+ /*We will copy the set of buffers which contains the required part.
+ This part can be the SOAP message , mime headers or the mime
+ binary in the case of none cahced.*/
+
+ axis2_char_t *part_str = NULL;
+ int i = 0;
+ size_t temp = 0;
+
+ part_str = AXIS2_MALLOC(env->allocator, sizeof(char) * (part_len + 1));
+
+ if(!part_str)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Failed in creating buffer");
+ return NULL;
+ }
+
+ /* Copy from the part starting buffer to the
+ * curent buffer */
+
+ for(i = marker; i < buf_num; i++)
+ {
+ if(buf_list[i])
+ {
+ memcpy(part_str + temp, buf_list[i], len_list[i]);
+ temp += len_list[i];
+ }
+ }
+ /* Finally we are copying from the final portion */
+
+ memcpy(part_str + temp, buf_list[i], pos - buf_list[i]);
+
+ part_str[part_len] = '\0';
+
+ return part_str;
+}
+
+AXIS2_EXTERN axutil_hash_t *AXIS2_CALL
+axiom_mime_parser_get_mime_parts_map(
+ axiom_mime_parser_t * mime_parser,
+ const axutil_env_t * env)
+{
+ return mime_parser->mime_parts_map;
+}
+
+AXIS2_EXTERN size_t AXIS2_CALL
+axiom_mime_parser_get_soap_body_len(
+ axiom_mime_parser_t * mime_parser,
+ const axutil_env_t * env)
+{
+ return mime_parser->soap_body_len;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axiom_mime_parser_get_soap_body_str(
+ axiom_mime_parser_t * mime_parser,
+ const axutil_env_t * env)
+{
+ return mime_parser->soap_body_str;
+}
+
+/*This is the new search function. This will first do a
+ search for the entire search string.Then will do a search
+ for the partial string which can be divided among two buffers.*/
+
+static axis2_char_t *
+axiom_mime_parser_search_string(
+ axiom_search_info_t *search_info,
+ const axutil_env_t *env)
+{
+ axis2_char_t *pos = NULL;
+ axis2_char_t *old_pos = NULL;
+ axis2_char_t *found = NULL;
+ size_t str_length = 0;
+ size_t search_length = 0;
+
+ str_length = strlen(search_info->search_str);
+
+ /*First lets search the entire buffer*/
+ if(!search_info->primary_search)
+ {
+ old_pos = search_info->buffer1;
+
+ do
+ {
+ /*find the first byte. We need to adhere to this
+ approach rather than straightaway using strstr
+ because the buffer1 can be containg binary data*/
+
+ pos = NULL;
+
+ search_length = search_info->buffer1 + search_info->len1 - old_pos - str_length + 1;
+
+ if(search_length < 0)
+ {
+ break;
+ }
+
+ if(old_pos)
+ {
+ pos = memchr(old_pos, *(search_info->search_str), search_length);
+ }
+
+ /* found it so lets check the remaining */
+
+ if(pos)
+ {
+ found = axutil_strstr(pos, search_info->search_str);
+ if(found)
+ {
+ search_info->match_len1 = found - search_info->buffer1;
+ break;
+ }
+ else
+ {
+ old_pos = pos + 1;
+ }
+ }
+ }
+ while(pos);
+ }
+
+ search_info->primary_search = AXIS2_TRUE;
+
+ if(found)
+ {
+ return found;
+ }
+
+ /*So we didn't find the string in the buffer
+ lets check whether it is divided in two buffers*/
+
+ else
+ {
+ size_t offset = 0;
+ pos = NULL;
+ old_pos = NULL;
+ found = NULL;
+ search_length = 0;
+
+ if(search_info->buffer2)
+ {
+ old_pos = search_info->buffer1 + search_info->len1 - str_length + 1;
+ do
+ {
+ /*First check the starting byte*/
+ pos = NULL;
+ found = NULL;
+
+ search_length = search_info->buffer1 + search_info->len1 - old_pos;
+
+ if(search_length < 0)
+ {
+ break;
+ }
+
+ pos = memchr(old_pos, *(search_info->search_str), search_length);
+
+ if(pos)
+ {
+ offset = search_info->buffer1 + search_info->len1 - pos;
+
+ /*First match the beginng to offset in buffer1*/
+
+ if(offset > 0)
+ {
+ if(memcmp(pos, search_info->search_str, offset) == 0)
+ {
+ found = pos;
+ }
+
+ /*We found something in buffer1 so lets match the
+ remaining in buffer2*/
+
+ if(found)
+ {
+ if(memcmp(search_info->buffer2, search_info->search_str + offset,
+ str_length - offset) == 0)
+ {
+ search_info->match_len2 = str_length - offset;
+ search_info->match_len1 = found - search_info->buffer1;
+ break;
+ }
+ else
+ {
+ old_pos = pos + 1;
+ }
+ }
+ else
+ {
+ old_pos = pos + 1;
+ }
+ }
+ }
+ }
+ while(pos);
+
+ /* We will set this to AXIS2_FALSE so when the next time this
+ * search method is called it will do a full search first for buffer1 */
+ search_info->primary_search = AXIS2_FALSE;
+
+ return found;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+}
+
+/* This method creates a data_handler out of the attachment
+ * and store the data_handler in the mime_parts map */
+
+static axis2_status_t
+axiom_mime_parser_store_attachment(
+ const axutil_env_t *env,
+ axiom_mime_parser_t *mime_parser,
+ axis2_char_t *mime_id,
+ axis2_char_t *mime_type,
+ axis2_char_t *mime_binary,
+ size_t mime_binary_len,
+ axis2_bool_t cached)
+{
+ if(mime_parser->mime_parts_map)
+ {
+ if(mime_id)
+ {
+ axiom_data_handler_t *data_handler = NULL;
+
+ /* Handling the case where attachment is cached using a callback */
+
+ if(mime_parser->callback_name && cached)
+ {
+ data_handler = axiom_data_handler_create(env, NULL, mime_type);
+ if(data_handler)
+ {
+ axiom_data_handler_set_cached(data_handler, env, AXIS2_TRUE);
+ axiom_data_handler_set_data_handler_type(data_handler, env,
+ AXIOM_DATA_HANDLER_TYPE_CALLBACK);
+ }
+ }
+
+ /* Handling the case where attachment is cached to a file*/
+
+ else if(mime_parser->attachment_dir && cached)
+ {
+ axis2_char_t *attachment_location = NULL;
+ axis2_char_t *encoded_mime_id = NULL;
+
+ /* Some times content-ids urls, hence we need to encode them
+ * becasue we can't create files with / */
+
+ encoded_mime_id = AXIS2_MALLOC(env->allocator, (sizeof(axis2_char_t)) * (strlen(
+ mime_id)));
+ memset(encoded_mime_id, 0, strlen(mime_id));
+ encoded_mime_id = axutil_url_encode(
+ env, encoded_mime_id, mime_id, (int)strlen(mime_id));
+ if(!encoded_mime_id)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Mime Id encoding failed");
+ return AXIS2_FAILURE;
+ }
+
+ attachment_location = axutil_stracat(env, mime_parser->attachment_dir,
+ encoded_mime_id);
+
+ AXIS2_FREE(env->allocator, encoded_mime_id);
+ encoded_mime_id = NULL;
+
+ if(attachment_location)
+ {
+
+ data_handler = axiom_data_handler_create(env, attachment_location, mime_type);
+ if(data_handler)
+ {
+ axiom_data_handler_set_cached(data_handler, env, AXIS2_TRUE);
+
+ }
+ AXIS2_FREE(env->allocator, attachment_location);
+ attachment_location = NULL;
+ }
+ }
+
+ /* Attachment is in memory, either it is small to be cached or
+ * user does not provided the attachment cached directory */
+
+ else if(mime_binary)
+ {
+ data_handler = axiom_data_handler_create(env, NULL, mime_type);
+ if(data_handler)
+ {
+ axiom_data_handler_set_binary_data(data_handler, env, mime_binary,
+ mime_binary_len - 2);
+ }
+ }
+ axiom_data_handler_set_mime_id(data_handler, env, mime_id);
+
+ axutil_hash_set(mime_parser->mime_parts_map, mime_id, AXIS2_HASH_KEY_STRING,
+ data_handler);
+ if(mime_type)
+ {
+ AXIS2_FREE(env->allocator, mime_type);
+ }
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Mime Id or Mime rype not found");
+ return AXIS2_FAILURE;
+ /*axis2_char_t temp_boundry[1024];
+ sprintf(temp_boundry, "--%s--", mime_boundary);
+ if (body_mime && axutil_strstr(body_mime, temp_boundry))
+ {
+ break;
+ }*/
+ }
+ return AXIS2_SUCCESS;
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+}
+
+/* This method will process the mime_headers for a particualr
+ attacment and return the mime_id */
+
+static axis2_char_t *
+axiom_mime_parser_process_mime_headers(
+ const axutil_env_t *env,
+ axiom_mime_parser_t *mime_parser,
+ axis2_char_t **mime_id,
+ axis2_char_t *mime_headers)
+{
+ axis2_char_t *id = NULL;
+ axis2_char_t *type = NULL;
+ axis2_char_t *pos = NULL;
+
+ /* Get the MIME ID */
+ if(mime_headers)
+ {
+ id = axutil_strcasestr(mime_headers, AXIOM_MIME_HEADER_CONTENT_ID);
+ type = axutil_strcasestr(mime_headers, AXIOM_MIME_HEADER_CONTENT_TYPE);
+ if(type)
+ {
+ axis2_char_t *end = NULL;
+ axis2_char_t *temp_type = NULL;
+ type += axutil_strlen(AXIOM_MIME_HEADER_CONTENT_TYPE);
+ while(type && *type && *type != ':')
+ {
+ type++;
+ }
+ type++;
+ while(type && *type && *type == ' ')
+ {
+ type++;
+ }
+ end = type;
+ while(end && *end && !isspace((int)*end))
+ {
+ end++;
+ }
+ if((end - type) > 0)
+ {
+ temp_type = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * ((end - type) + 1));
+ if(!temp_type)
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Failed in creating Content-Type");
+ return NULL;
+ }
+ memcpy(temp_type, type, (end - type));
+ temp_type[end - type] = '\0';
+ type = temp_type;
+ }
+ }
+ if(id)
+ {
+ id += axutil_strlen(AXIOM_MIME_HEADER_CONTENT_ID);
+ while(id && *id && *id != ':')
+ {
+ id++;
+ }
+ if(id)
+ {
+ while(id && *id && *id != '<')
+ {
+ id++;
+ }
+ id++;
+ pos = axutil_strstr(id, ">");
+ if(pos)
+ {
+ int mime_id_len = 0;
+ mime_id_len = (int)(pos - id);
+ *mime_id = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * mime_id_len + 1);
+ /* The MIME ID will be freed by the SOAP builder */
+ if(*mime_id)
+ {
+ memcpy(*mime_id, id, mime_id_len);
+ (*mime_id)[mime_id_len] = '\0';
+ }
+ else
+ {
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
+ "No memory. Failed in creating MIME ID");
+ return NULL;
+ }
+ }
+ }
+ }
+ else
+ {
+ /*axis2_char_t temp_boundry[1024];
+ sprintf(temp_boundry, "--%s--", mime_boundary);
+ if (body_mime && axutil_strstr(body_mime, temp_boundry))
+ {
+ break;
+ }*/
+ return NULL;
+ }
+ return type;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/*This is used to free some unwanted buffers. For example we did
+ not want the buffers which contains the data before the soap
+ envelope starts. */
+
+static void
+axiom_mime_parser_clear_buffers(
+ const axutil_env_t *env,
+ axis2_char_t **buf_list,
+ int free_from,
+ int free_to)
+{
+ int i = 0;
+
+ for(i = free_from; i <= free_to; i++)
+ {
+ if(buf_list[i])
+ {
+ AXIS2_FREE(env->allocator, buf_list[i]);
+ buf_list[i] = NULL;
+ }
+ }
+ return;
+}
+
+/* Instead of caching to a file this method will cache it
+ * to a buffer */
+
+static axis2_status_t
+axiom_mime_parser_cache_to_buffer(
+ const axutil_env_t *env,
+ axis2_char_t *buf,
+ size_t buf_len,
+ axiom_search_info_t *search_info,
+ axiom_mime_parser_t *mime_parser)
+{
+ axis2_char_t *data_buffer = NULL;
+ axis2_char_t *temp_buf = NULL;
+ size_t mime_binary_len = 0;
+
+ temp_buf = (axis2_char_t *)search_info->handler;
+ mime_binary_len = search_info->binary_size + buf_len;
+
+ if(mime_binary_len > 0)
+ {
+ data_buffer = AXIS2_MALLOC(env->allocator, sizeof(axis2_char_t) * (mime_binary_len));
+
+ if(data_buffer)
+ {
+ if(temp_buf && search_info->binary_size > 0)
+ {
+ memcpy(data_buffer, temp_buf, search_info->binary_size);
+ AXIS2_FREE(env->allocator, temp_buf);
+ temp_buf = NULL;
+ }
+ memcpy(data_buffer + (search_info->binary_size), buf, buf_len);
+ search_info->binary_size = mime_binary_len;
+ search_info->handler = (void *)data_buffer;
+
+ return AXIS2_SUCCESS;
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+ }
+ else
+ {
+ return AXIS2_FAILURE;
+ }
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_parser_set_buffer_size(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ int size)
+{
+ mime_parser->buffer_size = size;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_parser_set_max_buffers(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ int num)
+{
+ mime_parser->max_buffers = num;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_parser_set_attachment_dir(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_char_t *attachment_dir)
+{
+ mime_parser->attachment_dir = attachment_dir;
+}
+
+/* Set the path of the caching callnack to be loaded */
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_parser_set_caching_callback_name(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_char_t *callback_name)
+{
+ mime_parser->callback_name = callback_name;
+}
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_parser_set_mime_boundary(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_char_t *mime_boundary)
+{
+ mime_parser->mime_boundary = mime_boundary;
+}
+
+AXIS2_EXTERN axis2_char_t *AXIS2_CALL
+axiom_mime_parser_get_mime_boundary(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env)
+{
+ return mime_parser->mime_boundary;
+}
+
+/* Load the caching callback dll */
+
+static void*
+axiom_mime_parser_initiate_callback(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_char_t *mime_id,
+ void *user_param)
+{
+ axutil_dll_desc_t *dll_desc = NULL;
+ axutil_param_t *impl_info_param = NULL;
+ void *ptr = NULL;
+
+ if(mime_parser->callback_name)
+ {
+ AXIS2_LOG_DEBUG(env->log, AXIS2_LOG_SI, "Trying to load module = %s",
+ mime_parser->callback_name);
+ dll_desc = axutil_dll_desc_create(env);
+ axutil_dll_desc_set_name(dll_desc, env, mime_parser->callback_name);
+ impl_info_param = axutil_param_create(env, NULL, dll_desc);
+ /*Set the free function*/
+ 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. ERROR",
+ mime_parser->callback_name);
+ return NULL;
+ }
+
+ mime_parser->mtom_caching_callback = (axiom_mtom_caching_callback_t *)ptr;
+ mime_parser->mtom_caching_callback->param = impl_info_param;
+ mime_parser->mtom_caching_callback->user_param = user_param;
+
+ return AXIOM_MTOM_CACHING_CALLBACK_INIT_HANDLER(mime_parser->mtom_caching_callback, env,
+ mime_id);
+ }
+
+ else
+ {
+ return NULL;
+ }
+
+}
+
+/* This method will tell whether there are more data in the
+ * stream */
+
+static axis2_bool_t
+axiom_mime_parser_is_more_data(
+ axiom_mime_parser_t *mime_parser,
+ const axutil_env_t *env,
+ axis2_callback_info_t *callback_info)
+{
+ /* In the case of axutil_http_chunked stream it is the
+ * end of chunk */
+
+ if(callback_info->chunked_stream)
+ {
+ if(axutil_http_chunked_stream_get_end_of_chunks(callback_info->chunked_stream, env))
+ {
+ return AXIS2_FALSE;
+ }
+ else
+ {
+ return AXIS2_TRUE;
+ }
+ }
+
+ /* When we are using content length or any wrapped
+ * stream it will be the unread_length */
+
+ else if(callback_info->unread_len == 0)
+ {
+ return AXIS2_FALSE;
+ }
+ else
+ {
+ return AXIS2_TRUE;
+ }
+}
+
+static axis2_status_t
+axiom_mime_parser_cache_to_file(
+ const axutil_env_t* env,
+ axis2_char_t *buf,
+ size_t buf_len,
+ void *handler)
+{
+ size_t len = 0;
+ FILE *fp = NULL;
+
+ fp = (FILE *)handler;
+
+ len = fwrite(buf, 1, buf_len, fp);
+ if(len < 0)
+ {
+ return AXIS2_FAILURE;
+ }
+ else
+ {
+ return AXIS2_SUCCESS;
+ }
+}
+
diff --git a/axiom/src/attachments/mime_part.c b/axiom/src/attachments/mime_part.c
new file mode 100644
index 0000000..8343327
--- /dev/null
+++ b/axiom/src/attachments/mime_part.c
@@ -0,0 +1,535 @@
+/*
+ * 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 <axiom_mime_part.h>
+#include <axiom_data_handler.h>
+#include "axiom_mime_body_part.h"
+#include <axutil_string.h>
+#include <axiom_text.h>
+#include <axiom_mime_const.h>
+
+
+static axis2_status_t
+axiom_mime_part_write_body_part_to_list(
+ const axutil_env_t *env,
+ axutil_array_list_t *list,
+ axiom_mime_body_part_t *part,
+ axis2_char_t *boundary);
+
+static axis2_status_t
+axiom_mime_part_write_mime_boundary(
+ const axutil_env_t *env,
+ axutil_array_list_t *list,
+ axis2_char_t *boundary);
+
+static axis2_status_t
+axiom_mime_part_finish_adding_parts(
+ const axutil_env_t *env,
+ axutil_array_list_t *list,
+ axis2_char_t *boundary);
+
+/* This method will create a mime_part
+ * A mime part will encapsulate a buffer
+ * a file or a callback to load the attachment
+ which needs to be send */
+
+AXIS2_EXTERN axiom_mime_part_t *AXIS2_CALL
+axiom_mime_part_create(
+ const axutil_env_t *env)
+{
+ axiom_mime_part_t *mime_part = NULL;
+ mime_part = AXIS2_MALLOC(env->allocator, sizeof(axiom_mime_part_t));
+
+ if(mime_part)
+ {
+ mime_part->part = NULL;
+ mime_part->file_name = NULL;
+ mime_part->part_size = 0;
+ mime_part->type = AXIOM_MIME_PART_UNKNOWN;
+ mime_part->user_param = NULL;
+
+ return mime_part;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/* Frees the mime_part */
+
+AXIS2_EXTERN void AXIS2_CALL
+axiom_mime_part_free(
+ axiom_mime_part_t *mime_part,
+ const axutil_env_t *env)
+{
+ if(mime_part)
+ {
+ if(mime_part->type == AXIOM_MIME_PART_BUFFER)
+ {
+ if(mime_part->part)
+ {
+ AXIS2_FREE(env->allocator, mime_part->part);
+ mime_part->part = NULL;
+ }
+ }
+ else if(mime_part->type == AXIOM_MIME_PART_FILE)
+ {
+ if(mime_part->file_name)
+ {
+ AXIS2_FREE(env->allocator, mime_part->file_name);
+ mime_part->file_name = NULL;
+ }
+ }
+
+ AXIS2_FREE(env->allocator, mime_part);
+ mime_part = NULL;
+ }
+ return;
+}
+
+/* This method will create a mime_boundary buffer
+ * and based on the buffer creates a mime_part.
+ * This will be added to the array_list so later in the trasnport
+ * this can be put to the wire. */
+
+static axis2_status_t
+axiom_mime_part_write_mime_boundary(
+ const axutil_env_t *env,
+ axutil_array_list_t *list,
+ axis2_char_t *boundary)
+{
+ axis2_byte_t *byte_buffer = NULL;
+ axis2_byte_t *byte_stream = NULL;
+ int size = 0;
+ axiom_mime_part_t *boundary_part = NULL;
+
+ boundary_part = axiom_mime_part_create(env);
+
+ byte_buffer = (axis2_byte_t *)boundary;
+ size = axutil_strlen(boundary);
+
+ byte_stream = AXIS2_MALLOC(env->allocator, (size + 2) * sizeof(axis2_byte_t));
+ if(!byte_stream)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create byte stream");
+ return AXIS2_FAILURE;
+ }
+
+ /* Mime boundary is always in the following form
+ --MimeBoundary */
+
+ byte_stream[0] = AXIOM_MIME_BOUNDARY_BYTE;
+ byte_stream[1] = AXIOM_MIME_BOUNDARY_BYTE;
+
+ memcpy(byte_stream + 2, byte_buffer, size);
+
+ boundary_part->part = byte_stream;
+ boundary_part->part_size = size + 2;
+ boundary_part->type = AXIOM_MIME_PART_BUFFER;
+
+ axutil_array_list_add(list, env, boundary_part);
+
+ return AXIS2_SUCCESS;
+}
+
+/* This method will add the attachment file related information
+ to the list. It will create a mime_part from those information
+ and add to the list. If there are not data_handlers in the mime_body
+ then this method just add the headers. */
+
+static axis2_status_t
+axiom_mime_part_write_body_part_to_list(
+ const axutil_env_t *env,
+ axutil_array_list_t *list,
+ axiom_mime_body_part_t *part,
+ axis2_char_t *boundary)
+{
+ axiom_mime_part_t *crlf1 = NULL;
+ axiom_mime_part_t *crlf2 = NULL;
+ axis2_status_t status = AXIS2_SUCCESS;
+
+ /* We are adding accoarding to the following format here.
+ * --MimeBoundary
+ * mime_header1
+ * mime_header2
+ * mime_header3 */
+
+ status = axiom_mime_part_write_mime_boundary(env, list, boundary);
+
+ if(status != AXIS2_SUCCESS)
+ {
+ return status;
+ }
+
+ /* Then we will add the new line charator after
+ * the mime_boundary */
+
+ crlf1 = axiom_mime_part_create(env);
+
+ crlf1->part = (axis2_byte_t *)axutil_strdup(env, AXIS2_CRLF);
+ crlf1->part_size = 2;
+ crlf1->type = AXIOM_MIME_PART_BUFFER;
+
+ axutil_array_list_add(list, env, crlf1);
+
+ /*This method will fill the list with mime_headers and
+ *if there is an attachment with attachment details*/
+
+ axiom_mime_body_part_write_to_list(part, env, list);
+
+ /* Then add the next \r\n after the attachment */
+
+ crlf2 = axiom_mime_part_create(env);
+
+ crlf2->part = (axis2_byte_t *)axutil_strdup(env, AXIS2_CRLF);
+ crlf2->part_size = 2;
+ crlf2->type = AXIOM_MIME_PART_BUFFER;
+
+ axutil_array_list_add(list, env, crlf2);
+
+ return AXIS2_SUCCESS;
+}
+
+/* This methos will add the final mime_boundary
+ * It is in --MimeBoundary-- format */
+
+static axis2_status_t
+axiom_mime_part_finish_adding_parts(
+ const axutil_env_t *env,
+ axutil_array_list_t *list,
+ axis2_char_t *boundary)
+{
+ axis2_byte_t *byte_buffer = NULL;
+ axis2_byte_t *byte_stream = NULL;
+ int size = 0;
+ axiom_mime_part_t *final_part = NULL;
+
+ size = axutil_strlen(boundary);
+ byte_buffer = (axis2_byte_t *)boundary;
+
+ /* There is -- before and after so the length of the
+ * actual part is mime_boundary_len + 4 */
+
+ byte_stream = AXIS2_MALLOC(env->allocator, (size + 4) * sizeof(axis2_byte_t));
+ if(!byte_stream)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create byte stream");
+ return AXIS2_FAILURE;
+ }
+
+ /* Adding the starting -- */
+
+ byte_stream[0] = AXIOM_MIME_BOUNDARY_BYTE;
+ byte_stream[1] = AXIOM_MIME_BOUNDARY_BYTE;
+ if(byte_buffer)
+ {
+ memcpy(byte_stream + 2, byte_buffer, size);
+ }
+ else
+ {
+ AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "Byte buffer not available for writing");
+ }
+
+ /* Adding the final -- */
+
+ byte_stream[size + 2] = AXIOM_MIME_BOUNDARY_BYTE;
+ byte_stream[size + 3] = AXIOM_MIME_BOUNDARY_BYTE;
+
+ /* Now we add this as an mime_part to
+ * the list. */
+
+ final_part = axiom_mime_part_create(env);
+
+ if(!final_part)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create final_part");
+ return AXIS2_FAILURE;
+ }
+
+ final_part->part = byte_stream;
+ final_part->part_size = size + 4;
+ final_part->type = AXIOM_MIME_PART_BUFFER;
+
+ axutil_array_list_add(list, env, final_part);
+
+ return AXIS2_SUCCESS;
+}
+
+/* This is the method which creates the content-type string
+ which is in the HTTP header or in mime_headers*/
+
+AXIS2_EXTERN const axis2_char_t *AXIS2_CALL
+axiom_mime_part_get_content_type_for_mime(
+ const axutil_env_t *env,
+ axis2_char_t *boundary,
+ axis2_char_t *content_id,
+ axis2_char_t *char_set_encoding,
+ const axis2_char_t *soap_content_type)
+{
+ axis2_char_t *content_type_string = NULL;
+ axis2_char_t *temp_content_type_string = NULL;
+
+ content_type_string = axutil_strdup(env, AXIOM_MIME_TYPE_MULTIPART_RELATED);
+ if(!content_type_string)
+ {
+ AXIS2_LOG_WARNING(env->log, AXIS2_LOG_SI, "Creation of Content-Type string failed");
+ return NULL;
+ }
+ temp_content_type_string = axutil_stracat(env, content_type_string, "; ");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ if(boundary)
+ {
+ temp_content_type_string =
+ axutil_stracat(env, content_type_string,
+ AXIOM_MIME_HEADER_FIELD_BOUNDARY "=");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, boundary);
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, "; ");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ } temp_content_type_string =
+ axutil_stracat(env, content_type_string,
+ AXIOM_MIME_HEADER_FIELD_TYPE "=\"" AXIOM_MIME_TYPE_XOP_XML "\"");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, "; ");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ if(content_id)
+ {
+ temp_content_type_string =
+ axutil_stracat(env, content_type_string,
+ AXIOM_MIME_HEADER_FIELD_START "=\"<");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, content_id);
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, ">\"");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, "; ");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ }
+ if(soap_content_type)
+ {
+ temp_content_type_string =
+ axutil_stracat(env, content_type_string,
+ AXIOM_MIME_HEADER_FIELD_START_INFO "=\"");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, soap_content_type);
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, "\"; ");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ }
+ if(char_set_encoding)
+ {
+ temp_content_type_string =
+ axutil_stracat(env, content_type_string,
+ AXIOM_MIME_HEADER_FIELD_CHARSET "=\"");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, char_set_encoding);
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ temp_content_type_string = axutil_stracat(env, content_type_string, "\"");
+ AXIS2_FREE(env->allocator, content_type_string);
+ content_type_string = temp_content_type_string;
+ }
+
+ return content_type_string;
+}
+
+/* This method is the core of attachment sending
+ * part. It will build each and every part and put them in
+ * an array_list. Instead of a big buffer we pass the array_list
+ * with small buffers and attachment locations. */
+
+AXIS2_EXTERN axutil_array_list_t *AXIS2_CALL
+axiom_mime_part_create_part_list(
+ const axutil_env_t *env,
+ axis2_char_t *soap_body,
+ axutil_array_list_t *binary_node_list,
+ axis2_char_t *boundary,
+ axis2_char_t *content_id,
+ axis2_char_t *char_set_encoding,
+ const axis2_char_t *soap_content_type)
+{
+ axis2_status_t status = AXIS2_FAILURE;
+ axis2_char_t *header_value = NULL;
+ axis2_char_t *temp_header_value = NULL;
+ axis2_char_t *content_id_string = NULL;
+ axis2_char_t *temp_content_id_string = NULL;
+ axiom_mime_body_part_t *root_mime_body_part = NULL;
+ axis2_char_t *soap_body_buffer = NULL;
+ axutil_array_list_t *part_list = NULL;
+ axiom_mime_part_t *soap_part = NULL;
+
+ part_list = axutil_array_list_create(env, 0);
+
+ if(!part_list)
+ {
+ AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
+ AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "No memory. Cannot create part list array");
+ return NULL;
+ }
+
+ /* This mime_body part just keeps the mime_headers of the
+ * SOAP part. Since it is not created from an axiom_text
+ * this will not contain an attachment*/
+
+ root_mime_body_part = axiom_mime_body_part_create(env);
+
+ if(!root_mime_body_part)
+ {
+ return NULL;
+ }
+
+ /* In order to understand the following code which creates
+ * mime_headers go through the code with a sample mtom message */
+
+ /* Adding Content-Type Header */
+ header_value = axutil_strdup(env, AXIOM_MIME_TYPE_XOP_XML
+ ";" AXIOM_MIME_HEADER_FIELD_CHARSET "=");
+ temp_header_value = axutil_stracat(env, header_value, char_set_encoding);
+ AXIS2_FREE(env->allocator, header_value);
+ header_value = temp_header_value;
+ temp_header_value = axutil_stracat(env, header_value, ";"
+ AXIOM_MIME_HEADER_FIELD_TYPE "=\"");
+ AXIS2_FREE(env->allocator, header_value);
+ header_value = temp_header_value;
+ temp_header_value = axutil_stracat(env, header_value, soap_content_type);
+ AXIS2_FREE(env->allocator, header_value);
+ header_value = temp_header_value;
+ temp_header_value = axutil_stracat(env, header_value, "\";");
+ AXIS2_FREE(env->allocator, header_value);
+ header_value = temp_header_value;
+ AXIOM_MIME_BODY_PART_ADD_HEADER(root_mime_body_part, env, AXIOM_MIME_HEADER_CONTENT_TYPE,
+ header_value);
+
+ /* Adding Content Transfer Encoding header */
+
+ AXIOM_MIME_BODY_PART_ADD_HEADER(root_mime_body_part, env,
+ AXIOM_MIME_HEADER_CONTENT_TRANSFER_ENCODING, axutil_strdup(env,
+ AXIOM_MIME_CONTENT_TRANSFER_ENCODING_BINARY));
+
+ /* Adding Content ID header */
+
+ content_id_string = (axis2_char_t *)"<";
+ content_id_string = axutil_stracat(env, content_id_string, content_id);
+ temp_content_id_string = axutil_stracat(env, content_id_string, ">");
+ AXIS2_FREE(env->allocator, content_id_string);
+ content_id_string = temp_content_id_string;
+ AXIOM_MIME_BODY_PART_ADD_HEADER(root_mime_body_part, env, AXIOM_MIME_HEADER_CONTENT_ID,
+ content_id_string);
+
+ /* Now first insert the headers needed for SOAP */
+
+ /* After calling this method we have mime_headers of the SOAP envelope
+ * as a mime_part in the array_list */
+
+ status = axiom_mime_part_write_body_part_to_list(env, part_list, root_mime_body_part, boundary);
+
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+
+ /* Now add the SOAP body */
+
+ AXIOM_MIME_BODY_PART_FREE(root_mime_body_part, env);
+ root_mime_body_part = NULL;
+
+ soap_part = axiom_mime_part_create(env);
+
+ if(!soap_part)
+ {
+ return NULL;
+ }
+
+ /* The atachment's mime_boundary will start after a new line charator */
+
+ soap_body_buffer = axutil_stracat(env, soap_body, AXIS2_CRLF);
+
+ soap_part->part = (axis2_byte_t *)soap_body_buffer;
+ soap_part->part_size = (int)axutil_strlen(soap_body_buffer);
+ soap_part->type = AXIOM_MIME_PART_BUFFER;
+
+ axutil_array_list_add(part_list, env, soap_part);
+
+ /* Now we need to add each binary attachment to the array_list */
+
+ if(binary_node_list)
+ {
+ int j = 0;
+ for(j = 0; j < axutil_array_list_size(binary_node_list, env); j++)
+ {
+ /* Getting each attachment text node from the node list */
+
+ axiom_text_t *text = (axiom_text_t *)axutil_array_list_get(binary_node_list, env, j);
+ if(text)
+ {
+ axiom_mime_body_part_t *mime_body_part = NULL;
+ mime_body_part = axiom_mime_body_part_create_from_om_text(env, text);
+
+ /* Let's fill the mime_part arraylist with attachment data*/
+ if(!mime_body_part)
+ {
+ return NULL;
+ }
+
+ /* This call will create mime_headers for the attachment and put
+ * them to the array_list. Then put the attachment file_name to the
+ * list */
+
+ status = axiom_mime_part_write_body_part_to_list(env, part_list, mime_body_part,
+ boundary);
+
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+
+ AXIOM_MIME_BODY_PART_FREE(mime_body_part, env);
+ mime_body_part = NULL;
+ }
+ }
+ }
+
+ /* Now we have the SOAP message, all the attachments and headers are added to the list.
+ * So let's add the final mime_boundary with -- at the end */
+
+ status = axiom_mime_part_finish_adding_parts(env, part_list, boundary);
+ if(status == AXIS2_FAILURE)
+ {
+ return NULL;
+ }
+ return part_list;
+}
+