Post-merge commit plus irritating bug fixes. Pushing to test on clean VM. gnupg-2.1
authorKrista Bennett <krista@pep-project.org>
Wed, 12 Jul 2017 19:46:30 +0200
branchgnupg-2.1
changeset 1920c7e8570c9d25
parent 1914 e40bb1f761fe
parent 1916 fa80bffe8271
child 1921 2bbb3d83c7c1
Post-merge commit plus irritating bug fixes. Pushing to test on clean VM.
src/pgp_gpg.c
test/Makefile
     1.1 --- a/build-windows/pEpEngine.vcxproj	Wed Jul 12 14:01:26 2017 +0200
     1.2 +++ b/build-windows/pEpEngine.vcxproj	Wed Jul 12 19:46:30 2017 +0200
     1.3 @@ -123,6 +123,7 @@
     1.4      <ClCompile Include="..\src\pEpEngine.c" />
     1.5      <ClCompile Include="..\src\pgp_gpg.c" />
     1.6      <ClCompile Include="..\src\platform_windows.cpp" />
     1.7 +    <ClCompile Include="..\src\resource_id.c" />
     1.8      <ClCompile Include="..\src\sqlite3.c" />
     1.9      <ClCompile Include="..\src\stringlist.c" />
    1.10      <ClCompile Include="..\src\stringpair.c" />
    1.11 @@ -159,6 +160,7 @@
    1.12      <ClInclude Include="..\src\platform.h" />
    1.13      <ClInclude Include="..\src\platform_windows.h" />
    1.14      <ClInclude Include="..\src\resource.h" />
    1.15 +    <ClInclude Include="..\src\resource_id.h" />
    1.16      <ClInclude Include="..\src\sqlite3.h" />
    1.17      <ClInclude Include="..\src\stringlist.h" />
    1.18      <ClInclude Include="..\src\stringpair.h" />
     2.1 --- a/build-windows/pEpEngine.vcxproj.filters	Wed Jul 12 14:01:26 2017 +0200
     2.2 +++ b/build-windows/pEpEngine.vcxproj.filters	Wed Jul 12 19:46:30 2017 +0200
     2.3 @@ -102,6 +102,9 @@
     2.4      <ClCompile Include="..\src\sync_impl.c">
     2.5        <Filter>Quelldateien</Filter>
     2.6      </ClCompile>
     2.7 +    <ClCompile Include="..\src\resource_id.c">
     2.8 +      <Filter>Quelldateien</Filter>
     2.9 +    </ClCompile>
    2.10    </ItemGroup>
    2.11    <ItemGroup>
    2.12      <ClInclude Include="..\src\keymanagement.h">
    2.13 @@ -200,6 +203,9 @@
    2.14      <ClInclude Include="..\src\sync_impl.h">
    2.15        <Filter>Headerdateien</Filter>
    2.16      </ClInclude>
    2.17 +    <ClInclude Include="..\src\resource_id.h">
    2.18 +      <Filter>Headerdateien</Filter>
    2.19 +    </ClInclude>
    2.20    </ItemGroup>
    2.21    <ItemGroup>
    2.22      <Text Include="..\LICENSE.txt" />
     3.1 --- a/src/etpan_mime.c	Wed Jul 12 14:01:26 2017 +0200
     3.2 +++ b/src/etpan_mime.c	Wed Jul 12 19:46:30 2017 +0200
     3.3 @@ -183,7 +183,7 @@
     3.4  }
     3.5  
     3.6  struct mailmime * get_text_part(
     3.7 -        const char * filename,
     3.8 +        pEp_rid_list_t* resource,
     3.9          const char * mime_type,
    3.10          const char * text,
    3.11          size_t length,
    3.12 @@ -197,33 +197,45 @@
    3.13  	struct mailmime_parameter * param = NULL;
    3.14  	struct mailmime_disposition * disposition = NULL;
    3.15  	struct mailmime_mechanism * encoding = NULL;
    3.16 +    char* content_id = NULL;
    3.17      int r;
    3.18 +                
    3.19 +    if (resource != NULL && resource->rid != NULL) {
    3.20 +        switch (resource->rid_type) {
    3.21 +            case PEP_RID_CID:
    3.22 +                content_id = strdup(resource->rid);
    3.23 +                break;
    3.24 +            case PEP_RID_FILENAME:
    3.25 +            default:
    3.26 +                disposition_name = strdup(resource->rid);
    3.27 +                if (disposition_name == NULL)
    3.28 +                    goto enomem;
    3.29 +                    
    3.30 +                disposition =
    3.31 +                        mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
    3.32 +                                disposition_name, NULL, NULL, NULL, (size_t) -1);
    3.33 +
    3.34 +                if (disposition == NULL)
    3.35 +                    goto enomem;
    3.36 +
    3.37 +                disposition_name = NULL;                
    3.38 +                break;
    3.39 +        }    
    3.40 +    }
    3.41      
    3.42 -    if (filename != NULL) {
    3.43 -        disposition_name = strdup(filename);
    3.44 -        if (disposition_name == NULL)
    3.45 -            goto enomem;
    3.46 -    }
    3.47 -
    3.48      if (encoding_type) {
    3.49          encoding = mailmime_mechanism_new(encoding_type, NULL);
    3.50          if (encoding == NULL)
    3.51              goto enomem;
    3.52      }
    3.53  
    3.54 -    disposition =
    3.55 -            mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_INLINE,
    3.56 -                    disposition_name, NULL, NULL, NULL, (size_t) -1);
    3.57 -    if (disposition == NULL)
    3.58 -        goto enomem;
    3.59 -    disposition_name = NULL;
    3.60 -
    3.61 -    mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
    3.62 +    mime_fields = mailmime_fields_new_with_data(encoding, content_id, NULL,
    3.63              disposition, NULL);
    3.64      if (mime_fields == NULL)
    3.65          goto enomem;
    3.66      encoding = NULL;
    3.67      disposition = NULL;
    3.68 +    content_id = NULL;
    3.69  
    3.70  	content = mailmime_content_new_with_str(mime_type);
    3.71      if (content == NULL)
    3.72 @@ -269,7 +281,7 @@
    3.73  }
    3.74  
    3.75  struct mailmime * get_file_part(
    3.76 -        const char * filename,
    3.77 +        pEp_rid_list_t* resource,
    3.78          const char * mime_type,
    3.79          char * data,
    3.80          size_t length
    3.81 @@ -282,20 +294,32 @@
    3.82      struct mailmime_content * content = NULL;
    3.83      struct mailmime * mime = NULL;
    3.84      struct mailmime_fields * mime_fields = NULL;
    3.85 +    char* content_id = NULL;
    3.86      int r;
    3.87 -
    3.88 -    if (filename != NULL) {
    3.89 -        disposition_name = strdup(filename);
    3.90 -        if (disposition_name == NULL)
    3.91 -            goto enomem;
    3.92 +                
    3.93 +    if (resource != NULL && resource->rid != NULL) {
    3.94 +        switch (resource->rid_type) {
    3.95 +            case PEP_RID_CID:
    3.96 +                content_id = strdup(resource->rid);
    3.97 +                break;
    3.98 +            case PEP_RID_FILENAME:
    3.99 +            default:
   3.100 +                disposition_name = strdup(resource->rid);
   3.101 +                if (disposition_name == NULL)
   3.102 +                    goto enomem;
   3.103 +                    
   3.104 +                disposition =
   3.105 +                        mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
   3.106 +                                disposition_name, NULL, NULL, NULL, (size_t) -1);
   3.107 +                                
   3.108 +                if (disposition == NULL)
   3.109 +                    goto enomem;
   3.110 +                disposition_name = NULL;
   3.111 +                
   3.112 +                break;
   3.113 +        }    
   3.114      }
   3.115 -
   3.116 -    disposition =
   3.117 -            mailmime_disposition_new_with_data(MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
   3.118 -                    disposition_name, NULL, NULL, NULL, (size_t) -1);
   3.119 -    if (disposition == NULL)
   3.120 -        goto enomem;
   3.121 -    disposition_name = NULL;
   3.122 +    
   3.123  
   3.124      content = mailmime_content_new_with_str(mime_type);
   3.125      if (content == NULL)
   3.126 @@ -306,7 +330,7 @@
   3.127      if (encoding == NULL)
   3.128          goto enomem;
   3.129  
   3.130 -    mime_fields = mailmime_fields_new_with_data(encoding, NULL, NULL,
   3.131 +    mime_fields = mailmime_fields_new_with_data(encoding, content_id, NULL,
   3.132              disposition, NULL);
   3.133      if (mime_fields == NULL)
   3.134          goto enomem;
   3.135 @@ -340,7 +364,7 @@
   3.136          mailmime_fields_free(mime_fields);
   3.137      if (mime)
   3.138          mailmime_free(mime);
   3.139 -
   3.140 +    
   3.141      return NULL;
   3.142  }
   3.143  
   3.144 @@ -596,7 +620,9 @@
   3.145      return content;
   3.146  }
   3.147  
   3.148 -char * _get_filename(struct mailmime *mime)
   3.149 +
   3.150 +/* Return a list of identifier_type and resource id (filename, cid, etc) */
   3.151 +pEp_rid_list_t* _get_resource_id_list(struct mailmime *mime)
   3.152  {
   3.153      clist * _fieldlist = NULL;
   3.154  
   3.155 @@ -608,9 +634,22 @@
   3.156          return NULL;
   3.157  
   3.158      clistiter *cur;
   3.159 +
   3.160 +    pEp_rid_list_t* rid_list = NULL; 
   3.161 +    pEp_rid_list_t** rid_list_curr_p = &rid_list; 
   3.162 +        
   3.163      for (cur = clist_begin(_fieldlist); cur; cur = clist_next(cur)) {
   3.164          struct mailmime_field * _field = clist_content(cur);
   3.165 -        if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
   3.166 +        /* content_id */
   3.167 +        if (_field && _field->fld_type == MAILMIME_FIELD_ID) {
   3.168 +            pEp_rid_list_t* new_rid = (pEp_rid_list_t*)calloc(1, sizeof(pEp_rid_list_t));
   3.169 +            new_rid->rid_type = PEP_RID_CID;
   3.170 +            new_rid->rid = strdup(_field->fld_data.fld_id);
   3.171 +            *rid_list_curr_p = new_rid;
   3.172 +            rid_list_curr_p = &new_rid->next;
   3.173 +        }
   3.174 +        else if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
   3.175 +            /* filename */
   3.176              if (_field->fld_data.fld_disposition &&
   3.177                      _field->fld_data.fld_disposition->dsp_parms) {
   3.178                  clist * _parmlist =
   3.179 @@ -620,14 +659,66 @@
   3.180                          clist_next(cur2)) {
   3.181                      struct mailmime_disposition_parm * param =
   3.182                              clist_content(cur2);
   3.183 -                    if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME)
   3.184 -                        return param->pa_data.pa_filename;
   3.185 +                    if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME) {
   3.186 +                        pEp_rid_list_t* new_rid = (pEp_rid_list_t*)calloc(1, sizeof(pEp_rid_list_t));
   3.187 +                        new_rid->rid_type = PEP_RID_FILENAME;
   3.188 +                        new_rid->rid = strdup(param->pa_data.pa_filename);
   3.189 +                        *rid_list_curr_p = new_rid;
   3.190 +                        rid_list_curr_p = &new_rid->next;
   3.191 +                    }                
   3.192                  }
   3.193              }
   3.194          }
   3.195      }
   3.196 +    /* Will almost certainly usually be a singleton, but we need to be able to decide */
   3.197 +    return rid_list;
   3.198 +}
   3.199  
   3.200 -    return NULL;
   3.201 +
   3.202 +/* FIXME: about to be obsoleted? */
   3.203 +char * _get_filename_or_cid(struct mailmime *mime)
   3.204 +{
   3.205 +    clist * _fieldlist = NULL;
   3.206 +
   3.207 +    assert(mime);
   3.208 +
   3.209 +    if (mime->mm_mime_fields && mime->mm_mime_fields->fld_list)
   3.210 +        _fieldlist = mime->mm_mime_fields->fld_list;
   3.211 +    else
   3.212 +        return NULL;
   3.213 +
   3.214 +    clistiter *cur;
   3.215 +    
   3.216 +    char* _temp_filename_ptr = NULL;
   3.217 +    
   3.218 +    for (cur = clist_begin(_fieldlist); cur; cur = clist_next(cur)) {
   3.219 +        struct mailmime_field * _field = clist_content(cur);
   3.220 +        if (_field && _field->fld_type == MAILMIME_FIELD_ID) {
   3.221 +            /* We prefer CIDs to filenames when both are present */
   3.222 +            free(_temp_filename_ptr); /* can be null, it's ok */
   3.223 +            return build_uri("cid", _field->fld_data.fld_id); 
   3.224 +        }
   3.225 +        else if (_field && _field->fld_type == MAILMIME_FIELD_DISPOSITION) {
   3.226 +            if (_field->fld_data.fld_disposition &&
   3.227 +                    _field->fld_data.fld_disposition->dsp_parms &&
   3.228 +                    !_temp_filename_ptr) {
   3.229 +                clist * _parmlist =
   3.230 +                        _field->fld_data.fld_disposition->dsp_parms;
   3.231 +                clistiter *cur2;
   3.232 +                for (cur2 = clist_begin(_parmlist); cur2; cur2 =
   3.233 +                        clist_next(cur2)) {
   3.234 +                    struct mailmime_disposition_parm * param =
   3.235 +                            clist_content(cur2);
   3.236 +                    if (param->pa_type == MAILMIME_DISPOSITION_PARM_FILENAME) {
   3.237 +                        _temp_filename_ptr = build_uri("file", param->pa_data.pa_filename);
   3.238 +                        break;
   3.239 +                    }                
   3.240 +                }
   3.241 +            }
   3.242 +        }
   3.243 +    }
   3.244 +    /* Ok, it wasn't a CID */
   3.245 +    return _temp_filename_ptr;
   3.246  }
   3.247  
   3.248  static bool parameter_has_value(
   3.249 @@ -784,4 +875,3 @@
   3.250  
   3.251      return EINVAL;
   3.252  }
   3.253 -
     4.1 --- a/src/etpan_mime.h	Wed Jul 12 14:01:26 2017 +0200
     4.2 +++ b/src/etpan_mime.h	Wed Jul 12 19:46:30 2017 +0200
     4.3 @@ -7,6 +7,8 @@
     4.4  #include <libetpan/mailmime.h>
     4.5  #include <libetpan/mailmime_encode.h>
     4.6  
     4.7 +#include "resource_id.h"
     4.8 +
     4.9  struct mailmime * part_new_empty(
    4.10          struct mailmime_content * content,
    4.11          struct mailmime_fields * mime_fields,
    4.12 @@ -16,7 +18,7 @@
    4.13  struct mailmime * get_pgp_encrypted_part(void);
    4.14  
    4.15  struct mailmime * get_text_part(
    4.16 -        const char * filename,
    4.17 +        pEp_rid_list_t* resource,
    4.18          const char * mime_type,
    4.19          const char * text,
    4.20          size_t length,
    4.21 @@ -24,7 +26,7 @@
    4.22      );
    4.23  
    4.24  struct mailmime * get_file_part(
    4.25 -        const char * filename,
    4.26 +        pEp_rid_list_t* resource,
    4.27          const char * mime_type,
    4.28          char * data,
    4.29          size_t length
    4.30 @@ -70,7 +72,9 @@
    4.31  
    4.32  clist * _get_fields(struct mailmime * mime);
    4.33  struct mailmime_content * _get_content(struct mailmime * mime);
    4.34 -char * _get_filename(struct mailmime *mime);
    4.35 +char * _get_filename_or_cid(struct mailmime *mime);
    4.36 +pEp_rid_list_t* _get_resource_id_list(struct mailmime *mime);
    4.37 +char* _build_uri(char* uri_prefix, char* resource);
    4.38  bool _is_multipart(struct mailmime_content *content, const char *subtype);
    4.39  bool _is_PGP_MIME(struct mailmime_content *content);
    4.40  bool _is_text_part(struct mailmime_content *content, const char *subtype);
    4.41 @@ -80,4 +84,3 @@
    4.42          char **type,
    4.43          char **charset
    4.44      );
    4.45 -
     5.1 --- a/src/message_api.c	Wed Jul 12 14:01:26 2017 +0200
     5.2 +++ b/src/message_api.c	Wed Jul 12 19:46:30 2017 +0200
     5.3 @@ -20,6 +20,29 @@
     5.4  #define _MAX(A, B) ((B) > (A) ? (B) : (A))
     5.5  #endif
     5.6  
     5.7 +static char* _get_resource_ptr_noown(char* uri) {
     5.8 +    char* uri_delim = strstr(uri, "://");
     5.9 +    if (!uri_delim)
    5.10 +        return uri;
    5.11 +    else
    5.12 +        return uri + 3;
    5.13 +}
    5.14 +
    5.15 +static char* get_resource(char* uri) {
    5.16 +    const char* resource_ptr = _get_resource_ptr_noown(uri);
    5.17 +    char* resource_str = NULL;
    5.18 +    if (resource_ptr)
    5.19 +        resource_str = strdup(resource_ptr);
    5.20 +    return resource_str;
    5.21 +}
    5.22 +
    5.23 +static bool is_file_uri(char* str) {
    5.24 +    return(strncmp(str, "file://", 7) == 0);
    5.25 +}
    5.26 +
    5.27 +static bool is_cid_uri(const char* str) {
    5.28 +    return(strncmp(str, "cid://", 6) == 0);
    5.29 +}
    5.30  
    5.31  static bool string_equality(const char *s1, const char *s2)
    5.32  {
    5.33 @@ -48,7 +71,7 @@
    5.34  {
    5.35      assert(fe);
    5.36  
    5.37 -    if (bl == NULL || bl->filename == NULL || fe == NULL)
    5.38 +    if (bl == NULL || bl->filename == NULL || fe == NULL || is_cid_uri(bl->filename))
    5.39          return false;
    5.40  
    5.41      assert(bl && bl->filename);
    5.42 @@ -427,7 +450,7 @@
    5.43      dst->attachments = _a;
    5.44  
    5.45      _a = bloblist_add(_a, ctext, csize, "application/octet-stream",
    5.46 -        "msg.asc");
    5.47 +        "file://msg.asc");
    5.48      if (_a == NULL)
    5.49          goto enomem;
    5.50  
    5.51 @@ -528,7 +551,7 @@
    5.52          if (ctext) {
    5.53  
    5.54              bloblist_t *_a = bloblist_add(dst->attachments, ctext, csize,
    5.55 -                "application/octet-stream", "PGPexch.htm.pgp");
    5.56 +                "application/octet-stream", "file://PGPexch.htm.pgp");
    5.57              if (_a == NULL)
    5.58                  goto enomem;
    5.59              if (dst->attachments == NULL)
    5.60 @@ -567,24 +590,34 @@
    5.61                  if (ctext) {
    5.62                      char *filename = NULL;
    5.63  
    5.64 -                    if (_s->filename) {
    5.65 +                    char *attach_fn = _s->filename;
    5.66 +                    if (attach_fn && !is_cid_uri(attach_fn)) {
    5.67                          size_t len = strlen(_s->filename);
    5.68                          size_t bufsize = len + 5; // length of .pgp extension + NUL
    5.69 +                        bool already_uri = false;
    5.70 +                        if (is_file_uri(attach_fn))
    5.71 +                            already_uri = true;
    5.72 +                        else
    5.73 +                            bufsize += 7; // length of file://
    5.74 +                            
    5.75                          filename = calloc(1, bufsize);
    5.76                          if (filename == NULL)
    5.77                              goto enomem;
    5.78  
    5.79 -                        strlcpy(filename, _s->filename, bufsize);
    5.80 +                        if (!already_uri)
    5.81 +                            strlcpy(filename, "file://", bufsize);
    5.82 +                        // First char is NUL, so we're ok, even if not copying above. (calloc)
    5.83 +                        strlcat(filename, _s->filename, bufsize);
    5.84                          strlcat(filename, ".pgp", bufsize);
    5.85                      }
    5.86                      else {
    5.87 -                        filename = calloc(1, 20);
    5.88 +                        filename = calloc(1, 27);
    5.89                          if (filename == NULL)
    5.90                              goto enomem;
    5.91  
    5.92                          ++n;
    5.93                          n &= 0xffff;
    5.94 -                        snprintf(filename, 20, "Attachment%d.pgp", n);
    5.95 +                        snprintf(filename, 20, "file://Attachment%d.pgp", n);
    5.96                      }
    5.97  
    5.98                      _d = bloblist_add(_d, ctext, csize, "application/octet-stream",
    5.99 @@ -736,7 +769,7 @@
   5.100  {
   5.101      assert(blob);
   5.102  
   5.103 -    if (blob == NULL || blob->filename == NULL)
   5.104 +    if (blob == NULL || blob->filename == NULL || is_cid_uri(blob->filename))
   5.105          return false;
   5.106  
   5.107      char *ext = strrchr(blob->filename, '.');
   5.108 @@ -760,12 +793,13 @@
   5.109  {
   5.110      assert(blob);
   5.111      assert(blob->filename);
   5.112 -    if (blob == NULL || blob->filename == NULL)
   5.113 +    if (blob == NULL || blob->filename == NULL || is_cid_uri(blob->filename))
   5.114          return false;
   5.115  
   5.116 -    if (strncmp(blob->filename, "PGPexch.htm.", 12) == 0) {
   5.117 -        if (strcmp(blob->filename + 11, ".pgp") == 0 ||
   5.118 -            strcmp(blob->filename + 11, ".asc") == 0)
   5.119 +    const char* bare_filename_ptr = _get_resource_ptr_noown(blob->filename);
   5.120 +    if (strncmp(bare_filename_ptr, "PGPexch.htm.", 12) == 0) {
   5.121 +        if (strcmp(bare_filename_ptr + 11, ".pgp") == 0 ||
   5.122 +            strcmp(bare_filename_ptr + 11, ".asc") == 0)
   5.123              return true;
   5.124      }
   5.125  
   5.126 @@ -775,7 +809,7 @@
   5.127  static char * without_double_ending(const char *filename)
   5.128  {
   5.129      assert(filename);
   5.130 -    if (filename == NULL)
   5.131 +    if (filename == NULL || is_cid_uri(filename))
   5.132          return NULL;
   5.133  
   5.134      char *ext = strrchr(filename, '.');
   5.135 @@ -1012,7 +1046,7 @@
   5.136      assert(size);
   5.137  
   5.138       bloblist_t *bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
   5.139 -                      "pEpkey.asc");
   5.140 +                      "file://pEpkey.asc");
   5.141  
   5.142      if (msg->attachments == NULL && bl)
   5.143          msg->attachments = bl;
     6.1 --- a/src/mime.c	Wed Jul 12 14:01:26 2017 +0200
     6.2 +++ b/src/mime.c	Wed Jul 12 19:46:30 2017 +0200
     6.3 @@ -9,6 +9,7 @@
     6.4  #include <assert.h>
     6.5  #include <errno.h>
     6.6  
     6.7 +#include "resource_id.h"
     6.8  #include "etpan_mime.h"
     6.9  #include "wrappers.h"
    6.10  
    6.11 @@ -118,8 +119,13 @@
    6.12      if (mime == NULL)
    6.13          goto enomem;
    6.14  
    6.15 -    submime = get_text_part("msg.txt", "text/plain", plaintext, strlen(plaintext),
    6.16 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
    6.17 +    
    6.18 +    submime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
    6.19              MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    6.20 +    free_rid_list(resource);
    6.21 +    resource = NULL;
    6.22 +    
    6.23      assert(submime);
    6.24      if (submime == NULL)
    6.25          goto enomem;
    6.26 @@ -134,8 +140,12 @@
    6.27          submime = NULL;
    6.28      }
    6.29  
    6.30 -    submime = get_text_part("msg.html", "text/html", htmltext, strlen(htmltext),
    6.31 +    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
    6.32 +    submime = get_text_part(resource, "text/html", htmltext, strlen(htmltext),
    6.33              MAILMIME_MECHANISM_QUOTED_PRINTABLE);
    6.34 +    free_rid_list(resource);
    6.35 +    resource = NULL;
    6.36 +    
    6.37      assert(submime);
    6.38      if (submime == NULL)
    6.39          goto enomem;
    6.40 @@ -186,7 +196,10 @@
    6.41      else
    6.42          mime_type = blob->mime_type;
    6.43  
    6.44 -    mime = get_file_part(blob->filename, mime_type, blob->value, blob->size);
    6.45 +    pEp_rid_list_t* resource = parse_uri(blob->filename);
    6.46 +    mime = get_file_part(resource, mime_type, blob->value, blob->size);
    6.47 +    free_rid_list(resource);
    6.48 +    
    6.49      assert(mime);
    6.50      if (mime == NULL)
    6.51          goto enomem;
    6.52 @@ -559,6 +572,39 @@
    6.53      return status;
    6.54  }
    6.55  
    6.56 +static bool has_exceptional_extension(char* filename) {
    6.57 +    if (!filename)
    6.58 +        return false;
    6.59 +    int len = strlen(filename);
    6.60 +    if (len < 4)
    6.61 +        return false;
    6.62 +    char* ext_start = filename + (len - 4);
    6.63 +    if (strcmp(ext_start, ".pgp") == 0 || strcmp(ext_start, ".gpg") == 0 ||
    6.64 +        strcmp(ext_start, ".asc") == 0 || strcmp(ext_start, ".pEp") == 0)
    6.65 +        return true;
    6.66 +    return false;
    6.67 +}
    6.68 +
    6.69 +static pEp_rid_list_t* choose_resource_id(pEp_rid_list_t* rid_list) {
    6.70 +    pEp_rid_list_t* retval = rid_list;
    6.71 +    
    6.72 +    /* multiple elements - least common case */
    6.73 +    if (rid_list && rid_list->next) {
    6.74 +        pEp_rid_list_t* rid_list_curr = rid_list;
    6.75 +        retval = rid_list; 
    6.76 +        
    6.77 +        while (rid_list_curr) {
    6.78 +            pEp_resource_id_type rid_type = rid_list_curr->rid_type;
    6.79 +            if (rid_type == PEP_RID_CID)
    6.80 +                retval = rid_list_curr;
    6.81 +            else if (rid_type == PEP_RID_FILENAME && has_exceptional_extension(rid_list_curr->rid))
    6.82 +                return rid_list_curr;
    6.83 +            rid_list_curr = rid_list_curr->next;
    6.84 +        }
    6.85 +    } 
    6.86 +    return retval;
    6.87 +}
    6.88 +
    6.89  static PEP_STATUS mime_encode_message_plain(
    6.90          const message *msg,
    6.91          bool omit_fields,
    6.92 @@ -586,12 +632,19 @@
    6.93              goto pep_error;
    6.94      }
    6.95      else {
    6.96 -        if (is_PGP_message_text(plaintext))
    6.97 -            mime = get_text_part("msg.asc", "application/octet-stream", plaintext,
    6.98 +        pEp_rid_list_t* resource = NULL;
    6.99 +        if (is_PGP_message_text(plaintext)) {
   6.100 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
   6.101 +            mime = get_text_part(resource, "application/octet-stream", plaintext,
   6.102                      strlen(plaintext), MAILMIME_MECHANISM_7BIT);
   6.103 -        else
   6.104 -            mime = get_text_part("msg.txt", "text/plain", plaintext, strlen(plaintext),
   6.105 +        }
   6.106 +        else {
   6.107 +            resource = new_rid_node(PEP_RID_FILENAME, "msg.txt");
   6.108 +            mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
   6.109                      MAILMIME_MECHANISM_QUOTED_PRINTABLE);
   6.110 +        }
   6.111 +        free_rid_list(resource);
   6.112 +        
   6.113          assert(mime);
   6.114          if (mime == NULL)
   6.115              goto enomem;
   6.116 @@ -694,8 +747,12 @@
   6.117          submime = NULL;
   6.118      }
   6.119  
   6.120 -    submime = get_text_part("msg.asc", "application/octet-stream", plaintext,
   6.121 +    pEp_rid_list_t* resource = new_rid_node(PEP_RID_FILENAME, "msg.asc");
   6.122 +    submime = get_text_part(resource, "application/octet-stream", plaintext,
   6.123              plaintext_size, MAILMIME_MECHANISM_7BIT);
   6.124 +            
   6.125 +    free_rid_list(resource);
   6.126 +    
   6.127      assert(submime);
   6.128      if (submime == NULL)
   6.129          goto enomem;
   6.130 @@ -1343,19 +1400,50 @@
   6.131                  if (status)
   6.132                      return status;
   6.133  
   6.134 -                filename = _get_filename(mime);
   6.135 +                pEp_rid_list_t* resource_id_list = _get_resource_id_list(mime);
   6.136 +                pEp_rid_list_t* chosen_resource_id = choose_resource_id(resource_id_list);
   6.137 +                
   6.138 +                //filename = _get_filename_or_cid(mime);
   6.139                  char *_filename = NULL;
   6.140 -                if (filename) {
   6.141 +                
   6.142 +                if (chosen_resource_id) {
   6.143 +                    filename = chosen_resource_id->rid;
   6.144                      size_t index = 0;
   6.145 +                    /* NOTA BENE */
   6.146 +                    /* The prefix we just added shouldn't be a problem - this is about decoding %XX (RFC 2392) */
   6.147 +                    /* If it becomes one, we have some MESSY fixing to do. :(                                  */
   6.148                      r = mailmime_encoded_phrase_parse("utf-8", filename,
   6.149                              strlen(filename), &index, "utf-8", &_filename);
   6.150 -                    if (r)
   6.151 +                    if (r) {
   6.152                          goto enomem;
   6.153 +                    }
   6.154 +                    char* file_prefix = NULL;
   6.155 +                    
   6.156 +                    /* in case there are others later */
   6.157 +                    switch (chosen_resource_id->rid_type) {
   6.158 +                        case PEP_RID_CID:
   6.159 +                            file_prefix = "cid";
   6.160 +                            break;
   6.161 +                        case PEP_RID_FILENAME:
   6.162 +                            file_prefix = "file";
   6.163 +                            break;
   6.164 +                        default:
   6.165 +                            break;
   6.166 +                    }
   6.167 +
   6.168 +                    
   6.169 +                    if (file_prefix) {
   6.170 +                        filename = build_uri(file_prefix, _filename);
   6.171 +                        free(_filename);
   6.172 +                        _filename = filename;
   6.173 +                    }
   6.174                  }
   6.175  
   6.176                  bloblist_t *_a = bloblist_add(msg->attachments, data, size,
   6.177                          mime_type, _filename);
   6.178                  free(_filename);
   6.179 +                free_rid_list(resource_id_list);
   6.180 +                resource_id_list = NULL;
   6.181                  if (_a == NULL)
   6.182                      return PEP_OUT_OF_MEMORY;
   6.183                  if (msg->attachments == NULL)
     7.1 --- a/src/pgp_gpg.c	Wed Jul 12 14:01:26 2017 +0200
     7.2 +++ b/src/pgp_gpg.c	Wed Jul 12 19:46:30 2017 +0200
     7.3 @@ -278,7 +278,15 @@
     7.4          gpg.gpgme_get_key
     7.5              = (gpgme_get_key_t) (intptr_t) dlsym(gpgme, "gpgme_get_key");
     7.6          assert(gpg.gpgme_get_key);
     7.7 -
     7.8 +        
     7.9 +#ifdef GPGME_VERSION_NUMBER 
    7.10 +#if (GPGME_VERSION_NUMBER >= 0x010700)
    7.11 +        gpg.gpgme_op_createkey
    7.12 +            = (gpgme_op_createkey_t) (intptr_t) dlsym(gpgme,
    7.13 +            "gpgme_op_createkey");
    7.14 +        assert(gpg.gpgme_op_createkey);        
    7.15 +#endif
    7.16 +#endif
    7.17          gpg.gpgme_op_genkey
    7.18              = (gpgme_op_genkey_t) (intptr_t) dlsym(gpgme,
    7.19              "gpgme_op_genkey");
    7.20 @@ -1063,30 +1071,28 @@
    7.21  static PEP_STATUS _pgp_createkey(PEP_SESSION session, pEp_identity *identity) {
    7.22      PEP_STATUS status = PEP_VERSION_MISMATCH;
    7.23  
    7.24 -    if (identity && identity->address) {
    7.25 -    
    7.26 +    if (identity && identity->address) {    
    7.27  #ifdef GPGME_VERSION_NUMBER 
    7.28  #if (GPGME_VERSION_NUMBER >= 0x010700)
    7.29 -    gpgme_error_t gpgme_error;
    7.30 -    gpgme_error = gpg.gpgme_op_createkey(session->ctx, identity->address, "RSA", 
    7.31 -                                         0, 31536000, NULL, GPGME_CREATE_NOPASSWD);
    7.32 -    gpgme_error = _GPGERR(gpgme_error);
    7.33 -    if (gpgme_error != GPG_ERR_NOT_SUPPORTED) {
    7.34 -        switch (gpgme_error) {
    7.35 -        case GPG_ERR_NO_ERROR:
    7.36 -            break;
    7.37 -        case GPG_ERR_INV_VALUE:
    7.38 -            return PEP_ILLEGAL_VALUE;
    7.39 -        case GPG_ERR_GENERAL:
    7.40 -            return PEP_CANNOT_CREATE_KEY;
    7.41 -        default:
    7.42 -            assert(0);
    7.43 -            return PEP_UNKNOWN_ERROR;
    7.44 -        }        
    7.45 -    }
    7.46 +        gpgme_error_t gpgme_error;
    7.47 +        gpgme_error = gpg.gpgme_op_createkey(session->ctx, identity->address, "RSA", 
    7.48 +                                             0, 31536000, NULL, GPGME_CREATE_NOPASSWD);
    7.49 +        gpgme_error = _GPGERR(gpgme_error);
    7.50 +        if (gpgme_error != GPG_ERR_NOT_SUPPORTED) {
    7.51 +            switch (gpgme_error) {
    7.52 +            case GPG_ERR_NO_ERROR:
    7.53 +                return PEP_STATUS_OK;
    7.54 +            case GPG_ERR_INV_VALUE:
    7.55 +                return PEP_ILLEGAL_VALUE;
    7.56 +            case GPG_ERR_GENERAL:
    7.57 +                return PEP_CANNOT_CREATE_KEY;
    7.58 +            default:
    7.59 +                assert(0);
    7.60 +                return PEP_UNKNOWN_ERROR;
    7.61 +            }        
    7.62 +        }
    7.63  #endif
    7.64  #endif
    7.65 -
    7.66      }
    7.67      
    7.68      return status;
    7.69 @@ -1104,7 +1110,7 @@
    7.70  
    7.71      PEP_STATUS status = _pgp_createkey(session, identity);
    7.72      
    7.73 -    if (status != PEP_STATUS_OK || 
    7.74 +    if (status != PEP_STATUS_OK && 
    7.75          status != PEP_VERSION_MISMATCH)
    7.76          return status;
    7.77  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/resource_id.c	Wed Jul 12 19:46:30 2017 +0200
     8.3 @@ -0,0 +1,70 @@
     8.4 +// This file is under GNU General Public License 3.0
     8.5 +// see LICENSE.txt
     8.6 +
     8.7 +#include "pEp_internal.h"
     8.8 +#include "resource_id.h"
     8.9 +
    8.10 +pEp_rid_list_t* new_rid_node(pEp_resource_id_type type, const char* resource) {
    8.11 +    pEp_rid_list_t* retval = (pEp_rid_list_t*)calloc(1, sizeof(pEp_rid_list_t));
    8.12 +    retval->rid_type = type;
    8.13 +    retval->rid = strdup(resource);
    8.14 +    return retval;
    8.15 +}
    8.16 +
    8.17 +void free_rid_list(pEp_rid_list_t* list) {
    8.18 +    while (list) {
    8.19 +        pEp_rid_list_t* nextptr = list->next;
    8.20 +        free(list->rid);
    8.21 +        free(list);
    8.22 +        list = nextptr;
    8.23 +    }
    8.24 +}
    8.25 +
    8.26 +const char* get_resource_ptr_noown(const char* uri) {
    8.27 +    char* uri_delim = strstr(uri, "://");
    8.28 +    if (!uri_delim)
    8.29 +        return uri;
    8.30 +    else
    8.31 +        return uri_delim + 3;
    8.32 +}
    8.33 +
    8.34 +char* get_resource(char* uri) {
    8.35 +    const char* resource_ptr = get_resource_ptr_noown(uri);
    8.36 +    char* resource_str = NULL;
    8.37 +    if (resource_ptr)
    8.38 +        resource_str = strdup(resource_ptr);
    8.39 +    return resource_str;
    8.40 +}
    8.41 +
    8.42 +bool is_file_uri(char* str) {
    8.43 +    return(!str ? false : strncmp(str, "file://", 7) == 0);
    8.44 +}
    8.45 +
    8.46 +bool is_cid_uri(const char* str) {
    8.47 +    return(!str ? false : strncmp(str, "cid://", 6) == 0);
    8.48 +}
    8.49 +
    8.50 +pEp_rid_list_t* parse_uri(const char* uri) {
    8.51 +    if (!uri)
    8.52 +        return NULL;
    8.53 +    pEp_resource_id_type type = (is_cid_uri(uri) ? PEP_RID_CID : PEP_RID_FILENAME);
    8.54 +    const char* resource = get_resource_ptr_noown(uri);
    8.55 +    return new_rid_node(type, resource);
    8.56 +}
    8.57 +
    8.58 +char* build_uri(const char* uri_prefix, const char* resource) {
    8.59 +    if (!uri_prefix || !resource)
    8.60 +        return NULL;
    8.61 +    const char* delim = "://";
    8.62 +    const int delim_len = 3;
    8.63 +    int prefix_len = strlen(uri_prefix);
    8.64 +    int resource_len = strlen(resource);
    8.65 +    int retval_len = prefix_len + delim_len + resource_len;
    8.66 +
    8.67 +    char* retval = calloc(1, retval_len + 1);
    8.68 +    strlcpy(retval, uri_prefix, retval_len + 1);
    8.69 +    strlcat(retval, delim, retval_len + 1);
    8.70 +    strlcat(retval, resource, retval_len + 1);
    8.71 +    
    8.72 +    return retval;
    8.73 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/resource_id.h	Wed Jul 12 19:46:30 2017 +0200
     9.3 @@ -0,0 +1,34 @@
     9.4 +// This file is under GNU General Public License 3.0
     9.5 +// see LICENSE.txt
     9.6 +
     9.7 +#pragma once
     9.8 +
     9.9 +/* structs to contain info about parsed resource ids (filenames, uids) */
    9.10 +typedef enum _resource_id_type {
    9.11 +    PEP_RID_FILENAME,
    9.12 +    PEP_RID_CID
    9.13 +} pEp_resource_id_type;
    9.14 +
    9.15 +typedef struct pEp_rid_list_t pEp_rid_list_t;
    9.16 +
    9.17 +struct pEp_rid_list_t {
    9.18 +    pEp_resource_id_type rid_type;
    9.19 +    char* rid;
    9.20 +    pEp_rid_list_t* next;    
    9.21 +};
    9.22 +
    9.23 +pEp_rid_list_t* new_rid_node(pEp_resource_id_type type, const char* resource);
    9.24 +
    9.25 +void free_rid_list(pEp_rid_list_t* list);
    9.26 +
    9.27 +pEp_rid_list_t* parse_uri(const char* uri);
    9.28 +
    9.29 +char* build_uri(const char* uri_prefix, const char* resource);
    9.30 +
    9.31 +const char* get_resource_ptr_noown(const char* uri);
    9.32 +
    9.33 +char* get_resource(char* uri);
    9.34 +
    9.35 +bool is_file_uri(char* str);
    9.36 +
    9.37 +bool is_cid_uri(const char* str);
    10.1 --- a/src/sync_impl.c	Wed Jul 12 14:01:26 2017 +0200
    10.2 +++ b/src/sync_impl.c	Wed Jul 12 19:46:30 2017 +0200
    10.3 @@ -851,7 +851,7 @@
    10.4              for (stringlist_t *_keylist=keylist; _keylist!=NULL; _keylist=_keylist->next) {
    10.5                  char *fpr = _keylist->value;
    10.6                  static char filename[MAX_LINELENGTH];
    10.7 -                int result = snprintf(filename, MAX_LINELENGTH, "%s-sec.asc", fpr);
    10.8 +                int result = snprintf(filename, MAX_LINELENGTH, "file://%s-sec.asc", fpr);
    10.9                  if (result < 0)
   10.10                      goto enomem;
   10.11                  char *key = NULL;
   10.12 @@ -969,4 +969,3 @@
   10.13  
   10.14      return group_key_extra_dst;
   10.15  }
   10.16 -
    11.1 --- a/test/Makefile	Wed Jul 12 14:01:26 2017 +0200
    11.2 +++ b/test/Makefile	Wed Jul 12 19:46:30 2017 +0200
    11.3 @@ -49,22 +49,12 @@
    11.4  
    11.5  TEST_CMD_PFX = $(LIBPATH)=$(HOME)/lib:../src HOME=$(TEST_HOME)
    11.6  
    11.7 -define killgpg =
    11.8 -endef
    11.9 -ifeq ("$(OPENPGP)","NETPGP")
   11.10 -    killgpg_if_using_it =
   11.11 -else
   11.12 -    killgpg_if_using_it = $(killgpg)
   11.13 -endif
   11.14 -
   11.15  test_home_skel:
   11.16 -	$(killgpg)
   11.17  	mkdir -p test_home_skel
   11.18 -	-cat 0x*.asc *_sec.asc | gpg2 --import --homedir $(TEST_GNUPGHOME_SKEL)
   11.19 -	$(killgpg)
   11.20 +	mkdir -p $(TEST_GNUPGHOME_SKEL)/private-keys-v1.d
   11.21 +	gpg2 --import --batch --homedir $(TEST_GNUPGHOME_SKEL) 0x*.asc *_sec.asc
   11.22  
   11.23  test_home_: test_home_skel
   11.24 -	$(killgpg_if_using_it)
   11.25  	rm -rf test_home
   11.26  	cp -a test_home_skel test_home
   11.27  
    12.1 --- a/test/revoke_regen_attach_test.cc	Wed Jul 12 14:01:26 2017 +0200
    12.2 +++ b/test/revoke_regen_attach_test.cc	Wed Jul 12 19:46:30 2017 +0200
    12.3 @@ -68,8 +68,8 @@
    12.4  
    12.5      cout << msg->attachments->filename;
    12.6      assert(bloblist_length(msg->attachments) == 2);
    12.7 -    assert(strcmp(msg->attachments->filename, "pEpkey.asc") == 0);
    12.8 -    assert(strcmp(msg->attachments->next->filename, "pEpkey.asc") == 0);
    12.9 +    assert(strcmp(msg->attachments->filename, "file://pEpkey.asc") == 0);
   12.10 +    assert(strcmp(msg->attachments->next->filename, "file://pEpkey.asc") == 0);
   12.11  
   12.12      cout << "message contains 2 key attachements.\n";
   12.13  
   12.14 @@ -82,4 +82,3 @@
   12.15  
   12.16      return 0;
   12.17  }
   12.18 -