summaryrefslogtreecommitdiffstats
path: root/axiom/src/attachments/data_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'axiom/src/attachments/data_handler.c')
-rw-r--r--axiom/src/attachments/data_handler.c572
1 files changed, 572 insertions, 0 deletions
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;
+}
+