author | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2005-03-18 20:17:03 (UTC) |
commit | 9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf (patch) (side-by-side diff) | |
tree | 2528e6cc740225ca0f47d5ac8ff70f7d3bb10621 /libetpan/src/engine/mailprivacy_tools.c | |
parent | 9319998f20f03dcc217fbb39656755dc65226276 (diff) | |
download | kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.zip kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.gz kdepimpi-9e549686b23b6dffdcbd09c9b10dc2cb795fbcdf.tar.bz2 |
Initial revision
Diffstat (limited to 'libetpan/src/engine/mailprivacy_tools.c') (more/less context) (show whitespace changes)
-rw-r--r-- | libetpan/src/engine/mailprivacy_tools.c | 1283 |
1 files changed, 1283 insertions, 0 deletions
diff --git a/libetpan/src/engine/mailprivacy_tools.c b/libetpan/src/engine/mailprivacy_tools.c new file mode 100644 index 0000000..cae2ef8 --- a/dev/null +++ b/libetpan/src/engine/mailprivacy_tools.c @@ -0,0 +1,1283 @@ +/* + * libEtPan! -- a mail library + * + * Copyright (C) 2001, 2005 - DINH Viet Hoa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the libEtPan! project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * $Id$ + */ + +#include "mailprivacy_tools.h" + +#include <stdlib.h> +#include <string.h> +#include <libgen.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <libetpan/mailmessage.h> +#include <ctype.h> +#include "mailprivacy.h" +#include <libetpan/libetpan-config.h> +#include <libetpan/data_message_driver.h> + +void mailprivacy_mime_clear(struct mailmime * mime) +{ + struct mailmime_data * data; + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + data = mime->mm_data.mm_single; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + break; + + case MAILMIME_MULTIPLE: + data = mime->mm_data.mm_multipart.mm_preamble; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + data = mime->mm_data.mm_multipart.mm_epilogue; + if (data != NULL) { + if (data->dt_type == MAILMIME_DATA_FILE) + unlink(data->dt_data.dt_filename); + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * submime; + + submime = clist_content(cur); + + mailprivacy_mime_clear(submime); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + mailprivacy_mime_clear(mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + +static FILE * get_tmp_file(char * filename) +{ + int fd; + mode_t old_mask; + FILE * f; + + old_mask = umask(0077); + fd = mkstemp(filename); + umask(old_mask); + if (fd == -1) + return NULL; + + f = fdopen(fd, "r+"); + if (f == NULL) { + close(fd); + unlink(filename); + } + + return f; +} + +FILE * mailprivacy_get_tmp_file(struct mailprivacy * privacy, + char * filename, size_t size) +{ + snprintf(filename, size, "%s/libetpan-privacy-XXXXXX", privacy->tmp_dir); + return get_tmp_file(filename); +} + + +static char * dup_file(struct mailprivacy * privacy, + char * source_filename) +{ + char filename[PATH_MAX]; + FILE * dest_f; + int r; + struct stat stat_info; + char * dest_filename; + char * mapping; + size_t written; + int fd; + + dest_f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename)); + if (dest_f == NULL) + goto err; + + dest_filename = strdup(filename); + if (dest_filename == NULL) + goto close_dest; + + fd = open(source_filename, O_RDONLY); + if (fd < 0) + goto free_dest; + + r = fstat(fd, &stat_info); + if (r < 0) + goto close_src; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == MAP_FAILED) + goto close_src; + + written = fwrite(mapping, 1, stat_info.st_size, dest_f); + if (written != (size_t) stat_info.st_size) + goto unmap; + + munmap(mapping, stat_info.st_size); + close(fd); + fclose(dest_f); + + return dest_filename; + + unmap: + munmap(mapping, stat_info.st_size); + close_src: + close(fd); + free_dest: + free(dest_filename); + close_dest: + fclose(dest_f); + err: + return NULL; +} + + +/* + mime_data_replace() + + write a mime part to a file and change the reference of mailmime_data + to the file. +*/ + +static int mime_data_replace(struct mailprivacy * privacy, + int encoding_type, + struct mailmime_data * data) +{ + char filename[PATH_MAX]; + FILE * f; + size_t written; + char * dup_filename; + int res; + int r; + int decoded; + + if (data->dt_type != MAILMIME_DATA_TEXT) { + res = MAIL_NO_ERROR; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, sizeof(filename)); + if (f == NULL) { + res = MAIL_ERROR_FILE; + goto err; + } + + decoded = 0; + if (encoding_type != -1) { + char * content; + size_t content_len; + size_t cur_token; + + cur_token = 0; + r = mailmime_part_parse(data->dt_data.dt_text.dt_data, + data->dt_data.dt_text.dt_length, + &cur_token, encoding_type, &content, &content_len); + + if (r == MAILIMF_NO_ERROR) { + /* write decoded */ + written = fwrite(content, 1, content_len, f); + if (written != content_len) { + fclose(f); + unlink(filename); + res = MAIL_ERROR_FILE; + goto err; + } + mmap_string_unref(content); + + decoded = 1; + data->dt_encoded = 0; + } + } + + if (!decoded) { + written = fwrite(data->dt_data.dt_text.dt_data, 1, + data->dt_data.dt_text.dt_length, f); + if (written != data->dt_data.dt_text.dt_length) { + fclose(f); + unlink(filename); + res = MAIL_ERROR_FILE; + goto err; + } + } + + fclose(f); + + dup_filename = strdup(filename); + if (dup_filename == NULL) { + unlink(filename); + res = MAIL_ERROR_MEMORY; + goto err; + } + + data->dt_type = MAILMIME_DATA_FILE; + data->dt_data.dt_filename = dup_filename; + + return MAIL_NO_ERROR; + + err: + return res; +} + + +/* + recursive_replace_single_parts() + + write all parts of the given mime part to file. +*/ + +static int recursive_replace_single_parts(struct mailprivacy * privacy, + struct mailmime * mime) +{ + int r; + int res; + clistiter * cur; + + mime->mm_mime_start = NULL; + + switch(mime->mm_type) { + case MAILMIME_SINGLE: + if (mime->mm_data.mm_single != NULL) { + int encoding_type; + struct mailmime_single_fields single_fields; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + + if (single_fields.fld_encoding != NULL) + encoding_type = single_fields.fld_encoding->enc_type; + else + encoding_type = -1; + + r = mime_data_replace(privacy, encoding_type, mime->mm_data.mm_single); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + break; + + case MAILMIME_MULTIPLE: + if (mime->mm_data.mm_multipart.mm_preamble != NULL) { + r = mime_data_replace(privacy, -1, + mime->mm_data.mm_multipart.mm_preamble); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + if (mime->mm_data.mm_multipart.mm_epilogue != NULL) { + r = mime_data_replace(privacy, -1, + mime->mm_data.mm_multipart.mm_epilogue); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + r = recursive_replace_single_parts(privacy, child); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + r = recursive_replace_single_parts(privacy, + mime->mm_data.mm_message.mm_msg_mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto err; + } + } + break; + } + + return MAIL_NO_ERROR; + + err: + return res; +} + +/* + mailprivacy_get_mime() + + parse the message in MIME structure, + all single MIME parts are stored in files. + + privacy can be set to NULL to disable privacy check. +*/ + +int mailprivacy_get_mime(struct mailprivacy * privacy, + int check_privacy, + char * content, size_t content_len, + struct mailmime ** result_mime) +{ + struct mailmime * mime; + mailmessage * msg; + int r; + int res; + +#if 0 + int check_privacy; + + check_privacy = (privacy != NULL); +#endif + + /* + use message data driver, get bodystructure and + convert all the data part in MAILMIME_SINGLE to files. + */ + + msg = data_message_init(content, content_len); + if (msg == NULL) { + res = MAIL_ERROR_MEMORY; + goto err; + } + +#if 0 + if (msg->mime == NULL) { + if (check_privacy) { + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + } + else { + /* + don't use etpan_msg_get_bodystructure because it is not useful + and to avoid loops due to security part + */ + r = mailmessage_get_bodystructure(msg, &mime); + } + } + else { + mime = msg->mime; + } +#endif + + if (check_privacy) + r = mailprivacy_msg_get_bodystructure(privacy, msg, &mime); + else + r = mailmessage_get_bodystructure(msg, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto free_msg; + } + + /* + should be done so that the MIME structure need not to be unregistered. + */ + mailprivacy_recursive_unregister_mime(privacy, mime); + + r = recursive_replace_single_parts(privacy, mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto clear_mime; + } + + data_message_detach_mime(msg); +#if 0 + if (check_privacy) + mailprivacy_msg_flush(privacy, msg); + else + mailmessage_flush(msg); +#endif + mailprivacy_msg_flush(privacy, msg); + mailmessage_free(msg); + + * result_mime = mime; + + return MAIL_NO_ERROR; + + clear_mime: + mailprivacy_mime_clear(mime); + mailprivacy_msg_flush(privacy, msg); + free_msg: + mailmessage_free(msg); + err: + return res; +} + +#ifndef LIBETPAN_SYSTEM_BASENAME +static char * libetpan_basename(char * filename) +{ + char * next; + char * p; + + p = filename; + next = strchr(p, '/'); + + while (next != NULL) { + p = next; + next = strchr(p + 1, '/'); + } + + if (p == filename) + return filename; + else + return p + 1; +} +#else +#define libetpan_basename(a) basename(a) +#endif + +struct mailmime * +mailprivacy_new_file_part(struct mailprivacy * privacy, + char * filename, + char * default_content_type, int default_encoding) +{ + char basename_buf[PATH_MAX]; + char * name; + struct mailmime_mechanism * encoding; + struct mailmime_content * content; + struct mailmime * mime; + int r; + char * dup_filename; + struct mailmime_fields * mime_fields; + int encoding_type; + char * content_type_str; + int do_encoding; + + if (filename != NULL) { + strncpy(basename_buf, filename, PATH_MAX); + name = libetpan_basename(basename_buf); + } + else { + name = NULL; + } + + encoding = NULL; + + /* default content-type */ + if (default_content_type == NULL) + content_type_str = "application/octet-stream"; + else + content_type_str = default_content_type; + + content = mailmime_content_new_with_str(content_type_str); + if (content == NULL) { + goto free_content; + } + + do_encoding = 1; + if (content->ct_type->tp_type == MAILMIME_TYPE_COMPOSITE_TYPE) { + struct mailmime_composite_type * composite; + + composite = content->ct_type->tp_data.tp_composite_type; + + switch (composite->ct_type) { + case MAILMIME_COMPOSITE_TYPE_MESSAGE: + if (strcasecmp(content->ct_subtype, "rfc822") == 0) + do_encoding = 0; + break; + + case MAILMIME_COMPOSITE_TYPE_MULTIPART: + do_encoding = 0; + break; + } + } + + if (do_encoding) { + if (default_encoding == -1) + encoding_type = MAILMIME_MECHANISM_BASE64; + else + encoding_type = default_encoding; + + /* default Content-Transfer-Encoding */ + encoding = mailmime_mechanism_new(encoding_type, NULL); + if (encoding == NULL) { + goto free_content; + } + } + + mime_fields = mailmime_fields_new_with_data(encoding, + NULL, NULL, NULL, NULL); + if (mime_fields == NULL) { + goto free_content; + } + + mime = mailmime_new_empty(content, mime_fields); + if (mime == NULL) { + goto free_mime_fields; + } + + if ((filename != NULL) && (mime->mm_type == MAILMIME_SINGLE)) { + /* + duplicates the file so that the file can be deleted when + the MIME part is done + */ + dup_filename = dup_file(privacy, filename); + if (dup_filename == NULL) { + goto free_mime; + } + + r = mailmime_set_body_file(mime, dup_filename); + if (r != MAILIMF_NO_ERROR) { + free(dup_filename); + goto free_mime; + } + } + + return mime; + + free_mime: + mailmime_free(mime); + goto err; + free_mime_fields: + mailmime_fields_free(mime_fields); + mailmime_content_free(content); + goto err; + free_content: + if (encoding != NULL) + mailmime_mechanism_free(encoding); + if (content != NULL) + mailmime_content_free(content); + err: + return NULL; +} + + +int mailmime_substitute(struct mailmime * old_mime, + struct mailmime * new_mime) +{ + struct mailmime * parent; + + parent = old_mime->mm_parent; + if (parent == NULL) + return MAIL_ERROR_INVAL; + + if (old_mime->mm_parent_type == MAILMIME_MESSAGE) + parent->mm_data.mm_message.mm_msg_mime = new_mime; + else /* MAILMIME_MULTIPLE */ + old_mime->mm_multipart_pos->data = new_mime; + new_mime->mm_parent = parent; + new_mime->mm_parent_type = old_mime->mm_parent_type; + + /* detach old_mime */ + old_mime->mm_parent = NULL; + old_mime->mm_parent_type = MAILMIME_NONE; + + return MAIL_NO_ERROR; +} + + + +/* write mime headers and body to a file, CR LF fixed */ + +int mailprivacy_fetch_mime_body_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + FILE * f; + char * content; + size_t content_len; + int col; + + if (mime->mm_parent_type == MAILMIME_NONE) { + res = MAIL_ERROR_INVAL; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) { + res = MAIL_ERROR_FETCH; + goto err; + } + + r = mailprivacy_msg_fetch_section_mime(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto close; + } + + col = 0; + r = mailimf_string_write(f, &col, content, content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto close; + } + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto close; + } + + r = mailimf_string_write(f, &col, content, content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = r; + goto close; + } + + fclose(f); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + err: + return res; +} + + +int mailprivacy_get_part_from_file(struct mailprivacy * privacy, + int check_security, char * filename, + struct mailmime ** result_mime) +{ + int fd; + struct mailmime * mime; + int r; + struct stat stat_info; + int res; + char * mapping; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + res = MAIL_ERROR_FILE; + goto err; + } + + r = fstat(fd, &stat_info); + if (r < 0) { + res = MAIL_ERROR_FILE; + goto close; + } + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == MAP_FAILED) { + res = MAIL_ERROR_FILE; + goto close; + } + + /* check recursive parts if privacy is set */ + r = mailprivacy_get_mime(privacy, check_security, + mapping, stat_info.st_size, &mime); + if (r != MAIL_NO_ERROR) { + res = r; + goto unmap; + } + + if (mime->mm_type == MAILMIME_MESSAGE) { + struct mailmime * submime; + + submime = mime->mm_data.mm_message.mm_msg_mime; + if (mime->mm_data.mm_message.mm_msg_mime != NULL) { + mailmime_remove_part(submime); + mailmime_free(mime); + + mime = submime; + } + } + + munmap(mapping, stat_info.st_size); + + close(fd); + + * result_mime = mime; + + return MAIL_NO_ERROR; + + unmap: + munmap(mapping, stat_info.st_size); + close: + close(fd); + err: + return res; +} + +int mail_quote_filename(char * result, size_t size, char * path) +{ + char * p; + char * result_p; + size_t remaining; + + result_p = result; + remaining = size; + + for(p = path ; * p != '\0' ; p ++) { + + if (isalpha(* p) || isdigit(* p) || (* p == '/')) { + if (remaining > 0) { + * result_p = * p; + result_p ++; + remaining --; + } + else { + result[size - 1] = '\0'; + return -1; + } + } + else { + if (remaining >= 2) { + * result_p = '\\'; + result_p ++; + * result_p = * p; + result_p ++; + remaining -= 2; + } + else { + result[size - 1] = '\0'; + return -1; + } + } + } + if (remaining > 0) { + * result_p = '\0'; + } + else { + result[size - 1] = '\0'; + return -1; + } + + return 0; +} + + +static void prepare_mime_single(struct mailmime * mime) +{ + struct mailmime_single_fields single_fields; + int encoding; + int r; + + if (mime->mm_mime_fields != NULL) { + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) { + encoding = single_fields.fld_encoding->enc_type; + switch (encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + single_fields.fld_encoding->enc_type = + MAILMIME_MECHANISM_QUOTED_PRINTABLE; + break; + } + } + else { + struct mailmime_mechanism * mechanism; + struct mailmime_field * field; + + mechanism = + mailmime_mechanism_new(MAILMIME_MECHANISM_QUOTED_PRINTABLE, NULL); + if (mechanism == NULL) + return; + + field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, + NULL, mechanism, NULL, NULL, 0, NULL, NULL); + if (field == NULL) { + mailmime_mechanism_free(mechanism); + return; + } + + r = clist_append(mime->mm_mime_fields->fld_list, field); + if (r < 0) { + mailmime_field_free(field); + return; + } + } + } + + if (mime->mm_type == MAILMIME_SINGLE) { + switch (mime->mm_data.mm_single->dt_encoding) { + case MAILMIME_MECHANISM_8BIT: + case MAILMIME_MECHANISM_7BIT: + case MAILMIME_MECHANISM_BINARY: + mime->mm_data.mm_single->dt_encoding = + MAILMIME_MECHANISM_QUOTED_PRINTABLE; + mime->mm_data.mm_single->dt_encoded = 0; + break; + } + } +} + +/* + mailprivacy_prepare_mime() + + we assume we built ourself the message. +*/ + +void mailprivacy_prepare_mime(struct mailmime * mime) +{ + clistiter * cur; + + switch (mime->mm_type) { + case MAILMIME_SINGLE: + if (mime->mm_data.mm_single != NULL) { + prepare_mime_single(mime); + } + break; + + case MAILMIME_MULTIPLE: + for(cur = clist_begin(mime->mm_data.mm_multipart.mm_mp_list) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime * child; + + child = clist_content(cur); + + mailprivacy_prepare_mime(child); + } + break; + + case MAILMIME_MESSAGE: + if (mime->mm_data.mm_message.mm_msg_mime) { + mailprivacy_prepare_mime(mime->mm_data.mm_message.mm_msg_mime); + } + break; + } +} + + +char * mailprivacy_dup_imf_file(struct mailprivacy * privacy, + char * source_filename) +{ + char filename[PATH_MAX]; + FILE * dest_f; + int r; + struct stat stat_info; + char * dest_filename; + char * mapping; + int fd; + int col; + + dest_f = mailprivacy_get_tmp_file(privacy, + filename, sizeof(filename)); + if (dest_f == NULL) + goto err; + + dest_filename = strdup(filename); + if (dest_filename == NULL) + goto close_dest; + + fd = open(source_filename, O_RDONLY); + if (fd < 0) + goto free_dest; + + r = fstat(fd, &stat_info); + if (r < 0) + goto close_src; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == MAP_FAILED) + goto close_src; + + col = 0; + r = mailimf_string_write(dest_f, &col, mapping, stat_info.st_size); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + munmap(mapping, stat_info.st_size); + close(fd); + fclose(dest_f); + + return dest_filename; + + unmap: + munmap(mapping, stat_info.st_size); + close_src: + close(fd); + free_dest: + free(dest_filename); + close_dest: + fclose(dest_f); + err: + return NULL; +} + +/* TODO : better function to duplicate mime fields, currenly such inelegant */ + +struct mailmime_fields * +mailprivacy_mime_fields_dup(struct mailprivacy * privacy, + struct mailmime_fields * mime_fields) +{ + FILE * f; + char tmp_file[PATH_MAX]; + int col; + int r; + struct mailmime_fields * dup_mime_fields; + int fd; + char * mapping; + struct stat stat_info; + struct mailimf_fields * fields; + size_t cur_token; + + f = mailprivacy_get_tmp_file(privacy, tmp_file, sizeof(tmp_file)); + if (f == NULL) + goto err; + + col = 0; + r = mailmime_fields_write(f, &col, mime_fields); + if (r != MAILIMF_NO_ERROR) + goto unlink; + + fflush(f); + + fd = fileno(f); + if (fd == -1) + goto unlink; + + r = fstat(fd, &stat_info); + if (r < 0) + goto unlink; + + mapping = mmap(NULL, stat_info.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (mapping == MAP_FAILED) + goto unlink; + + cur_token = 0; + r = mailimf_optional_fields_parse(mapping, stat_info.st_size, + &cur_token, &fields); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + r = mailmime_fields_parse(fields, &dup_mime_fields); + mailimf_fields_free(fields); + if (r != MAILIMF_NO_ERROR) + goto unmap; + + munmap(mapping, stat_info.st_size); + fclose(f); + unlink(tmp_file); + + return dup_mime_fields; + + unmap: + munmap(mapping, stat_info.st_size); + unlink: + fclose(f); + unlink(tmp_file); + err: + return NULL; +} + + + +struct mailmime_parameter * +mailmime_parameter_dup(struct mailmime_parameter * param) +{ + char * name; + char * value; + struct mailmime_parameter * dup_param; + + name = strdup(param->pa_name); + if (name == NULL) + goto err; + + value = strdup(param->pa_value); + if (value == NULL) + goto free_name; + + dup_param = mailmime_parameter_new(name, value); + if (dup_param == NULL) + goto free_value; + + return dup_param; + + free_value: + free(value); + free_name: + free(name); + err: + return NULL; +} + +struct mailmime_composite_type * +mailmime_composite_type_dup(struct mailmime_composite_type * composite_type) +{ + struct mailmime_composite_type * dup_composite; + char * token; + + token = NULL; + if (composite_type->ct_token != NULL) { + token = strdup(composite_type->ct_token); + if (token == NULL) + goto err; + } + + dup_composite = mailmime_composite_type_new(composite_type->ct_type, token); + if (dup_composite == NULL) + goto free_token; + + return dup_composite; + + free_token: + if (token != NULL) + free(token); + err: + return NULL; +} + +struct mailmime_discrete_type * +mailmime_discrete_type_dup(struct mailmime_discrete_type * discrete_type) +{ + struct mailmime_discrete_type * dup_discrete; + char * extension; + + extension = NULL; + if (discrete_type->dt_extension != NULL) { + extension = strdup(discrete_type->dt_extension); + if (extension == NULL) + goto err; + } + + dup_discrete = mailmime_discrete_type_new(discrete_type->dt_type, extension); + if (dup_discrete == NULL) + goto free_extension; + + return dup_discrete; + + free_extension: + if (extension != NULL) + free(extension); + err: + return NULL; +} + +struct mailmime_type * mailmime_type_dup(struct mailmime_type * type) +{ + struct mailmime_type * dup_type; + struct mailmime_discrete_type * discrete_type; + struct mailmime_composite_type * composite_type; + + discrete_type = NULL; + composite_type = NULL; + switch (type->tp_type) { + case MAILMIME_TYPE_DISCRETE_TYPE: + discrete_type = + mailmime_discrete_type_dup(type->tp_data.tp_discrete_type); + if (discrete_type == NULL) + goto err; + break; + + composite_type = + mailmime_composite_type_dup(type->tp_data.tp_composite_type); + if (composite_type == NULL) + goto free_discrete; + } + + dup_type = mailmime_type_new(type->tp_type, discrete_type, composite_type); + if (dup_type == NULL) + goto free_composite; + + return dup_type; + + free_composite: + if (composite_type != NULL) + mailmime_composite_type_free(composite_type); + free_discrete: + if (discrete_type != NULL) + mailmime_discrete_type_free(discrete_type); + err: + return NULL; +} + +struct mailmime_content * +mailmime_content_dup(struct mailmime_content * content) +{ + clist * list; + struct mailmime_type * type; + int r; + struct mailmime_content * dup_content; + char * subtype; + + type = mailmime_type_dup(content->ct_type); + if (type == NULL) + goto err; + + subtype = strdup(content->ct_subtype); + if (subtype == NULL) + goto free_type; + + list = clist_new(); + if (list == NULL) + goto free_subtype; + + if (content->ct_parameters != NULL) { + clistiter * cur; + + for(cur = clist_begin(content->ct_parameters) ; + cur != NULL ; cur = clist_next(cur)) { + struct mailmime_parameter * param; + + param = mailmime_parameter_dup(clist_content(cur)); + if (param == NULL) + goto free_list; + + r = clist_append(list, param); + if (r < 0) { + mailmime_parameter_free(param); + goto free_list; + } + } + } + + dup_content = mailmime_content_new(type, subtype, list); + if (dup_content == NULL) + goto free_list; + + return dup_content; + + free_list: + clist_foreach(list, (clist_func) mailmime_parameter_free, NULL); + free_subtype: + free(subtype); + free_type: + mailmime_type_free(type); + err: + return NULL; +} + + +struct mailmime_parameter * +mailmime_param_new_with_data(char * name, char * value) +{ + char * param_name; + char * param_value; + struct mailmime_parameter * param; + + param_name = strdup(name); + if (param_name == NULL) + goto err; + + param_value = strdup(value); + if (param_value == NULL) + goto free_name; + + param = mailmime_parameter_new(param_name, param_value); + if (param == NULL) + goto free_value; + + return param; + + free_value: + free(param_value); + free_name: + free(param_name); + err: + return NULL; +} + + +int mailprivacy_fetch_decoded_to_file(struct mailprivacy * privacy, + char * filename, size_t size, + mailmessage * msg, struct mailmime * mime) +{ + int r; + int res; + FILE * f; + char * content; + size_t content_len; + size_t written; + struct mailmime_single_fields single_fields; + int encoding; + size_t cur_token; + char * parsed_content; + size_t parsed_content_len; + + mailmime_single_fields_init(&single_fields, mime->mm_mime_fields, + mime->mm_content_type); + if (single_fields.fld_encoding != NULL) + encoding = single_fields.fld_encoding->enc_type; + else + encoding = MAILMIME_MECHANISM_8BIT; + + r = mailprivacy_msg_fetch_section(privacy, msg, mime, + &content, &content_len); + if (r != MAIL_NO_ERROR) { + res = MAIL_ERROR_FETCH; + goto err; + } + + cur_token = 0; + r = mailmime_part_parse(content, content_len, &cur_token, + encoding, &parsed_content, &parsed_content_len); + mailprivacy_msg_fetch_result_free(privacy, msg, content); + if (r != MAILIMF_NO_ERROR) { + res = MAIL_ERROR_PARSE; + goto err; + } + + f = mailprivacy_get_tmp_file(privacy, filename, size); + if (f == NULL) { + res = MAIL_ERROR_FETCH; + goto free_fetch; + } + written = fwrite(parsed_content, 1, parsed_content_len, f); + if (written != parsed_content_len) { + res = MAIL_ERROR_FILE; + goto close; + } + fclose(f); + + mmap_string_unref(parsed_content); + + return MAIL_NO_ERROR; + + close: + fclose(f); + unlink(filename); + free_fetch: + mmap_string_unref(parsed_content); + err: + return res; +} + |