author | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
commit | e3b89230f065c48c84b48c88edb6eb088374c487 (patch) (side-by-side diff) | |
tree | 162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/mime/mailmime_decode.c | |
parent | 2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff) | |
download | kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2 |
Initial revision
Diffstat (limited to 'kmicromail/libetpan/mime/mailmime_decode.c') (more/less context) (ignore whitespace changes)
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_decode.c | 533 |
1 files changed, 533 insertions, 0 deletions
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 <ctype.h> +#include <unistd.h> +#include <sys/mman.h> +#include <string.h> +#include <stdlib.h> + +#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); +} |