ENGINE-400 and friends should be fixed now ENGINE-400
authorKrista Bennett <krista@pep-project.org>
Mon, 12 Mar 2018 02:37:00 +0100
branchENGINE-400
changeset 2562a381a9bd101c
parent 2559 1db16cd8e50c
child 2563 95183ae74227
ENGINE-400 and friends should be fixed now
src/etpan_mime.c
src/etpan_mime.h
src/mime.c
     1.1 --- a/src/etpan_mime.c	Fri Mar 09 07:18:37 2018 +0100
     1.2 +++ b/src/etpan_mime.c	Mon Mar 12 02:37:00 2018 +0100
     1.3 @@ -541,6 +541,7 @@
     1.4      return NULL;
     1.5  }
     1.6  
     1.7 +
     1.8  struct mailimf_field * create_optional_field(
     1.9          const char *field,
    1.10          const char *value
    1.11 @@ -554,7 +555,10 @@
    1.12      if (_field == NULL)
    1.13          goto enomem;
    1.14  
    1.15 -    _value = mailmime_encode_subject_header("utf-8", value, 0);
    1.16 +    if (!must_field_value_be_encoded(value))
    1.17 +        _value = strdup(value);
    1.18 +    else    
    1.19 +        _value = mailmime_encode_subject_header("utf-8", value, 0);
    1.20      if (_value == NULL)
    1.21          goto enomem;
    1.22  
    1.23 @@ -885,3 +889,39 @@
    1.24  
    1.25      return EINVAL;
    1.26  }
    1.27 +
    1.28 +// Only for null-terminated field strings.
    1.29 +// can this field be transported as is without modification?)
    1.30 +// (See rfc2822, section 2.2.3 - libetpan's handling isn't quite what
    1.31 +// we need here.)
    1.32 +bool must_field_value_be_encoded(const char* field_value) {
    1.33 +    
    1.34 +    int val_len = strlen(field_value);
    1.35 +    const char* end_ptr = field_value + val_len;
    1.36 +
    1.37 +    const char* cur_char_ptr = field_value;
    1.38 +    while (cur_char_ptr < end_ptr) {
    1.39 +        char cur_char = *cur_char_ptr;
    1.40 +        if (cur_char > 127)
    1.41 +            return true;
    1.42 +        // FIXME - do we need to deal with CRCRLF here?
    1.43 +        //         I guess in the worst case, it gets encoded, which
    1.44 +        //         is *supposed* to be harmless...
    1.45 +        if (cur_char == '\r') {
    1.46 +            const char* next = cur_char_ptr + 1;
    1.47 +            const char* nextnext = next + 1;
    1.48 +            if (next >= end_ptr || nextnext >= end_ptr
    1.49 +                || *next != '\n'
    1.50 +                || (*nextnext != ' ' && *nextnext != '\t')) {
    1.51 +                return true;
    1.52 +            }            
    1.53 +        }
    1.54 +        else if (cur_char == '\n') {
    1.55 +            const char* prev = cur_char_ptr - 1;
    1.56 +            if (prev == field_value || *prev != '\r')
    1.57 +                return true;
    1.58 +        }
    1.59 +        cur_char_ptr++;
    1.60 +    }    
    1.61 +    return false;
    1.62 +}
     2.1 --- a/src/etpan_mime.h	Fri Mar 09 07:18:37 2018 +0100
     2.2 +++ b/src/etpan_mime.h	Mon Mar 12 02:37:00 2018 +0100
     2.3 @@ -79,6 +79,7 @@
     2.4  bool _is_multipart(struct mailmime_content *content, const char *subtype);
     2.5  bool _is_PGP_MIME(struct mailmime_content *content);
     2.6  bool _is_text_part(struct mailmime_content *content, const char *subtype);
     2.7 +bool must_field_value_be_encoded(const char* field_value);
     2.8  
     2.9  int _get_content_type(
    2.10          const struct mailmime_content *content,
     3.1 --- a/src/mime.c	Fri Mar 09 07:18:37 2018 +0100
     3.2 +++ b/src/mime.c	Mon Mar 12 02:37:00 2018 +0100
     3.3 @@ -299,8 +299,10 @@
     3.4      char *_username = NULL;
     3.5      struct mailimf_mailbox *mb;
     3.6  
     3.7 -    _username = ident->username ? mailmime_encode_subject_header("utf-8",
     3.8 -            ident->username, 0) : strdup("");
     3.9 +    _username = (ident->username && must_field_value_be_encoded(ident->username))
    3.10 +                  ? mailmime_encode_subject_header("utf-8", ident->username, 0) 
    3.11 +                  : strdup("");
    3.12 +                  
    3.13      if (_username == NULL)
    3.14          goto enomem;
    3.15  
    3.16 @@ -418,7 +420,7 @@
    3.17      stringlist_t *_sl;
    3.18      for (_sl = sl; _sl; _sl = _sl->next) {
    3.19          int r;
    3.20 -        char * value = (transport_encode ?
    3.21 +        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
    3.22                          mailmime_encode_subject_header("utf-8", _sl->value, 0) :
    3.23                          strdup(_sl->value));
    3.24          assert(value);
    3.25 @@ -517,7 +519,11 @@
    3.26          }
    3.27      }
    3.28  
    3.29 -    char *_subject = mailmime_encode_subject_header("utf-8", subject, 1);
    3.30 +    char* _subject = NULL;
    3.31 +    if (!must_field_value_be_encoded(subject))
    3.32 +        _subject = strdup(subject);
    3.33 +    else    
    3.34 +        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
    3.35      if (_subject == NULL)
    3.36          goto enomem;
    3.37  
    3.38 @@ -607,7 +613,11 @@
    3.39      }
    3.40  
    3.41      if (msg->comments) {
    3.42 -        char *comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
    3.43 +        char *comments = NULL;
    3.44 +        if (!must_field_value_be_encoded(msg->comments))
    3.45 +            comments = strdup(comments);
    3.46 +        else 
    3.47 +            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
    3.48          if (comments == NULL)
    3.49              goto enomem;
    3.50  
    3.51 @@ -625,12 +635,8 @@
    3.52              char *key = _l->value->key;
    3.53              char *value = _l->value->value;
    3.54              if (key && value) {
    3.55 -                char *_value = mailmime_encode_subject_header("utf-8", value, 1);
    3.56 -                if (_value == NULL)
    3.57 -                    goto enomem;
    3.58 +                r = _append_optional_field(fields_list, key, value);
    3.59  
    3.60 -                r = _append_optional_field(fields_list, key, _value);
    3.61 -                free(_value);
    3.62                  if (r)
    3.63                      goto enomem;
    3.64              }