Merged in enigmail encoding fixes (ENGINE-400 and friends)
authorKrista Bennett <krista@pep-project.org>
Mon, 12 Mar 2018 02:59:53 +0100
changeset 25657f9edcc2f6c9
parent 2561 46fccf362b21
parent 2564 2db5cc88bdd4
child 2569 26ea88612990
child 2570 c907f9904e73
Merged in enigmail encoding fixes (ENGINE-400 and friends)
     1.1 --- a/src/etpan_mime.c	Fri Mar 09 07:35:38 2018 +0100
     1.2 +++ b/src/etpan_mime.c	Mon Mar 12 02:59:53 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 || cur_char < 0)
    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:35:38 2018 +0100
     2.2 +++ b/src/etpan_mime.h	Mon Mar 12 02:59:53 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/message_api.c	Fri Mar 09 07:35:38 2018 +0100
     3.2 +++ b/src/message_api.c	Mon Mar 12 02:59:53 2018 +0100
     3.3 @@ -3586,7 +3586,7 @@
     3.4      }
     3.5  
     3.6      // FIXME: test with att
     3.7 -    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, false);
     3.8 +    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true);
     3.9  
    3.10      if (status == PEP_STATUS_OK)
    3.11      {
     4.1 --- a/src/mime.c	Fri Mar 09 07:35:38 2018 +0100
     4.2 +++ b/src/mime.c	Mon Mar 12 02:59:53 2018 +0100
     4.3 @@ -299,8 +299,10 @@
     4.4      char *_username = NULL;
     4.5      struct mailimf_mailbox *mb;
     4.6  
     4.7 -    _username = ident->username ? mailmime_encode_subject_header("utf-8",
     4.8 -            ident->username, 0) : strdup("");
     4.9 +    _username = (ident->username && must_field_value_be_encoded(ident->username))
    4.10 +                  ? mailmime_encode_subject_header("utf-8", ident->username, 0) 
    4.11 +                  : strdup("");
    4.12 +                  
    4.13      if (_username == NULL)
    4.14          goto enomem;
    4.15  
    4.16 @@ -418,7 +420,7 @@
    4.17      stringlist_t *_sl;
    4.18      for (_sl = sl; _sl; _sl = _sl->next) {
    4.19          int r;
    4.20 -        char * value = (transport_encode ?
    4.21 +        char * value = ((transport_encode && must_field_value_be_encoded(_sl->value)) ?
    4.22                          mailmime_encode_subject_header("utf-8", _sl->value, 0) :
    4.23                          strdup(_sl->value));
    4.24          assert(value);
    4.25 @@ -438,8 +440,7 @@
    4.26      return cl;
    4.27  }
    4.28  
    4.29 -static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result,
    4.30 -                               bool transport_encode)
    4.31 +static PEP_STATUS build_fields(const message *msg, struct mailimf_fields **result)
    4.32  {
    4.33      PEP_STATUS status = PEP_STATUS_OK;
    4.34      struct mailimf_fields * fields = NULL;
    4.35 @@ -518,19 +519,19 @@
    4.36          }
    4.37      }
    4.38  
    4.39 -    /* if (subject) */ {
    4.40 -        char *_subject = (transport_encode ? 
    4.41 -                          mailmime_encode_subject_header("utf-8", subject, 1) :
    4.42 -                          strdup(subject));
    4.43 -        if (_subject == NULL)
    4.44 -            goto enomem;
    4.45 +    char* _subject = NULL;
    4.46 +    if (!must_field_value_be_encoded(subject))
    4.47 +        _subject = strdup(subject);
    4.48 +    else    
    4.49 +        _subject = mailmime_encode_subject_header("utf-8", subject, 1);
    4.50 +    if (_subject == NULL)
    4.51 +        goto enomem;
    4.52  
    4.53 -        r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
    4.54 -                (_new_func_t) mailimf_subject_new, _subject);
    4.55 -        if (r) {
    4.56 -            free(_subject);
    4.57 -            goto enomem;
    4.58 -        }
    4.59 +    r = _append_field(fields_list, MAILIMF_FIELD_SUBJECT,
    4.60 +            (_new_func_t) mailimf_subject_new, _subject);
    4.61 +    if (r) {
    4.62 +        free(_subject);
    4.63 +        goto enomem;
    4.64      }
    4.65  
    4.66      if (msg->cc) {
    4.67 @@ -573,7 +574,7 @@
    4.68      }
    4.69  
    4.70      if (msg->in_reply_to) {
    4.71 -        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, transport_encode);
    4.72 +        clist *in_reply_to = stringlist_to_clist(msg->in_reply_to, true);
    4.73          if (in_reply_to == NULL)
    4.74              goto enomem;
    4.75  
    4.76 @@ -586,7 +587,7 @@
    4.77      }
    4.78  
    4.79      if (msg->references) {
    4.80 -        clist *references = stringlist_to_clist(msg->references, transport_encode);
    4.81 +        clist *references = stringlist_to_clist(msg->references, true);
    4.82          if (references == NULL)
    4.83              goto enomem;
    4.84  
    4.85 @@ -599,7 +600,7 @@
    4.86      }
    4.87  
    4.88      if (msg->keywords) {
    4.89 -        clist *keywords = stringlist_to_clist(msg->keywords, transport_encode);
    4.90 +        clist *keywords = stringlist_to_clist(msg->keywords, true);
    4.91          if (keywords == NULL)
    4.92              goto enomem;
    4.93  
    4.94 @@ -612,9 +613,11 @@
    4.95      }
    4.96  
    4.97      if (msg->comments) {
    4.98 -        char *comments = (transport_encode ?
    4.99 -                          mailmime_encode_subject_header("utf-8", msg->comments, 0) :
   4.100 -                          strdup(msg->comments));
   4.101 +        char *comments = NULL;
   4.102 +        if (!must_field_value_be_encoded(msg->comments))
   4.103 +            comments = strdup(comments);
   4.104 +        else 
   4.105 +            comments = mailmime_encode_subject_header("utf-8", msg->comments, 0);
   4.106          if (comments == NULL)
   4.107              goto enomem;
   4.108  
   4.109 @@ -632,14 +635,8 @@
   4.110              char *key = _l->value->key;
   4.111              char *value = _l->value->value;
   4.112              if (key && value) {
   4.113 -                char *_value = (transport_encode ?
   4.114 -                                mailmime_encode_subject_header("utf-8", value, 0) :
   4.115 -                                strdup(value));
   4.116 -                if (_value == NULL)
   4.117 -                    goto enomem;
   4.118 +                r = _append_optional_field(fields_list, key, value);
   4.119  
   4.120 -                r = _append_optional_field(fields_list, key, _value);
   4.121 -                free(_value);
   4.122                  if (r)
   4.123                      goto enomem;
   4.124              }
   4.125 @@ -997,7 +994,7 @@
   4.126      mime = NULL;
   4.127  
   4.128      if (!omit_fields) {
   4.129 -        status = build_fields(msg, &fields, transport_encode);
   4.130 +        status = build_fields(msg, &fields);
   4.131          if (status != PEP_STATUS_OK)
   4.132              goto pep_error;
   4.133