From 9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf Mon Sep 17 00:00:00 2001 From: zautrix Date: Fri, 18 Mar 2005 20:17:03 +0000 Subject: Initial revision --- (limited to 'libetpan/src/low-level/mime/mailmime_types_helper.c') diff --git a/libetpan/src/low-level/mime/mailmime_types_helper.c b/libetpan/src/low-level/mime/mailmime_types_helper.c new file mode 100644 index 0000000..e45330c --- a/dev/null +++ b/libetpan/src/low-level/mime/mailmime_types_helper.c @@ -0,0 +1,1385 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailmime_types_helper.h" +#include "clist.h" + +#include "mailmime.h" + +#include +#include +#include +#include +#include + +#define MIME_VERSION (1 << 16) + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields) +{ + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) + return field->fld_data.fld_encoding->enc_type; + } + + return MAILMIME_MECHANISM_8BIT; +} + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename) +{ + return mailmime_disposition_new_with_data(type, filename, + NULL, NULL, NULL, (size_t) -1); + +} + +struct mailmime_fields * mailmime_fields_new_empty(void) +{ + clist * list; + struct mailmime_fields * fields; + + list = clist_new(); + if (list == NULL) + goto err; + + fields = mailmime_fields_new(list); + if (fields == NULL) + goto free; + + return fields; + + free: + clist_free(list); + err: + return NULL; +} + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field) +{ + int r; + + r = clist_append(fields->fld_list, field); + if (r < 0) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + +static void mailmime_field_detach(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = NULL; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = NULL; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = NULL; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = NULL; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = NULL; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = NULL; + break; + } +} + +struct mailmime_fields * +mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_empty(); + if (fields == NULL) + goto err; + +#if 0 + if (content != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TYPE, + content, NULL, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } +#endif + + if (encoding != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, encoding, NULL, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (id != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_ID, + NULL, NULL, id, NULL, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (description != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DESCRIPTION, + NULL, NULL, NULL, description, 0, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (disposition != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, disposition, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + if (language != NULL) { + field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, + NULL, NULL, NULL, NULL, 0, NULL, language); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + +struct mailmime_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language) +{ + struct mailmime_field * field; + struct mailmime_fields * fields; + int r; + + fields = mailmime_fields_new_with_data(encoding, id, description, + disposition, language); + if (fields == NULL) + goto err; + + field = mailmime_field_new(MAILMIME_FIELD_VERSION, + NULL, NULL, NULL, NULL, MIME_VERSION, NULL, NULL); + if (field == NULL) + goto free; + + r = mailmime_fields_add(fields, field); + if (r != MAILIMF_NO_ERROR) { + mailmime_field_detach(field); + mailmime_field_free(field); + goto free; + } + + return fields; + + free: + clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); + mailmime_fields_free(fields); + err: + return NULL; +} + + +struct mailmime_content * mailmime_get_content_message(void) +{ + clist * list; + struct mailmime_composite_type * composite_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + composite_type = + mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, + NULL); + if (composite_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, + NULL, composite_type); + if (mime_type == NULL) + goto free_composite; + composite_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_mime_type; + + subtype = strdup("rfc822"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_mime_type: + mailmime_type_free(mime_type); + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return NULL; +} + +struct mailmime_content * mailmime_get_content_text(void) +{ + clist * list; + struct mailmime_discrete_type * discrete_type; + struct mailmime_type * mime_type; + struct mailmime_content * content; + char * subtype; + + discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, + NULL); + if (discrete_type == NULL) + goto err; + + mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, + discrete_type, NULL); + if (mime_type == NULL) + goto free_discrete; + discrete_type = NULL; + + list = clist_new(); + if (list == NULL) + goto free_type; + + subtype = strdup("plain"); + if (subtype == NULL) + goto free_list; + + content = mailmime_content_new(mime_type, subtype, list); + if (content == NULL) + goto free_subtype; + + return content; + + free_subtype: + free(subtype); + free_list: + clist_free(list); + free_type: + mailmime_type_free(mime_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + + + + + + + + +/* mailmime build */ + + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + msg_content = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 1, NULL, 0, filename); + if (msg_content == NULL) + goto free_fields; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_data * msg_content; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) { + goto err; + } + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_fields; + + msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 1, data_str, length, NULL); + if (msg_content == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + msg_content, NULL, NULL, NULL, + NULL, NULL); + if (build_info == NULL) + goto free_msg_content; + + return build_info; + + free_msg_content: + mailmime_data_free(msg_content); + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime) +{ + struct mailmime_content * content; + struct mailmime * build_info; + struct mailmime_fields * mime_fields; + + content = mailmime_get_content_message(); + if (content == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_version(NULL, NULL, + NULL, NULL, NULL); + if (mime_fields == NULL) + goto free_content; + + build_info = mailmime_new(MAILMIME_MESSAGE, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, NULL, + NULL, msg_mime); + if (build_info == NULL) + goto free_fields; + + return build_info; + + free_fields: + mailmime_fields_free(mime_fields); + free_content: + mailmime_content_free(content); + err: + return NULL; +} + +#define MAX_MESSAGE_ID 512 + +static char * generate_boundary() +{ + char id[MAX_MESSAGE_ID]; + time_t now; + char name[MAX_MESSAGE_ID]; + long value; + + now = time(NULL); + value = random(); + + gethostname(name, MAX_MESSAGE_ID); + snprintf(id, MAX_MESSAGE_ID, "%lx_%lx_%x", now, value, getpid()); + + return strdup(id); +} + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields) +{ + struct mailmime * build_info; + clist * list; + int r; + int mime_type; + + list = NULL; + + switch (content->ct_type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + goto err; + } + break; + + default: + goto err; + } + + if (mime_type == MAILMIME_MULTIPLE) { + char * attr_name; + char * attr_value; + struct mailmime_parameter * param; + clist * parameters; + char * boundary; + + list = clist_new(); + if (list == NULL) + goto err; + + attr_name = strdup("boundary"); + if (attr_name == NULL) + goto free_list; + + boundary = generate_boundary(); + attr_value = boundary; + if (attr_name == NULL) { + free(attr_name); + goto free_list; + } + + param = mailmime_parameter_new(attr_name, attr_value); + if (param == NULL) { + free(attr_value); + free(attr_name); + goto free_list; + } + + if (content->ct_parameters == NULL) { + parameters = clist_new(); + if (parameters == NULL) { + mailmime_parameter_free(param); + goto free_list; + } + } + else + parameters = content->ct_parameters; + + r = clist_append(parameters, param); + if (r != 0) { + clist_free(parameters); + mailmime_parameter_free(param); + goto free_list; + } + + if (content->ct_parameters == NULL) + content->ct_parameters = parameters; + } + + build_info = mailmime_new(mime_type, + NULL, 0, mime_fields, content, + NULL, NULL, NULL, list, + NULL, NULL); + if (build_info == NULL) { + clist_free(list); + return NULL; + } + + return build_info; + + free_list: + clist_free(list); + err: + return NULL; +} + + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + struct mailmime * build_info; +#if 0 + int mime_type; +#endif + int res; + + cur_token = 0; + r = mailmime_content_parse(content_type, strlen(content_type), + &cur_token, + &content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + +#if 0 + switch (content->type->type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type = MAILMIME_SINGLE; + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content->type->composite_type->type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + mime_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->subtype, "rfc822") == 0) + mime_type = MAILMIME_MESSAGE; + else + mime_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free; + } +#endif + + build_info = mailmime_new_empty(content, mime_fields); + if (build_info == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = build_info; + + return MAILIMF_NO_ERROR; + + free: + mailmime_content_free(content); + err: + return res; +} + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_preamble = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + struct mailmime_data * data; + + data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_multipart.mm_epilogue = data; + + return MAILIMF_NO_ERROR; +} + + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_FILE, encoding, + 0, NULL, 0, filename); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length) +{ + int encoding; + struct mailmime_data * data; + + encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); + + data = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, + 0, data_str, length, NULL); + if (data == NULL) + return MAILIMF_ERROR_MEMORY; + + build_info->mm_data.mm_single = data; + + return MAILIMF_NO_ERROR; +} + + +/* add a part as subpart of a mime part */ + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part) +{ + int r; + + if (build_info->mm_type == MAILMIME_MESSAGE) { + build_info->mm_data.mm_message.mm_msg_mime = part; + part->mm_parent_type = MAILMIME_MESSAGE; + part->mm_parent = build_info; + } + else if (build_info->mm_type == MAILMIME_MULTIPLE) { + r = clist_append(build_info->mm_data.mm_multipart.mm_mp_list, part); + if (r != 0) + return MAILIMF_ERROR_MEMORY; + + part->mm_parent_type = MAILMIME_MULTIPLE; + part->mm_parent = build_info; + part->mm_multipart_pos = + clist_end(build_info->mm_data.mm_multipart.mm_mp_list); + } + else { + return MAILIMF_ERROR_INVAL; + } + return MAILIMF_NO_ERROR; +} + +/* detach part from parent */ + +void mailmime_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + + parent = mime->mm_parent; + if (parent == NULL) + return; + + switch (mime->mm_parent_type) { + case MAILMIME_MESSAGE: + mime->mm_parent = NULL; + parent->mm_data.mm_message.mm_msg_mime = NULL; + break; + + case MAILMIME_MULTIPLE: + mime->mm_parent = NULL; + clist_delete(parent->mm_data.mm_multipart.mm_mp_list, + mime->mm_multipart_pos); + break; + } +} + + +/* + attach a part to a mime part and create multipart/mixed + when needed, when the parent part has already some part + attached to it. +*/ + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub) +{ + struct mailmime * saved_sub; + struct mailmime * mp; + int res; + int r; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + res = MAILIMF_ERROR_INVAL; + goto err; + + case MAILMIME_MULTIPLE: + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + /* MAILMIME_MESSAGE */ + + if (mime->mm_data.mm_message.mm_msg_mime == NULL) { + /* there is no subpart, we can simply attach it */ + + r = mailmime_add_part(mime, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + return MAILIMF_NO_ERROR; + } + + if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) { + /* in case the subpart is multipart, simply attach it to the subpart */ + + return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); + } + + /* we save the current subpart, ... */ + + saved_sub = mime->mm_data.mm_message.mm_msg_mime; + + /* create a multipart */ + + mp = mailmime_multiple_new("multipart/mixed"); + if (mp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + /* detach the saved subpart from the parent */ + + mailmime_remove_part(saved_sub); + + /* the created multipart is the new child of the parent */ + + r = mailmime_add_part(mime, mp); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_mp; + } + + /* then, attach the saved subpart and ... */ + + r = mailmime_add_part(mp, saved_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + /* the given part to the parent */ + + r = mailmime_add_part(mp, mime_sub); + if (r != MAILIMF_NO_ERROR) { + res = MAILIMF_ERROR_MEMORY; + goto free_saved_sub; + } + + return MAILIMF_NO_ERROR; + + free_mp: + mailmime_free(mp); + free_saved_sub: + mailmime_free(saved_sub); + err: + return res; +} + + + +/* detach part from parent and free it only if the part has no child */ + +int mailmime_smart_remove_part(struct mailmime * mime) +{ + struct mailmime * parent; + int res; + + parent = mime->mm_parent; + if (parent == NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + switch (mime->mm_type) { + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_MULTIPLE: + if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) { + res = MAILIMF_ERROR_INVAL; + goto err; + } + + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + case MAILMIME_SINGLE: + mailmime_remove_part(mime); + + mailmime_free(mime); + + return MAILIMF_NO_ERROR; + + default: + return MAILIMF_ERROR_INVAL; + } + + err: + return res; +} + + +/* create a mailmime_content structure (Content-Type field) */ + +struct mailmime_content * mailmime_content_new_with_str(const char * str) +{ + int r; + size_t cur_token; + struct mailmime_content * content; + + cur_token = 0; + r = mailmime_content_parse(str, strlen(str), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} + +/* create MIME fields with only the field Content-Transfer-Encoding */ + +struct mailmime_fields * mailmime_fields_new_encoding(int type) +{ + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + encoding = mailmime_mechanism_new(type, NULL); + if (encoding == NULL) + goto err; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) + goto free; + + return mime_fields; + + free: + mailmime_mechanism_free(encoding); + err: + return NULL; +} + + +/* create a multipart MIME part */ + +struct mailmime * mailmime_multiple_new(const char * type) +{ + struct mailmime_fields * mime_fields; + struct mailmime_content * content; + struct mailmime * mp; + + mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); + if (mime_fields == NULL) + goto err; + + content = mailmime_content_new_with_str(type); + if (content == NULL) + goto free_fields; + + mp = mailmime_new_empty(content, mime_fields); + if (mp == NULL) + goto free_content; + + return mp; + + free_content: + mailmime_content_free(content); + free_fields: + mailmime_fields_free(mime_fields); + err: + return NULL; +} + + + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * mm_fields) +{ + build_info->mm_data.mm_message.mm_fields = mm_fields; +} + +#if 0 +struct mailmime_content * mailmime_get_content(char * mime_type) +{ + struct mailmime_content *content; + int r; + size_t cur_token; + + cur_token = 0; + r = mailmime_content_parse(mime_type, strlen(mime_type), + &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return NULL; + + return content; +} +#endif + + + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size) +{ + struct mailmime_disposition_type * dsp_type; + clist * list; + int r; + struct mailmime_disposition_parm * parm; + struct mailmime_disposition * dsp; + + dsp_type = mailmime_disposition_type_new(type, NULL); + if (dsp_type == NULL) + goto err; + + list = clist_new(); + if (list == NULL) + goto free_dsp_type; + + if (filename != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, + filename, NULL, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (creation_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_CREATION_DATE, + NULL, creation_date, NULL, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (modification_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + NULL, NULL, modification_date, NULL, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (read_date != NULL) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_READ_DATE, + NULL, NULL, NULL, read_date, 0, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + if (size != (size_t) -1) { + parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_SIZE, + NULL, NULL, NULL, NULL, size, NULL); + if (parm == NULL) + goto free_list; + + r = clist_append(list, parm); + if (r < 0) { + mailmime_disposition_parm_free(parm); + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + + return dsp; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_dsp_type: + mailmime_disposition_type_free(dsp_type); + err: + return NULL; +} + + +static void mailmime_disposition_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_disposition * fld_disposition) +{ + clistiter * cur; + + single_fields->fld_disposition = fld_disposition; + + for(cur = clist_begin(fld_disposition->dsp_parms) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = clist_content(cur); + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + single_fields->fld_disposition_filename = param->pa_data.pa_filename; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + single_fields->fld_disposition_creation_date = + param->pa_data.pa_creation_date; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + single_fields->fld_disposition_modification_date = + param->pa_data.pa_modification_date; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + single_fields->fld_disposition_read_date = + param->pa_data.pa_read_date; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + single_fields->fld_disposition_size = param->pa_data.pa_size; + break; + } + } +} + +static void mailmime_content_single_fields_init(struct + mailmime_single_fields * single_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + single_fields->fld_content = fld_content; + + for(cur = clist_begin(fld_content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, "boundary") == 0) + single_fields->fld_content_boundary = param->pa_value; + + if (strcasecmp(param->pa_name, "charset") == 0) + single_fields->fld_content_charset = param->pa_value; + + if (strcasecmp(param->pa_name, "name") == 0) + single_fields->fld_content_name = param->pa_value; + } +} + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + clistiter * cur; + + memset(single_fields, 0, sizeof(struct mailmime_single_fields)); + + if (fld_content != NULL) + mailmime_content_single_fields_init(single_fields, fld_content); + + if (fld_fields == NULL) + return; + + for(cur = clist_begin(fld_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + mailmime_content_single_fields_init(single_fields, + field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + single_fields->fld_encoding = field->fld_data.fld_encoding; + break; + + case MAILMIME_FIELD_ID: + single_fields->fld_id = field->fld_data.fld_id; + break; + + case MAILMIME_FIELD_DESCRIPTION: + single_fields->fld_description = field->fld_data.fld_description; + break; + + case MAILMIME_FIELD_VERSION: + single_fields->fld_version = field->fld_data.fld_version; + break; + + case MAILMIME_FIELD_DISPOSITION: + mailmime_disposition_single_fields_init(single_fields, + field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + single_fields->fld_language = field->fld_data.fld_language; + break; + } + } +} + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content) +{ + struct mailmime_single_fields * single_fields; + + single_fields = malloc(sizeof(struct mailmime_single_fields)); + if (single_fields == NULL) + goto err; + + mailmime_single_fields_init(single_fields, fld_fields, fld_content); + + return single_fields; + + err: + return NULL; +} + + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields) +{ + free(single_fields); +} + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type) +{ + struct mailmime_disposition * dsp; + struct mailmime_mechanism * encoding; + struct mailmime_fields * mime_fields; + + dsp = mailmime_disposition_new_with_data(dsp_type, + filename, NULL, NULL, NULL, (size_t) -1); + if (dsp == NULL) + goto err; + + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) + goto free_dsp; + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, dsp, NULL); + if (mime_fields == NULL) + goto free_encoding; + + return mime_fields; + + free_encoding: + mailmime_encoding_free(encoding); + free_dsp: + mailmime_disposition_free(dsp); + err: + return NULL; +} + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length) +{ + return mailmime_data_new(MAILMIME_DATA_TEXT, encoding, encoded, data, length, NULL); +} + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename) +{ + return mailmime_data_new(MAILMIME_DATA_FILE, encoding, encoded, NULL, 0, filename); +} + -- cgit v0.9.0.2