@ -71,6 +71,9 @@
static int mailmime_charset_parse ( const char * message , size_t length ,
size_t * indx , char * * charset ) ;
static int detect_CRCR ( const char * message , size_t length ,
size_t * indx ) ;
enum {
MAILMIME_ENCODING_B ,
MAILMIME_ENCODING_Q
@ -124,12 +127,16 @@ int mailmime_encoded_phrase_parse(const char * default_fromcode,
type = TYPE_ERROR ; /* XXX - removes a gcc warning */
// Start parsing
while ( 1 ) {
int has_fwd ;
word = NULL ;
// Try to parse this part of the message as mime-encoded
r = mailmime_encoded_word_parse ( message , length , & cur_token , & word , & has_fwd , & missing_closing_quote ) ;
if ( r = = MAILIMF_NO_ERROR ) {
// Either it was mime-encoded or there was no error.
if ( ( ! first ) & & has_fwd ) {
if ( type ! = TYPE_ENCODED_WORD ) {
if ( mmap_string_append_c ( gphrase , ' ' ) = = NULL ) {
@ -171,6 +178,7 @@ int mailmime_encoded_phrase_parse(const char * default_fromcode,
}
if ( wordutf8 ! = NULL ) {
// append the word (converted to the proper charset)
if ( mmap_string_append ( gphrase , wordutf8 ) = = NULL ) {
mailmime_encoded_word_free ( word ) ;
free ( wordutf8 ) ;
@ -183,17 +191,38 @@ int mailmime_encoded_phrase_parse(const char * default_fromcode,
first = FALSE ;
}
else if ( r = = MAILIMF_ERROR_PARSE ) {
// Wasn't mime-encoded
/* do nothing */
}
else {
// Some error condition we didn't expect
res = r ;
goto free ;
}
if ( r = = MAILIMF_ERROR_PARSE ) {
// Not mime-encoded, so parse as if it isn't
char * raw_word ;
raw_word = NULL ;
// Check for special case of word=^CRCR.
// We need to be sure we advanced the cur_token
// past it. Usually with an empty string.
if ( first ) {
r = detect_CRCR ( message , length , & cur_token ) ;
if ( r = = MAILIMF_NO_ERROR ) {
// We've advanced the token and pretend
// the first CR isn't there. Let the algorithm
// take care of the legit CRLF.
if ( mmap_string_append_c ( gphrase , ' ' ) = = NULL ) {
res = MAILIMF_ERROR_MEMORY ;
goto free ;
}
first = FALSE ;
break ;
}
}
r = mailmime_non_encoded_word_parse ( message , length ,
& cur_token , & raw_word , & has_fwd ) ;
if ( r = = MAILIMF_NO_ERROR ) {
@ -296,17 +325,21 @@ mailmime_non_encoded_word_parse(const char * message, size_t length,
cur_token = * indx ;
has_fwd = 0 ;
// Check to see if it starts with folding whitespace
r = mailimf_fws_parse ( message , length , & cur_token ) ;
if ( r = = MAILIMF_NO_ERROR ) {
if ( r = = MAILIMF_NO_ERROR ) { // it does
has_fwd = 1 ;
}
if ( ( r ! = MAILIMF_NO_ERROR ) & & ( r ! = MAILIMF_ERROR_PARSE ) ) {
// legit error
res = r ;
goto err ;
}
begin = cur_token ;
// Get the word up to the next =? or whitespace
state = 0 ;
end = FALSE ;
while ( 1 ) {
@ -325,7 +358,7 @@ mailmime_non_encoded_word_parse(const char * message, size_t length,
state = 1 ;
break ;
case ' ? ' :
if ( state = = 1 ) {
if ( state = = 1 ) { // begin of mime-encoding?
cur_token - - ;
end = TRUE ;
}
@ -340,7 +373,7 @@ mailmime_non_encoded_word_parse(const char * message, size_t length,
cur_token + + ;
}
if ( cur_token - begin = = 0 ) {
if ( cur_token - begin = = 0 ) { // we processed nothing, bail
res = MAILIMF_ERROR_PARSE ;
goto err ;
}
@ -389,14 +422,15 @@ int mailmime_encoded_word_parse(const char * message, size_t length,
missing_closing_quote = 0 ;
has_fwd = 0 ;
r = mailimf_fws_parse ( message , length , & cur_token ) ;
if ( r = = MAILIMF_NO_ERROR ) {
if ( r = = MAILIMF_NO_ERROR ) { // there was folding whitespace, now consumed
has_fwd = 1 ;
}
if ( ( r ! = MAILIMF_NO_ERROR ) & & ( r ! = MAILIMF_ERROR_PARSE ) ) {
if ( ( r ! = MAILIMF_NO_ERROR ) & & ( r ! = MAILIMF_ERROR_PARSE ) ) { // actual error
res = r ;
goto err ;
}
// check for opening quote, consume if so
opening_quote = FALSE ;
r = mailimf_char_parse ( message , length , & cur_token , ' \" ' ) ;
if ( r = = MAILIMF_NO_ERROR ) {
@ -410,42 +444,50 @@ int mailmime_encoded_word_parse(const char * message, size_t length,
goto err ;
}
// Check for MIME encoded-word syntax
// =?charset?encoding?encoded text?=
r = mailimf_token_case_insensitive_parse ( message , length , & cur_token , " =? " ) ;
if ( r ! = MAILIMF_NO_ERROR ) {
res = r ;
goto err ;
}
// get charset
r = mailmime_charset_parse ( message , length , & cur_token , & charset ) ;
if ( r ! = MAILIMF_NO_ERROR ) {
res = r ;
goto err ;
}
// charset terminator
r = mailimf_char_parse ( message , length , & cur_token , ' ? ' ) ;
if ( r ! = MAILIMF_NO_ERROR ) {
res = r ;
goto free_charset ;
}
// get encoding
r = mailmime_encoding_parse ( message , length , & cur_token , & encoding ) ;
if ( r ! = MAILIMF_NO_ERROR ) {
res = r ;
goto free_charset ;
}
// encoding terminator
r = mailimf_char_parse ( message , length , & cur_token , ' ? ' ) ;
if ( r ! = MAILIMF_NO_ERROR ) {
res = r ;
goto free_charset ;
}
// get encoded text
end = FALSE ;
end_encoding = cur_token ;
while ( 1 ) {
if ( end_encoding > = length )
break ;
// are we done?
if ( end_encoding + 1 < length ) {
if ( ( message [ end_encoding ] = = ' ? ' ) & & ( message [ end_encoding + 1 ] = = ' = ' ) ) {
end = TRUE ;
@ -458,44 +500,49 @@ int mailmime_encoded_word_parse(const char * message, size_t length,
end_encoding + + ;
}
// decode text
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 ;
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 ;
}
// Copy decoded text
if ( decoded_len > 0 )
memcpy ( text , decoded , decoded_len ) ;
text [ decoded_len ] = ' \0 ' ;
mailmime_decoded_part_free ( decoded ) ;
// Detect if we stopped parsing the *encoded* text (before we sent it off to
// be decoded because we hit the terminator, or because we hit the end
// of the specified length
r = mailimf_token_case_insensitive_parse ( message , length , & cur_token , " ?= " ) ;
#if 0
if ( r ! = MAILIMF_NO_ERROR ) {
@ -618,3 +665,20 @@ static int mailmime_etoken_parse(const char * message, size_t length,
indx , result ,
is_etoken_char ) ;
}
static int detect_CRCR ( const char * message , size_t length ,
size_t * indx ) {
size_t cur_token = * indx ;
int r = mailimf_char_parse ( message , length , & cur_token , ' \r ' ) ;
if ( r = = MAILIMF_NO_ERROR ) {
r = mailimf_char_parse ( message , length , & cur_token , ' \r ' ) ;
if ( r = = MAILIMF_NO_ERROR ) {
// Yup, there was a CRCR here.
// Advance token past the first \r
* indx = ( * indx ) + 1 ;
return r ;
}
}
// Leave indx alone and move on.
return MAILIMF_ERROR_PARSE ; // not actual error. Usual behaviour.
}