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