Can't seem to keep the branches separate - except for the "forwarded" changes, this should probably all be in 559, but was done in 551. ENGINE-559
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Sun, 19 May 2019 15:13:55 +0200
branchENGINE-559
changeset 37291c6553767712
parent 3728 3e8c536a1634
child 3730 922720c27d9a
Can't seem to keep the branches separate - except for the "forwarded" changes, this should probably all be in 559, but was done in 551.
src/etpan_mime.c
src/keymanagement.c
src/message_api.c
src/pEpEngine.c
src/pEpEngine.h
src/pEp_internal.h
test/src/util/test_util.cc
     1.1 --- a/src/etpan_mime.c	Fri May 17 17:44:19 2019 +0200
     1.2 +++ b/src/etpan_mime.c	Sun May 19 15:13:55 2019 +0200
     1.3 @@ -390,7 +390,7 @@
     1.4      stringpair_list_t* extra_params = NULL;
     1.5      
     1.6      if (set_attachment_forward_comment)
     1.7 -        extra_params = new_stringpair_list(new_stringpair("forward", "no"));
     1.8 +        extra_params = new_stringpair_list(new_stringpair("forwarded", "no"));
     1.9      
    1.10      mime = part_new_empty(content, mime_fields, extra_params, 1);
    1.11      free_stringpair_list(extra_params);
    1.12 @@ -2628,7 +2628,7 @@
    1.13                              for (cur = clist_begin(content->ct_parameters); cur; cur =
    1.14                                   clist_next(cur)) {
    1.15                                  struct mailmime_parameter * param = clist_content(cur);
    1.16 -                                if (param && param->pa_name && strcasecmp(param->pa_name, "forward") == 0) {
    1.17 +                                if (param && param->pa_name && strcasecmp(param->pa_name, "forwarded") == 0) {
    1.18                                      if (param->pa_value && strcasecmp(param->pa_value, "no") == 0) {
    1.19                                          *raise_msg_attachment = true;
    1.20                                          break;
     2.1 --- a/src/keymanagement.c	Fri May 17 17:44:19 2019 +0200
     2.2 +++ b/src/keymanagement.c	Sun May 19 15:13:55 2019 +0200
     2.3 @@ -1692,8 +1692,6 @@
     2.4                  }
     2.5                  ident->me = true;
     2.6                  ident->flags = flags;
     2.7 -                ident->pEp_version = (float)
     2.8 -                    sqlite3_column_double(session->own_identities_retrieve, 6);
     2.9  
    2.10                  _bl = identity_list_add(_bl, ident);
    2.11                  if (_bl == NULL) {
     3.1 --- a/src/message_api.c	Fri May 17 17:44:19 2019 +0200
     3.2 +++ b/src/message_api.c	Sun May 19 15:13:55 2019 +0200
     3.3 @@ -2981,11 +2981,25 @@
     3.4      return status;
     3.5  }
     3.6  
     3.7 +// ident is in_only and should have been updated
     3.8 +static PEP_STATUS pEp_version_upgrade_or_ignore(
     3.9 +        PEP_SESSION session,
    3.10 +        pEp_identity* ident,
    3.11 +        float version_number) {
    3.12 +            
    3.13 +    PEP_STATUS status = PEP_STATUS_OK;        
    3.14 +    if (version_number > ident->_pEp_version)
    3.15 +        status = set_pEp_version(session, ident, version_number);        
    3.16 +    
    3.17 +    return status;    
    3.18 +}
    3.19 +
    3.20  // FIXME: myself ??????
    3.21  static PEP_STATUS update_sender_to_pEp_trust(
    3.22          PEP_SESSION session, 
    3.23          pEp_identity* sender, 
    3.24 -        stringlist_t* keylist) 
    3.25 +        stringlist_t* keylist,
    3.26 +        float version_number) 
    3.27  {
    3.28      assert(session);
    3.29      assert(sender);
    3.30 @@ -2996,9 +3010,11 @@
    3.31          
    3.32      free(sender->fpr);
    3.33      sender->fpr = NULL;
    3.34 -    
    3.35 -    PEP_STATUS status = 
    3.36 -            is_me(session, sender) ? myself(session, sender) : update_identity(session, sender);
    3.37 +
    3.38 +    PEP_STATUS status = PEP_STATUS_OK;
    3.39 +
    3.40 +    // Seems status doesn't matter
    3.41 +    is_me(session, sender) ? myself(session, sender) : update_identity(session, sender);
    3.42  
    3.43      if (EMPTYSTR(sender->fpr) || strcmp(sender->fpr, keylist->value) != 0) {
    3.44          free(sender->fpr);
    3.45 @@ -3023,11 +3039,19 @@
    3.46      
    3.47      // Could be done elegantly, but we do this explicitly here for readability.
    3.48      // This file's code is difficult enough to parse. But change at will.
    3.49 -    switch (sender->comm_type) {
    3.50 +    switch (sender->comm_type) {            
    3.51          case PEP_ct_OpenPGP_unconfirmed:
    3.52          case PEP_ct_OpenPGP:
    3.53              sender->comm_type = PEP_ct_pEp_unconfirmed | (sender->comm_type & PEP_ct_confirmed);
    3.54              status = set_trust(session, sender);
    3.55 +            if (status != PEP_STATUS_OK)
    3.56 +                break;
    3.57 +        case PEP_ct_pEp:
    3.58 +        case PEP_ct_pEp_unconfirmed:
    3.59 +            // set version
    3.60 +            if (version_number == 0)
    3.61 +                version_number = 2;
    3.62 +            status = pEp_version_upgrade_or_ignore(session, sender, version_number);    
    3.63              break;
    3.64          default:
    3.65              status = PEP_CANNOT_SET_TRUST;
    3.66 @@ -3314,6 +3338,7 @@
    3.67      char* signer_fpr = NULL;
    3.68      bool is_pEp_msg = is_a_pEpmessage(src);
    3.69      bool myself_read_only = (src->dir == PEP_dir_incoming);
    3.70 +    float pEp_version = 0;
    3.71  
    3.72      // Grab input flags
    3.73      bool reencrypt = (((*flags & PEP_decrypt_flag_untrusted_server) > 0) && *keylist && !EMPTYSTR((*keylist)->value));
    3.74 @@ -3330,34 +3355,39 @@
    3.75      *keylist = NULL;
    3.76      *rating = PEP_rating_undefined;
    3.77  //    *flags = 0;
    3.78 -    
    3.79 +
    3.80      /*** End init ***/
    3.81  
    3.82 -    // Ok, before we do anything, if it's a pEp message, regardless of whether it's
    3.83 +    // KB: FIXME - we should do this once we've seen an inner message in the case 
    3.84 +    // of pEp users. Since we've not used 1.0 in a billion years (but will receive 
    3.85 +    // 1.0 messages from pEp users who don't yet know WE are pEp users), we should 
    3.86 +    // sort this out sanely, not upfront.
    3.87 +    //
    3.88 +    // Was: Ok, before we do anything, if it's a pEp message, regardless of whether it's
    3.89      // encrypted or not, we set the sender as a pEp user. This has NOTHING to do
    3.90      // with the key.
    3.91 -    if (src->from && !(is_me(session, src->from))) {
    3.92 -        if (is_pEp_msg) {
    3.93 -            pEp_identity* tmp_from = src->from;
    3.94 -            
    3.95 -            // Ensure there's a user id
    3.96 -            if (EMPTYSTR(tmp_from->user_id) && tmp_from->address) {
    3.97 -                status = update_identity(session, tmp_from);
    3.98 -                if (status == PEP_CANNOT_FIND_IDENTITY) {
    3.99 -                    tmp_from->user_id = calloc(1, strlen(tmp_from->address) + 6);
   3.100 -                    if (!tmp_from->user_id)
   3.101 -                        return PEP_OUT_OF_MEMORY;
   3.102 -                    snprintf(tmp_from->user_id, strlen(tmp_from->address) + 6,
   3.103 -                             "TOFU_%s", tmp_from->address);        
   3.104 -                    status = PEP_STATUS_OK;
   3.105 -                }
   3.106 -            }
   3.107 -            if (status == PEP_STATUS_OK) {
   3.108 -                // Now set user as PEP (may also create an identity if none existed yet)
   3.109 -                status = set_as_pEp_user(session, tmp_from);
   3.110 -            }
   3.111 -        }
   3.112 -    }
   3.113 +    // if (src->from && !(is_me(session, src->from))) {
   3.114 +    //     if (is_pEp_msg) {
   3.115 +    //         pEp_identity* tmp_from = src->from;
   3.116 +    // 
   3.117 +    //         // Ensure there's a user id
   3.118 +    //         if (EMPTYSTR(tmp_from->user_id) && tmp_from->address) {
   3.119 +    //             status = update_identity(session, tmp_from);
   3.120 +    //             if (status == PEP_CANNOT_FIND_IDENTITY) {
   3.121 +    //                 tmp_from->user_id = calloc(1, strlen(tmp_from->address) + 6);
   3.122 +    //                 if (!tmp_from->user_id)
   3.123 +    //                     return PEP_OUT_OF_MEMORY;
   3.124 +    //                 snprintf(tmp_from->user_id, strlen(tmp_from->address) + 6,
   3.125 +    //                          "TOFU_%s", tmp_from->address);        
   3.126 +    //                 status = PEP_STATUS_OK;
   3.127 +    //             }
   3.128 +    //         }
   3.129 +    //         if (status == PEP_STATUS_OK) {
   3.130 +    //             // Now set user as PEP (may also create an identity if none existed yet)
   3.131 +    //             status = set_as_pEp_user(session, tmp_from);
   3.132 +    //         }
   3.133 +    //     }
   3.134 +    // }
   3.135      // We really need key used in signing to do anything further on the pEp comm_type.
   3.136      // So we can't adjust the rating of the sender just yet.
   3.137  
   3.138 @@ -3373,16 +3403,16 @@
   3.139      import_header_keys(session, src);
   3.140      
   3.141      // FIXME: is this really necessary here?
   3.142 -    if (src->from) {
   3.143 -        if (!is_me(session, src->from))
   3.144 -            status = update_identity(session, src->from);
   3.145 -        else
   3.146 -            status = _myself(session, src->from, false, false, myself_read_only);
   3.147 -        
   3.148 -        // We absolutely should NOT be bailing here unless it's a serious error
   3.149 -        if (status == PEP_OUT_OF_MEMORY)
   3.150 -            return status;
   3.151 -    }
   3.152 +    // if (src->from) {
   3.153 +    //     if (!is_me(session, src->from))
   3.154 +    //         status = update_identity(session, src->from);
   3.155 +    //     else
   3.156 +    //         status = _myself(session, src->from, false, false, myself_read_only);
   3.157 +    // 
   3.158 +    //     // We absolutely should NOT be bailing here unless it's a serious error
   3.159 +    //     if (status == PEP_OUT_OF_MEMORY)
   3.160 +    //         return status;
   3.161 +    // }
   3.162      
   3.163      /*** End Import any attached public keys and update identities accordingly ***/
   3.164      
   3.165 @@ -3582,6 +3612,8 @@
   3.166                          goto pEp_error;
   3.167                                  
   3.168                      if (inner_message) {
   3.169 +                        is_pEp_msg = is_a_pEpmessage(inner_message);
   3.170 +                        
   3.171                          // Though this will strip any message info on the
   3.172                          // attachment, this is safe, as we do not
   3.173                          // produce more than one attachment-as-message,
   3.174 @@ -3592,16 +3624,17 @@
   3.175  
   3.176                          const stringpair_list_t* pEp_protocol_version = NULL;
   3.177                          pEp_protocol_version = stringpair_list_find(inner_message->opt_fields, "X-pEp-Version");
   3.178 -                        unsigned int pEp_v_major = 0;
   3.179 -                        unsigned int pEp_v_minor = 0;
   3.180 +                        
   3.181                          if (pEp_protocol_version && !EMPTYSTR(pEp_protocol_version->value->value)) {
   3.182                              // Roker is of course right. Meh :)
   3.183 -                            if (sscanf(pEp_protocol_version->value->value, "%u.%u", &pEp_v_major, &pEp_v_minor) != 2) {
   3.184 -                                pEp_v_major = 0;
   3.185 -                                pEp_v_minor = 0;
   3.186 +                            if (sscanf(pEp_protocol_version->value->value, "%f", &pEp_version) != 1) {
   3.187 +                                pEp_version = 0;
   3.188                              }
   3.189                          }
   3.190  
   3.191 +                        // Sort out pEp user status and version number based on INNER message.
   3.192 +                        
   3.193 +                        
   3.194                          bool is_inner = false;
   3.195                          bool is_key_reset = false;
   3.196  
   3.197 @@ -3613,7 +3646,7 @@
   3.198                          if (status != PEP_STATUS_OK)
   3.199                              goto pEp_error;                                         
   3.200                              
   3.201 -                        if (((pEp_v_major == 2) && (pEp_v_minor > 0)) || (pEp_v_major > 2)) {
   3.202 +                        if (pEp_version < 2) {
   3.203                              stringpair_list_t* searched = stringpair_list_find(inner_message->opt_fields, "X-pEp-Sender-FPR");                             
   3.204                              inner_message->_sender_fpr = ((searched && searched->value && searched->value->value) ? strdup(searched->value->value) : NULL);
   3.205                              searched = stringpair_list_find(inner_message->opt_fields, X_PEP_MSG_WRAP_KEY);
   3.206 @@ -3673,13 +3706,6 @@
   3.207                              //src = msg = inner_message;
   3.208                              calculated_src = msg = inner_message;
   3.209                              
   3.210 -                            // FIXME: should this be msg???
   3.211 -                            if (src->from) {
   3.212 -                                if (!is_me(session, src->from))
   3.213 -                                    update_identity(session, (src->from));
   3.214 -                                else
   3.215 -                                    _myself(session, src->from, false, false, myself_read_only);
   3.216 -                            }
   3.217                          }
   3.218                          else { // should never happen
   3.219                              status = PEP_UNKNOWN_ERROR;
   3.220 @@ -3700,14 +3726,35 @@
   3.221                  //  else {} // shouldn't be anything to be done here
   3.222      
   3.223              } // end if (has_inner || wrap_info)
   3.224 +            else {
   3.225 +                
   3.226 +            } // this we do if this isn't an inner message
   3.227 +            
   3.228 +            pEp_identity* cs_from = calculated_src->from;
   3.229 +            if (cs_from && !EMPTYSTR(cs_from->address)) {
   3.230 +                if (!is_me(session, cs_from)) {
   3.231 +                    status = update_identity(session, cs_from);
   3.232 +                    if (status == PEP_CANNOT_FIND_IDENTITY) {
   3.233 +                        cs_from->user_id = calloc(1, strlen(cs_from->address) + 6);
   3.234 +                        if (!cs_from->user_id)
   3.235 +                            return PEP_OUT_OF_MEMORY;
   3.236 +                        snprintf(cs_from->user_id, strlen(cs_from->address) + 6,
   3.237 +                                 "TOFU_%s", cs_from->address);        
   3.238 +                        status = PEP_STATUS_OK;
   3.239 +                    }
   3.240 +                }
   3.241 +                else
   3.242 +                    status = _myself(session, cs_from, false, false, myself_read_only);
   3.243 +            }                                                                        
   3.244          } // end if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED)
   3.245          
   3.246          *rating = decrypt_rating(decrypt_status);
   3.247          
   3.248          // Ok, so if it was signed and it's all verified, we can update
   3.249          // eligible signer comm_types to PEP_ct_pEp_*
   3.250 +        // This also sets and upgrades pEp version
   3.251          if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && is_pEp_msg && calculated_src->from)
   3.252 -            status = update_sender_to_pEp_trust(session, calculated_src->from, _keylist);
   3.253 +            status = update_sender_to_pEp_trust(session, calculated_src->from, _keylist, pEp_version);
   3.254  
   3.255          /* Ok, now we have a keylist used for decryption/verification.
   3.256             now we need to update the message rating with the 
     4.1 --- a/src/pEpEngine.c	Fri May 17 17:44:19 2019 +0200
     4.2 +++ b/src/pEpEngine.c	Sun May 19 15:13:55 2019 +0200
     4.3 @@ -83,7 +83,7 @@
     4.4  static const char *sql_get_identity =  
     4.5      "select fpr, username, comm_type, lang,"
     4.6      "   identity.flags | pgp_keypair.flags,"
     4.7 -    "   is_own, pEp_version"
     4.8 +    "   is_own"
     4.9      "   from identity"
    4.10      "   join person on id = identity.user_id"
    4.11      "   join pgp_keypair on fpr = identity.main_key_id"
    4.12 @@ -101,7 +101,7 @@
    4.13  static const char *sql_get_identities_by_main_key_id =  
    4.14      "select address, identity.user_id, username, comm_type, lang,"
    4.15      "   identity.flags | pgp_keypair.flags,"
    4.16 -    "   is_own, pEp_version"
    4.17 +    "   is_own"
    4.18      "   from identity"
    4.19      "   join person on id = identity.user_id"
    4.20      "   join pgp_keypair on fpr = identity.main_key_id"
    4.21 @@ -113,7 +113,7 @@
    4.22  
    4.23  static const char *sql_get_identity_without_trust_check =  
    4.24      "select identity.main_key_id, username, lang,"
    4.25 -    "   identity.flags, is_own, pEp_version"
    4.26 +    "   identity.flags, is_own"
    4.27      "   from identity"
    4.28      "   join person on id = identity.user_id"
    4.29      "   where (case when (address = ?1) then (1)"
    4.30 @@ -127,7 +127,7 @@
    4.31  
    4.32  static const char *sql_get_identities_by_address =  
    4.33      "select user_id, identity.main_key_id, username, lang,"
    4.34 -    "   identity.flags, is_own, pEp_version"
    4.35 +    "   identity.flags, is_own"
    4.36      "   from identity"
    4.37      "   join person on id = identity.user_id"
    4.38      "   where (case when (address = ?1) then (1)"
    4.39 @@ -141,7 +141,7 @@
    4.40  static const char *sql_get_identities_by_userid =  
    4.41      "select address, fpr, username, comm_type, lang,"
    4.42      "   identity.flags | pgp_keypair.flags,"
    4.43 -    "   is_own, pEp_version"
    4.44 +    "   is_own"
    4.45      "   from identity"
    4.46      "   join person on id = identity.user_id"
    4.47      "   join pgp_keypair on fpr = identity.main_key_id"
    4.48 @@ -239,22 +239,20 @@
    4.49  static const char *sql_set_identity_entry = 
    4.50      "insert into identity ("
    4.51      "       address, main_key_id, "
    4.52 -    "       user_id, flags, is_own, pEp_version"
    4.53 +    "       user_id, flags, is_own"
    4.54      "   ) values ("
    4.55      "       ?1,"
    4.56      "       upper(replace(?2,' ','')),"
    4.57      "       ?3,"
    4.58      "       ?4,"
    4.59 -    "       ?5,"
    4.60 -    "       ?6"
    4.61 +    "       ?5"
    4.62      "   );";
    4.63      
    4.64  static const char* sql_update_identity_entry =    
    4.65      "update identity "
    4.66      "   set main_key_id = upper(replace(?2,' ','')), "
    4.67      "       flags = ?4, " 
    4.68 -    "       is_own = ?5, "
    4.69 -    "       pEp_version = ?6 "
    4.70 +    "       is_own = ?5 "
    4.71      "   where (case when (address = ?1) then (1)"
    4.72      "               when (lower(address) = lower(?1)) then (1)"
    4.73      "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1) "
    4.74 @@ -303,6 +301,16 @@
    4.75      "          end) = 1"
    4.76      "          and user_id = ?3 ;";
    4.77  
    4.78 +static const char *sql_set_pEp_version =
    4.79 +    "update identity "
    4.80 +    "   set pEp_version = ?1 "
    4.81 +    "   where (case when (address = ?2) then (1)"
    4.82 +    "               when (lower(address) = lower(?2)) then (1)"
    4.83 +    "               when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1) "
    4.84 +    "               else 0 "
    4.85 +    "          end) = 1 "
    4.86 +    "          and user_id = ?3 ;";
    4.87 +
    4.88  static const char *sql_set_trust =
    4.89      "insert into trust (user_id, pgp_keypair_fpr, comm_type) "
    4.90      "values (?1, upper(replace(?2,' ','')), ?3) ;";
    4.91 @@ -355,7 +363,7 @@
    4.92  
    4.93  static const char *sql_i18n_token = 
    4.94      "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
    4.95 -
    4.96 +    
    4.97  // blacklist
    4.98  static const char *sql_blacklist_add = 
    4.99      "insert or ignore into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
   4.100 @@ -395,7 +403,7 @@
   4.101  
   4.102  static const char *sql_own_identities_retrieve =  
   4.103      "select address, fpr, identity.user_id, username,"
   4.104 -    "   lang, identity.flags | pgp_keypair.flags, pEp_version"
   4.105 +    "   lang, identity.flags | pgp_keypair.flags"
   4.106      "   from identity"
   4.107      "   join person on id = identity.user_id"
   4.108      "   join pgp_keypair on fpr = identity.main_key_id"
   4.109 @@ -906,7 +914,7 @@
   4.110      sqlite3_busy_timeout(_session->system_db, 1000);
   4.111  
   4.112  // increment this when patching DDL
   4.113 -#define _DDL_USER_VERSION "12"
   4.114 +#define _DDL_USER_VERSION "11"
   4.115  
   4.116      if (in_first) {
   4.117  
   4.118 @@ -967,7 +975,7 @@
   4.119                  "   comment text,\n"
   4.120                  "   flags integer default 0,\n"
   4.121                  "   is_own integer default 0,\n"
   4.122 -                "   pEp_version real default 0.0,\n"                
   4.123 +                "   pEp_version real default 0,\n"
   4.124                  "   timestamp integer default (datetime('now')),\n"
   4.125                  "   primary key (address, user_id)\n"
   4.126                  ");\n"
   4.127 @@ -1073,9 +1081,9 @@
   4.128          // Sometimes the user_version wasn't set correctly. 
   4.129          if (version == 1) {
   4.130              bool version_changed = true;
   4.131 -            if (table_contains_column(_session, "identity", "pEp_version") > 0) {
   4.132 +            if (table_contains_column(_session, "identity", "pEp_version")) {
   4.133                  version = 12;
   4.134 -            } // N.B. Version 11 was a DB internal fix; there's no identifying information, but this is only one extra exec.
   4.135 +            }
   4.136              else if (db_contains_table(_session, "social_graph") > 0) {
   4.137                  if (!table_contains_column(_session, "person", "device_group"))
   4.138                      version = 10;
   4.139 @@ -1433,12 +1441,13 @@
   4.140                  int_result = sqlite3_exec(
   4.141                      _session->db,
   4.142                      "alter table identity\n"
   4.143 -                    "   add column pEp_version real default 0.0;\n",
   4.144 +                    "   add column pEp_version real default 0\n",
   4.145                      NULL,
   4.146                      NULL,
   4.147                      NULL
   4.148                  );
   4.149 -                assert(int_result == SQLITE_OK);                
   4.150 +                if (status != PEP_STATUS_OK)
   4.151 +                    return status;                
   4.152              }
   4.153          }        
   4.154          else { 
   4.155 @@ -1638,6 +1647,11 @@
   4.156              NULL);
   4.157      assert(int_result == SQLITE_OK);
   4.158  
   4.159 +    int_result = sqlite3_prepare_v2(_session->db, sql_set_pEp_version,
   4.160 +            (int)strlen(sql_set_pEp_version), &_session->set_pEp_version,
   4.161 +            NULL);
   4.162 +    assert(int_result == SQLITE_OK);
   4.163 +
   4.164      int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
   4.165              (int)strlen(sql_set_trust), &_session->set_trust, NULL);
   4.166      assert(int_result == SQLITE_OK);
   4.167 @@ -2468,8 +2482,6 @@
   4.168              sqlite3_column_int(session->get_identity, 4);
   4.169          _identity->me = (unsigned int)
   4.170              sqlite3_column_int(session->get_identity, 5);
   4.171 -        _identity->pEp_version = (float)
   4.172 -            sqlite3_column_double(session->get_identity, 6);
   4.173      
   4.174          *identity = _identity;
   4.175          break;
   4.176 @@ -2544,8 +2556,6 @@
   4.177              sqlite3_column_int(session->get_identities_by_userid, 5);
   4.178          ident->me = (unsigned int)
   4.179              sqlite3_column_int(session->get_identities_by_userid, 6);
   4.180 -        ident->pEp_version = (float)
   4.181 -            sqlite3_column_double(session->get_identities_by_userid, 7);
   4.182      
   4.183          identity_list_add(*identities, ident);
   4.184          ident = NULL;
   4.185 @@ -2612,8 +2622,6 @@
   4.186              sqlite3_column_int(session->get_identities_by_main_key_id, 5);
   4.187          ident->me = (unsigned int)
   4.188              sqlite3_column_int(session->get_identities_by_main_key_id, 6);
   4.189 -        ident->pEp_version = (float)
   4.190 -            sqlite3_column_double(session->get_identities_by_main_key_id, 7);
   4.191      
   4.192          identity_list_add(*identities, ident);
   4.193          ident = NULL;
   4.194 @@ -2684,8 +2692,6 @@
   4.195              sqlite3_column_int(session->get_identity_without_trust_check, 3);
   4.196          _identity->me = (unsigned int)
   4.197              sqlite3_column_int(session->get_identity_without_trust_check, 4);
   4.198 -        _identity->pEp_version = (float)
   4.199 -            sqlite3_column_double(session->get_identity_without_trust_check, 5);
   4.200      
   4.201          *identity = _identity;
   4.202          break;
   4.203 @@ -2751,8 +2757,6 @@
   4.204              sqlite3_column_int(session->get_identities_by_address, 4);
   4.205          ident->me = (unsigned int)
   4.206              sqlite3_column_int(session->get_identities_by_address, 5);
   4.207 -        ident->pEp_version = (float)
   4.208 -            sqlite3_column_double(session->get_identities_by_address, 6);
   4.209      
   4.210          if (ident_list)
   4.211              identity_list_add(ident_list, ident);
   4.212 @@ -2909,7 +2913,6 @@
   4.213              SQLITE_STATIC);
   4.214      sqlite3_bind_int(set_or_update, 4, identity->flags);
   4.215      sqlite3_bind_int(set_or_update, 5, identity->me);
   4.216 -    sqlite3_bind_double(set_or_update, 6, identity->pEp_version);
   4.217      int result = sqlite3_step(set_or_update);
   4.218      sqlite3_reset(set_or_update);
   4.219      if (result != SQLITE_DONE)
   4.220 @@ -3023,7 +3026,7 @@
   4.221                                         guard_transaction);
   4.222  }
   4.223  
   4.224 -// This will NOT call set_as_pEp_user; you have to do that separately.
   4.225 +// This will NOT call set_as_pEp_user, nor set_pEp_version; you have to do that separately.
   4.226  DYNAMIC_API PEP_STATUS set_identity(
   4.227          PEP_SESSION session, const pEp_identity *identity
   4.228      )
   4.229 @@ -3155,6 +3158,29 @@
   4.230      return status;
   4.231  }
   4.232  
   4.233 +// This ONLY sets the version flag. Must be called outside of a transaction.
   4.234 +PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, float new_pEp_version) {
   4.235 +    assert(session);
   4.236 +    assert(!EMPTYSTR(ident->user_id));
   4.237 +    assert(!EMPTYSTR(ident->address));
   4.238 +    
   4.239 +    sqlite3_reset(session->set_pEp_version);
   4.240 +    sqlite3_bind_double(session->set_pEp_version, 1, new_pEp_version);
   4.241 +    sqlite3_bind_text(session->set_pEp_version, 2, ident->address, -1,
   4.242 +            SQLITE_STATIC);
   4.243 +    sqlite3_bind_text(session->set_pEp_version, 3, ident->user_id, -1,
   4.244 +            SQLITE_STATIC);
   4.245 +    
   4.246 +    int result = sqlite3_step(session->set_pEp_version);
   4.247 +    sqlite3_reset(session->set_pEp_version);
   4.248 +        
   4.249 +    if (result != SQLITE_DONE)
   4.250 +        return PEP_CANNOT_SET_PEP_VERSION;
   4.251 +    
   4.252 +    return PEP_STATUS_OK;
   4.253 +}
   4.254 +
   4.255 +
   4.256  PEP_STATUS exists_person(PEP_SESSION session, pEp_identity* identity,
   4.257                           bool* exists) {            
   4.258      
     5.1 --- a/src/pEpEngine.h	Fri May 17 17:44:19 2019 +0200
     5.2 +++ b/src/pEpEngine.h	Sun May 19 15:13:55 2019 +0200
     5.3 @@ -68,6 +68,7 @@
     5.4      PEP_CANNOT_SET_TRUST                            = 0x0384,
     5.5      PEP_KEY_BLACKLISTED                             = 0x0385,
     5.6      PEP_CANNOT_FIND_PERSON                          = 0x0386,
     5.7 +    PEP_CANNOT_SET_PEP_VERSION                      = 0X0387,
     5.8      
     5.9      PEP_CANNOT_FIND_ALIAS                           = 0x0391,
    5.10      PEP_CANNOT_SET_ALIAS                            = 0x0392,
    5.11 @@ -630,9 +631,8 @@
    5.12      PEP_comm_type comm_type;    // type of communication with this ID
    5.13      char lang[3];               // language of conversation
    5.14                                  // ISO 639-1 ALPHA-2, last byte is 0
    5.15 -    float pEp_version;          // Used to determine highest seenencryption format.
    5.16 -                                // default is 2.0 for pEp users                            
    5.17      bool me;                    // if this is the local user herself/himself
    5.18 +    float _pEp_version;         // highest version of pEp message received, if any
    5.19      identity_flags_t flags;     // identity_flag1 | identity_flag2 | ...
    5.20  } pEp_identity;
    5.21  
    5.22 @@ -1386,6 +1386,8 @@
    5.23  
    5.24  PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr);
    5.25  
    5.26 +PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, float new_pEp_version);
    5.27 +
    5.28  // exposed for testing
    5.29  PEP_STATUS set_person(PEP_SESSION session, pEp_identity* identity,
    5.30                        bool guard_transaction);
     6.1 --- a/src/pEp_internal.h	Fri May 17 17:44:19 2019 +0200
     6.2 +++ b/src/pEp_internal.h	Sun May 19 15:13:55 2019 +0200
     6.3 @@ -195,6 +195,7 @@
     6.4      sqlite3_stmt *exists_identity_entry;        
     6.5      sqlite3_stmt *set_identity_flags;
     6.6      sqlite3_stmt *unset_identity_flags;
     6.7 +    sqlite3_stmt *set_pEp_version;    
     6.8      sqlite3_stmt *set_trust;
     6.9      sqlite3_stmt *update_trust;
    6.10      sqlite3_stmt *exists_trust_entry;
     7.1 --- a/test/src/util/test_util.cc	Fri May 17 17:44:19 2019 +0200
     7.2 +++ b/test/src/util/test_util.cc	Sun May 19 15:13:55 2019 +0200
     7.3 @@ -184,6 +184,8 @@
     7.4              return "PEP_CANNOT_SET_PERSON";
     7.5          case PEP_CANNOT_SET_PGP_KEYPAIR:
     7.6              return "PEP_CANNOT_SET_PGP_KEYPAIR";
     7.7 +        case PEP_CANNOT_SET_PEP_VERSION:
     7.8 +            return "PEP_CANNOT_SET_PEP_VERSION";
     7.9          case PEP_CANNOT_SET_IDENTITY:
    7.10              return "PEP_CANNOT_SET_IDENTITY";
    7.11          case PEP_CANNOT_SET_TRUST: