From e3b89230f065c48c84b48c88edb6eb088374c487 Mon Sep 17 00:00:00 2001 From: zautrix Date: Sat, 03 Jul 2004 16:33:12 +0000 Subject: Initial revision --- (limited to 'kmicromail/libetpan/mime/mailmime_write.c') diff --git a/kmicromail/libetpan/mime/mailmime_write.c b/kmicromail/libetpan/mime/mailmime_write.c new file mode 100644 index 0000000..5c3b1f7 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_write.c @@ -0,0 +1,1416 @@ +/* + * libEtPan! -- a mail stuff library + * + * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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_write.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mailimf_write.h" +#include "mailmime_content.h" +#include "mailmime_types_helper.h" + +#define MAX_MAIL_COL 78 + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_field_write(FILE * f, int * col, + struct mailmime_field * field); + +static int mailmime_id_write(FILE * f, int * col, char * id); + +static int mailmime_description_write(FILE * f, int * col, char * descr); + +static int mailmime_version_write(FILE * f, int * col, uint32_t version); + +static int mailmime_encoding_write(FILE * f, int * col, + struct mailmime_mechanism * encoding); + +static int mailmime_language_write(FILE * f, int * col, + struct mailmime_language * language); + +static int mailmime_disposition_write(FILE * f, int * col, + struct mailmime_disposition * + disposition); + +static int +mailmime_disposition_param_write(FILE * f, int * col, + struct mailmime_disposition_parm * param); + +static int mailmime_parameter_write(FILE * f, int * col, + struct mailmime_parameter * param); + +/* +static int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); +*/ + +static int mailmime_type_write(FILE * f, int * col, + struct mailmime_type * type); + +static int +mailmime_discrete_type_write(FILE * f, int * col, + struct mailmime_discrete_type * discrete_type); + +static int +mailmime_composite_type_write(FILE * f, int * col, + struct mailmime_composite_type * composite_type); + +static int mailmime_sub_write(FILE * f, int * col, + struct mailmime * build_info); + + +/* ***** */ + +int mailmime_fields_write(FILE * f, int * col, struct mailmime_fields * fields) +{ + int r; + clistiter * cur; + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = cur->data; + r = mailmime_field_write(f, col, field); + if (r != MAILIMF_NO_ERROR) + return r; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_field_write(FILE * f, int * col, + struct mailmime_field * field) +{ + int r; + + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + r = mailmime_content_write(f, col, field->fld_data.fld_content); + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + r = mailmime_encoding_write(f, col, field->fld_data.fld_encoding); + break; + + case MAILMIME_FIELD_ID: + r = mailmime_id_write(f, col, field->fld_data.fld_id); + break; + + case MAILMIME_FIELD_DESCRIPTION: + r = mailmime_description_write(f, col, field->fld_data.fld_description); + break; + + case MAILMIME_FIELD_VERSION: + r = mailmime_version_write(f, col, field->fld_data.fld_version); + break; + + case MAILMIME_FIELD_DISPOSITION: + r = mailmime_disposition_write(f, col, field->fld_data.fld_disposition); + break; + + case MAILMIME_FIELD_LANGUAGE: + r = mailmime_language_write(f, col, field->fld_data.fld_language); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_id_write(FILE * f, int * col, char * id) +{ + int r; + + r = mailimf_string_write(f, col, "Content-ID: ", 12); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "<", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, id, strlen(id)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, ">", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_description_write(FILE * f, int * col, char * descr) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Description: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, descr, strlen(descr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_version_write(FILE * f, int * col, uint32_t version) +{ + int r; + char versionstr[40]; + + r = mailimf_string_write(f, col, "MIME-Version: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF); + + r = mailimf_string_write(f, col, versionstr, strlen(versionstr)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_encoding_write(FILE * f, int * col, + struct mailmime_mechanism * encoding) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Transfer-Encoding: ", 27); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (encoding->enc_type) { + case MAILMIME_MECHANISM_7BIT: + r = mailimf_string_write(f, col, "7bit", 4); + break; + + case MAILMIME_MECHANISM_8BIT: + r = mailimf_string_write(f, col, "8bit", 4); + break; + + case MAILMIME_MECHANISM_BINARY: + r = mailimf_string_write(f, col, "binary", 6); + break; + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + r = mailimf_string_write(f, col, "quoted-printable", 16); + break; + + case MAILMIME_MECHANISM_BASE64: + r = mailimf_string_write(f, col, "base64", 6); + break; + + case MAILMIME_MECHANISM_TOKEN: + r = mailimf_string_write(f, col, encoding->enc_token, + strlen(encoding->enc_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_language_write(FILE * f, int * col, + struct mailmime_language * language) +{ + int r; + clistiter * cur; + int first; + + r = mailimf_string_write(f, col, "Content-Language: ", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + first = TRUE; + + for(cur = clist_begin(language->lg_list) ; cur != NULL ; + cur = clist_next(cur)) { + char * lang; + size_t len; + + lang = clist_content(cur); + len = strlen(lang); + + if (!first) { + r = mailimf_string_write(f, col, ", ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + first = FALSE; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailimf_string_write(f, col, lang, len); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return MAILIMF_NO_ERROR; +} + +static int mailmime_disposition_write(FILE * f, int * col, + struct mailmime_disposition * + disposition) +{ + struct mailmime_disposition_type * dsp_type; + int r; + clistiter * cur; + + dsp_type = disposition->dsp_type; + + r = mailimf_string_write(f, col, "Content-Disposition: ", 21); + if (r != MAILIMF_NO_ERROR) + return r; + + switch (dsp_type->dsp_type) { + case MAILMIME_DISPOSITION_TYPE_INLINE: + r = mailimf_string_write(f, col, "inline", 6); + break; + + case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: + r = mailimf_string_write(f, col, "attachment", 10); + break; + + case MAILMIME_DISPOSITION_TYPE_EXTENSION: + r = mailimf_string_write(f, col, dsp_type->dsp_extension, + strlen(dsp_type->dsp_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + for(cur = clist_begin(disposition->dsp_parms) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_disposition_parm * param; + + param = cur->data; + + r = mailimf_string_write(f, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_disposition_param_write(f, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_disposition_param_write(FILE * f, int * col, + struct mailmime_disposition_parm * param) +{ + size_t len; + char sizestr[20]; + int r; + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + len = strlen("filename=") + strlen(param->pa_data.pa_filename); + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date); + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + len = strlen("modification-date=") + + strlen(param->pa_data.pa_modification_date); + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + len = strlen("read-date=") + strlen(param->pa_data.pa_read_date); + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + snprintf(sizestr, 20, "%u", param->pa_data.pa_size); + len = strlen("size=") + strlen(sizestr); + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + len = strlen(param->pa_data.pa_parameter->pa_name) + 1 + + strlen(param->pa_data.pa_parameter->pa_value); + break; + + default: + return MAILIMF_ERROR_INVAL; + } + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + switch (param->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailimf_string_write(f, col, "filename=", 9); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, + param->pa_data.pa_filename, strlen(param->pa_data.pa_filename)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailimf_string_write(f, col, "creation-date=", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_data.pa_creation_date, + strlen(param->pa_data.pa_creation_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailimf_string_write(f, col, "modification-date=", 18); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, + param->pa_data.pa_modification_date, + strlen(param->pa_data.pa_modification_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailimf_string_write(f, col, "read-date=", 10); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_data.pa_read_date, + strlen(param->pa_data.pa_read_date)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailimf_string_write(f, col, "size=", 5); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, sizestr, strlen(sizestr)); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_DISPOSITION_PARM_PARAMETER: + r = mailmime_parameter_write(f, col, param->pa_data.pa_parameter); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_parameter_write(FILE * f, int * col, + struct mailmime_parameter * param) +{ + int r; + + r = mailimf_string_write(f, col, param->pa_name, + strlen(param->pa_name)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "=", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_quoted_string_write(f, col, param->pa_value, + strlen(param->pa_value)); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content) +{ + clistiter * cur; + size_t len; + int r; + + r = mailmime_type_write(f, col, content->ct_type); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "/", 1); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, content->ct_subtype, + strlen(content->ct_subtype)); + if (r != MAILIMF_NO_ERROR) + return r; + + if (content->ct_parameters != NULL) { + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = cur->data; + + r = mailimf_string_write(f, col, "; ", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + len = strlen(param->pa_name) + 1 + strlen(param->pa_value); + + if (* col > 1) { + + if (* col + len > MAX_MAIL_COL) { + r = mailimf_string_write(f, col, "\r\n ", 3); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 1; +#endif + } + } + + r = mailmime_parameter_write(f, col, param); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + return MAILIMF_NO_ERROR; +} + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content) +{ + int r; + + r = mailimf_string_write(f, col, "Content-Type: ", 14); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_content_type_write(f, col, content); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_type_write(FILE * f, int * col, + struct mailmime_type * type) +{ + int r; + + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + r = mailmime_discrete_type_write(f, col, type->tp_data.tp_discrete_type); + break; + + case MAILMIME_TYPE_COMPOSITE_TYPE: + r = mailmime_composite_type_write(f, col, type->tp_data.tp_composite_type); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_discrete_type_write(FILE * f, int * col, + struct mailmime_discrete_type * discrete_type) +{ + int r; + + switch (discrete_type->dt_type) { + case MAILMIME_DISCRETE_TYPE_TEXT: + r = mailimf_string_write(f, col, "text", 4); + break; + + case MAILMIME_DISCRETE_TYPE_IMAGE: + r = mailimf_string_write(f, col, "image", 5); + break; + + case MAILMIME_DISCRETE_TYPE_AUDIO: + r = mailimf_string_write(f, col, "audio", 5); + break; + + case MAILMIME_DISCRETE_TYPE_VIDEO: + r = mailimf_string_write(f, col, "video", 5); + break; + + case MAILMIME_DISCRETE_TYPE_APPLICATION: + r = mailimf_string_write(f, col, "application", 11); + break; + + case MAILMIME_DISCRETE_TYPE_EXTENSION: + r = mailimf_string_write(f, col, discrete_type->dt_extension, + strlen(discrete_type->dt_extension)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_composite_type_write(FILE * f, int * col, + struct mailmime_composite_type * composite_type) +{ + int r; + + switch (composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + r = mailimf_string_write(f, col, "message", 7); + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + r = mailimf_string_write(f, col, "multipart", 9); + break; + + case MAILMIME_COMPOSITE_TYPE_EXTENSION: + r = mailimf_string_write(f, col, composite_type->ct_token, + strlen(composite_type->ct_token)); + break; + + default: + r = MAILIMF_ERROR_INVAL; + break; + } + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + + + + +/* ****************************************************************** */ +/* message */ + +/* +static int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int is_text); +*/ + +static int mailmime_text_content_write(FILE * f, int * col, int encoding, + int istext, + const char * text, size_t size); + +/* +static int mailmime_base64_write(FILE * f, int * col, + char * text, size_t size); + +static int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + char * text, size_t size); +*/ + +static int mailmime_part_write(FILE * f, int * col, + struct mailmime * build_info) +{ + clistiter * cur; + int first; + int r; + char * boundary; + int istext; + + istext = TRUE; + boundary = NULL; + + if (build_info->mm_content_type != NULL) { + if (build_info->mm_type == MAILMIME_MULTIPLE) { + boundary = mailmime_extract_boundary(build_info->mm_content_type); + if (boundary == NULL) + return MAILIMF_ERROR_INVAL; + } + + if (build_info->mm_content_type->ct_type->tp_type == + MAILMIME_TYPE_DISCRETE_TYPE) { + if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type != + MAILMIME_DISCRETE_TYPE_TEXT) + istext = FALSE; + } + } + + switch (build_info->mm_type) { + case MAILMIME_SINGLE: + + /* 1-part body */ + + if (build_info->mm_data.mm_single != NULL) { + r = mailmime_data_write(f, col, build_info->mm_data.mm_single, istext); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MULTIPLE: + + /* multi-part */ + + + /* preamble */ + + if (build_info->mm_data.mm_multipart.mm_preamble != NULL) { + r = mailmime_data_write(f, col, + build_info->mm_data.mm_multipart.mm_preamble, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + /* sub-parts */ + + first = TRUE; + + for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * subpart; + + subpart = cur->data; + + if (!first) { + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + else { + first = FALSE; + } + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailmime_sub_write(f, col, subpart); + if (r != MAILIMF_NO_ERROR) + return r; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, boundary, strlen(boundary)); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_string_write(f, col, "--", 2); + if (r != MAILIMF_NO_ERROR) + return r; + + + /* epilogue */ + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mailmime_data_write(f, col, + build_info->mm_data.mm_multipart.mm_epilogue, TRUE); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_MESSAGE: + + if (build_info->mm_data.mm_message.mm_fields != NULL) { + r = mailimf_fields_write(f, col, + build_info->mm_data.mm_message.mm_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* encapsuled message */ + + if (build_info->mm_data.mm_message.mm_msg_mime != NULL) { + r = mailmime_sub_write(f, col, + build_info->mm_data.mm_message.mm_msg_mime); + if (r != MAILIMF_NO_ERROR) + return r; + } + break; + + } + + return MAILIMF_NO_ERROR; +} + + +static int mailmime_sub_write(FILE * f, int * col, + struct mailmime * build_info) +{ + int r; + +#if 0 + * col = 0; +#endif + /* MIME field - Content-Type */ + + if (build_info->mm_content_type != NULL) { + r = mailmime_content_write(f, col, build_info->mm_content_type); + if (r != MAILIMF_NO_ERROR) + return r; + } + + /* other MIME fields */ + + if (build_info->mm_type != MAILMIME_MESSAGE) { + if (build_info->mm_mime_fields != NULL) { + r = mailmime_fields_write(f, col, build_info->mm_mime_fields); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + + return mailmime_part_write(f, col, build_info); +} + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info) +{ + if (build_info->mm_parent != NULL) + return mailmime_sub_write(f, col, build_info); + else + return mailmime_part_write(f, col, build_info); +} + + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext) +{ + int fd; + int r; + char * text; + struct stat buf; + int res; + + switch (data->dt_type) { + case MAILMIME_DATA_TEXT: + + if (data->dt_encoded) { + r = mailimf_string_write(f, col, + data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + else { + r = mailmime_text_content_write(f, col, data->dt_encoding, istext, + data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length); + if (r != MAILIMF_NO_ERROR) + return r; + } + + break; + + case MAILMIME_DATA_FILE: + fd = open(data->dt_data.dt_filename, O_RDONLY); + if (fd < 0) { + res = MAILIMF_ERROR_FILE; + goto err; + } + + r = fstat(fd, &buf); + if (r < 0) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (buf.st_size != 0) { + text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (text == NULL) { + res = MAILIMF_ERROR_FILE; + goto close; + } + + if (data->dt_encoded) { + r = mailimf_string_write(f, col, text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + else { + r = mailmime_text_content_write(f, col, data->dt_encoding, istext, + text, buf.st_size); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto unmap; + } + } + + munmap(text, buf.st_size); + } + close(fd); + + if (r != MAILIMF_NO_ERROR) + return r; + + break; + + unmap: + munmap(text, buf.st_size); + close: + close(fd); + err: + return res; + } + + return MAILIMF_NO_ERROR; +} + +static int mailmime_text_content_write(FILE * f, int * col, int encoding, + int istext, + const char * text, size_t size) +{ + switch (encoding) { + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_write(f, col, istext, text, size); + break; + + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_write(f, col, text, size); + break; + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailimf_string_write(f, col, text, size); + } +} + + +static const char base64_encoding[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#define BASE64_MAX_COL 76 + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size) +{ + int a; + int b; + int c; + size_t remains; + const char * p; + size_t count; + char ogroup[4]; + int r; + + remains = size; + p = text; + + while (remains > 0) { + switch (remains) { + case 1: + a = (unsigned char) p[0]; + b = 0; + c = 0; + count = 1; + break; + case 2: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = 0; + count = 2; + break; + default: + a = (unsigned char) p[0]; + b = (unsigned char) p[1]; + c = (unsigned char) p[2]; + count = 3; + break; + } + + ogroup[0]= base64_encoding[a >> 2]; + ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)]; + ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)]; + ogroup[3]= base64_encoding[c & 0x3F]; + + switch (count) { + case 1: + ogroup[2]= '='; + ogroup[3]= '='; + break; + case 2: + ogroup[3]= '='; + break; + } + + if (* col + 4 > BASE64_MAX_COL) { + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; +#if 0 + * col = 0; +#endif + } + + r = mailimf_string_write(f, col, ogroup, 4); + if (r != MAILIMF_NO_ERROR) + return r; + + remains -= count; + p += count; + } + + r = mailimf_string_write(f, col, "\r\n", 2); + + return MAILIMF_NO_ERROR; +} + +#if 0 +#define MAX_WRITE_SIZE 512 +#endif + +enum { + STATE_INIT, + STATE_CR, + STATE_SPACE, + STATE_SPACE_CR, +}; + +#if 0 +static inline int write_try_buf(FILE * f, int * col, + char ** pstart, size_t * plen) +{ + int r; + + if (* plen >= MAX_WRITE_SIZE) { + r = mailimf_string_write(f, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} +#endif + +static inline int write_remaining(FILE * f, int * col, + const char ** pstart, size_t * plen) +{ + int r; + + if (* plen > 0) { + r = mailimf_string_write(f, col, * pstart, * plen); + if (r != MAILIMF_NO_ERROR) + return r; + * plen = 0; + } + + return MAILIMF_NO_ERROR; +} + + + +#define QP_MAX_COL 72 + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size) +{ + size_t i; + const char * start; + size_t len; + char hexstr[6]; + int r; + int state; + + start = text; + len = 0; + state = STATE_INIT; + + i = 0; + while (i < size) { + unsigned char ch; + + if (* col + len > QP_MAX_COL) { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + + r = mailimf_string_write(f, col, "=\r\n", 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + + ch = text[i]; + + switch (state) { + + case STATE_INIT: + switch (ch) { + case ' ': + case '\t': + state = STATE_SPACE; + break; + + case '\r': + state = STATE_CR; + break; + + case '!': + case '"': + case '#': + case '$': + case '@': + case '[': + case '\\': + case ']': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + case '=': + case '?': + case '_': + case 'F': /* there is no more 'From' at the beginning of a line */ + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + if (istext && (ch == '\n')) { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + break; + } + else { + if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) { + len ++; + } + else { + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + + snprintf(hexstr, 6, "=%02X", ch); + + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + } + } + + break; + } + + i ++; + break; + + case STATE_CR: + switch (ch) { + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + r = mailimf_string_write(f, col, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) + return r; + i ++; + state = STATE_INIT; + break; + + default: + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i; + snprintf(hexstr, 6, "=%02X", '\r'); + r = mailimf_string_write(f, col, hexstr, 3); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + break; + + case STATE_SPACE: + switch (ch) { + case '\r': + state = STATE_SPACE_CR; + i ++; + break; + + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + case ' ': + case '\t': + len ++; + i ++; + break; + + default: +#if 0 + len += 2; + state = STATE_INIT; + i ++; +#endif + len ++; + state = STATE_INIT; + break; + } + + break; + + case STATE_SPACE_CR: + switch (ch) { + case '\n': + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + i ++; + break; + + default: + r = write_remaining(f, col, &start, &len); + if (r != MAILIMF_NO_ERROR) + return r; + start = text + i + 1; + snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r'); + r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); + if (r != MAILIMF_NO_ERROR) + return r; + state = STATE_INIT; + break; + } + + break; + } + } + + return MAILIMF_NO_ERROR; +} -- cgit v0.9.0.2