| /* |
| * 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; |
| } |
| |