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') diff --git a/kmicromail/libetpan/mime/.libs/libmailmime.a b/kmicromail/libetpan/mime/.libs/libmailmime.a new file mode 100644 index 0000000..902b9d9 --- a/dev/null +++ b/kmicromail/libetpan/mime/.libs/libmailmime.a Binary files differ diff --git a/kmicromail/libetpan/mime/TODO b/kmicromail/libetpan/mime/TODO new file mode 100644 index 0000000..df02810 --- a/dev/null +++ b/kmicromail/libetpan/mime/TODO @@ -0,0 +1,10 @@ +- see about the RFC2047, beginning in mailmime_decode.[ch] +- content-langage +- single mime_field +- RFC 2048 +- RFC 2049 +- RFC 2231 +- RFC 2387 +- RFC 2424 +- RFC 2557 + diff --git a/kmicromail/libetpan/mime/mailmime.c b/kmicromail/libetpan/mime/mailmime.c new file mode 100644 index 0000000..e920722 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime.c @@ -0,0 +1,1408 @@ +/* + * 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.h" + +/* + RFC 2045 + RFC 2046 + RFC 2047 + RFC 2048 + RFC 2049 + RFC 2231 + RFC 2387 + RFC 2424 + RFC 2557 + + RFC 2183 Content-Disposition + + RFC 1766 Language + */ + +#include +#include +#include + +#include "mailmime_types.h" +#include "mailmime_disposition.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * index, + char ** result); +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_composite_type ** result); + +static int is_text(char ch); + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_discrete_type ** result); + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int is_token(char ch); + +static int mailmime_token_parse(const char * message, size_t length, + size_t * index, + char ** token); + +static int is_tspecials(char ch); + +static int mailmime_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_type ** result); + +/* +int mailmime_version_parse(const char * message, guint32 length, + guint32 * index, + guint32 * result); +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * index, + gchar ** result); +*/ + +/* ********************************************************************** */ + +/* +x attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. +*/ + +static int mailmime_attribute_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + return mailmime_token_parse(message, length, index, result); +} + +/* +x composite-type := "message" / "multipart" / extension-token +*/ + +static int +mailmime_composite_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_composite_type ** result) +{ + char * extension_token; + int type; + struct mailmime_composite_type * ct; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + extension_token = NULL; + + type = MAILMIME_COMPOSITE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "message"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MESSAGE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "multipart"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_COMPOSITE_TYPE_MULTIPART; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + ct = mailmime_composite_type_new(type, extension_token); + if (ct == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_extension; + } + + * result = ct; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_extension: + if (extension_token != NULL) + mailmime_extension_token_free(extension_token); + err: + return res; +} + +/* +x content := "Content-Type" ":" type "/" subtype + *(";" parameter) + ; Matching of media type and subtype + ; is ALWAYS case-insensitive. +*/ + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result) +{ + size_t cur_token; + struct mailmime_type * type; + char * subtype; + clist * parameters_list; + struct mailmime_content * content; + int r; + int res; + + cur_token = * index; + + mailimf_cfws_parse(message, length, &cur_token); + + r = mailmime_type_parse(message, length, &cur_token, &type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '/'); + switch (r) { + case MAILIMF_NO_ERROR: + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_subtype_parse(message, length, &cur_token, &subtype); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_type; + } + break; + + case MAILIMF_ERROR_PARSE: + subtype = strdup("unknown"); + break; + + default: + res = r; + goto free_type; + } + + parameters_list = clist_new(); + if (parameters_list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + size_t final_token; + struct mailmime_parameter * parameter; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r != MAILIMF_NO_ERROR) { + cur_token = final_token; + break; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_type; + } + + r = mailmime_parameter_parse(message, length, &cur_token, ¶meter); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto err; + } + + r = clist_append(parameters_list, parameter); + if (r < 0) { + mailmime_parameter_free(parameter); + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + } + + content = mailmime_content_new(type, subtype, parameters_list); + if (content == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_parameters; + } + + * result = content; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_parameters: + clist_foreach(parameters_list, (clist_func) mailmime_parameter_free, NULL); + clist_free(parameters_list); + + mailmime_subtype_free(subtype); + free_type: + mailmime_type_free(type); + err: + return res; +} + +/* +x description := "Content-Description" ":" *text +*/ + +static int is_text(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch < 1) + return FALSE; + + if ((uch == 10) || (uch == 13)) + return FALSE; + + return TRUE; +} + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + return mailimf_custom_string_parse(message, length, + index, result, + is_text); +} + +/* +x discrete-type := "text" / "image" / "audio" / "video" / + "application" / extension-token +*/ + +/* currently porting */ + +static int +mailmime_discrete_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_discrete_type ** result) +{ + char * extension; + int type; + struct mailmime_discrete_type * discrete_type; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + extension = NULL; + + type = MAILMIME_DISCRETE_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "text"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_TEXT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "image"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_IMAGE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "audio"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_AUDIO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "video"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_VIDEO; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "application"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_APPLICATION; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, + &cur_token, &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISCRETE_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + discrete_type = mailmime_discrete_type_new(type, extension); + if (discrete_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = discrete_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mailmime_extension_token_free(extension); + err: + return res; +} + +/* +x encoding := "Content-Transfer-Encoding" ":" mechanism +*/ + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result) +{ + return mailmime_mechanism_parse(message, length, index, result); +} + +/* +x entity-headers := [ content CRLF ] + [ encoding CRLF ] + [ id CRLF ] + [ description CRLF ] + *( MIME-extension-field CRLF ) + */ + +enum { + FIELD_STATE_START, + FIELD_STATE_T, + FIELD_STATE_D +}; + +static int guess_field_type(char * name) +{ + int state; + + if (* name == 'M') + return MAILMIME_FIELD_VERSION; + + if (strncasecmp(name, "Content-", 8) != 0) + return MAILMIME_FIELD_NONE; + + name += 8; + + state = FIELD_STATE_START; + + while (1) { + + switch (state) { + + case FIELD_STATE_START: + switch ((char) toupper((unsigned char) * name)) { + case 'T': + state = FIELD_STATE_T; + break; + case 'I': + return MAILMIME_FIELD_ID; + case 'D': + state = FIELD_STATE_D; + break; + case 'L': + return MAILMIME_FIELD_LANGUAGE; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_T: + switch ((char) toupper((unsigned char) * name)) { + case 'Y': + return MAILMIME_FIELD_TYPE; + case 'R': + return MAILMIME_FIELD_TRANSFER_ENCODING; + default: + return MAILMIME_FIELD_NONE; + } + break; + + case FIELD_STATE_D: + switch ((char) toupper((unsigned char) * name)) { + case 'E': + return MAILMIME_FIELD_DESCRIPTION; + case 'I': + return MAILMIME_FIELD_DISPOSITION; + default: + return MAILMIME_FIELD_NONE; + } + break; + } + name ++; + } +} + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result) +{ + char * name; + char * value; + int guessed_type; + size_t cur_token; + struct mailmime_content * content; + struct mailmime_mechanism * encoding; + char * id; + char * description; + uint32_t version; + struct mailmime_field * mime_field; + struct mailmime_language * language; + struct mailmime_disposition * disposition; + int res; + int r; + + name = field->fld_name; + value = field->fld_value; + cur_token = 0; + + content = NULL; + encoding = NULL; + id = NULL; + description = NULL; + version = 0; + disposition = NULL; + language = NULL; + + guessed_type = guess_field_type(name); + + switch (guessed_type) { + case MAILMIME_FIELD_TYPE: + if (strcasecmp(name, "Content-Type") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_content_parse(value, strlen(value), &cur_token, &content); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (strcasecmp(name, "Content-Transfer-Encoding") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_ID: + if (strcasecmp(name, "Content-ID") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_id_parse(value, strlen(value), &cur_token, &id); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DESCRIPTION: + if (strcasecmp(name, "Content-Description") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_description_parse(value, strlen(value), + &cur_token, &description); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_VERSION: + if (strcasecmp(name, "MIME-Version") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_version_parse(value, strlen(value), &cur_token, &version); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_DISPOSITION: + if (strcasecmp(name, "Content-Disposition") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_disposition_parse(value, strlen(value), + &cur_token, &disposition); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + case MAILMIME_FIELD_LANGUAGE: + if (strcasecmp(name, "Content-Language") != 0) + return MAILIMF_ERROR_PARSE; + r = mailmime_language_parse(value, strlen(value), &cur_token, &language); + if (r != MAILIMF_NO_ERROR) + return r; + break; + + default: + return MAILIMF_ERROR_PARSE; + } + + mime_field = mailmime_field_new(guessed_type, content, encoding, + id, description, version, disposition, + language); + if (mime_field == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime_field; + + return MAILIMF_NO_ERROR; + + free: + if (content != NULL) + mailmime_content_free(content); + if (encoding != NULL) + mailmime_encoding_free(encoding); + if (id != NULL) + mailmime_id_free(id); + if (description != NULL) + mailmime_description_free(description); + return res; +} + +/* +x extension-token := ietf-token / x-token +*/ + +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailmime_token_parse(message, length, index, result); +} + +/* + hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") + ; Octet must be used for characters > 127, =, + ; SPACEs or TABs at the ends of lines, and is + ; recommended for any character not listed in + ; RFC 2049 as "mail-safe". +*/ + +/* +x iana-token := +*/ + +/* +x ietf-token := +*/ + +/* +x id := "Content-ID" ":" msg-id +*/ + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_msg_id_parse(message, length, index, result); +} + +/* +x mechanism := "7bit" / "8bit" / "binary" / + "quoted-printable" / "base64" / + ietf-token / x-token +*/ + +static int mailmime_mechanism_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result) +{ + char * token; + int type; + struct mailmime_mechanism * mechanism; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + type = MAILMIME_MECHANISM_ERROR; /* XXX - removes a gcc warning */ + + token = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "7bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_7BIT; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "8bit"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_8BIT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "binary"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BINARY; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "quoted-printable"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "base64"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_BASE64; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_token_parse(message, length, &cur_token, &token); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_MECHANISM_TOKEN; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mechanism = mailmime_mechanism_new(type, token); + if (mechanism == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mechanism; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (token != NULL) + mailmime_token_free(token); + err: + return res; +} + +/* +x MIME-extension-field := +*/ + +/* +in headers + +x MIME-message-headers := entity-headers + fields + version CRLF + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +/* +in message + +x MIME-part-headers := entity-headers + [fields] + ; Any field not beginning with + ; "content-" can have no defined + ; meaning and may be ignored. + ; The ordering of the header + ; fields implied by this BNF + ; definition should be ignored. +*/ + +#if 0 +int +mailmime_unparsed_fields_parse(struct mailimf_unparsed_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + if (fields->list == NULL) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + for(cur = clist_begin(fields->list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_optional_field * field = cur->data; + struct mailmime_field * mime_field; + + r = mailmime_field_parse(field, &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} +#endif + +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result) +{ + clistiter * cur; + struct mailmime_fields * mime_fields; + clist * list; + int r; + int res; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + for(cur = clist_begin(fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailimf_field * field; + struct mailmime_field * mime_field; + + field = clist_content(cur); + + if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { + r = mailmime_field_parse(field->fld_data.fld_optional_field, + &mime_field); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_field); + if (r < 0) { + mailmime_field_free(mime_field); + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free_list; + } + } + } + + if (clist_begin(list) == NULL) { + res = MAILIMF_ERROR_PARSE; + goto free_list; + } + + mime_fields = mailmime_fields_new(list); + if (mime_fields == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = mime_fields; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_field_free, NULL); + clist_free(list); + err: + return res; +} + +/* +x parameter := attribute "=" value +*/ + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result) +{ + char * attribute; + char * value; + struct mailmime_parameter * parameter; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + r = mailmime_attribute_parse(message, length, &cur_token, &attribute); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_attr; + } + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_attr; + } + + parameter = mailmime_parameter_new(attribute, value); + if (parameter == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_value; + } + + * result = parameter; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_value: + mailmime_value_free(value); + free_attr: + mailmime_attribute_free(attribute); + err: + return res; +} + +/* + ptext := hex-octet / safe-char +*/ + +/* + qp-line := *(qp-segment transport-padding CRLF) + qp-part transport-padding +*/ + +/* + qp-part := qp-section + ; Maximum length of 76 characters +*/ + +/* + qp-section := [*(ptext / SPACE / TAB) ptext] +*/ + +/* + qp-segment := qp-section *(SPACE / TAB) "=" + ; Maximum length of 76 characters +*/ + +/* + quoted-printable := qp-line *(CRLF qp-line) +*/ + +/* + safe-char := + ; Characters not listed as "mail-safe" in + ; RFC 2049 are also not recommended. +*/ + +/* +x subtype := extension-token / iana-token +*/ + +static int mailmime_subtype_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailmime_extension_token_parse(message, length, index, result); +} + +/* +x token := 1* +*/ + +static int is_token(char ch) +{ + unsigned char uch = (unsigned char) ch; + + if (uch > 0x7F) + return FALSE; + + if (uch == ' ') + return FALSE; + + if (is_tspecials(ch)) + return FALSE; + + return TRUE; +} + + +static int mailmime_token_parse(const char * message, size_t length, + size_t * index, + char ** token) +{ + return mailimf_custom_string_parse(message, length, + index, token, + is_token); +} + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + +/* +enum { + LWSP_1, + LWSP_2, + LWSP_3, + LWSP_4, + LWSP_OK +}; + +gboolean mailmime_transport_padding_parse(gconst char * message, guint32 length, + guint32 * index) +{ + guint32 cur_token; + gint state; + guint32 last_valid_pos; + + cur_token = * index; + + if (cur_token >= length) + return FALSE; + + state = LWSP_1; + + while (state != LWSP_OUT) { + + if (cur_token >= length) + return FALSE; + + switch (state) { + case LWSP_1: + last_valid_pos = cur_token; + + switch (message[cur_token]) { + case '\r': + state = LWSP_2; + break; + case '\n': + state = LWSP_3; + break; + case ' ': + case '\t': + state = LWSP_4; + break; + default: + state = LWSP_OK; + break; + } + case LWSP_2: + switch (message[cur_token]) { + case '\n': + state = LWSP_3; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + case LWSP_3: + switch (message[cur_token]) { + case ' ': + case '\t': + state = LWSP_1; + break; + default: + state = LWSP_OUT; + cur_token = last_valid_pos; + break; + } + + cur_token ++; + } + } + + * index = cur_token; + + return TRUE; +} +*/ + +/* +x tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values +*/ + +static int is_tspecials(char ch) +{ + switch (ch) { + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '\\': + case '\"': + case '/': + case '[': + case ']': + case '?': + case '=': + return TRUE; + default: + return FALSE; + } +} + +/* +x type := discrete-type / composite-type +*/ + +static int mailmime_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_type ** result) +{ + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + size_t cur_token; + struct mailmime_type * mime_type; + int type; + int res; + int r; + + cur_token = * index; + + discrete_type = NULL; + composite_type = NULL; + + type = MAILMIME_TYPE_ERROR; /* XXX - removes a gcc warning */ + + r = mailmime_composite_type_parse(message, length, &cur_token, + &composite_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_COMPOSITE_TYPE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_discrete_type_parse(message, length, &cur_token, + &discrete_type); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_TYPE_DISCRETE_TYPE; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + mime_type = mailmime_type_new(type, discrete_type, composite_type); + if (mime_type == NULL) { + res = r; + goto free; + } + + * result = mime_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + err: + return res; +} + +/* +x value := token / quoted-string +*/ + +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + int r; + + r = mailmime_token_parse(message, length, index, result); + + if (r == MAILIMF_ERROR_PARSE) + r = mailimf_quoted_string_parse(message, length, index, result); + + if (r != MAILIMF_NO_ERROR) + return r; + + return MAILIMF_NO_ERROR; +} + +/* +x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT +*/ + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result) +{ + size_t cur_token; + uint32_t hi; + uint32_t low; + uint32_t version; + int r; + + cur_token = * index; + + r = mailimf_number_parse(message, length, &cur_token, &hi); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '.'); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &low); + if (r != MAILIMF_NO_ERROR) + return r; + + version = (hi << 16) + low; + + * result = version; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +x x-token := +*/ + +/* +static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, + guint32 * index, + gchar ** result) +{ + guint32 cur_token; + gchar * token; + gchar * x_token; + gboolean min_x; + + cur_token = * index; + + if (!mailimf_char_parse(message, length, &cur_token, 'x')) { + if (!mailimf_char_parse(message, length, &cur_token, 'X')) + return FALSE; + min_x = FALSE; + } + else + min_x = TRUE; + + if (!mailimf_char_parse(message, length, &cur_token, '-')) + return FALSE; + + if (!mailmime_token_parse(message, length, &cur_token, &token)) + return FALSE; + + if (min_x) + x_token = g_strconcat("x-", token, NULL); + else + x_token = g_strconcat("X-", token, NULL); + mailmime_token_free(token); + + if (x_token == NULL) + return FALSE; + + * result = x_token; + * index = cur_token; + + return TRUE; +} +*/ + + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result) +{ + size_t cur_token; + int r; + int res; + clist * list; + int first; + struct mailmime_language * language; + + cur_token = * index; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + while (1) { + char * atom; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, ','); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = mailimf_atom_parse(message, length, &cur_token, &atom); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + + r = clist_append(list, atom); + if (r < 0) { + mailimf_atom_free(atom); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + language = mailmime_language_new(list); + if (language == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = language; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + clist_foreach(list, (clist_func) mailimf_atom_free, NULL); + clist_free(list); + err: + return res; +} diff --git a/kmicromail/libetpan/mime/mailmime.h b/kmicromail/libetpan/mime/mailmime.h new file mode 100644 index 0000000..c834967 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime.h @@ -0,0 +1,100 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_H + +#define MAILMIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +int mailmime_content_parse(const char * message, size_t length, + size_t * index, + struct mailmime_content ** result); + +int mailmime_description_parse(const char * message, size_t length, + size_t * index, + char ** result); + +int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, + struct mailmime_mechanism ** result); + +int +mailmime_field_parse(struct mailimf_optional_field * field, + struct mailmime_field ** result); + +int mailmime_id_parse(const char * message, size_t length, + size_t * index, char ** result); + +int +mailmime_fields_parse(struct mailimf_fields * + fields, + struct mailmime_fields ** + result); + +int mailmime_version_parse(const char * message, size_t length, + size_t * index, + uint32_t * result); + +int +mailmime_extension_token_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailmime_parameter_parse(const char * message, size_t length, + size_t * index, + struct mailmime_parameter ** result); + +int mailmime_value_parse(const char * message, size_t length, + size_t * index, char ** result); + +int mailmime_language_parse(const char * message, size_t length, + size_t * index, + struct mailmime_language ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_content.c b/kmicromail/libetpan/mime/mailmime_content.c new file mode 100644 index 0000000..c73812d --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_content.c @@ -0,0 +1,2164 @@ +/* + * 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 "mailimf.h" + +#include +#include + +#include "mailmime.h" +#include "mailmime_types.h" +#include "mmapstring.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* + RFC 2045 + RFC 2046 + RFC 2047 + + RFC 2231 +*/ + + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * index, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + + + +char * mailmime_content_charset_get(struct mailmime_content * content) +{ + char * charset; + + charset = mailmime_content_param_get(content, "charset"); + if (charset == NULL) + return "us-ascii"; + else + return charset; +} + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name) +{ + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = clist_content(cur); + + if (strcasecmp(param->pa_name, name) == 0) + return param->pa_value; + } + + return NULL; +} + + +/* + boundary := 0*69 bcharsnospace +*/ + +/* + bchars := bcharsnospace / " " +*/ + +/* + bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / + "+" / "_" / "," / "-" / "." / + "/" / ":" / "=" / "?" +*/ + +/* + body-part := <"message" as defined in RFC 822, with all + header fields optional, not starting with the + specified dash-boundary, and with the + delimiter not occurring anywhere in the + body part. Note that the semantics of a + part differ from the semantics of a message, + as described in the text.> +*/ + +/* + close-delimiter := delimiter "--" +*/ + +/* + dash-boundary := "--" boundary + ; boundary taken from the value of + ; boundary parameter of the + ; Content-Type field. +*/ + +/* + delimiter := CRLF dash-boundary +*/ + +/* + discard-text := *(*text CRLF) + ; May be ignored or discarded. +*/ + +/* + encapsulation := delimiter transport-padding + CRLF body-part +*/ + +/* + epilogue := discard-text +*/ + +/* + multipart-body := [preamble CRLF] + dash-boundary transport-padding CRLF + body-part *encapsulation + close-delimiter transport-padding + [CRLF epilogue] +*/ + +/* + preamble := discard-text +*/ + +/* + transport-padding := *LWSP-char + ; Composers MUST NOT generate + ; non-zero length transport + ; padding, but receivers MUST + ; be able to handle padding + ; added by message transports. +*/ + + +/* + ACCESS-TYPE + EXPIRATION + SIZE + PERMISSION +*/ + +/* + 5.2.3.2. The 'ftp' and 'tftp' Access-Types + NAME + SITE + + (3) Before any data are retrieved, using FTP, the user will + generally need to be asked to provide a login id and a + password for the machine named by the site parameter. + For security reasons, such an id and password are not + specified as content-type parameters, but must be + obtained from the user. + + optional : + DIRECTORY + MODE +*/ + +/* +5.2.3.3. The 'anon-ftp' Access-Type +*/ + +/* +5.2.3.4. The 'local-file' Access-Type +NAME +SITE +*/ + +/* +5.2.3.5. The 'mail-server' Access-Type +SERVER +SUBJECT +*/ + + +enum { + PREAMBLE_STATE_A0, + PREAMBLE_STATE_A, + PREAMBLE_STATE_A1, + PREAMBLE_STATE_B, + PREAMBLE_STATE_C, + PREAMBLE_STATE_D, + PREAMBLE_STATE_E +}; + +static int mailmime_preamble_parse(const char * message, size_t length, + size_t * index, int beol) +{ + int state; + size_t cur_token; + + cur_token = * index; + if (beol) + state = PREAMBLE_STATE_A0; + else + state = PREAMBLE_STATE_A; + + while (state != PREAMBLE_STATE_E) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (state) { + case PREAMBLE_STATE_A0: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_A1; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_A1: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + + case PREAMBLE_STATE_B: + switch (message[cur_token]) { + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + case '-': + state = PREAMBLE_STATE_D; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_C: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_D; + break; + case '\r': + state = PREAMBLE_STATE_B; + break; + case '\n': + state = PREAMBLE_STATE_C; + break; + default: + state = PREAMBLE_STATE_A0; + break; + } + break; + + case PREAMBLE_STATE_D: + switch (message[cur_token]) { + case '-': + state = PREAMBLE_STATE_E; + break; + default: + state = PREAMBLE_STATE_A; + break; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int mailmime_boundary_parse(const char * message, size_t length, + size_t * index, char * boundary) +{ + size_t cur_token; + size_t len; + + cur_token = * index; + + len = strlen(boundary); + + if (cur_token + len >= length) + return MAILIMF_ERROR_PARSE; + + if (strncmp(message + cur_token, boundary, len) != 0) + return MAILIMF_ERROR_PARSE; + + cur_token += len; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int is_wsp(char ch) +{ + if ((ch == ' ') || (ch == '\t')) + return TRUE; + + return FALSE; +} + +static int mailmime_lwsp_parse(const char * message, size_t length, + size_t * index) +{ + size_t cur_token; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + while (is_wsp(message[cur_token])) { + cur_token ++; + if (cur_token >= length) + break; + } + + if (cur_token == * index) + return MAILIMF_ERROR_PARSE; + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +/* +gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * index) +*/ + +enum { + BODY_PART_DASH2_STATE_0, + BODY_PART_DASH2_STATE_1, + BODY_PART_DASH2_STATE_2, + BODY_PART_DASH2_STATE_3, + BODY_PART_DASH2_STATE_4, + BODY_PART_DASH2_STATE_5, + BODY_PART_DASH2_STATE_6 +}; + +static int +mailmime_body_part_dash2_parse(const char * message, size_t length, + size_t * index, char * boundary, + const char ** result, size_t * result_size) +{ + int state; + size_t cur_token; + size_t size; + size_t begin_text; + size_t end_text; + int r; + + cur_token = * index; + state = BODY_PART_DASH2_STATE_0; + + begin_text = cur_token; + end_text = length; + + while (state != BODY_PART_DASH2_STATE_5) { + + if (cur_token >= length) + break; + + switch(state) { + + case BODY_PART_DASH2_STATE_0: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_1: + switch (message[cur_token]) { + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_2: + switch (message[cur_token]) { + case '-': + end_text = cur_token; + state = BODY_PART_DASH2_STATE_3; + break; + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_3: + switch (message[cur_token]) { + case '\r': + state = BODY_PART_DASH2_STATE_1; + break; + case '\n': + state = BODY_PART_DASH2_STATE_2; + break; + case '-': + state = BODY_PART_DASH2_STATE_4; + break; + default: + state = BODY_PART_DASH2_STATE_0; + break; + } + break; + + case BODY_PART_DASH2_STATE_4: + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) + state = BODY_PART_DASH2_STATE_5; + else + state = BODY_PART_DASH2_STATE_6; + + break; + } + + if ((state != BODY_PART_DASH2_STATE_5) && + (state != BODY_PART_DASH2_STATE_6)) + cur_token ++; + + if (state == BODY_PART_DASH2_STATE_6) + state = BODY_PART_DASH2_STATE_0; + } + + end_text --; + if (end_text >= 1) + if (message[end_text - 1] == '\r') + end_text --; + + size = end_text - begin_text; + +#if 0 + body_part = mailimf_body_new(message + begin_text, size); + if (body_part == NULL) + goto err; +#endif + + * result = message + begin_text; + * result_size = size; + * index = cur_token; + + return MAILIMF_NO_ERROR; +#if 0 + err: + return MAILIMF_ERROR_PARSE; +#endif +} + +enum { + MULTIPART_CLOSE_STATE_0, + MULTIPART_CLOSE_STATE_1, + MULTIPART_CLOSE_STATE_2, + MULTIPART_CLOSE_STATE_3, + MULTIPART_CLOSE_STATE_4 +}; + +static int mailmime_multipart_close_parse(const char * message, size_t length, + size_t * index) +{ + int state; + size_t cur_token; + + cur_token = * index; + state = MULTIPART_CLOSE_STATE_0; + + while (state != MULTIPART_CLOSE_STATE_4) { + + switch(state) { + + case MULTIPART_CLOSE_STATE_0: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_1; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_1: + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch (message[cur_token]) { + case '-': + state = MULTIPART_CLOSE_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_CLOSE_STATE_2: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case ' ': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\t': + state = MULTIPART_CLOSE_STATE_2; + break; + case '\r': + state = MULTIPART_CLOSE_STATE_3; + break; + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + + case MULTIPART_CLOSE_STATE_3: + if (cur_token >= length) { + state = MULTIPART_CLOSE_STATE_4; + break; + } + + switch (message[cur_token]) { + case '\n': + state = MULTIPART_CLOSE_STATE_4; + break; + default: + state = MULTIPART_CLOSE_STATE_4; + break; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +enum { + MULTIPART_NEXT_STATE_0, + MULTIPART_NEXT_STATE_1, + MULTIPART_NEXT_STATE_2 +}; + +int mailmime_multipart_next_parse(const char * message, size_t length, + size_t * index) +{ + int state; + size_t cur_token; + + cur_token = * index; + state = MULTIPART_NEXT_STATE_0; + + while (state != MULTIPART_NEXT_STATE_2) { + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch(state) { + + case MULTIPART_NEXT_STATE_0: + switch (message[cur_token]) { + case ' ': + state = MULTIPART_NEXT_STATE_0; + break; + case '\t': + state = MULTIPART_NEXT_STATE_0; + break; + case '\r': + state = MULTIPART_NEXT_STATE_1; + break; + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + + case MULTIPART_NEXT_STATE_1: + switch (message[cur_token]) { + case '\n': + state = MULTIPART_NEXT_STATE_2; + break; + default: + return MAILIMF_ERROR_PARSE; + } + break; + } + + cur_token ++; + } + + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +static int +mailmime_multipart_body_parse(const char * message, size_t length, + size_t * index, char * boundary, + int default_subtype, + clist ** result, + struct mailmime_data ** p_preamble, + struct mailmime_data ** p_epilogue) +{ + size_t cur_token; + clist * list; + int r; + int res; +#if 0 + size_t begin; +#endif + size_t preamble_begin; + size_t preamble_length; + size_t preamble_end; +#if 0 + int no_preamble; + size_t before_crlf; +#endif + size_t epilogue_begin; + size_t epilogue_length; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + size_t part_begin; + + preamble = NULL; + epilogue = NULL; + + cur_token = * index; + preamble_begin = cur_token; + +#if 0 + no_preamble = FALSE; +#endif + preamble_end = preamble_begin; + +#if 0 + r = mailmime_preamble_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ +#if 0 + preamble_end = cur_token - 2; +#endif + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + no_preamble = TRUE; + } + else { + res = r; + goto err; + } + + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { +#if 0 + preamble_end = cur_token - 2; +#endif + } + else if (r == MAILIMF_ERROR_PARSE) { + no_preamble = TRUE; + break; + } + else { + res = r; + goto err; + } + } + + if (no_preamble) { +#if 0 + preamble_end = cur_token; +#endif + } + else { + + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + before_crlf = cur_token; + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { +#if 0 + preamble_end = before_crlf; +#endif + /* remove the CR LF at the end of preamble if any */ + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + } + preamble_length = preamble_end - begin; +#endif + + r = mailmime_preamble_parse(message, length, &cur_token, 1); + if (r == MAILIMF_NO_ERROR) { + while (1) { + + preamble_end = cur_token; + r = mailmime_boundary_parse(message, length, &cur_token, boundary); + if (r == MAILIMF_NO_ERROR) { + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailmime_preamble_parse(message, length, &cur_token, 0); + if (r == MAILIMF_NO_ERROR) { + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto err; + } + } + } + + preamble_end -= 2; + if (preamble_end != preamble_begin) { + /* try to find the real end of the preamble (strip CR LF) */ + if (message[preamble_end - 1] == '\n') { + preamble_end --; + if (preamble_end - 1 >= preamble_begin) { + if (message[preamble_end - 1] == '\r') + preamble_end --; + } + } + else if (message[preamble_end - 1] == '\r') { + preamble_end --; + } + } + preamble_length = preamble_end - preamble_begin; + + part_begin = cur_token; + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } +#if 0 + if (r == MAILIMF_ERROR_PARSE) + break; +#endif + + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + part_begin = cur_token; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto err; + } + } + + cur_token = part_begin; + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + while (1) { + size_t bp_token; + struct mailmime * mime_bp; + const char * data_str; + size_t data_size; + struct mailimf_fields * fields; + struct mailmime_fields * mime_fields; + + r = mailmime_body_part_dash2_parse(message, length, &cur_token, + boundary, &data_str, &data_size); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + + bp_token = 0; + + + r = mailimf_optional_fields_parse(data_str, data_size, + &bp_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailimf_crlf_parse(data_str, data_size, &bp_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free; + } + + mime_fields = NULL; + r = mailmime_fields_parse(fields, &mime_fields); + mailimf_fields_free(fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, default_subtype, NULL, + mime_fields, &mime_bp); + if (r == MAILIMF_NO_ERROR) { + r = clist_append(list, mime_bp); + if (r < 0) { + mailmime_free(mime_bp); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + break; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + r = mailmime_multipart_next_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_multipart_close_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } + break; + } + else { + res = r; + goto free; + } + } + + epilogue_begin = length; + /* parse transport-padding */ + while (1) { + r = mailmime_lwsp_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free; + } +#if 0 + if (r == MAILIMF_ERROR_PARSE) + break; +#endif + +#if 0 + before_crlf = cur_token; +#endif + r = mailimf_crlf_parse(message, length, &cur_token); + if (r == MAILIMF_NO_ERROR) { + epilogue_begin = cur_token; + break; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + break; + } + else { + res = r; + goto free; + } + } + + /* add preamble and epilogue */ + + epilogue_length = length - epilogue_begin; + + if (preamble_length != 0) { + preamble = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + preamble_begin, preamble_length, + NULL); + if (preamble == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + if (epilogue_length != 0) { + epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, + MAILMIME_MECHANISM_8BIT, 1, + message + epilogue_begin, epilogue_length, + NULL); + if (epilogue == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + + /* end of preamble and epilogue */ + + cur_token = length; + + * result = list; + * p_preamble = preamble; + * p_epilogue = epilogue; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + err: + return res; +} + +enum { + MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + MAILMIME_DEFAULT_TYPE_MESSAGE +}; + + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result) +{ + struct mailmime * mime; + int r; + int res; + struct mailmime_content * content_message; + size_t cur_token; + struct mailmime_fields * mime_fields; + const char * data_str; + size_t data_size; + size_t bp_token; + + cur_token = * index; + + content_message = mailmime_get_content_message(); + if (content_message == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + mime_fields = mailmime_fields_new_with_data(content_message, + NULL, + NULL, + NULL, + NULL, + NULL); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } +#endif + mime_fields = mailmime_fields_new_empty(); + if (mime_fields == NULL) { + mailmime_content_free(content_message); + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + data_str = message + cur_token; + data_size = length - cur_token; + + bp_token = 0; + r = mailmime_parse_with_default(data_str, data_size, + &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + content_message, mime_fields, &mime); + cur_token += bp_token; + if (r != MAILIMF_NO_ERROR) { + mailmime_fields_free(mime_fields); + res = r; + goto free; + } + + * index = cur_token; + * result = mime; + + return MAILIMF_NO_ERROR; + + free: + mailmime_fields_free(mime_fields); + err: + return res; +} + + +char * mailmime_extract_boundary(struct mailmime_content * content_type) +{ + char * boundary; + + boundary = mailmime_content_param_get(content_type, "boundary"); + + if (boundary != NULL) { + int len; + char * new_boundary; + + len = strlen(boundary); + new_boundary = malloc(len + 1); + if (new_boundary == NULL) + return NULL; + + if (boundary[0] == '"') { + strncpy(new_boundary, boundary + 1, len - 2); + new_boundary[len - 2] = 0; + } + else + strcpy(new_boundary, boundary); + + boundary = new_boundary; + } + + return boundary; +} + +static void remove_unparsed_mime_headers(struct mailimf_fields * fields) +{ + clistiter * cur; + + cur = clist_begin(fields->fld_list); + while (cur != NULL) { + struct mailimf_field * field; + int delete; + + field = clist_content(cur); + + switch (field->fld_type) { + case MAILIMF_FIELD_OPTIONAL_FIELD: + delete = 0; + if (strncasecmp(field->fld_data.fld_optional_field->fld_name, + "Content-", 8) == 0) { + char * name; + + name = field->fld_data.fld_optional_field->fld_name + 8; + if ((strcasecmp(name, "Type") == 0) + || (strcasecmp(name, "Transfer-Encoding") == 0) + || (strcasecmp(name, "ID") == 0) + || (strcasecmp(name, "Description") == 0) + || (strcasecmp(name, "Disposition") == 0) + || (strcasecmp(name, "Language") == 0)) { + delete = 1; + } + } + else if (strcasecmp(field->fld_data.fld_optional_field->fld_name, + "MIME-Version") == 0) { + delete = 1; + } + + if (delete) { + cur = clist_delete(fields->fld_list, cur); + mailimf_field_free(field); + } + else { + cur = clist_next(cur); + } + break; + + default: + cur = clist_next(cur); + } + } +} + +static int mailmime_parse_with_default(const char * message, size_t length, + size_t * index, int default_type, + struct mailmime_content * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result) +{ + size_t cur_token; + + int body_type; + + int encoding; + struct mailmime_data * body; + char * boundary; + struct mailimf_fields * fields; + clist * list; + struct mailmime * msg_mime; + + struct mailmime * mime; + + int r; + int res; + struct mailmime_data * preamble; + struct mailmime_data * epilogue; + + /* + note that when this function is called, content type is always detached, + even if the function fails + */ + + preamble = NULL; + epilogue = NULL; + + cur_token = * index; + + /* get content type */ + + if (content_type == NULL) { + if (mime_fields != NULL) { + clistiter * cur; + + for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime_field * field; + + field = clist_content(cur); + if (field->fld_type == MAILMIME_FIELD_TYPE) { + content_type = field->fld_data.fld_content; + + /* detach content type from list */ + field->fld_data.fld_content = NULL; + clist_delete(mime_fields->fld_list, cur); + mailmime_field_free(field); + /* + there may be a leak due to the detached content type + in case the function fails + */ + break; + } + } + } + } + + /* set default type if no content type */ + + if (content_type == NULL) { + /* content_type is detached, in any case, we will have to free it */ + if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { + content_type = mailmime_get_content_text(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else /* message */ { + body_type = MAILMIME_MESSAGE; + + content_type = mailmime_get_content_message(); + if (content_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + } + + /* get the body type */ + + boundary = NULL; /* XXX - removes a gcc warning */ + + switch (content_type->ct_type->tp_type) { + case MAILMIME_TYPE_COMPOSITE_TYPE: + switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + boundary = mailmime_extract_boundary(content_type); + + if (boundary == NULL) + body_type = MAILMIME_SINGLE; + else + body_type = MAILMIME_MULTIPLE; + break; + + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + + if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) + body_type = MAILMIME_MESSAGE; + else + body_type = MAILMIME_SINGLE; + break; + + default: + res = MAILIMF_ERROR_INVAL; + goto free_content; + } + break; + + default: /* MAILMIME_TYPE_DISCRETE_TYPE */ + body_type = MAILMIME_SINGLE; + break; + } + + /* set body */ + + if (mime_fields != NULL) + encoding = mailmime_transfer_encoding_get(mime_fields); + else + encoding = MAILMIME_MECHANISM_8BIT; + + cur_token = * index; + body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, + message + cur_token, length - cur_token, + NULL); + if (body == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + + /* in case of composite, parse the sub-part(s) */ + + list = NULL; + msg_mime = NULL; + fields = NULL; + + switch (body_type) { + case MAILMIME_MESSAGE: + { + struct mailmime_fields * submime_fields; + + r = mailimf_envelope_and_optional_fields_parse(message, length, + &cur_token, &fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_content; + } + + r = mailimf_crlf_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + submime_fields = NULL; + r = mailmime_fields_parse(fields, &submime_fields); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + mailimf_fields_free(fields); + res = r; + goto free_content; + } + + remove_unparsed_mime_headers(fields); + + r = mailmime_parse_with_default(message, length, + &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, + NULL, submime_fields, &msg_mime); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + mailmime_fields_free(mime_fields); + msg_mime = NULL; + } + else { + mailmime_fields_free(mime_fields); + res = r; + goto free_content; + } + } + + break; + + case MAILMIME_MULTIPLE: + { + int default_subtype; + + default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; + if (content_type != NULL) + if (strcasecmp(content_type->ct_subtype, "digest") == 0) + default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; + + cur_token = * index; + r = mailmime_multipart_body_parse(message, length, + &cur_token, boundary, + default_subtype, + &list, &preamble, &epilogue); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_content; + } + } + else { + res = r; + goto free_content; + } + + free(boundary); + } + break; + + default: /* MAILMIME_SINGLE */ + /* do nothing */ + break; + } + + mime = mailmime_new(body_type, message, length, + mime_fields, content_type, + body, preamble, /* preamble */ + epilogue, /* epilogue */ + list, fields, msg_mime); + if (mime == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = mime; + * index = length; + + return MAILIMF_NO_ERROR; + + free: + if (epilogue != NULL) + mailmime_data_free(epilogue); + if (preamble != NULL) + mailmime_data_free(preamble); + if (msg_mime != NULL) + mailmime_free(msg_mime); + if (list != NULL) { + clist_foreach(list, (clist_func) mailmime_free, NULL); + clist_free(list); + } + free_content: + mailmime_content_free(content_type); + err: + return res; +} + +static int mailmime_get_section_list(struct mailmime * mime, + clistiter * list, struct mailmime ** result) +{ + uint32_t id; + struct mailmime * data; + struct mailmime * submime; + + if (list == NULL) { + * result = mime; + return MAILIMF_NO_ERROR; + } + + id = * ((uint32_t *) clist_content(list)); + + data = NULL; + switch (mime->mm_type) { + case MAILMIME_SINGLE: + return MAILIMF_ERROR_INVAL; + + case MAILMIME_MULTIPLE: + data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + if (clist_next(list) != NULL) + return mailmime_get_section_list(data, clist_next(list), result); + else { + * result = data; + return MAILIMF_NO_ERROR; + } + + case MAILMIME_MESSAGE: + submime = mime->mm_data.mm_message.mm_msg_mime; + switch (submime->mm_type) { + case MAILMIME_MULTIPLE: + data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1); + if (data == NULL) + return MAILIMF_ERROR_INVAL; + return mailmime_get_section_list(data, clist_next(list), result); + + default: + if (id != 1) + return MAILIMF_ERROR_INVAL; + + data = submime; + if (data == NULL) + return MAILIMF_ERROR_INVAL; + + return mailmime_get_section_list(data, clist_next(list), result); + } + break; + + default: + return MAILIMF_ERROR_INVAL; + } +} + +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result) +{ + return mailmime_get_section_list(mime, + clist_begin(section->sec_list), result); +} + + + + + + + + + + + + + + + +/* ************************************************************************* */ +/* MIME part decoding */ + +static inline signed char get_base64_value(char ch) +{ + if ((ch >= 'A') && (ch <= 'Z')) + return ch - 'A'; + if ((ch >= 'a') && (ch <= 'z')) + return ch - 'a' + 26; + if ((ch >= '0') && (ch <= '9')) + return ch - '0' + 52; + switch (ch) { + case '+': + return 62; + case '/': + return 63; + case '=': /* base64 padding */ + return -1; + default: + return -1; + } +} + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len) +{ + size_t cur_token; + size_t i; + char chunk[4]; + int chunk_index; + char out[3]; + MMAPString * mmapstr; + int res; + int r; + size_t written; + + cur_token = * index; + chunk_index = 0; + written = 0; + + mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + i = 0; + while (1) { + signed char value; + + value = -1; + while (value == -1) { + + if (cur_token >= length) + break; + + value = get_base64_value(message[cur_token]); + cur_token ++; + } + + if (value == -1) + break; + + chunk[chunk_index] = value; + chunk_index ++; + + if (chunk_index == 4) { + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + out[2] = (chunk[2] << 6) | (chunk[3]); + + chunk[0] = 0; + chunk[1] = 0; + chunk[2] = 0; + chunk[3] = 0; + + chunk_index = 0; + + if (mmap_string_append_len(mmapstr, out, 3) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += 3; + } + } + + if (chunk_index != 0) { + size_t len; + + len = 0; + out[0] = (chunk[0] << 2) | (chunk[1] >> 4); + len ++; + + if (chunk_index >= 3) { + out[1] = (chunk[1] << 4) | (chunk[2] >> 2); + len ++; + } + + if (mmap_string_append_len(mmapstr, out, len) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + written += len; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + + +static inline int hexa_to_char(char hexdigit) +{ + if ((hexdigit >= '0') && (hexdigit <= '9')) + return hexdigit - '0'; + if ((hexdigit >= 'a') && (hexdigit <= 'f')) + return hexdigit - 'a' + 10; + if ((hexdigit >= 'A') && (hexdigit <= 'F')) + return hexdigit - 'A' + 10; + return 0; +} + +static inline char to_char(const char * hexa) +{ + return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]); +} + +enum { + STATE_NORMAL, + STATE_CODED, + STATE_OUT, + STATE_CR, +}; + + +static int write_decoded_qp(MMAPString * mmapstr, + const char * start, size_t count) +{ + if (mmap_string_append_len(mmapstr, start, count) == NULL) + return MAILIMF_ERROR_MEMORY; + + return MAILIMF_NO_ERROR; +} + + +#define WRITE_MAX_QP 512 + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header) +{ + size_t cur_token; + int state; + int r; + char ch; + size_t count; + const char * start; + MMAPString * mmapstr; + int res; + size_t written; + + state = STATE_NORMAL; + cur_token = * index; + + count = 0; + start = message + cur_token; + written = 0; + + mmapstr = mmap_string_sized_new(length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + +#if 0 + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') { + length --; + } + } + } +#endif + + while (state != STATE_OUT) { + + if (cur_token >= length) { + state = STATE_OUT; + break; + } + + switch (state) { + + case STATE_CODED: + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + switch (message[cur_token]) { + case '=': + if (cur_token + 1 >= length) { + /* error but ignore it */ + state = STATE_NORMAL; + start = message + cur_token; + cur_token ++; + count ++; + break; + } + + switch (message[cur_token + 1]) { + + case '\n': + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + + case '\r': + if (cur_token + 2 >= length) { + state = STATE_OUT; + break; + } + + if (message[cur_token + 2] == '\n') + cur_token += 3; + else + cur_token += 2; + + start = message + cur_token; + + state = STATE_NORMAL; + + break; + + default: + if (cur_token + 2 >= length) { + /* error but ignore it */ + cur_token ++; + + start = message + cur_token; + + count ++; + state = STATE_NORMAL; + break; + } + +#if 0 + /* flush before writing additionnal information */ + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; +#endif + + ch = to_char(message + cur_token + 1); + + if (mmap_string_append_c(mmapstr, ch) == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + cur_token += 3; + written ++; + + start = message + cur_token; + + state = STATE_NORMAL; + break; + } + break; + } + break; /* end of STATE_ENCODED */ + + case STATE_NORMAL: + + switch (message[cur_token]) { + + case '=': + state = STATE_CODED; + break; + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + break; + + case '\r': + state = STATE_CR; + cur_token ++; + break; + + case '_': + if (in_header) { + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + if (mmap_string_append_c(mmapstr, ' ') == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + written ++; + cur_token ++; + start = message + cur_token; + + break; + } + /* WARINING : must be followed by switch default action */ + + default: + if (count >= WRITE_MAX_QP) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + start = message + cur_token; + } + + count ++; + cur_token ++; + break; + } + break; /* end of STATE_NORMAL */ + + case STATE_CR: + switch (message[cur_token]) { + + case '\n': + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + cur_token ++; + start = message + cur_token; + state = STATE_NORMAL; + break; + + default: + /* flush before writing additionnal information */ + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + start = message + cur_token; + + r = write_decoded_qp(mmapstr, "\r\n", 2); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += 2; + state = STATE_NORMAL; + } + break; /* end of STATE_CR */ + } + } + + if (count > 0) { + r = write_decoded_qp(mmapstr, start, count); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free; + } + written += count; + count = 0; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = cur_token; + * result = mmapstr->str; + * result_len = written; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len) +{ + MMAPString * mmapstr; + size_t cur_token; + int r; + int res; + + cur_token = * index; + + if (length >= 1) { + if (message[length - 1] == '\n') { + length --; + if (length >= 1) + if (message[length - 1] == '\r') + length --; + } + } + + mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); + if (mmapstr == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + r = mmap_string_ref(mmapstr); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * index = length; + * result = mmapstr->str; + * result_len = length - cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(mmapstr); + err: + return res; +} + + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len) +{ + switch (encoding) { + case MAILMIME_MECHANISM_BASE64: + return mailmime_base64_body_parse(message, length, index, + result, result_len); + + case MAILMIME_MECHANISM_QUOTED_PRINTABLE: + return mailmime_quoted_printable_body_parse(message, length, index, + result, result_len, FALSE); + + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_BINARY: + default: + return mailmime_binary_body_parse(message, length, index, + result, result_len); + } +} + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result) +{ + clist * list; + int res; + struct mailmime_section * section_id; + int r; + + if (mime->mm_parent == NULL) { + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + section_id = mailmime_section_new(list); + if (section_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + } + else { + uint32_t id; + uint32_t * p_id; + clistiter * cur; + struct mailmime * parent; + + r = mailmime_get_section_id(mime->mm_parent, §ion_id); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + parent = mime->mm_parent; + switch (parent->mm_type) { + case MAILMIME_MULTIPLE: + id = 1; + for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + if (clist_content(cur) == mime) + break; + id ++; + } + + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = id; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + break; + + case MAILMIME_MESSAGE: + if ((mime->mm_type == MAILMIME_SINGLE) || + (mime->mm_type == MAILMIME_MESSAGE)) { + p_id = malloc(sizeof(* p_id)); + if (p_id == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + * p_id = 1; + + r = clist_append(section_id->sec_list, p_id); + if (r < 0) { + free(p_id); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + } + + * result = section_id; + + return MAILIMF_NO_ERROR; + + free: + mailmime_section_free(section_id); + err: + return res; +} diff --git a/kmicromail/libetpan/mime/mailmime_content.h b/kmicromail/libetpan/mime/mailmime_content.h new file mode 100644 index 0000000..df4b232 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_content.h @@ -0,0 +1,89 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_CONTENT_H + +#define MAILMIME_CONTENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +char * mailmime_content_charset_get(struct mailmime_content * content); + +char * mailmime_content_param_get(struct mailmime_content * content, + char * name); + +int mailmime_parse(const char * message, size_t length, + size_t * index, struct mailmime ** result); + +int mailmime_get_section(struct mailmime * mime, + struct mailmime_section * section, + struct mailmime ** result); + + +char * mailmime_extract_boundary(struct mailmime_content * content_type); + + +/* decode */ + +int mailmime_base64_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +int mailmime_quoted_printable_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len, int in_header); + + +int mailmime_binary_body_parse(const char * message, size_t length, + size_t * index, char ** result, + size_t * result_len); + +int mailmime_part_parse(const char * message, size_t length, + size_t * index, + int encoding, char ** result, size_t * result_len); + + +int mailmime_get_section_id(struct mailmime * mime, + struct mailmime_section ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_decode.c b/kmicromail/libetpan/mime/mailmime_decode.c new file mode 100644 index 0000000..3025dcb --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_decode.c @@ -0,0 +1,533 @@ +/* + * 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$ + */ + +/* + RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three: + Message Header Extensions for Non-ASCII Text +*/ + +#include "mailmime_decode.h" + +#include +#include +#include +#include +#include + +#include "mailmime_content.h" + +#include "charconv.h" +#include "mmapstring.h" +#include "mailimf.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * index, char ** charset); + +enum { + MAILMIME_ENCODING_B, + MAILMIME_ENCODING_Q +}; + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, int * result); + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * index, + char ** result); + +static int +mailmime_encoded_word_parse(const char * message, size_t length, + size_t * index, + struct mailmime_encoded_word ** result); + + +enum { + TYPE_ERROR, + TYPE_WORD, + TYPE_ENCODED_WORD, +}; + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result) +{ + MMAPString * gphrase; + struct mailmime_encoded_word * word; + int first; + size_t cur_token; + int r; + int res; + char * str; + char * wordutf8; + int type; + + cur_token = * index; + + gphrase = mmap_string_new(""); + if (gphrase == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + first = TRUE; + + type = TYPE_ERROR; /* XXX - removes a gcc warning */ + + while (1) { + + r = mailmime_encoded_word_parse(message, length, &cur_token, &word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (type != TYPE_ENCODED_WORD) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + } + type = TYPE_ENCODED_WORD; + wordutf8 = NULL; + r = charconv(tocode, word->wd_charset, word->wd_text, + strlen(word->wd_text), &wordutf8); + switch (r) { + case MAIL_CHARCONV_ERROR_MEMORY: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_MEMORY; + goto free; + + case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: + case MAIL_CHARCONV_ERROR_CONV: + mailmime_encoded_word_free(word); + res = MAILIMF_ERROR_PARSE; + goto free; + } + + if (wordutf8 != NULL) { + if (mmap_string_append(gphrase, wordutf8) == NULL) { + mailmime_encoded_word_free(word); + free(wordutf8); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + free(wordutf8); + } + mailmime_encoded_word_free(word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto free; + } + + if (r == MAILIMF_ERROR_PARSE) { + char * raw_word; + + r = mailmime_non_encoded_word_parse(message, length, + &cur_token, &raw_word); + if (r == MAILIMF_NO_ERROR) { + if (!first) { + if (mmap_string_append_c(gphrase, ' ') == NULL) { + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + } + type = TYPE_WORD; + + wordutf8 = NULL; + r = charconv(tocode, default_fromcode, raw_word, + strlen(raw_word), &wordutf8); + + if (wordutf8 != NULL) { + if (mmap_string_append(gphrase, wordutf8) == NULL) { + free(wordutf8); + free(raw_word); + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + free(wordutf8); + } + free(raw_word); + first = FALSE; + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free; + } + } + } + + if (first) { + res = MAILIMF_ERROR_PARSE; + goto free; + } + + str = strdup(gphrase->str); + if (str == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + mmap_string_free(gphrase); + + * result = str; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + mmap_string_free(gphrase); + err: + return res; +} + +static int +mailmime_non_encoded_word_parse(const char * message, size_t length, + size_t * index, + char ** result) +{ + int end; + size_t cur_token; + int res; + char * text; + int r; + size_t begin; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + begin = cur_token; + + end = FALSE; + while (1) { + if (cur_token >= length) + break; + + switch (message[cur_token]) { + case ' ': + case '\t': + case '\r': + case '\n': + end = TRUE; + break; + } + + if (end) + break; + + cur_token ++; + } + + if (cur_token - begin == 0) { + res = MAILIMF_ERROR_PARSE; + goto err; + } + + text = malloc(cur_token - begin + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto err; + } + + memcpy(text, message + begin, cur_token - begin); + text[cur_token - begin] = '\0'; + + * index = cur_token; + * result = text; + + return MAILIMF_NO_ERROR; + + err: + return res; +} + +static int mailmime_encoded_word_parse(const char * message, size_t length, + size_t * index, + struct mailmime_encoded_word ** result) +{ + size_t cur_token; + char * charset; + int encoding; + char * text; + size_t end_encoding; + char * decoded; + size_t decoded_len; + struct mailmime_encoded_word * ew; + int r; + int res; + int opening_quote; + int end; + + cur_token = * index; + + r = mailimf_fws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + opening_quote = FALSE; + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if (r == MAILIMF_NO_ERROR) { + opening_quote = TRUE; + } + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?"); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailmime_charset_parse(message, length, &cur_token, &charset); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailmime_encoding_parse(message, length, &cur_token, &encoding); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + r = mailimf_char_parse(message, length, &cur_token, '?'); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + end = FALSE; + end_encoding = cur_token; + while (1) { + if (end_encoding >= length) + break; + + switch (message[end_encoding]) { + case '?': +#if 0 + case ' ': +#endif + end = TRUE; + break; + } + + if (end) + break; + + end_encoding ++; + } + + decoded_len = 0; + decoded = NULL; + switch (encoding) { + case MAILMIME_ENCODING_B: + r = mailmime_base64_body_parse(message, end_encoding, + &cur_token, &decoded, + &decoded_len); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + break; + case MAILMIME_ENCODING_Q: + r = mailmime_quoted_printable_body_parse(message, end_encoding, + &cur_token, &decoded, + &decoded_len, TRUE); + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_charset; + } + + break; + } + + text = malloc(decoded_len + 1); + if (text == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_charset; + } + + if (decoded_len > 0) + memcpy(text, decoded, decoded_len); + text[decoded_len] = '\0'; + + mailmime_decoded_part_free(decoded); + + r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?="); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto free_encoded_text; + } + + if (opening_quote) { + r = mailimf_char_parse(message, length, &cur_token, '\"'); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto free_encoded_text; + } + } + + ew = mailmime_encoded_word_new(charset, text); + if (ew == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_encoded_text; + } + + * result = ew; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_encoded_text: + mailmime_encoded_text_free(text); + free_charset: + mailmime_charset_free(charset); + err: + return res; +} + +static int mailmime_charset_parse(const char * message, size_t length, + size_t * index, char ** charset) +{ + return mailmime_etoken_parse(message, length, index, charset); +} + +static int mailmime_encoding_parse(const char * message, size_t length, + size_t * index, int * result) +{ + size_t cur_token; + int encoding; + + cur_token = * index; + + if (cur_token >= length) + return MAILIMF_ERROR_PARSE; + + switch ((char) toupper((unsigned char) message[cur_token])) { + case 'Q': + encoding = MAILMIME_ENCODING_Q; + break; + case 'B': + encoding = MAILMIME_ENCODING_B; + break; + default: + return MAILIMF_ERROR_INVAL; + } + + cur_token ++; + + * result = encoding; + * index = cur_token; + + return MAILIMF_NO_ERROR; +} + +int is_etoken_char(char ch) +{ + unsigned char uch = ch; + + if (uch < 31) + return FALSE; + + switch (uch) { + case ' ': + case '(': + case ')': + case '<': + case '>': + case '@': + case ',': + case ';': + case ':': + case '"': + case '/': + case '[': + case ']': + case '?': + case '.': + case '=': + return FALSE; + } + + return TRUE; +} + +static int mailmime_etoken_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_custom_string_parse(message, length, + index, result, + is_etoken_char); +} diff --git a/kmicromail/libetpan/mime/mailmime_decode.h b/kmicromail/libetpan/mime/mailmime_decode.h new file mode 100644 index 0000000..034db6f --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_decode.h @@ -0,0 +1,55 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_DECODE_H + +#define MAILMIME_DECODE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_encoded_phrase_parse(const char * default_fromcode, + const char * message, size_t length, + size_t * index, const char * tocode, + char ** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_disposition.c b/kmicromail/libetpan/mime/mailmime_disposition.c new file mode 100644 index 0000000..9d8dfec --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_disposition.c @@ -0,0 +1,595 @@ +/* + * 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_disposition.h" +#include "mailmime.h" + +#include +#include + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_parm ** + result); + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result); + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * index, size_t * result); + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * index, char ** result); + +/* + disposition := "Content-Disposition" ":" + disposition-type + *(";" disposition-parm) + +*/ + + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result) +{ + size_t final_token; + size_t cur_token; + struct mailmime_disposition_type * dsp_type; + clist * list; + struct mailmime_disposition * dsp; + int r; + int res; + + cur_token = * index; + + r = mailmime_disposition_type_parse(message, length, &cur_token, + &dsp_type); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + list = clist_new(); + if (list == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_type; + } + + while (1) { + struct mailmime_disposition_parm * param; + + final_token = cur_token; + r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + break; + } + else { + res = r; + goto free_list; + } + + r = mailmime_disposition_parm_parse(message, length, &cur_token, ¶m); + if (r == MAILIMF_NO_ERROR) { + /* do nothing */ + } + else if (r == MAILIMF_ERROR_PARSE) { + cur_token = final_token; + break; + } + else { + res = r; + goto free_list; + } + + r = clist_append(list, param); + if (r < 0) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + } + + dsp = mailmime_disposition_new(dsp_type, list); + if (dsp == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free_list; + } + + * result = dsp; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free_list: + clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(list); + free_type: + mailmime_disposition_type_free(dsp_type); + err: + return res; +} + +/* + disposition-type := "inline" + / "attachment" + / extension-token + ; values are not case-sensitive + +*/ + + + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result) +{ + size_t cur_token; + int type; + char * extension; + struct mailmime_disposition_type * dsp_type; + int r; + int res; + + cur_token = * index; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */ + + extension = NULL; + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "inline"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_INLINE; + + if (r == MAILIMF_ERROR_PARSE) { + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "attachment"); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; + } + + if (r == MAILIMF_ERROR_PARSE) { + r = mailmime_extension_token_parse(message, length, &cur_token, + &extension); + if (r == MAILIMF_NO_ERROR) + type = MAILMIME_DISPOSITION_TYPE_EXTENSION; + } + + if (r != MAILIMF_NO_ERROR) { + res = r; + goto err; + } + + dsp_type = mailmime_disposition_type_new(type, extension); + if (dsp_type == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_type; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (extension != NULL) + free(extension); + err: + return res; +} + +/* + disposition-parm := filename-parm + / creation-date-parm + / modification-date-parm + / read-date-parm + / size-parm + / parameter +*/ + + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index) +{ + if (index >= length) + return MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch ((char) toupper((unsigned char) message[index])) { + case 'F': + return MAILMIME_DISPOSITION_PARM_FILENAME; + case 'C': + return MAILMIME_DISPOSITION_PARM_CREATION_DATE; + case 'M': + return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE; + case 'R': + return MAILMIME_DISPOSITION_PARM_READ_DATE; + case 'S': + return MAILMIME_DISPOSITION_PARM_SIZE; + default: + return MAILMIME_DISPOSITION_PARM_PARAMETER; + } +} + +static int +mailmime_disposition_parm_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_parm ** + result) +{ + char * filename; + char * creation_date; + char * modification_date; + char * read_date; + size_t size; + struct mailmime_parameter * parameter; + size_t cur_token; + struct mailmime_disposition_parm * dsp_parm; + int type; + int guessed_type; + int r; + int res; + + cur_token = * index; + + filename = NULL; + creation_date = NULL; + modification_date = NULL; + read_date = NULL; + size = 0; + parameter = NULL; + + r = mailimf_cfws_parse(message, length, &cur_token); + if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { + res = r; + goto err; + } + + guessed_type = mailmime_disposition_guess_type(message, length, cur_token); + + type = MAILMIME_DISPOSITION_PARM_PARAMETER; + + switch (guessed_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + r = mailmime_filename_parm_parse(message, length, &cur_token, + &filename); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + r = mailmime_creation_date_parm_parse(message, length, &cur_token, + &creation_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + r = mailmime_modification_date_parm_parse(message, length, &cur_token, + &modification_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_READ_DATE: + r = mailmime_read_date_parm_parse(message, length, &cur_token, + &read_date); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + + case MAILMIME_DISPOSITION_PARM_SIZE: + r = mailmime_size_parm_parse(message, length, &cur_token, + &size); + if (r == MAILIMF_NO_ERROR) + type = guessed_type; + else if (r == MAILIMF_ERROR_PARSE) { + /* do nothing */ + } + else { + res = r; + goto err; + } + break; + } + + if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { + r = mailmime_parameter_parse(message, length, &cur_token, + ¶meter); + if (r != MAILIMF_NO_ERROR) { + type = guessed_type; + res = r; + goto err; + } + } + + dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date, + modification_date, read_date, + size, parameter); + + if (dsp_parm == NULL) { + res = MAILIMF_ERROR_MEMORY; + goto free; + } + + * result = dsp_parm; + * index = cur_token; + + return MAILIMF_NO_ERROR; + + free: + if (filename != NULL) + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + if (creation_date != NULL) + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + if (modification_date != NULL) + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + if (read_date != NULL) + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + if (parameter != NULL) + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + err: + return res; +} + +/* + filename-parm := "filename" "=" value +*/ + +static int +mailmime_filename_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "filename"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_value_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + creation-date-parm := "creation-date" "=" quoted-date-time +*/ + +static int +mailmime_creation_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + int r; + size_t cur_token; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "creation-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + modification-date-parm := "modification-date" "=" quoted-date-time +*/ + +static int +mailmime_modification_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "modification-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + read-date-parm := "read-date" "=" quoted-date-time +*/ + +static int +mailmime_read_date_parm_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + char * value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "read-date"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + size-parm := "size" "=" 1*DIGIT +*/ + +static int +mailmime_size_parm_parse(const char * message, size_t length, + size_t * index, size_t * result) +{ + uint32_t value; + size_t cur_token; + int r; + + cur_token = * index; + + r = mailimf_token_case_insensitive_parse(message, length, + &cur_token, "size"); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); + if (r != MAILIMF_NO_ERROR) + return r; + + r = mailimf_number_parse(message, length, &cur_token, &value); + if (r != MAILIMF_NO_ERROR) + return r; + + * index = cur_token; + * result = value; + + return MAILIMF_NO_ERROR; +} + +/* + quoted-date-time := quoted-string + ; contents MUST be an RFC 822 `date-time' + ; numeric timezones (+HHMM or -HHMM) MUST be used +*/ + +static int +mailmime_quoted_date_time_parse(const char * message, size_t length, + size_t * index, char ** result) +{ + return mailimf_quoted_string_parse(message, length, index, result); +} diff --git a/kmicromail/libetpan/mime/mailmime_disposition.h b/kmicromail/libetpan/mime/mailmime_disposition.h new file mode 100644 index 0000000..e3bba15 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_disposition.h @@ -0,0 +1,62 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_DISPOSITION_H + +#define MAILMIME_DISPOSITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_disposition_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition ** result); + +int +mailmime_disposition_type_parse(const char * message, size_t length, + size_t * index, + struct mailmime_disposition_type ** result); + +int mailmime_disposition_guess_type(const char * message, size_t length, + size_t index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kmicromail/libetpan/mime/mailmime_types.c b/kmicromail/libetpan/mime/mailmime_types.c new file mode 100644 index 0000000..a81c87a --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types.c @@ -0,0 +1,750 @@ +/* + * 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_types.h" +#include "mmapstring.h" + +#include +#include + +void mailmime_attribute_free(char * attribute) +{ + mailmime_token_free(attribute); +} + + + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token) +{ + struct mailmime_composite_type * ct; + + ct = malloc(sizeof(* ct)); + if (ct == NULL) + return NULL; + + ct->ct_type = ct_type; + ct->ct_token = ct_token; + + return ct; +} + +void mailmime_composite_type_free(struct mailmime_composite_type * ct) +{ + if (ct->ct_token != NULL) + mailmime_extension_token_free(ct->ct_token); + free(ct); +} + + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters) +{ + struct mailmime_content * content; + + content = malloc(sizeof(* content)); + if (content == NULL) + return NULL; + + content->ct_type = ct_type; + content->ct_subtype = ct_subtype; + content->ct_parameters = ct_parameters; + + return content; +} + +void mailmime_content_free(struct mailmime_content * content) +{ + mailmime_type_free(content->ct_type); + mailmime_subtype_free(content->ct_subtype); + if (content->ct_parameters != NULL) { + clist_foreach(content->ct_parameters, + (clist_func) mailmime_parameter_free, NULL); + clist_free(content->ct_parameters); + } + + free(content); +} + + +void mailmime_description_free(char * description) +{ + free(description); +} + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension) +{ + struct mailmime_discrete_type * discrete_type; + + discrete_type = malloc(sizeof(* discrete_type)); + if (discrete_type == NULL) + return NULL; + + discrete_type->dt_type = dt_type; + discrete_type->dt_extension = dt_extension; + + return discrete_type; +} + +void mailmime_discrete_type_free(struct mailmime_discrete_type * discrete_type) +{ + if (discrete_type->dt_extension != NULL) + mailmime_extension_token_free(discrete_type->dt_extension); + free(discrete_type); +} + +void mailmime_encoding_free(struct mailmime_mechanism * encoding) +{ + mailmime_mechanism_free(encoding); +} + +void mailmime_extension_token_free(char * extension) +{ + mailmime_token_free(extension); +} + +void mailmime_id_free(char * id) +{ + mailimf_msg_id_free(id); +} + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token) +{ + struct mailmime_mechanism * mechanism; + + mechanism = malloc(sizeof(* mechanism)); + if (mechanism == NULL) + return NULL; + + mechanism->enc_type = enc_type; + mechanism->enc_token = enc_token; + + return mechanism; +} + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism) +{ + if (mechanism->enc_token != NULL) + mailmime_token_free(mechanism->enc_token); + free(mechanism); +} + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value) +{ + struct mailmime_parameter * parameter; + + parameter = malloc(sizeof(* parameter)); + if (parameter == NULL) + return NULL; + + parameter->pa_name = pa_name; + parameter->pa_value = pa_value; + + return parameter; +} + +void mailmime_parameter_free(struct mailmime_parameter * parameter) +{ + mailmime_attribute_free(parameter->pa_name); + mailmime_value_free(parameter->pa_value); + free(parameter); +} + + +void mailmime_subtype_free(char * subtype) +{ + mailmime_extension_token_free(subtype); +} + + +void mailmime_token_free(char * token) +{ + free(token); +} + + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type) +{ + struct mailmime_type * mime_type; + + mime_type = malloc(sizeof(* mime_type)); + if (mime_type == NULL) + return NULL; + + mime_type->tp_type = tp_type; + switch (tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mime_type->tp_data.tp_discrete_type = tp_discrete_type; + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mime_type->tp_data.tp_composite_type = tp_composite_type; + break; + } + + return mime_type; +} + +void mailmime_type_free(struct mailmime_type * type) +{ + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + mailmime_discrete_type_free(type->tp_data.tp_discrete_type); + break; + case MAILMIME_TYPE_COMPOSITE_TYPE: + mailmime_composite_type_free(type->tp_data.tp_composite_type); + break; + } + free(type); +} + +void mailmime_value_free(char * value) +{ + free(value); +} + + +/* +void mailmime_x_token_free(gchar * x_token) +{ + g_free(x_token); +} +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language) +{ + struct mailmime_field * field; + + field = malloc(sizeof(* field)); + if (field == NULL) + return NULL; + field->fld_type = fld_type; + + switch (fld_type) { + case MAILMIME_FIELD_TYPE: + field->fld_data.fld_content = fld_content; + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + field->fld_data.fld_encoding = fld_encoding; + break; + case MAILMIME_FIELD_ID: + field->fld_data.fld_id = fld_id; + break; + case MAILMIME_FIELD_DESCRIPTION: + field->fld_data.fld_description = fld_description; + break; + case MAILMIME_FIELD_VERSION: + field->fld_data.fld_version = fld_version; + break; + case MAILMIME_FIELD_DISPOSITION: + field->fld_data.fld_disposition = fld_disposition; + break; + case MAILMIME_FIELD_LANGUAGE: + field->fld_data.fld_language = fld_language; + break; + } + return field; +} + +void mailmime_field_free(struct mailmime_field * field) +{ + switch (field->fld_type) { + case MAILMIME_FIELD_TYPE: + if (field->fld_data.fld_content != NULL) + mailmime_content_free(field->fld_data.fld_content); + break; + case MAILMIME_FIELD_TRANSFER_ENCODING: + if (field->fld_data.fld_encoding != NULL) + mailmime_encoding_free(field->fld_data.fld_encoding); + break; + case MAILMIME_FIELD_ID: + if (field->fld_data.fld_id != NULL) + mailmime_id_free(field->fld_data.fld_id); + break; + case MAILMIME_FIELD_DESCRIPTION: + if (field->fld_data.fld_description != NULL) + mailmime_description_free(field->fld_data.fld_description); + break; + case MAILMIME_FIELD_DISPOSITION: + if (field->fld_data.fld_disposition != NULL) + mailmime_disposition_free(field->fld_data.fld_disposition); + break; + case MAILMIME_FIELD_LANGUAGE: + if (field->fld_data.fld_language != NULL) + mailmime_language_free(field->fld_data.fld_language); + break; + } + + free(field); +} + +struct mailmime_fields * mailmime_fields_new(clist * fld_list) +{ + struct mailmime_fields * fields; + + fields = malloc(sizeof(* fields)); + if (fields == NULL) + return NULL; + + fields->fld_list = fld_list; + + return fields; +} + +void mailmime_fields_free(struct mailmime_fields * fields) +{ + clist_foreach(fields->fld_list, (clist_func) mailmime_field_free, NULL); + clist_free(fields->fld_list); + free(fields); +} + + +/* +struct mailmime_body_part * +mailmime_body_part_new(gchar * text, guint32 size) +{ + struct mailmime_body_part * body_part; + + body_part = g_new(struct mailmime_body_part, 1); + if (body_part == NULL) + return NULL; + + body_part->text = text; + body_part->size = size; + + return body_part; +} + +void mailmime_body_part_free(struct mailmime_body_part * body_part) +{ + g_free(body_part); +} +*/ + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list) +{ + struct mailmime_multipart_body * mp_body; + + mp_body = malloc(sizeof(* mp_body)); + if (mp_body == NULL) + return NULL; + + mp_body->bd_list = bd_list; + + return mp_body; +} + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body) +{ + clist_foreach(mp_body->bd_list, (clist_func) mailimf_body_free, NULL); + clist_free(mp_body->bd_list); + free(mp_body); +} + + + + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime) +{ + struct mailmime * mime; + clistiter * cur; + + mime = malloc(sizeof(* mime)); + if (mime == NULL) + return NULL; + + mime->mm_parent = NULL; + mime->mm_parent_type = MAILMIME_NONE; + mime->mm_multipart_pos = NULL; + + mime->mm_type = mm_type; + mime->mm_mime_start = mm_mime_start; + mime->mm_length = mm_length; + mime->mm_mime_fields = mm_mime_fields; + mime->mm_content_type = mm_content_type; + + mime->mm_body = mm_body; + + switch (mm_type) { + case MAILMIME_SINGLE: + mime->mm_data.mm_single = mm_body; + break; + + case MAILMIME_MULTIPLE: + mime->mm_data.mm_multipart.mm_preamble = mm_preamble; + mime->mm_data.mm_multipart.mm_epilogue = mm_epilogue; + mime->mm_data.mm_multipart.mm_mp_list = mm_mp_list; + + for(cur = clist_begin(mm_mp_list) ; cur != NULL ; + cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + submime->mm_parent = mime; + submime->mm_parent_type = MAILMIME_MULTIPLE; + submime->mm_multipart_pos = cur; + } + break; + + case MAILMIME_MESSAGE: + mime->mm_data.mm_message.mm_fields = mm_fields; + mime->mm_data.mm_message.mm_msg_mime = mm_msg_mime; + if (mm_msg_mime != NULL) { + mm_msg_mime->mm_parent = mime; + mm_msg_mime->mm_parent_type = MAILMIME_MESSAGE; + } + break; + + } + + return mime; +} + +void mailmime_free(struct mailmime * mime) +{ + if (mime->mm_body != NULL) + mailmime_data_free(mime->mm_body); + switch (mime->mm_type) { + case MAILMIME_SINGLE: + /* do nothing */ + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_preamble); + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) + mailmime_data_free(mime->mm_data.mm_multipart.mm_epilogue); + clist_foreach(mime->mm_data.mm_multipart.mm_mp_list, + (clist_func) mailmime_free, NULL); + clist_free(mime->mm_data.mm_multipart.mm_mp_list); + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_fields != NULL) + mailimf_fields_free(mime->mm_data.mm_message.mm_fields); + if (mime->mm_data.mm_message.mm_msg_mime != NULL) + mailmime_free(mime->mm_data.mm_message.mm_msg_mime); + break; + + } + if (mime->mm_mime_fields != NULL) + mailmime_fields_free(mime->mm_mime_fields); + if (mime->mm_content_type != NULL) + mailmime_content_free(mime->mm_content_type); + free(mime); +} + + + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text) +{ + struct mailmime_encoded_word * ew; + + ew = malloc(sizeof(* ew)); + if (ew == NULL) + return NULL; + ew->wd_charset = wd_charset; + ew->wd_text = wd_text; + + return ew; +} + +void mailmime_charset_free(char * charset) +{ + free(charset); +} + +void mailmime_encoded_text_free(char * text) +{ + free(text); +} + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew) +{ + mailmime_charset_free(ew->wd_charset); + mailmime_encoded_text_free(ew->wd_text); + free(ew); +} + + + +/* mailmime_disposition */ + + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms) +{ + struct mailmime_disposition * dsp; + + dsp = malloc(sizeof(* dsp)); + if (dsp == NULL) + return NULL; + dsp->dsp_type = dsp_type; + dsp->dsp_parms = dsp_parms; + + return dsp; +} + +void mailmime_disposition_free(struct mailmime_disposition * dsp) +{ + mailmime_disposition_type_free(dsp->dsp_type); + clist_foreach(dsp->dsp_parms, + (clist_func) mailmime_disposition_parm_free, NULL); + clist_free(dsp->dsp_parms); + free(dsp); +} + + + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dsp_type, char * dsp_extension) +{ + struct mailmime_disposition_type * m_dsp_type; + + m_dsp_type = malloc(sizeof(* m_dsp_type)); + if (m_dsp_type == NULL) + return NULL; + + m_dsp_type->dsp_type = dsp_type; + m_dsp_type->dsp_extension = dsp_extension; + + return m_dsp_type; +} + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type) +{ + if (dsp_type->dsp_extension != NULL) + free(dsp_type->dsp_extension); + free(dsp_type); +} + + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter) +{ + struct mailmime_disposition_parm * dsp_parm; + + dsp_parm = malloc(sizeof(* dsp_parm)); + if (dsp_parm == NULL) + return NULL; + + dsp_parm->pa_type = pa_type; + switch (pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + dsp_parm->pa_data.pa_filename = pa_filename; + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + dsp_parm->pa_data.pa_creation_date = pa_creation_date; + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + dsp_parm->pa_data.pa_modification_date = pa_modification_date; + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + dsp_parm->pa_data.pa_read_date = pa_read_date; + break; + case MAILMIME_DISPOSITION_PARM_SIZE: + dsp_parm->pa_data.pa_size = pa_size; + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + dsp_parm->pa_data.pa_parameter = pa_parameter; + break; + } + + return dsp_parm; +} + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm) +{ + switch (dsp_parm->pa_type) { + case MAILMIME_DISPOSITION_PARM_FILENAME: + mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); + break; + case MAILMIME_DISPOSITION_PARM_CREATION_DATE: + mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); + break; + case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: + mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); + break; + case MAILMIME_DISPOSITION_PARM_READ_DATE: + mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); + break; + case MAILMIME_DISPOSITION_PARM_PARAMETER: + mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); + break; + } + + free(dsp_parm); +} + + +void mailmime_filename_parm_free(char * filename) +{ + mailmime_value_free(filename); +} + +void mailmime_creation_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_modification_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_read_date_parm_free(char * date) +{ + mailmime_quoted_date_time_free(date); +} + +void mailmime_quoted_date_time_free(char * date) +{ + mailimf_quoted_string_free(date); +} + +struct mailmime_section * mailmime_section_new(clist * sec_list) +{ + struct mailmime_section * section; + + section = malloc(sizeof(* section)); + if (section == NULL) + return NULL; + + section->sec_list = sec_list; + + return section; +} + +void mailmime_section_free(struct mailmime_section * section) +{ + clist_foreach(section->sec_list, (clist_func) free, NULL); + clist_free(section->sec_list); + free(section); +} + + + +struct mailmime_language * mailmime_language_new(clist * lg_list) +{ + struct mailmime_language * lang; + + lang = malloc(sizeof(* lang)); + if (lang == NULL) + return NULL; + + lang->lg_list = lg_list; + + return lang; +} + +void mailmime_language_free(struct mailmime_language * lang) +{ + clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL); + clist_free(lang->lg_list); + free(lang); +} + +void mailmime_decoded_part_free(char * part) +{ + mmap_string_unref(part); +} + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename) +{ + struct mailmime_data * mime_data; + + mime_data = malloc(sizeof(* mime_data)); + if (mime_data == NULL) + return NULL; + + mime_data->dt_type = dt_type; + mime_data->dt_encoding = dt_encoding; + mime_data->dt_encoded = dt_encoded; + switch (dt_type) { + case MAILMIME_DATA_TEXT: + mime_data->dt_data.dt_text.dt_data = dt_data; + mime_data->dt_data.dt_text.dt_length = dt_length; + break; + case MAILMIME_DATA_FILE: + mime_data->dt_data.dt_filename = dt_filename; + break; + } + + return mime_data; +} + +void mailmime_data_free(struct mailmime_data * mime_data) +{ + switch (mime_data->dt_type) { + case MAILMIME_DATA_FILE: + free(mime_data->dt_data.dt_filename); + break; + } + free(mime_data); +} diff --git a/kmicromail/libetpan/mime/mailmime_types.h b/kmicromail/libetpan/mime/mailmime_types.h new file mode 100644 index 0000000..3bb3b10 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types.h @@ -0,0 +1,440 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_TYPES_H + +#define MAILMIME_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +enum { + MAILMIME_COMPOSITE_TYPE_ERROR, + MAILMIME_COMPOSITE_TYPE_MESSAGE, + MAILMIME_COMPOSITE_TYPE_MULTIPART, + MAILMIME_COMPOSITE_TYPE_EXTENSION +}; + +struct mailmime_composite_type { + int ct_type; + char * ct_token; +}; + + +struct mailmime_content { + struct mailmime_type * ct_type; + char * ct_subtype; + clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ +}; + + +enum { + MAILMIME_DISCRETE_TYPE_ERROR, + MAILMIME_DISCRETE_TYPE_TEXT, + MAILMIME_DISCRETE_TYPE_IMAGE, + MAILMIME_DISCRETE_TYPE_AUDIO, + MAILMIME_DISCRETE_TYPE_VIDEO, + MAILMIME_DISCRETE_TYPE_APPLICATION, + MAILMIME_DISCRETE_TYPE_EXTENSION +}; + +struct mailmime_discrete_type { + int dt_type; + char * dt_extension; +}; + +enum { + MAILMIME_FIELD_NONE, + MAILMIME_FIELD_TYPE, + MAILMIME_FIELD_TRANSFER_ENCODING, + MAILMIME_FIELD_ID, + MAILMIME_FIELD_DESCRIPTION, + MAILMIME_FIELD_VERSION, + MAILMIME_FIELD_DISPOSITION, + MAILMIME_FIELD_LANGUAGE, +}; + +struct mailmime_field { + int fld_type; + union { + struct mailmime_content * fld_content; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + struct mailmime_language * fld_language; + } fld_data; +}; + +enum { + MAILMIME_MECHANISM_ERROR, + MAILMIME_MECHANISM_7BIT, + MAILMIME_MECHANISM_8BIT, + MAILMIME_MECHANISM_BINARY, + MAILMIME_MECHANISM_QUOTED_PRINTABLE, + MAILMIME_MECHANISM_BASE64, + MAILMIME_MECHANISM_TOKEN +}; + +struct mailmime_mechanism { + int enc_type; + char * enc_token; +}; + + +struct mailmime_fields { + clist * fld_list; /* list of (struct mailmime_field *) */ +}; + + +struct mailmime_parameter { + char * pa_name; + char * pa_value; +}; + +enum { + MAILMIME_TYPE_ERROR, + MAILMIME_TYPE_DISCRETE_TYPE, + MAILMIME_TYPE_COMPOSITE_TYPE +}; + +struct mailmime_type { + int tp_type; + union { + struct mailmime_discrete_type * tp_discrete_type; + struct mailmime_composite_type * tp_composite_type; + } tp_data; +}; + +void mailmime_attribute_free(char * attribute); + +struct mailmime_composite_type * +mailmime_composite_type_new(int ct_type, char * ct_token); + +void mailmime_composite_type_free(struct mailmime_composite_type * ct); + +struct mailmime_content * +mailmime_content_new(struct mailmime_type * ct_type, + char * ct_subtype, + clist * ct_parameters); + +void mailmime_content_free(struct mailmime_content * content); + +void mailmime_description_free(char * description); + +struct mailmime_discrete_type * +mailmime_discrete_type_new(int dt_type, char * dt_extension); + +void mailmime_discrete_type_free(struct mailmime_discrete_type * + discrete_type); + +void mailmime_encoding_free(struct mailmime_mechanism * encoding); + +void mailmime_extension_token_free(char * extension); + +void mailmime_id_free(char * id); + +struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); + +void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); + +struct mailmime_parameter * +mailmime_parameter_new(char * pa_name, char * pa_value); + +void mailmime_parameter_free(struct mailmime_parameter * parameter); + +void mailmime_subtype_free(char * subtype); + +void mailmime_token_free(char * token); + +struct mailmime_type * +mailmime_type_new(int tp_type, + struct mailmime_discrete_type * tp_discrete_type, + struct mailmime_composite_type * tp_composite_type); + +void mailmime_type_free(struct mailmime_type * type); + +void mailmime_value_free(char * value); + + + +struct mailmime_language { + clist * lg_list; /* atom (char *) */ +}; + +struct mailmime_language * mailmime_language_new(clist * lg_list); + +void mailmime_language_free(struct mailmime_language * lang); + + +/* +void mailmime_x_token_free(gchar * x_token); +*/ + +struct mailmime_field * +mailmime_field_new(int fld_type, + struct mailmime_content * fld_content, + struct mailmime_mechanism * fld_encoding, + char * fld_id, + char * fld_description, + uint32_t fld_version, + struct mailmime_disposition * fld_disposition, + struct mailmime_language * fld_language); + +void mailmime_field_free(struct mailmime_field * field); + +struct mailmime_fields * mailmime_fields_new(clist * fld_list); + +void mailmime_fields_free(struct mailmime_fields * fields); + + +struct mailmime_multipart_body { + clist * bd_list; +}; + +struct mailmime_multipart_body * +mailmime_multipart_body_new(clist * bd_list); + +void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); + + +enum { + MAILMIME_DATA_TEXT, + MAILMIME_DATA_FILE, +}; + +struct mailmime_data { + int dt_type; + int dt_encoding; + int dt_encoded; + union { + struct { + const char * dt_data; + size_t dt_length; + } dt_text; + char * dt_filename; + } dt_data; +}; + +struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, + int dt_encoded, const char * dt_data, size_t dt_length, + char * dt_filename); + +void mailmime_data_free(struct mailmime_data * mime_data); + + +enum { + MAILMIME_NONE, + MAILMIME_SINGLE, + MAILMIME_MULTIPLE, + MAILMIME_MESSAGE, +}; + +struct mailmime { + /* parent information */ + int mm_parent_type; + struct mailmime * mm_parent; + clistiter * mm_multipart_pos; + + int mm_type; + const char * mm_mime_start; + size_t mm_length; + + struct mailmime_fields * mm_mime_fields; + struct mailmime_content * mm_content_type; + + struct mailmime_data * mm_body; + union { + /* single part */ + struct mailmime_data * mm_single; /* XXX - was body */ + + /* multi-part */ + struct { + struct mailmime_data * mm_preamble; + struct mailmime_data * mm_epilogue; + clist * mm_mp_list; + } mm_multipart; + + /* message */ + struct { + struct mailimf_fields * mm_fields; + struct mailmime * mm_msg_mime; + } mm_message; + + } mm_data; +}; + +struct mailmime * mailmime_new(int mm_type, + const char * mm_mime_start, size_t mm_length, + struct mailmime_fields * mm_mime_fields, + struct mailmime_content * mm_content_type, + struct mailmime_data * mm_body, + struct mailmime_data * mm_preamble, + struct mailmime_data * mm_epilogue, + clist * mm_mp_list, + struct mailimf_fields * mm_fields, + struct mailmime * mm_msg_mime); + +void mailmime_free(struct mailmime * mime); + +struct mailmime_encoded_word { + char * wd_charset; + char * wd_text; +}; + +struct mailmime_encoded_word * +mailmime_encoded_word_new(char * wd_charset, char * wd_text); + +void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); + +void mailmime_charset_free(char * charset); + +void mailmime_encoded_text_free(char * text); + + +struct mailmime_disposition { + struct mailmime_disposition_type * dsp_type; + clist * dsp_parms; /* struct mailmime_disposition_parm */ +}; + + +enum { + MAILMIME_DISPOSITION_TYPE_ERROR, + MAILMIME_DISPOSITION_TYPE_INLINE, + MAILMIME_DISPOSITION_TYPE_ATTACHMENT, + MAILMIME_DISPOSITION_TYPE_EXTENSION +}; + +struct mailmime_disposition_type { + int dsp_type; + char * dsp_extension; +}; + + +enum { + MAILMIME_DISPOSITION_PARM_FILENAME, + MAILMIME_DISPOSITION_PARM_CREATION_DATE, + MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, + MAILMIME_DISPOSITION_PARM_READ_DATE, + MAILMIME_DISPOSITION_PARM_SIZE, + MAILMIME_DISPOSITION_PARM_PARAMETER +}; + +struct mailmime_disposition_parm { + int pa_type; + union { + char * pa_filename; + char * pa_creation_date; + char * pa_modification_date; + char * pa_read_date; + size_t pa_size; + struct mailmime_parameter * pa_parameter; + } pa_data; +}; + +struct mailmime_disposition * +mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, + clist * dsp_parms); + +void mailmime_disposition_free(struct mailmime_disposition * dsp); + +struct mailmime_disposition_type * +mailmime_disposition_type_new(int dt_type, char * dt_extension); + +void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); + +struct mailmime_disposition_parm * +mailmime_disposition_parm_new(int pa_type, + char * pa_filename, + char * pa_creation_date, + char * pa_modification_date, + char * pa_read_date, + size_t pa_size, + struct mailmime_parameter * pa_parameter); + +void mailmime_disposition_parm_free(struct mailmime_disposition_parm * + dsp_parm); + +void mailmime_filename_parm_free(char * filename); + +void mailmime_creation_date_parm_free(char * date); + +void mailmime_modification_date_parm_free(char * date); + +void mailmime_read_date_parm_free(char * date); + +void mailmime_quoted_date_time_free(char * date); + +struct mailmime_section { + clist * sec_list; /* list of (uint32 *) */ +}; + +struct mailmime_section * mailmime_section_new(clist * list); + +void mailmime_section_free(struct mailmime_section * section); + + +void mailmime_decoded_part_free(char * part); + +struct mailmime_single_fields { + struct mailmime_content * fld_content; + char * fld_content_charset; + char * fld_content_boundary; + char * fld_content_name; + struct mailmime_mechanism * fld_encoding; + char * fld_id; + char * fld_description; + uint32_t fld_version; + struct mailmime_disposition * fld_disposition; + char * fld_disposition_filename; + char * fld_disposition_creation_date; + char * fld_disposition_modification_date; + char * fld_disposition_read_date; + size_t fld_disposition_size; + struct mailmime_language * fld_language; +}; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kmicromail/libetpan/mime/mailmime_types_helper.c b/kmicromail/libetpan/mime/mailmime_types_helper.c new file mode 100644 index 0000000..83fa1d4 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types_helper.c @@ -0,0 +1,1385 @@ +/* + * 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_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); +} + diff --git a/kmicromail/libetpan/mime/mailmime_types_helper.h b/kmicromail/libetpan/mime/mailmime_types_helper.h new file mode 100644 index 0000000..608acca --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types_helper.h @@ -0,0 +1,165 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_TYPES_HELPER_H + +#define MAILMIME_TYPES_HELPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +int mailmime_transfer_encoding_get(struct mailmime_fields * fields); + +struct mailmime_disposition * +mailmime_disposition_new_filename(int type, char * filename); + +struct mailmime_fields * mailmime_fields_new_empty(void); + +int mailmime_fields_add(struct mailmime_fields * fields, + struct mailmime_field * field); + +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_fields * +mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, + char * id, + char * description, + struct mailmime_disposition * disposition, + struct mailmime_language * language); + +struct mailmime_content * mailmime_get_content_message(void); +struct mailmime_content * mailmime_get_content_text(void); +/* struct mailmime_content * mailmime_get_content(char * mime_type); */ + +#define mailmime_get_content mailmime_content_new_with_str + +struct mailmime_data * +mailmime_data_new_data(int encoding, int encoded, + const char * data, size_t length); + +struct mailmime_data * +mailmime_data_new_file(int encoding, int encoded, + char * filename); + +#if 0 +struct mailmime * +mailmime_new_message_file(char * filename); + +struct mailmime * +mailmime_new_message_text(char * data_str, size_t length); +#endif + +struct mailmime * +mailmime_new_message_data(struct mailmime * msg_mime); + +struct mailmime * +mailmime_new_empty(struct mailmime_content * content, + struct mailmime_fields * mime_fields); + +int +mailmime_new_with_content(const char * content_type, + struct mailmime_fields * mime_fields, + struct mailmime ** result); + +int mailmime_set_preamble_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_epilogue_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_preamble_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_epilogue_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_set_body_file(struct mailmime * build_info, + char * filename); + +int mailmime_set_body_text(struct mailmime * build_info, + char * data_str, size_t length); + +int mailmime_add_part(struct mailmime * build_info, + struct mailmime * part); + +void mailmime_remove_part(struct mailmime * mime); + +void mailmime_set_imf_fields(struct mailmime * build_info, + struct mailimf_fields * fields); + + +struct mailmime_disposition * +mailmime_disposition_new_with_data(int type, + char * filename, char * creation_date, char * modification_date, + char * read_date, size_t size); + +void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, + struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +struct mailmime_single_fields * +mailmime_single_fields_new(struct mailmime_fields * fld_fields, + struct mailmime_content * fld_content); + +void mailmime_single_fields_free(struct mailmime_single_fields * + single_fields); + +int mailmime_smart_add_part(struct mailmime * mime, + struct mailmime * mime_sub); + +int mailmime_smart_remove_part(struct mailmime * mime); + +struct mailmime_content * mailmime_content_new_with_str(const char * str); + +struct mailmime_fields * mailmime_fields_new_encoding(int type); + +struct mailmime * mailmime_multiple_new(const char * type); + +struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, + char * filename, int encoding_type); + +#ifdef __cplusplus +} +#endif + +#endif 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; +} diff --git a/kmicromail/libetpan/mime/mailmime_write.h b/kmicromail/libetpan/mime/mailmime_write.h new file mode 100644 index 0000000..96f8777 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_write.h @@ -0,0 +1,73 @@ +/* + * 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$ + */ + +#ifndef MAILMIME_WRITE_H + +#define MAILMIME_WRITE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int mailmime_fields_write(FILE * f, int * col, + struct mailmime_fields * fields); + +int mailmime_content_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_content_type_write(FILE * f, int * col, + struct mailmime_content * content); + +int mailmime_write(FILE * f, int * col, + struct mailmime * build_info); + +int mailmime_quoted_printable_write(FILE * f, int * col, int istext, + const char * text, size_t size); + +int mailmime_base64_write(FILE * f, int * col, + const char * text, size_t size); + +int mailmime_data_write(FILE * f, int * col, + struct mailmime_data * data, + int istext); + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v0.9.0.2