src/pEpEngine.c
author Krista Bennett <krista@pep-project.org>
Wed, 07 Feb 2018 16:42:56 +0100
branchENGINE-250
changeset 2483 7fb3205f2893
parent 2481 dd1eaa8cc1eb
child 2486 7534aeca7061
permissions -rw-r--r--
ENGINE-250: foreign keys are now on and tests pass. Be aware that with the amount of time we may have been running with them off, there may be other execution paths that cause trouble. File bugs against any DB errors.
vb@1517
     1
// This file is under GNU General Public License 3.0
vb@1517
     2
// see LICENSE.txt
vb@1517
     3
vb@125
     4
#include "pEp_internal.h"
vb@98
     5
#include "dynamic_api.h"
vb@28
     6
#include "cryptotech.h"
vb@28
     7
#include "transport.h"
vb@515
     8
#include "blacklist.h"
vb@0
     9
krista@2176
    10
#include <time.h>
krista@2176
    11
#include <stdlib.h>
krista@2479
    12
#include <sqlite3.h>
krista@2176
    13
krista@2483
    14
#define _PEP_SQLITE_DEBUG 0
krista@2480
    15
krista@2125
    16
static volatile int init_count = -1;
vb@62
    17
krista@1884
    18
// sql overloaded functions - modified from sqlite3.c
krista@1884
    19
static void _sql_lower(sqlite3_context* ctx, int argc, sqlite3_value** argv) {
krista@1884
    20
    char *z1;
krista@1884
    21
    const char *z2;
krista@1884
    22
    int i, n;
krista@1884
    23
    z2 = (char*)sqlite3_value_text(argv[0]);
krista@1884
    24
    n = sqlite3_value_bytes(argv[0]);
krista@1884
    25
    /* Verify that the call to _bytes() does not invalidate the _text() pointer */
krista@1884
    26
    assert( z2==(char*)sqlite3_value_text(argv[0]) );
krista@1884
    27
    if( z2 ){
krista@1884
    28
        z1 = (char*)sqlite3_malloc(n+1);
krista@1884
    29
        if( z1 ){
krista@1884
    30
            for(i=0; i<n; i++){
krista@1884
    31
                char c = z2[i];
krista@1884
    32
                char c_mod = c | 0x20;
krista@1884
    33
                if (c_mod < 0x61 || c_mod > 0x7a)
krista@1884
    34
                    c_mod = c;
krista@1884
    35
                z1[i] = c_mod;
krista@1884
    36
            }
krista@1884
    37
            z1[n] = '\0';
krista@1884
    38
            sqlite3_result_text(ctx, z1, n, sqlite3_free);
krista@1884
    39
        }
krista@1884
    40
    }
krista@1884
    41
}
krista@1884
    42
krista@2480
    43
#if _PEP_SQLITE_DEBUG
krista@2479
    44
int sql_trace_callback (unsigned trace_constant, 
krista@2479
    45
                        void* context_ptr,
krista@2479
    46
                        void* P,
krista@2479
    47
                        void* X) {
krista@2479
    48
    switch (trace_constant) {
krista@2479
    49
        case SQLITE_TRACE_STMT:
krista@2479
    50
            fprintf(stderr, "SQL_DEBUG: STMT - ");
krista@2479
    51
            const char* X_str = (const char*) X;
krista@2479
    52
            if (!EMPTYSTR(X_str) && X_str[0] == '-' && X_str[1] == '-')
krista@2479
    53
                fprintf(stderr, "%s\n", X_str);
krista@2479
    54
            else
krista@2479
    55
                fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P));
krista@2479
    56
            break;
krista@2479
    57
        case SQLITE_TRACE_ROW:
krista@2479
    58
            fprintf(stderr, "SQL_DEBUG: ROW - ");
krista@2479
    59
            fprintf(stderr, "%s\n", sqlite3_expanded_sql((sqlite3_stmt*)P));
krista@2479
    60
            break;            
krista@2479
    61
        case SQLITE_TRACE_CLOSE:
krista@2479
    62
            fprintf(stderr, "SQL_DEBUG: CLOSE - ");
krista@2479
    63
            break;
krista@2479
    64
        default:
krista@2479
    65
            break;
krista@2479
    66
    }
krista@2479
    67
    return 0;
krista@2479
    68
}
krista@2480
    69
#endif
krista@1884
    70
edouard@1518
    71
// sql manipulation statements
edouard@1518
    72
static const char *sql_log = 
edouard@1518
    73
    "insert into log (title, entity, description, comment)"
edouard@1518
    74
     "values (?1, ?2, ?3, ?4);";
edouard@1518
    75
edouard@1518
    76
static const char *sql_trustword = 
edouard@1518
    77
    "select id, word from wordlist where lang = lower(?1) "
edouard@1518
    78
    "and id = ?2 ;";
edouard@1518
    79
edouard@1518
    80
static const char *sql_get_identity =  
edouard@1518
    81
    "select fpr, username, comm_type, lang,"
krista@2461
    82
    "   identity.flags | pgp_keypair.flags,"
krista@2461
    83
    "   is_own"
edouard@1518
    84
    "   from identity"
edouard@1518
    85
    "   join person on id = identity.user_id"
edouard@1518
    86
    "   join pgp_keypair on fpr = identity.main_key_id"
edouard@1518
    87
    "   join trust on id = trust.user_id"
krista@1884
    88
    "       and pgp_keypair_fpr = identity.main_key_id"    
krista@1884
    89
    "   where (case when (address = ?1) then (1)"
krista@1884
    90
    "               when (lower(address) = lower(?1)) then (1)"
krista@1884
    91
    "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
krista@1884
    92
    "               else 0"
krista@1884
    93
    "          end) = 1"
krista@1868
    94
    "   and identity.user_id = ?2;";
edouard@1518
    95
krista@2461
    96
static const char *sql_get_identity_without_trust_check =  
krista@2461
    97
    "select identity.main_key_id, username, lang,"
krista@2461
    98
    "   identity.flags, is_own"
krista@2461
    99
    "   from identity"
krista@2461
   100
    "   join person on id = identity.user_id"
krista@2461
   101
    "   where (case when (address = ?1) then (1)"
krista@2461
   102
    "               when (lower(address) = lower(?1)) then (1)"
krista@2461
   103
    "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
krista@2461
   104
    "               else 0"
krista@2461
   105
    "          end) = 1"
krista@2461
   106
    "   and identity.user_id = ?2;";
krista@2461
   107
krista@2461
   108
static const char *sql_get_identities_by_address =  
krista@2461
   109
    "select user_id, identity.main_key_id, username, lang,"
krista@2461
   110
    "   identity.flags, is_own"
krista@2461
   111
    "   from identity"
krista@2461
   112
    "   join person on id = identity.user_id"
krista@2461
   113
    "   where (case when (address = ?1) then (1)"
krista@2461
   114
    "               when (lower(address) = lower(?1)) then (1)"
krista@2461
   115
    "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
krista@2461
   116
    "               else 0"
krista@2461
   117
    "          end) = 1;";
krista@2461
   118
krista@1799
   119
static const char *sql_replace_identities_fpr =  
krista@1799
   120
    "update identity"
krista@1799
   121
    "   set main_key_id = ?1 "
krista@1799
   122
    "   where main_key_id = ?2 ;";
krista@2461
   123
    
krista@2461
   124
static const char *sql_remove_fpr_as_default =
krista@2461
   125
    "update person set main_key_id = NULL where main_key_id = ?1 ;"
krista@2461
   126
    "update identity set main_key_id = NULL where main_key_id = ?1 ;";
krista@1793
   127
edouard@1518
   128
// Set person, but if already exist, only update.
edouard@1518
   129
// if main_key_id already set, don't touch.
edouard@1518
   130
static const char *sql_set_person = 
krista@2479
   131
     "insert into person (id, username, lang, main_key_id, device_group)"
krista@2477
   132
     "  values (?1, ?2, ?3,"
krista@2478
   133
//     "    (select coalesce( "
krista@2478
   134
//     "          (select main_key_id from person where id = ?1), " 
krista@2478
   135
//     "           upper(replace(?4,' ','')))),"
krista@2478
   136
    "   ?4,"
krista@2478
   137
     "    (select device_group from person where id = ?1)) ;";
krista@2478
   138
krista@2478
   139
static const char *sql_update_person = 
krista@2477
   140
    "update person "
krista@2477
   141
    "   set username = ?2, "
krista@2477
   142
    "       lang = ?3, "
krista@2477
   143
    "       main_key_id =  "
krista@2477
   144
    "           (select coalesce( "
krista@2477
   145
    "               (select main_key_id from person where id = ?1), " 
krista@2477
   146
    "                upper(replace(?4,' ','')))),"         
krista@2477
   147
    "       device_group = "
krista@2477
   148
    "           (select device_group from person where id = ?1)"
krista@2477
   149
    "   where id = ?1 ;";
krista@2477
   150
    
krista@2468
   151
static const char *sql_set_as_pep_user =
krista@2468
   152
    "update person set is_pep_user = 1 "
krista@2468
   153
    "   where id = ?1 ; ";
krista@2468
   154
krista@2468
   155
static const char *sql_is_pep_user =
krista@2468
   156
    "select is_pep_user from person "
krista@2468
   157
    "   where id = ?1 ; ";
krista@2468
   158
krista@2468
   159
static const char* sql_exists_person = 
krista@2468
   160
    "select count(*) from person "
krista@2468
   161
    "   where id = ?1 ;";
krista@2468
   162
edouard@1518
   163
static const char *sql_set_device_group = 
edouard@1518
   164
    "update person set device_group = ?1 "
krista@2468
   165
    "   where id = ?2;";
krista@2461
   166
krista@2461
   167
// This will cascade to identity and trust
krista@2461
   168
static const char* sql_replace_userid =
krista@2461
   169
    "update person set id = ?1 " 
krista@2468
   170
    "   where id = ?2;";
krista@2461
   171
krista@2461
   172
static const char *sql_replace_main_user_fpr =  
krista@2461
   173
    "update person "
krista@2461
   174
    "   set main_key_id = ?1 "
krista@2461
   175
    "   where id = ?2 ;";
krista@2461
   176
krista@2461
   177
static const char *sql_get_main_user_fpr =  
krista@2461
   178
    "select main_key_id from person"
krista@2461
   179
    "   where id = ?1 ;";
krista@2461
   180
krista@2461
   181
static const char *sql_refresh_userid_default_key =
krista@2461
   182
    "update person "
krista@2461
   183
    "   set main_key_id = "
krista@2461
   184
    "       (select identity.main_key_id from identity "
krista@2461
   185
    "           join trust on trust.user_id = identity.user_id "
krista@2461
   186
    "               and trust.pgp_keypair_fpr = identity.main_key_id "
krista@2461
   187
    "           join person on identity.user_id = identity.user_id "
krista@2461
   188
    "       where identity.user_id = ?1 "
krista@2461
   189
    "       order by trust.comm_type desc "
krista@2461
   190
    "       limit 1) "
krista@2461
   191
    "where id = ?1 ; ";
edouard@1518
   192
edouard@1518
   193
static const char *sql_get_device_group = 
edouard@1518
   194
    "select device_group from person "
krista@2461
   195
    "where id = ?1;";
edouard@1518
   196
edouard@1518
   197
static const char *sql_set_pgp_keypair = 
krista@2477
   198
    "insert or ignore into pgp_keypair (fpr) "
edouard@1518
   199
    "values (upper(replace(?1,' ',''))) ;";
edouard@1518
   200
krista@2480
   201
static const char* sql_exists_identity_entry = 
krista@2480
   202
    "select count(*) from identity "
krista@2481
   203
    "   where (case when (address = ?1) then (1)"
krista@2481
   204
    "               when (lower(address) = lower(?1)) then (1)"
krista@2481
   205
    "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1)"
krista@2481
   206
    "               else 0"
krista@2481
   207
    "          end) = 1"
krista@2481
   208
    "    and user_id = ?2;";
krista@2481
   209
 
krista@2478
   210
static const char *sql_set_identity_entry = 
krista@2479
   211
    "insert into identity ("
krista@2477
   212
    "       address, main_key_id, "
krista@2477
   213
    "       user_id, flags, is_own"
krista@2477
   214
    "   ) values ("
krista@2477
   215
    "       ?1,"
krista@2477
   216
    "       upper(replace(?2,' ','')),"
krista@2477
   217
    "       ?3,"
krista@2477
   218
    "       ?4,"
krista@2477
   219
    "       ?5"
krista@2478
   220
    "   );";
krista@2478
   221
    
krista@2478
   222
static const char* sql_update_identity_entry =    
krista@2477
   223
    "update identity "
krista@2477
   224
    "   set main_key_id = upper(replace(?2,' ','')), "
krista@2477
   225
    "       flags = ?4, " 
krista@2477
   226
    "       is_own = ?5 "
krista@2481
   227
    "   where (case when (address = ?1) then (1)"
krista@2481
   228
    "               when (lower(address) = lower(?1)) then (1)"
krista@2481
   229
    "               when (replace(lower(address),'.','') = replace(lower(?1),'.','')) then (1) "
krista@2481
   230
    "               else 0 "
krista@2481
   231
    "          end) = 1 "
krista@2481
   232
    "          and user_id = ?3 ;";
krista@2477
   233
edouard@1518
   234
    // " (select"
edouard@1518
   235
    // "   coalesce("
edouard@1518
   236
    // "    (select flags from identity"
edouard@1518
   237
    // "     where address = ?1 and"
edouard@1518
   238
    // "           user_id = ?3),"
edouard@1518
   239
    // "    0)"
edouard@1518
   240
    // " ) | (?4 & 255)"
edouard@1518
   241
    /* set_identity ignores previous flags, and doesn't filter machine flags */
edouard@1518
   242
        
edouard@1518
   243
static const char *sql_set_identity_flags = 
edouard@1518
   244
    "update identity set flags = "
edouard@1518
   245
    "    ((?1 & 255) | (select flags from identity"
krista@2481
   246
    "                    where (case when (address = ?2) then (1)"
krista@2481
   247
    "                                when (lower(address) = lower(?2)) then (1)"
krista@2481
   248
    "                                when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)"
krista@2481
   249
    "                                else 0 "    
krista@2481
   250
    "                           end) = 1 "
krista@2481
   251
    "                           and user_id = ?3)) "
krista@2481
   252
    "   where (case when (address = ?2) then (1)"
krista@2481
   253
    "               when (lower(address) = lower(?2)) then (1)"
krista@2481
   254
    "               when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)"
krista@2481
   255
    "               else 0"
krista@2481
   256
    "          end) = 1"
krista@2481
   257
    "          and user_id = ?3 ;";
edouard@1518
   258
edouard@1518
   259
static const char *sql_unset_identity_flags = 
edouard@1518
   260
    "update identity set flags = "
edouard@1518
   261
    "    ( ~(?1 & 255) & (select flags from identity"
krista@2481
   262
    "                    where (case when (address = ?2) then (1)"
krista@2481
   263
    "                                when (lower(address) = lower(?2)) then (1)"
krista@2481
   264
    "                                when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)"
krista@2481
   265
    "                                else 0 "    
krista@2481
   266
    "                           end) = 1 "
krista@2481
   267
    "                           and user_id = ?3)) "
krista@2481
   268
    "   where (case when (address = ?2) then (1)"
krista@2481
   269
    "               when (lower(address) = lower(?2)) then (1)"
krista@2481
   270
    "               when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1)"
krista@2481
   271
    "               else 0"
krista@2481
   272
    "          end) = 1"
krista@2481
   273
    "          and user_id = ?3 ;";
edouard@1518
   274
edouard@1518
   275
static const char *sql_set_trust =
krista@2479
   276
    "insert into trust (user_id, pgp_keypair_fpr, comm_type) "
krista@2478
   277
    "values (?1, upper(replace(?2,' ','')), ?3) ;";
krista@2478
   278
krista@2478
   279
static const char *sql_update_trust =
krista@2477
   280
    "update trust set comm_type = ?3 " 
krista@2477
   281
    "   where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));";
krista@2480
   282
krista@2480
   283
static const char* sql_exists_trust_entry = 
krista@2480
   284
    "select count(*) from trust "
krista@2480
   285
    "   where user_id = ?1 and pgp_keypair_fpr = upper(replace(?2,' ',''));";
krista@2477
   286
    
krista@1799
   287
static const char *sql_update_trust_for_fpr =
krista@1799
   288
    "update trust "
krista@1799
   289
    "set comm_type = ?1 "
krista@1799
   290
    "where pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
krista@1799
   291
edouard@1518
   292
static const char *sql_get_trust = 
edouard@1518
   293
    "select comm_type from trust where user_id = ?1 "
edouard@1518
   294
    "and pgp_keypair_fpr = upper(replace(?2,' ','')) ;";
edouard@1518
   295
edouard@1518
   296
static const char *sql_least_trust = 
edouard@1632
   297
    "select min(comm_type) from trust where"
edouard@1632
   298
    " pgp_keypair_fpr = upper(replace(?1,' ',''))"
edouard@1632
   299
    " and comm_type != 0;"; // ignores PEP_ct_unknown
edouard@1632
   300
    // returns PEP_ct_unknown only when no known trust is recorded
edouard@1518
   301
edouard@1518
   302
static const char *sql_mark_as_compromized = 
edouard@1518
   303
    "update trust not indexed set comm_type = 15"
edouard@1518
   304
    " where pgp_keypair_fpr = upper(replace(?1,' ','')) ;";
krista@2461
   305
    
edouard@1518
   306
static const char *sql_crashdump = 
edouard@1518
   307
    "select timestamp, title, entity, description, comment"
edouard@1518
   308
    " from log order by timestamp desc limit ?1 ;";
edouard@1518
   309
edouard@1518
   310
static const char *sql_languagelist = 
edouard@1518
   311
    "select i18n_language.lang, name, phrase" 
edouard@1518
   312
    " from i18n_language join i18n_token using (lang) where i18n_token.id = 1000;" ;
edouard@1518
   313
edouard@1518
   314
static const char *sql_i18n_token = 
edouard@1518
   315
    "select phrase from i18n_token where lang = lower(?1) and id = ?2 ;";
edouard@1518
   316
edouard@1518
   317
// blacklist
edouard@1518
   318
static const char *sql_blacklist_add = 
krista@2477
   319
    "insert or ignore into blacklist_keys (fpr) values (upper(replace(?1,' ',''))) ;"
edouard@1518
   320
    "delete from identity where main_key_id = upper(replace(?1,' ','')) ;"
edouard@1518
   321
    "delete from pgp_keypair where fpr = upper(replace(?1,' ','')) ;";
edouard@1518
   322
edouard@1518
   323
static const char *sql_blacklist_delete =
edouard@1518
   324
    "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
edouard@1518
   325
edouard@1518
   326
static const char *sql_blacklist_is_listed = 
edouard@1518
   327
    "select count(*) from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
edouard@1518
   328
edouard@1518
   329
static const char *sql_blacklist_retrieve = 
edouard@1518
   330
    "select * from blacklist_keys ;";
edouard@1518
   331
                
edouard@1518
   332
edouard@1518
   333
// Own keys
krista@2461
   334
// We only care if it's 0 or non-zero
edouard@1518
   335
static const char *sql_own_key_is_listed = 
edouard@1518
   336
    "select count(*) from ("
krista@2461
   337
    "   select pgp_keypair_fpr from trust"
krista@2461
   338
    "      join identity on trust.user_id = identity.user_id"
krista@2461
   339
    "      where pgp_keypair_fpr = upper(replace(?1,' ',''))"
krista@2461
   340
    "           and identity.is_own = 1"
krista@2461
   341
    ");";
edouard@1518
   342
edouard@1518
   343
static const char *sql_own_identities_retrieve =  
krista@2461
   344
    "select address, fpr, username, identity.user_id, "
edouard@1518
   345
    "   lang, identity.flags | pgp_keypair.flags"
edouard@1518
   346
    "   from identity"
edouard@1518
   347
    "   join person on id = identity.user_id"
edouard@1518
   348
    "   join pgp_keypair on fpr = identity.main_key_id"
edouard@1518
   349
    "   join trust on id = trust.user_id"
edouard@1518
   350
    "       and pgp_keypair_fpr = identity.main_key_id"
krista@2461
   351
    "   where identity.is_own = 1"
edouard@1518
   352
    "       and (identity.flags & ?1) = 0;";
krista@2461
   353
krista@2461
   354
static const char *sql_own_keys_retrieve = 
krista@2461
   355
    "select pgp_keypair_fpr from trust"
krista@2461
   356
    "   join identity on trust.user_id = identity.user_id"
krista@2461
   357
    "   where identity.is_own = 1";
krista@2461
   358
krista@2461
   359
static const char* sql_get_user_default_key =
krista@2461
   360
    "select main_key_id from person" 
krista@2461
   361
    "   where id = ?1;";
krista@2461
   362
krista@2461
   363
static const char* sql_get_default_own_userid =
krista@2461
   364
    "select id from person"
krista@2461
   365
    "   join identity on id = identity.user_id"
krista@2461
   366
    "   where identity.is_own = 1";
edouard@1518
   367
edouard@1518
   368
// Sequence
edouard@1518
   369
static const char *sql_sequence_value1 = 
edouard@1518
   370
    "insert or replace into sequences (name, value, own) "
edouard@1518
   371
    "values (?1, "
edouard@1602
   372
    "       (select coalesce((select value + 1 from sequences "
edouard@1602
   373
    "           where name = ?1), 1 )), "
edouard@1602
   374
    "       (select coalesce((select own or ?2 from sequences "
edouard@1602
   375
    "           where name = ?1), ?2))) ; ";
edouard@1518
   376
edouard@1518
   377
static const char *sql_sequence_value2 = 
edouard@1518
   378
    "select value, own from sequences where name = ?1 ;";
edouard@1518
   379
edouard@1518
   380
static const char *sql_sequence_value3 = 
edouard@1636
   381
    "insert or replace into sequences (name, value, own) "
edouard@1636
   382
    "values (?1, "
edouard@1636
   383
    "        ?2, "
edouard@1636
   384
    "       (select coalesce((select own or ?3 from sequences "
edouard@1636
   385
    "           where name = ?1), ?3))) ; ";
edouard@1518
   386
        
edouard@1518
   387
// Revocation tracking
edouard@1518
   388
static const char *sql_set_revoked =
edouard@1518
   389
    "insert or replace into revoked_keys ("
edouard@1518
   390
    "    revoked_fpr, replacement_fpr, revocation_date) "
edouard@1518
   391
    "values (upper(replace(?1,' ','')),"
edouard@1518
   392
    "        upper(replace(?2,' ','')),"
edouard@1518
   393
    "        ?3) ;";
edouard@1518
   394
        
edouard@1518
   395
static const char *sql_get_revoked = 
edouard@1518
   396
    "select revoked_fpr, revocation_date from revoked_keys"
edouard@1518
   397
    "    where replacement_fpr = upper(replace(?1,' ','')) ;";
edouard@1518
   398
krista@2461
   399
static const char *sql_get_userid_alias_default =
krista@2461
   400
    "select default_id from alternate_user_id "
krista@2461
   401
    "   where alternate_id = ?1 ; ";
krista@2461
   402
krista@2471
   403
// Revocation tracking
krista@2471
   404
static const char *sql_add_mistrusted_key =
krista@2478
   405
    "insert or replace into mistrusted_keys (fpr) "
krista@2471
   406
    "   values (upper(replace(?1,' ',''))) ;";
krista@2471
   407
        
krista@2471
   408
static const char *sql_delete_mistrusted_key = 
krista@2471
   409
    "delete from blacklist_keys where fpr = upper(replace(?1,' ','')) ;";
krista@2471
   410
krista@2471
   411
static const char *sql_is_mistrusted_key = 
krista@2471
   412
    "select count(*) from mistrusted_keys where fpr = upper(replace(?1,' ','')) ;";
krista@2471
   413
krista@2461
   414
static const char *sql_add_userid_alias =
krista@2479
   415
    "insert or replace into alternate_user_id (alternate_id, default_id) "
krista@2479
   416
    "values (?2, ?1) ;";
krista@2461
   417
    
vb@928
   418
static int user_version(void *_version, int count, char **text, char **name)
vb@928
   419
{
vb@928
   420
    assert(_version);
vb@928
   421
    assert(count == 1);
vb@928
   422
    assert(text && text[0]);
vb@928
   423
    if (!(_version && count == 1 && text && text[0]))
vb@928
   424
        return -1;
vb@928
   425
vb@928
   426
    int *version = (int *) _version;
vb@928
   427
    *version = atoi(text[0]);
vb@928
   428
    return 0;
vb@928
   429
}
vb@928
   430
krista@2461
   431
static int table_contains_column(PEP_SESSION session, const char* table_name,
krista@2461
   432
                                                      const char* col_name) {
krista@2461
   433
krista@2461
   434
krista@2461
   435
    if (!session || !table_name || !col_name)
krista@2461
   436
        return -1;
krista@2461
   437
        
krista@2461
   438
    // Table names can't be SQL parameters, so we do it this way.
krista@2461
   439
    
krista@2461
   440
    // these two must be the same number.
krista@2461
   441
    char sql_buf[500];
krista@2461
   442
    const size_t max_q_len = 500;
krista@2461
   443
    
krista@2461
   444
    size_t t_size, c_size, q_size;
krista@2461
   445
    
krista@2461
   446
    const char* q1 = "SELECT "; // 7
krista@2461
   447
    const char* q2 = " from "; // 6
krista@2461
   448
    const char* q3 = ";";       // 1
krista@2461
   449
    
krista@2461
   450
    q_size = 14;
krista@2461
   451
    t_size = strlen(table_name);
krista@2461
   452
    c_size = strlen(col_name);
krista@2461
   453
    
krista@2461
   454
    size_t query_len = q_size + c_size + t_size + 1;
krista@2461
   455
    
krista@2461
   456
    if (query_len > max_q_len)
krista@2461
   457
        return -1;
krista@2461
   458
krista@2461
   459
    strlcpy(sql_buf, q1, max_q_len);
krista@2461
   460
    strlcat(sql_buf, col_name, max_q_len);
krista@2461
   461
    strlcat(sql_buf, q2, max_q_len);
krista@2461
   462
    strlcat(sql_buf, table_name, max_q_len);
krista@2461
   463
    strlcat(sql_buf, q3, max_q_len);
krista@2461
   464
krista@2461
   465
    sqlite3_stmt *stmt; 
krista@2461
   466
krista@2461
   467
    sqlite3_prepare_v2(session->db, sql_buf, -1, &stmt, NULL);
krista@2461
   468
krista@2461
   469
    int retval = 0;
krista@2461
   470
krista@2461
   471
    int rc = sqlite3_step(stmt);  
krista@2461
   472
    if (rc == SQLITE_DONE || rc == SQLITE_OK || rc == SQLITE_ROW) {
krista@2461
   473
        retval = 1;
krista@2461
   474
    }
krista@2461
   475
krista@2461
   476
    sqlite3_finalize(stmt);      
krista@2461
   477
        
krista@2461
   478
    return retval;
krista@2461
   479
}
krista@2461
   480
krista@2477
   481
void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){
krista@2477
   482
  fprintf(stderr, "(%d) %s\n", iErrCode, zMsg);
krista@2477
   483
}
krista@2477
   484
vb@0
   485
DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
vb@0
   486
{
vb@65
   487
    PEP_STATUS status = PEP_STATUS_OK;
roker@529
   488
    int int_result;
Edouard@693
   489
    
vb@62
   490
    bool in_first = false;
edouard@1752
   491
    bool very_first = false;
vb@8
   492
vb@62
   493
    assert(sqlite3_threadsafe());
vb@62
   494
    if (!sqlite3_threadsafe())
vb@62
   495
        return PEP_INIT_SQLITE3_WITHOUT_MUTEX;
vb@62
   496
vb@62
   497
    // a little race condition - but still a race condition
vb@113
   498
    // mitigated by calling caveat (see documentation)
vb@62
   499
krista@2125
   500
    // this increment is made atomic IN THE ADAPTERS by
krista@2125
   501
    // guarding the call to init with the appropriate mutex.
krista@2124
   502
    int _count = ++init_count;
edouard@2112
   503
    if (_count == 0)
vb@62
   504
        in_first = true;
edouard@2112
   505
    
krista@2176
   506
    // Race condition mitigated by calling caveat starts here :
edouard@2112
   507
    // If another call to init() preempts right now, then preemptive call
edouard@2112
   508
    // will have in_first false, will not create SQL tables, and following
krista@2125
   509
    // calls relying on those tables will fail.
krista@2125
   510
    //
krista@2125
   511
    // Therefore, as above, adapters MUST guard init() with a mutex.
krista@2125
   512
    // 
krista@2125
   513
    // Therefore, first session
edouard@2112
   514
    // is to be created and last session to be deleted alone, and not
edouard@2112
   515
    // concurently to other sessions creation or deletion.
edouard@2112
   516
    // We expect adapters to enforce this either by implicitely creating a
edouard@2112
   517
    // client session, or by using synchronization primitive to protect
edouard@2112
   518
    // creation/deletion of first/last session from the app.
vb@0
   519
roker@529
   520
    assert(session);
vb@191
   521
    if (session == NULL)
vb@191
   522
        return PEP_ILLEGAL_VALUE;
vb@191
   523
roker@529
   524
    *session = NULL;
vb@0
   525
vb@107
   526
    pEpSession *_session = calloc(1, sizeof(pEpSession));
roker@529
   527
    assert(_session);
roker@529
   528
    if (_session == NULL)
roker@529
   529
        goto enomem;
vb@62
   530
roker@529
   531
    _session->version = PEP_ENGINE_VERSION;
vb@0
   532
roker@1722
   533
#ifdef DEBUG_ERRORSTACK
roker@1801
   534
    _session->errorstack = new_stringlist("init()");
roker@1722
   535
#endif
roker@1722
   536
vb@0
   537
    assert(LOCAL_DB);
vb@0
   538
    if (LOCAL_DB == NULL) {
vb@65
   539
        status = PEP_INIT_CANNOT_OPEN_DB;
vb@65
   540
        goto pep_error;
vb@0
   541
    }
krista@2477
   542
    
krista@2480
   543
#if _PEP_SQLITE_DEBUG    
krista@2477
   544
    sqlite3_config(SQLITE_CONFIG_LOG, errorLogCallback, NULL);
krista@2480
   545
#endif
vb@0
   546
roker@529
   547
    int_result = sqlite3_open_v2(
roker@529
   548
            LOCAL_DB,
roker@529
   549
            &_session->db,
roker@529
   550
            SQLITE_OPEN_READWRITE
roker@529
   551
                | SQLITE_OPEN_CREATE
roker@529
   552
                | SQLITE_OPEN_FULLMUTEX
roker@529
   553
                | SQLITE_OPEN_PRIVATECACHE,
roker@529
   554
            NULL 
roker@529
   555
        );
vb@0
   556
roker@529
   557
    if (int_result != SQLITE_OK) {
roker@529
   558
        status = PEP_INIT_CANNOT_OPEN_DB;
vb@65
   559
        goto pep_error;
roker@529
   560
    }
vb@0
   561
krista@2164
   562
    int_result = sqlite3_exec(
krista@2164
   563
            _session->db,
krista@2174
   564
            "PRAGMA locking_mode=NORMAL;\n"
krista@2164
   565
            "PRAGMA journal_mode=WAL;\n",
krista@2164
   566
            NULL,
krista@2164
   567
            NULL,
krista@2164
   568
            NULL
krista@2164
   569
        );
krista@2164
   570
krista@2164
   571
roker@529
   572
    sqlite3_busy_timeout(_session->db, BUSY_WAIT_TIME);
vb@0
   573
krista@2480
   574
#if _PEP_SQLITE_DEBUG
krista@2479
   575
    sqlite3_trace_v2(_session->db, 
krista@2479
   576
        SQLITE_TRACE_STMT | SQLITE_TRACE_ROW | SQLITE_TRACE_CLOSE,
krista@2479
   577
        sql_trace_callback,
krista@2479
   578
        NULL);
krista@2480
   579
#endif
krista@2479
   580
vb@0
   581
    assert(SYSTEM_DB);
vb@0
   582
    if (SYSTEM_DB == NULL) {
roker@529
   583
        status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
vb@65
   584
        goto pep_error;
vb@0
   585
    }
vb@0
   586
roker@529
   587
    int_result = sqlite3_open_v2(
roker@529
   588
            SYSTEM_DB, &_session->system_db,
roker@529
   589
            SQLITE_OPEN_READONLY
roker@529
   590
                | SQLITE_OPEN_FULLMUTEX
roker@529
   591
                | SQLITE_OPEN_SHAREDCACHE,
roker@529
   592
            NULL
roker@529
   593
        );
vb@0
   594
roker@529
   595
    if (int_result != SQLITE_OK) {
roker@529
   596
        status = PEP_INIT_CANNOT_OPEN_SYSTEM_DB;
vb@65
   597
        goto pep_error;
roker@529
   598
    }
vb@0
   599
roker@529
   600
    sqlite3_busy_timeout(_session->system_db, 1000);
vb@0
   601
vb@928
   602
// increment this when patching DDL
krista@2468
   603
#define _DDL_USER_VERSION "7"
vb@928
   604
vb@62
   605
    if (in_first) {
vb@1091
   606
vb@62
   607
        int_result = sqlite3_exec(
vb@62
   608
            _session->db,
vb@1008
   609
                "create table if not exists version_info (\n"
vb@456
   610
                "   id integer primary key,\n"
vb@1085
   611
                "   timestamp integer default (datetime('now')),\n"
vb@456
   612
                "   version text,\n"
vb@456
   613
                "   comment text\n"
vb@928
   614
                ");\n",
vb@928
   615
                NULL,
vb@928
   616
                NULL,
vb@928
   617
                NULL
vb@928
   618
        );
vb@928
   619
        int_result = sqlite3_exec(
vb@928
   620
            _session->db,
vb@948
   621
                "PRAGMA application_id = 0x23423423;\n"
vb@456
   622
                "create table if not exists log (\n"
vb@1085
   623
                "   timestamp integer default (datetime('now')),\n"
vb@456
   624
                "   title text not null,\n"
krista@2176
   625
                "   description text,\n"
vb@456
   626
                "   entity text not null,\n"
vb@456
   627
                "   comment text\n"
vb@456
   628
                ");\n"
vb@456
   629
                "create index if not exists log_timestamp on log (\n"
vb@456
   630
                "   timestamp\n"
vb@456
   631
                ");\n"
vb@456
   632
                "create table if not exists pgp_keypair (\n"
vb@456
   633
                "   fpr text primary key,\n"
vb@456
   634
                "   created integer,\n"
vb@456
   635
                "   expires integer,\n"
vb@944
   636
                "   comment text,\n"
vb@1085
   637
                "   flags integer default 0\n"
vb@456
   638
                ");\n"
vb@456
   639
                "create index if not exists pgp_keypair_expires on pgp_keypair (\n"
vb@456
   640
                "   expires\n"
vb@456
   641
                ");\n"
vb@456
   642
                "create table if not exists person (\n"
vb@456
   643
                "   id text primary key,\n"
vb@456
   644
                "   username text not null,\n"
vb@456
   645
                "   main_key_id text\n"
vb@456
   646
                "       references pgp_keypair (fpr)\n"
vb@456
   647
                "       on delete set null,\n"
vb@456
   648
                "   lang text,\n"
vb@951
   649
                "   comment text,\n"
krista@2468
   650
                "   device_group text,\n"
krista@2468
   651
                "   is_pep_user integer default 0\n"
vb@456
   652
                ");\n"
vb@456
   653
                "create table if not exists identity (\n"
Edouard@559
   654
                "   address text,\n"
vb@456
   655
                "   user_id text\n"
vb@456
   656
                "       references person (id)\n"
krista@2461
   657
                "       on delete cascade on update cascade,\n"
vb@456
   658
                "   main_key_id text\n"
vb@456
   659
                "       references pgp_keypair (fpr)\n"
vb@456
   660
                "       on delete set null,\n"
Edouard@559
   661
                "   comment text,\n"
krista@2461
   662
                "   flags integer default 0,\n"
krista@2461
   663
                "   is_own integer default 0,\n"
Edouard@559
   664
                "   primary key (address, user_id)\n"
vb@456
   665
                ");\n"
vb@456
   666
                "create table if not exists trust (\n"
vb@456
   667
                "   user_id text not null\n"
vb@456
   668
                "       references person (id)\n"
krista@2461
   669
                "       on delete cascade on update cascade,\n"
vb@456
   670
                "   pgp_keypair_fpr text not null\n"
vb@456
   671
                "       references pgp_keypair (fpr)\n"
vb@456
   672
                "       on delete cascade,\n"
vb@456
   673
                "   comm_type integer not null,\n"
Edouard@684
   674
                "   comment text,\n"
Edouard@684
   675
                "   primary key (user_id, pgp_keypair_fpr)\n"
vb@456
   676
                ");\n"
fdik@494
   677
                // blacklist
vb@456
   678
                "create table if not exists blacklist_keys (\n"
vb@456
   679
                "   fpr text primary key\n"
vb@456
   680
                ");\n"
vb@632
   681
                // sequences
vb@632
   682
                "create table if not exists sequences(\n"
vb@632
   683
                "   name text primary key,\n"
vb@1085
   684
                "   value integer default 0,\n"
vb@1085
   685
                "   own integer default 0\n"
vb@632
   686
                ");\n"
Edouard@693
   687
                "create table if not exists revoked_keys (\n"
Edouard@693
   688
                "   revoked_fpr text primary key,\n"
Edouard@693
   689
                "   replacement_fpr text not null\n"
Edouard@693
   690
                "       references pgp_keypair (fpr)\n"
Edouard@693
   691
                "       on delete cascade,\n"
Edouard@693
   692
                "   revocation_date integer\n"
Edouard@693
   693
                ");\n"
krista@2461
   694
                // user id aliases
krista@2461
   695
                "create table if not exists alternate_user_id (\n"
krista@2478
   696
                "    default_id text references person (id)\n"
krista@2478
   697
                "       on delete cascade on update cascade,\n"
krista@2461
   698
                "    alternate_id text primary key\n"
krista@2461
   699
                ");\n"
krista@2467
   700
                // mistrusted keys
krista@2467
   701
                "create table if not exists mistrusted_keys (\n"
krista@2467
   702
                "    fpr text primary key\n"
krista@2467
   703
                ");\n"
vb@456
   704
                ,
vb@62
   705
            NULL,
vb@62
   706
            NULL,
vb@62
   707
            NULL
vb@62
   708
        );
vb@62
   709
        assert(int_result == SQLITE_OK);
vb@0
   710
vb@928
   711
        int version;
vb@62
   712
        int_result = sqlite3_exec(
vb@62
   713
            _session->db,
vb@928
   714
            "pragma user_version;",
vb@928
   715
            user_version,
vb@928
   716
            &version,
vb@62
   717
            NULL
vb@62
   718
        );
krista@1884
   719
krista@1884
   720
        assert(int_result == SQLITE_OK);
krista@1884
   721
        
krista@1884
   722
        void (*xFunc_lower)(sqlite3_context*,int,sqlite3_value**) = &_sql_lower;
krista@1884
   723
        
krista@1884
   724
        int_result = sqlite3_create_function_v2(
krista@1884
   725
            _session->db,
krista@1884
   726
            "lower",
krista@1884
   727
            1,
krista@1884
   728
            SQLITE_UTF8 | SQLITE_DETERMINISTIC,
krista@1884
   729
            NULL,
krista@1884
   730
            xFunc_lower,
krista@1884
   731
            NULL,
krista@1884
   732
            NULL,
krista@1884
   733
            NULL);
vb@62
   734
        assert(int_result == SQLITE_OK);
krista@2477
   735
krista@2477
   736
        int_result = sqlite3_exec(
krista@2477
   737
            _session->db,
krista@2477
   738
            "pragma foreign_keys=ON;\n",
krista@2477
   739
            NULL,
krista@2477
   740
            NULL,
krista@2477
   741
            NULL
krista@2477
   742
        );
krista@2477
   743
krista@2477
   744
        assert(int_result == SQLITE_OK);
krista@2477
   745
krista@2461
   746
        
krista@2461
   747
        // Sometimes the user_version wasn't set correctly. Check to see if this
krista@2461
   748
        // is really necessary...
krista@2461
   749
        if (version == 1) {
krista@2461
   750
            bool version_changed = true;
krista@2468
   751
krista@2468
   752
            if (table_contains_column(_session, "person", "is_pep_user") > 0) {
krista@2468
   753
                version = 7;
krista@2468
   754
            }            
krista@2468
   755
            else if (table_contains_column(_session, "identity", "is_own") > 0) {
krista@2461
   756
                version = 6;
krista@2461
   757
            }
krista@2461
   758
            else if (table_contains_column(_session, "sequences", "own") > 0) {
krista@2461
   759
                version = 3;
krista@2461
   760
            }
krista@2461
   761
            else if (table_contains_column(_session, "pgp_keypair", "flags") > 0) {
krista@2461
   762
                version = 2;
krista@2461
   763
            }
krista@2461
   764
            else {
krista@2461
   765
                version_changed = false;
krista@2461
   766
            }
krista@2461
   767
            
krista@2461
   768
            if (version_changed) {
krista@2461
   769
                // set it in the DB, finally. Yeesh.
krista@2461
   770
                char verbuf[21]; // enough digits for a max-sized 64 bit int, cmon. 
krista@2461
   771
                sprintf(verbuf,"%d",version);
krista@2461
   772
                
krista@2461
   773
                size_t query_size = strlen(verbuf) + 25;
krista@2461
   774
                char* query = calloc(query_size, 1);
krista@2461
   775
                
krista@2461
   776
                strlcpy(query, "pragma user_version = ", query_size);
krista@2461
   777
                strlcat(query, verbuf, query_size);
krista@2461
   778
                strlcat(query, ";", query_size);
krista@2461
   779
                
krista@2461
   780
                int_result = sqlite3_exec(
krista@2461
   781
                    _session->db,
krista@2461
   782
                    query,
krista@2461
   783
                    user_version,
krista@2461
   784
                    &version,
krista@2461
   785
                    NULL
krista@2461
   786
                );
krista@2461
   787
                free(query);
krista@2461
   788
            }
krista@2461
   789
        }
krista@2461
   790
vb@0
   791
edouard@1604
   792
        if(version != 0) { 
edouard@1604
   793
            // Version has been already set
vb@934
   794
edouard@1604
   795
            // Early mistake : version 0 shouldn't have existed.
edouard@1604
   796
            // Numbering should have started at 1 to detect newly created DB.
edouard@1604
   797
            // Version 0 DBs are not anymore compatible.
krista@1032
   798
edouard@1604
   799
            // // Was version 0 compat code.
edouard@1604
   800
            // if (version < 1) {
edouard@1604
   801
            //     int_result = sqlite3_exec(
edouard@1604
   802
            //         _session->db,
edouard@1604
   803
            //         "alter table identity\n"
edouard@1604
   804
            //         "   add column flags integer default 0;\n",
edouard@1604
   805
            //         NULL,
edouard@1604
   806
            //         NULL,
edouard@1604
   807
            //         NULL
edouard@1604
   808
            //     );
edouard@1604
   809
            //     assert(int_result == SQLITE_OK);
edouard@1604
   810
            // }
krista@2461
   811
            
edouard@1604
   812
            if (version < 2) {
edouard@1604
   813
                int_result = sqlite3_exec(
edouard@1604
   814
                    _session->db,
edouard@1604
   815
                    "alter table pgp_keypair\n"
edouard@1604
   816
                    "   add column flags integer default 0;\n"
edouard@1604
   817
                    "alter table person\n"
edouard@1604
   818
                    "   add column device_group text;\n",
edouard@1604
   819
                    NULL,
edouard@1604
   820
                    NULL,
edouard@1604
   821
                    NULL
edouard@1604
   822
                );
edouard@1604
   823
                assert(int_result == SQLITE_OK);
edouard@1604
   824
            }
edouard@1604
   825
edouard@1604
   826
            if (version < 3) {
edouard@1604
   827
                int_result = sqlite3_exec(
edouard@1604
   828
                    _session->db,
edouard@1604
   829
                    "alter table sequences\n"
edouard@1604
   830
                    "   add column own integer default 0;\n",
edouard@1604
   831
                    NULL,
edouard@1604
   832
                    NULL,
edouard@1604
   833
                    NULL
edouard@1604
   834
                );
edouard@1604
   835
                assert(int_result == SQLITE_OK);
edouard@1604
   836
            }
edouard@1604
   837
edouard@1604
   838
            if (version < 5) {
edouard@1604
   839
                int_result = sqlite3_exec(
edouard@1604
   840
                    _session->db,
edouard@1604
   841
                    "delete from pgp_keypair where fpr = '';",
edouard@1604
   842
                    NULL,
edouard@1604
   843
                    NULL,
edouard@1604
   844
                    NULL
edouard@1604
   845
                );
edouard@1604
   846
                assert(int_result == SQLITE_OK);
edouard@1604
   847
                int_result = sqlite3_exec(
edouard@1604
   848
                    _session->db,
edouard@1604
   849
                    "delete from trust where pgp_keypair_fpr = '';",
edouard@1604
   850
                    NULL,
edouard@1604
   851
                    NULL,
edouard@1604
   852
                    NULL
edouard@1604
   853
                );
edouard@1604
   854
                assert(int_result == SQLITE_OK);
edouard@1604
   855
            }
krista@2461
   856
            
krista@2461
   857
            if (version < 6) {
krista@2461
   858
                int_result = sqlite3_exec(
krista@2461
   859
                    _session->db,
krista@2461
   860
                    "alter table identity\n"
krista@2461
   861
                    "   add column is_own integer default 0;\n",
krista@2461
   862
                    NULL,
krista@2461
   863
                    NULL,
krista@2461
   864
                    NULL
krista@2461
   865
                );
krista@2461
   866
                assert(int_result == SQLITE_OK);                
krista@2461
   867
                int_result = sqlite3_exec(
krista@2461
   868
                    _session->db,
krista@2461
   869
                    "update identity\n"
krista@2461
   870
                    "   set is_own = 1\n"
krista@2461
   871
                    "   where (user_id = '" PEP_OWN_USERID "');\n",
krista@2461
   872
                    NULL,
krista@2461
   873
                    NULL,
krista@2461
   874
                    NULL
krista@2461
   875
                );
krista@2461
   876
                assert(int_result == SQLITE_OK);    
krista@2461
   877
krista@2461
   878
                // Turns out that just adding "on update cascade" in
krista@2461
   879
                // sqlite is a PITA. We need to be able to cascade
krista@2461
   880
                // person->id replacements (for temp ids like "TOFU_")
krista@2461
   881
                // so here we go...
krista@2461
   882
                int_result = sqlite3_exec(
krista@2461
   883
                    _session->db,
krista@2461
   884
                    "PRAGMA foreign_keys=off;\n"
krista@2461
   885
                    "BEGIN TRANSACTION;\n"
krista@2461
   886
                    "ALTER TABLE identity RENAME TO _identity_old;\n"
krista@2461
   887
                    "create table identity (\n"
krista@2461
   888
                    "   address text,\n"
krista@2461
   889
                    "   user_id text\n"
krista@2461
   890
                    "       references person (id)\n"
krista@2461
   891
                    "       on delete cascade on update cascade,\n"
krista@2461
   892
                    "   main_key_id text\n"
krista@2461
   893
                    "       references pgp_keypair (fpr)\n"
krista@2461
   894
                    "       on delete set null,\n"
krista@2461
   895
                    "   comment text,\n"
krista@2461
   896
                    "   flags integer default 0,\n"
krista@2461
   897
                    "   is_own integer default 0,\n"
krista@2461
   898
                    "   primary key (address, user_id)\n"
krista@2461
   899
                    ");\n"
krista@2461
   900
                    "INSERT INTO identity SELECT * FROM _identity_old;\n"
krista@2461
   901
                    "DROP TABLE _identity_old;\n"
krista@2461
   902
                    "ALTER TABLE trust RENAME TO _trust_old;\n"
krista@2461
   903
                    "create table trust (\n"
krista@2461
   904
                    "   user_id text not null\n"
krista@2461
   905
                    "       references person (id)\n"
krista@2461
   906
                    "       on delete cascade on update cascade,\n"
krista@2461
   907
                    "   pgp_keypair_fpr text not null\n"
krista@2461
   908
                    "       references pgp_keypair (fpr)\n"
krista@2461
   909
                    "       on delete cascade,\n"
krista@2461
   910
                    "   comm_type integer not null,\n"
krista@2461
   911
                    "   comment text,\n"
krista@2461
   912
                    "   primary key (user_id, pgp_keypair_fpr)\n"
krista@2461
   913
                    ");\n"
krista@2461
   914
                    "INSERT INTO trust SELECT * FROM _trust_old;\n"
krista@2461
   915
                    "DROP TABLE _trust_old;\n"
krista@2461
   916
                    "COMMIT;\n"
krista@2461
   917
                    "\n"
krista@2461
   918
                    "PRAGMA foreign_keys=on;\n"
krista@2461
   919
                    "create table if not exists alternate_user_id (\n"
krista@2478
   920
                    "    default_id text references person (id)\n"
krista@2478
   921
                    "       on delete cascade on update cascade,\n"
krista@2461
   922
                    "    alternate_id text primary key\n"
krista@2461
   923
                    ");\n"
krista@2461
   924
                    ,
krista@2461
   925
                    NULL,
krista@2461
   926
                    NULL,
krista@2461
   927
                    NULL
krista@2461
   928
                );
krista@2461
   929
                assert(int_result == SQLITE_OK);    
krista@2461
   930
            }
krista@2468
   931
            if (version < 7) {
krista@2468
   932
                int_result = sqlite3_exec(
krista@2468
   933
                    _session->db,
krista@2468
   934
                    "alter table person\n"
krista@2468
   935
                    "   add column is_pep_user integer default 0;\n",
krista@2468
   936
                    NULL,
krista@2468
   937
                    NULL,
krista@2468
   938
                    NULL
krista@2468
   939
                );
krista@2468
   940
                assert(int_result == SQLITE_OK);
krista@2468
   941
                int_result = sqlite3_exec(
krista@2468
   942
                    _session->db,
krista@2468
   943
                    "update person\n"
krista@2468
   944
                    "   set is_pep_user = 1\n"
krista@2468
   945
                    "   where id = "
krista@2468
   946
                    "       (select distinct id from person "
krista@2468
   947
                    "               join trust on id = user_id "
krista@2468
   948
                    "               where (case when (comm_type = 127) then (id) "
krista@2468
   949
                    "                           when (comm_type = 255) then (id) "
krista@2468
   950
                    "                           else 0"
krista@2468
   951
                    "                      end) = id );\n",
krista@2468
   952
                    NULL,
krista@2468
   953
                    NULL,
krista@2468
   954
                    NULL
krista@2468
   955
                );
krista@2473
   956
                assert(int_result == SQLITE_OK);
krista@2473
   957
                
krista@2473
   958
                int_result = sqlite3_exec(
krista@2473
   959
                    _session->db,
krista@2471
   960
                    "create table if not exists mistrusted_keys (\n"
krista@2471
   961
                    "    fpr text primary key\n"
krista@2471
   962
                    ");\n",            
krista@2471
   963
                    NULL,
krista@2471
   964
                    NULL,
krista@2471
   965
                    NULL
krista@2471
   966
                );
krista@2468
   967
                assert(int_result == SQLITE_OK);    
krista@2468
   968
            }
krista@2468
   969
        }        
edouard@1752
   970
        else { 
edouard@1752
   971
            // Version from DB was 0, it means this is initial setup.
edouard@1752
   972
            // DB has just been created, and all tables are empty.
edouard@1752
   973
            very_first = true;
edouard@1752
   974
        }
vb@1453
   975
vb@928
   976
        if (version < atoi(_DDL_USER_VERSION)) {
vb@928
   977
            int_result = sqlite3_exec(
vb@928
   978
                _session->db,
vb@928
   979
                "pragma user_version = "_DDL_USER_VERSION";\n"
vb@928
   980
                "insert or replace into version_info (id, version)"
vb@928
   981
                    "values (1, '" PEP_ENGINE_VERSION "');",
vb@928
   982
                NULL,
vb@928
   983
                NULL,
vb@928
   984
                NULL
vb@928
   985
            );
vb@928
   986
            assert(int_result == SQLITE_OK);
vb@928
   987
        }
krista@2176
   988
        
krista@2176
   989
        // We need to init a few globals for message id that we'd rather not
krista@2176
   990
        // calculate more than once.
krista@2176
   991
        _init_globals();
vb@62
   992
    }
vb@62
   993
vb@951
   994
    int_result = sqlite3_prepare_v2(_session->db, sql_log,
vb@951
   995
            (int)strlen(sql_log), &_session->log, NULL);
roker@529
   996
    assert(int_result == SQLITE_OK);
vb@0
   997
vb@233
   998
    int_result = sqlite3_prepare_v2(_session->system_db, sql_trustword,
Edouard@417
   999
            (int)strlen(sql_trustword), &_session->trustword, NULL);
roker@529
  1000
    assert(int_result == SQLITE_OK);
vb@0
  1001
vb@0
  1002
    int_result = sqlite3_prepare_v2(_session->db, sql_get_identity,
Edouard@417
  1003
            (int)strlen(sql_get_identity), &_session->get_identity, NULL);
roker@529
  1004
    assert(int_result == SQLITE_OK);
vb@0
  1005
krista@2461
  1006
    int_result = sqlite3_prepare_v2(_session->db, sql_get_identity_without_trust_check,
krista@2461
  1007
            (int)strlen(sql_get_identity_without_trust_check), 
krista@2461
  1008
            &_session->get_identity_without_trust_check, NULL);
krista@2461
  1009
    assert(int_result == SQLITE_OK);
krista@2461
  1010
krista@2461
  1011
    int_result = sqlite3_prepare_v2(_session->db, sql_get_identities_by_address,
krista@2461
  1012
            (int)strlen(sql_get_identities_by_address), 
krista@2461
  1013
            &_session->get_identities_by_address, NULL);
krista@2461
  1014
    assert(int_result == SQLITE_OK);
krista@2461
  1015
krista@2461
  1016
    int_result = sqlite3_prepare_v2(_session->db, sql_get_user_default_key,
krista@2461
  1017
            (int)strlen(sql_get_user_default_key), &_session->get_user_default_key, NULL);
krista@2461
  1018
    assert(int_result == SQLITE_OK);
krista@2461
  1019
krista@2461
  1020
    int_result = sqlite3_prepare_v2(_session->db, sql_get_default_own_userid,
krista@2461
  1021
            (int)strlen(sql_get_default_own_userid), &_session->get_default_own_userid, NULL);
krista@2461
  1022
    assert(int_result == SQLITE_OK);
krista@2461
  1023
    
krista@2461
  1024
    int_result = sqlite3_prepare_v2(_session->db, sql_get_userid_alias_default,
krista@2461
  1025
            (int)strlen(sql_get_userid_alias_default), &_session->get_userid_alias_default, NULL);
krista@2461
  1026
    assert(int_result == SQLITE_OK);
krista@2461
  1027
krista@2461
  1028
    int_result = sqlite3_prepare_v2(_session->db, sql_add_userid_alias,
krista@2461
  1029
            (int)strlen(sql_add_userid_alias), &_session->add_userid_alias, NULL);
krista@2461
  1030
    assert(int_result == SQLITE_OK);
krista@2461
  1031
krista@2461
  1032
    int_result = sqlite3_prepare_v2(_session->db, sql_replace_userid,
krista@2461
  1033
            (int)strlen(sql_replace_userid), &_session->replace_userid, NULL);
krista@2461
  1034
    assert(int_result == SQLITE_OK);
krista@2461
  1035
krista@2461
  1036
    int_result = sqlite3_prepare_v2(_session->db, sql_replace_main_user_fpr,
krista@2461
  1037
            (int)strlen(sql_replace_main_user_fpr), &_session->replace_main_user_fpr, NULL);
krista@2461
  1038
    assert(int_result == SQLITE_OK);
krista@2461
  1039
krista@2461
  1040
    int_result = sqlite3_prepare_v2(_session->db, sql_get_main_user_fpr,
krista@2461
  1041
            (int)strlen(sql_get_main_user_fpr), &_session->get_main_user_fpr, NULL);
krista@2461
  1042
    assert(int_result == SQLITE_OK);
krista@2461
  1043
krista@2461
  1044
    int_result = sqlite3_prepare_v2(_session->db, sql_refresh_userid_default_key,
krista@2461
  1045
            (int)strlen(sql_refresh_userid_default_key), &_session->refresh_userid_default_key, NULL);
krista@2461
  1046
    assert(int_result == SQLITE_OK);
krista@2461
  1047
krista@1799
  1048
    int_result = sqlite3_prepare_v2(_session->db, sql_replace_identities_fpr,
krista@1799
  1049
            (int)strlen(sql_replace_identities_fpr), 
krista@1799
  1050
            &_session->replace_identities_fpr, NULL);
krista@1793
  1051
    assert(int_result == SQLITE_OK);
krista@2461
  1052
    
krista@2461
  1053
    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_default,
krista@2461
  1054
            (int)strlen(sql_remove_fpr_as_default), 
krista@2461
  1055
            &_session->remove_fpr_as_default, NULL);
krista@2461
  1056
    assert(int_result == SQLITE_OK);
krista@1793
  1057
vb@0
  1058
    int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
Edouard@417
  1059
            (int)strlen(sql_set_person), &_session->set_person, NULL);
vb@0
  1060
    assert(int_result == SQLITE_OK);
vb@62
  1061
krista@2478
  1062
    int_result = sqlite3_prepare_v2(_session->db, sql_update_person,
krista@2478
  1063
            (int)strlen(sql_update_person), &_session->update_person, NULL);
krista@2478
  1064
    assert(int_result == SQLITE_OK);
krista@2478
  1065
krista@2480
  1066
    int_result = sqlite3_prepare_v2(_session->db, sql_exists_person,
krista@2480
  1067
            (int)strlen(sql_exists_person), &_session->exists_person, NULL);
krista@2480
  1068
    assert(int_result == SQLITE_OK);
krista@2480
  1069
krista@2468
  1070
    int_result = sqlite3_prepare_v2(_session->db, sql_set_as_pep_user,
krista@2468
  1071
            (int)strlen(sql_set_as_pep_user), &_session->set_as_pep_user, NULL);
krista@2468
  1072
    assert(int_result == SQLITE_OK);
krista@2468
  1073
    
krista@2468
  1074
    int_result = sqlite3_prepare_v2(_session->db, sql_is_pep_user,
krista@2468
  1075
            (int)strlen(sql_is_pep_user), &_session->is_pep_user, NULL);
krista@2468
  1076
    assert(int_result == SQLITE_OK);
krista@2468
  1077
edouard@1234
  1078
    int_result = sqlite3_prepare_v2(_session->db, sql_set_device_group,
edouard@1234
  1079
            (int)strlen(sql_set_device_group), &_session->set_device_group, NULL);
edouard@1234
  1080
    assert(int_result == SQLITE_OK);
edouard@1234
  1081
edouard@1235
  1082
    int_result = sqlite3_prepare_v2(_session->db, sql_get_device_group,
edouard@1235
  1083
            (int)strlen(sql_get_device_group), &_session->get_device_group, NULL);
edouard@1235
  1084
    assert(int_result == SQLITE_OK);
edouard@1235
  1085
vb@0
  1086
    int_result = sqlite3_prepare_v2(_session->db, sql_set_pgp_keypair,
vb@951
  1087
            (int)strlen(sql_set_pgp_keypair), &_session->set_pgp_keypair,
vb@951
  1088
            NULL);
roker@529
  1089
    assert(int_result == SQLITE_OK);
vb@62
  1090
krista@2478
  1091
    int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_entry,
krista@2478
  1092
            (int)strlen(sql_set_identity_entry), &_session->set_identity_entry, NULL);
krista@2478
  1093
    assert(int_result == SQLITE_OK);
krista@2478
  1094
krista@2478
  1095
    int_result = sqlite3_prepare_v2(_session->db, sql_update_identity_entry,
krista@2478
  1096
            (int)strlen(sql_update_identity_entry), &_session->update_identity_entry, NULL);
roker@529
  1097
    assert(int_result == SQLITE_OK);
vb@62
  1098
krista@2480
  1099
    int_result = sqlite3_prepare_v2(_session->db, sql_exists_identity_entry,
krista@2480
  1100
            (int)strlen(sql_exists_identity_entry), &_session->exists_identity_entry, NULL);
krista@2480
  1101
    assert(int_result == SQLITE_OK);
krista@2480
  1102
vb@932
  1103
    int_result = sqlite3_prepare_v2(_session->db, sql_set_identity_flags,
vb@951
  1104
            (int)strlen(sql_set_identity_flags), &_session->set_identity_flags,
vb@951
  1105
            NULL);
vb@932
  1106
    assert(int_result == SQLITE_OK);
vb@932
  1107
edouard@1394
  1108
    int_result = sqlite3_prepare_v2(_session->db, sql_unset_identity_flags,
edouard@1394
  1109
            (int)strlen(sql_unset_identity_flags), &_session->unset_identity_flags,
edouard@1394
  1110
            NULL);
edouard@1394
  1111
    assert(int_result == SQLITE_OK);
edouard@1394
  1112
vb@0
  1113
    int_result = sqlite3_prepare_v2(_session->db, sql_set_trust,
Edouard@417
  1114
            (int)strlen(sql_set_trust), &_session->set_trust, NULL);
roker@529
  1115
    assert(int_result == SQLITE_OK);
vb@62
  1116
krista@2478
  1117
    int_result = sqlite3_prepare_v2(_session->db, sql_update_trust,
krista@2478
  1118
            (int)strlen(sql_update_trust), &_session->update_trust, NULL);
krista@2478
  1119
    assert(int_result == SQLITE_OK);
krista@2478
  1120
krista@2480
  1121
    int_result = sqlite3_prepare_v2(_session->db, sql_exists_trust_entry,
krista@2480
  1122
                 (int)strlen(sql_exists_trust_entry), &_session->exists_trust_entry, NULL);
krista@2480
  1123
    assert(int_result == SQLITE_OK);
krista@2480
  1124
krista@1799
  1125
    int_result = sqlite3_prepare_v2(_session->db, sql_update_trust_for_fpr,
krista@1799
  1126
            (int)strlen(sql_update_trust_for_fpr), &_session->update_trust_for_fpr, NULL);
krista@1799
  1127
    assert(int_result == SQLITE_OK);
krista@1799
  1128
vb@8
  1129
    int_result = sqlite3_prepare_v2(_session->db, sql_get_trust,
Edouard@417
  1130
            (int)strlen(sql_get_trust), &_session->get_trust, NULL);
vb@8
  1131
    assert(int_result == SQLITE_OK);
vb@0
  1132
vb@251
  1133
    int_result = sqlite3_prepare_v2(_session->db, sql_least_trust,
Edouard@417
  1134
            (int)strlen(sql_least_trust), &_session->least_trust, NULL);
vb@251
  1135
    assert(int_result == SQLITE_OK);
vb@251
  1136
vb@357
  1137
    int_result = sqlite3_prepare_v2(_session->db, sql_mark_as_compromized,
vb@951
  1138
            (int)strlen(sql_mark_as_compromized), &_session->mark_compromized,
vb@951
  1139
            NULL);
vb@357
  1140
    assert(int_result == SQLITE_OK);
vb@357
  1141
vb@453
  1142
    int_result = sqlite3_prepare_v2(_session->db, sql_crashdump,
vb@453
  1143
            (int)strlen(sql_crashdump), &_session->crashdump, NULL);
vb@453
  1144
    assert(int_result == SQLITE_OK);
vb@453
  1145
vb@458
  1146
    int_result = sqlite3_prepare_v2(_session->system_db, sql_languagelist,
vb@458
  1147
            (int)strlen(sql_languagelist), &_session->languagelist, NULL);
roker@529
  1148
    assert(int_result == SQLITE_OK);
vb@458
  1149
vb@458
  1150
    int_result = sqlite3_prepare_v2(_session->system_db, sql_i18n_token,
vb@458
  1151
            (int)strlen(sql_i18n_token), &_session->i18n_token, NULL);
roker@529
  1152
    assert(int_result == SQLITE_OK);
krista@2461
  1153
    
fdik@494
  1154
    // blacklist
fdik@494
  1155
fdik@494
  1156
    int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_add,
fdik@494
  1157
            (int)strlen(sql_blacklist_add), &_session->blacklist_add, NULL);
fdik@494
  1158
    assert(int_result == SQLITE_OK);
fdik@494
  1159
fdik@494
  1160
    int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_delete,
vb@951
  1161
            (int)strlen(sql_blacklist_delete), &_session->blacklist_delete,
vb@951
  1162
            NULL);
fdik@494
  1163
    assert(int_result == SQLITE_OK);
fdik@494
  1164
fdik@494
  1165
    int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_is_listed,
vb@951
  1166
            (int)strlen(sql_blacklist_is_listed),
vb@951
  1167
            &_session->blacklist_is_listed, NULL);
fdik@494
  1168
    assert(int_result == SQLITE_OK);
fdik@494
  1169
fdik@494
  1170
    int_result = sqlite3_prepare_v2(_session->db, sql_blacklist_retrieve,
vb@951
  1171
            (int)strlen(sql_blacklist_retrieve), &_session->blacklist_retrieve,
vb@951
  1172
            NULL);
vb@482
  1173
    assert(int_result == SQLITE_OK);
krista@1275
  1174
    
Edouard@584
  1175
    // Own keys
Edouard@584
  1176
    
Edouard@584
  1177
    int_result = sqlite3_prepare_v2(_session->db, sql_own_key_is_listed,
vb@951
  1178
            (int)strlen(sql_own_key_is_listed), &_session->own_key_is_listed,
vb@951
  1179
            NULL);
Edouard@584
  1180
    assert(int_result == SQLITE_OK);
Edouard@584
  1181
    
vb@955
  1182
    int_result = sqlite3_prepare_v2(_session->db, sql_own_identities_retrieve,
vb@955
  1183
            (int)strlen(sql_own_identities_retrieve),
vb@955
  1184
            &_session->own_identities_retrieve, NULL);
Edouard@584
  1185
    assert(int_result == SQLITE_OK);
vb@633
  1186
 
edouard@1394
  1187
    int_result = sqlite3_prepare_v2(_session->db, sql_own_keys_retrieve,
edouard@1394
  1188
            (int)strlen(sql_own_keys_retrieve),
edouard@1394
  1189
            &_session->own_keys_retrieve, NULL);
edouard@1394
  1190
    assert(int_result == SQLITE_OK);
edouard@1394
  1191
 
krista@2461
  1192
    // int_result = sqlite3_prepare_v2(_session->db, sql_set_own_key,
krista@2461
  1193
    //         (int)strlen(sql_set_own_key),
krista@2461
  1194
    //         &_session->set_own_key, NULL);
krista@2461
  1195
    // assert(int_result == SQLITE_OK);
edouard@1370
  1196
 
vb@633
  1197
    // Sequence
vb@633
  1198
vb@633
  1199
    int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value1,
vb@951
  1200
            (int)strlen(sql_sequence_value1), &_session->sequence_value1,
vb@951
  1201
            NULL);
vb@633
  1202
    assert(int_result == SQLITE_OK);
vb@633
  1203
vb@633
  1204
    int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value2,
vb@951
  1205
            (int)strlen(sql_sequence_value2), &_session->sequence_value2,
vb@951
  1206
            NULL);
krista@1032
  1207
    assert(int_result == SQLITE_OK);
krista@1032
  1208
vb@1085
  1209
    int_result = sqlite3_prepare_v2(_session->db, sql_sequence_value3,
vb@1085
  1210
            (int)strlen(sql_sequence_value3), &_session->sequence_value3,
vb@1085
  1211
            NULL);
vb@633
  1212
    assert(int_result == SQLITE_OK);
vb@633
  1213
Edouard@693
  1214
    // Revocation tracking
Edouard@693
  1215
    
Edouard@693
  1216
    int_result = sqlite3_prepare_v2(_session->db, sql_set_revoked,
vb@951
  1217
            (int)strlen(sql_set_revoked), &_session->set_revoked, NULL);
Edouard@693
  1218
    assert(int_result == SQLITE_OK);
Edouard@693
  1219
    
Edouard@693
  1220
    int_result = sqlite3_prepare_v2(_session->db, sql_get_revoked,
vb@951
  1221
            (int)strlen(sql_get_revoked), &_session->get_revoked, NULL);
Edouard@693
  1222
    assert(int_result == SQLITE_OK);
Edouard@693
  1223
    
krista@2471
  1224
    int_result = sqlite3_prepare_v2(_session->db, sql_add_mistrusted_key,
krista@2471
  1225
            (int)strlen(sql_add_mistrusted_key), &_session->add_mistrusted_key, NULL);
krista@2471
  1226
    assert(int_result == SQLITE_OK);
krista@2471
  1227
krista@2471
  1228
    int_result = sqlite3_prepare_v2(_session->db, sql_delete_mistrusted_key,
krista@2471
  1229
            (int)strlen(sql_delete_mistrusted_key), &_session->delete_mistrusted_key, NULL);
krista@2471
  1230
    assert(int_result == SQLITE_OK);
krista@2471
  1231
krista@2471
  1232
    int_result = sqlite3_prepare_v2(_session->db, sql_is_mistrusted_key,
krista@2471
  1233
            (int)strlen(sql_is_mistrusted_key), &_session->is_mistrusted_key, NULL);
krista@2471
  1234
    assert(int_result == SQLITE_OK);
krista@2471
  1235
    
vb@65
  1236
    status = init_cryptotech(_session, in_first);
vb@65
  1237
    if (status != PEP_STATUS_OK)
vb@65
  1238
        goto pep_error;
vb@0
  1239
vb@65
  1240
    status = init_transport_system(_session, in_first);
vb@65
  1241
    if (status != PEP_STATUS_OK)
vb@65
  1242
        goto pep_error;
vb@62
  1243
vb@65
  1244
    status = log_event(_session, "init", "pEp " PEP_ENGINE_VERSION, NULL, NULL);
vb@65
  1245
    if (status != PEP_STATUS_OK)
vb@65
  1246
        goto pep_error;
vb@65
  1247
vb@464
  1248
    // runtime config
vb@464
  1249
edouard@1752
  1250
    if (very_first)
edouard@1752
  1251
    {
edouard@1752
  1252
        // On first run, all private keys already present in PGP keyring 
edouard@1752
  1253
        // are taken as own in order to seamlessly integrate with
edouard@1752
  1254
        // pre-existing GPG setup.
edouard@1752
  1255
krista@2458
  1256
        // Note: earlier fears about danger because of DB reinitialisation should
krista@2458
  1257
        // be a non-issue here, as we ONLY take the ultimately trusted keys now.
krista@2458
  1258
        // Thus, unless the user has assigned ultimate trust through PGP, there is
krista@2458
  1259
        // no chance of automatically imported pEp keys from a previous run making
krista@2458
  1260
        // their way into PEP trusted status without explicit action (Bare imported
krista@2458
  1261
        // private keys have an 'unknown' trust designation in PGP).
krista@2458
  1262
krista@2458
  1263
        // We don't really worry about the status here.
krista@2478
  1264
//        status = import_trusted_own_keys(_session);        
edouard@1752
  1265
    }
vb@464
  1266
edouard@1603
  1267
    // sync_session set to own session by default
edouard@1603
  1268
    // sync_session is then never null on a valid session
edouard@1603
  1269
    _session->sync_session = _session;
edouard@1603
  1270
roker@529
  1271
    *session = _session;
krista@2176
  1272
    
krista@2176
  1273
    // Note: Following statement is NOT for any cryptographic/secure functionality; it is
krista@2176
  1274
    //       ONLY used for some randomness in generated outer message ID, which are
krista@2176
  1275
    //       required by the RFC to be globally unique!
krista@2176
  1276
    srand(time(NULL));
krista@2176
  1277
    
roker@529
  1278
    return PEP_STATUS_OK;
vb@65
  1279
vb@65
  1280
enomem:
vb@65
  1281
    status = PEP_OUT_OF_MEMORY;
vb@65
  1282
vb@65
  1283
pep_error:
vb@65
  1284
    release(_session);
vb@65
  1285
    return status;
vb@0
  1286
}
vb@0
  1287
vb@0
  1288
DYNAMIC_API void release(PEP_SESSION session)
vb@0
  1289
{
vb@62
  1290
    bool out_last = false;
krista@2124
  1291
    int _count = --init_count;
edouard@2112
  1292
    
edouard@2112
  1293
    assert(_count >= -1);
roker@529
  1294
    assert(session);
vb@0
  1295
edouard@2112
  1296
    if (!((_count >= -1) && session))
vb@191
  1297
        return;
vb@191
  1298
vb@62
  1299
    // a small race condition but still a race condition
vb@113
  1300
    // mitigated by calling caveat (see documentation)
krista@2125
  1301
    // (release() is to be guarded by a mutex by the caller)
edouard@2112
  1302
    if (_count == -1)
vb@62
  1303
        out_last = true;
vb@62
  1304
roker@529
  1305
    if (session) {
vb@986
  1306
roker@529
  1307
        if (session->db) {
vb@517
  1308
            if (session->log)
vb@517
  1309
                sqlite3_finalize(session->log);
vb@233
  1310
            if (session->trustword)
vb@233
  1311
                sqlite3_finalize(session->trustword);
vb@65
  1312
            if (session->get_identity)
vb@65
  1313
                sqlite3_finalize(session->get_identity);
krista@2461
  1314
            if (session->get_identity_without_trust_check)
krista@2461
  1315
                sqlite3_finalize(session->get_identity_without_trust_check);
krista@2461
  1316
            if (session->get_identities_by_address)
krista@2461
  1317
                sqlite3_finalize(session->get_identities_by_address);            
krista@2461
  1318
            if (session->get_user_default_key)
krista@2461
  1319
                sqlite3_finalize(session->get_user_default_key);    
krista@2461
  1320
            if (session->get_default_own_userid)
krista@2461
  1321
                sqlite3_finalize(session->get_default_own_userid);
krista@2461
  1322
            if (session->get_userid_alias_default)
krista@2461
  1323
                sqlite3_finalize(session->get_userid_alias_default);
krista@2461
  1324
            if (session->add_userid_alias)
krista@2461
  1325
                sqlite3_finalize(session->add_userid_alias);
krista@1799
  1326
            if (session->replace_identities_fpr)
krista@1799
  1327
                sqlite3_finalize(session->replace_identities_fpr);        
krista@2461
  1328
            if (session->remove_fpr_as_default)
krista@2461
  1329
                sqlite3_finalize(session->remove_fpr_as_default);            
vb@65
  1330
            if (session->set_person)
vb@65
  1331
                sqlite3_finalize(session->set_person);
krista@2468
  1332
            if (session->set_as_pep_user)
krista@2468
  1333
                sqlite3_finalize(session->set_as_pep_user);
krista@2468
  1334
            if (session->is_pep_user)
krista@2468
  1335
                sqlite3_finalize(session->is_pep_user);
krista@2468
  1336
            if (session->exists_person)
krista@2468
  1337
                sqlite3_finalize(session->exists_person);                        
edouard@1234
  1338
            if (session->set_device_group)
edouard@1234
  1339
                sqlite3_finalize(session->set_device_group);
edouard@1235
  1340
            if (session->get_device_group)
edouard@1235
  1341
                sqlite3_finalize(session->get_device_group);
vb@65
  1342
            if (session->set_pgp_keypair)
vb@65
  1343
                sqlite3_finalize(session->set_pgp_keypair);
krista@2480
  1344
            if (session->exists_identity_entry)
krista@2480
  1345
                sqlite3_finalize(session->exists_identity_entry);                
krista@2478
  1346
            if (session->set_identity_entry)
krista@2478
  1347
                sqlite3_finalize(session->set_identity_entry);
krista@2478
  1348
            if (session->update_identity_entry)
krista@2478
  1349
                sqlite3_finalize(session->update_identity_entry);    
vb@932
  1350
            if (session->set_identity_flags)
vb@932
  1351
                sqlite3_finalize(session->set_identity_flags);
edouard@1394
  1352
            if (session->unset_identity_flags)
edouard@1394
  1353
                sqlite3_finalize(session->unset_identity_flags);
krista@2480
  1354
            if (session->exists_trust_entry)
krista@2480
  1355
                sqlite3_finalize(session->exists_trust_entry);                                
vb@65
  1356
            if (session->set_trust)
vb@65
  1357
                sqlite3_finalize(session->set_trust);
krista@2478
  1358
            if (session->update_trust)
krista@2478
  1359
                sqlite3_finalize(session->update_trust);                
krista@1799
  1360
            if (session->update_trust_for_fpr)
krista@1799
  1361
                sqlite3_finalize(session->update_trust_for_fpr);
vb@65
  1362
            if (session->get_trust)
vb@65
  1363
                sqlite3_finalize(session->get_trust);
vb@251
  1364
            if (session->least_trust)
vb@251
  1365
                sqlite3_finalize(session->least_trust);
vb@517
  1366
            if (session->mark_compromized)
vb@517
  1367
                sqlite3_finalize(session->mark_compromized);
vb@517
  1368
            if (session->crashdump)
vb@517
  1369
                sqlite3_finalize(session->crashdump);
vb@517
  1370
            if (session->languagelist)
vb@517
  1371
                sqlite3_finalize(session->languagelist);
vb@517
  1372
            if (session->i18n_token)
vb@517
  1373
                sqlite3_finalize(session->i18n_token);
krista@2461
  1374
            if (session->replace_userid)
krista@2461
  1375
                sqlite3_finalize(session->replace_userid);
krista@2461
  1376
            if (session->replace_main_user_fpr)
krista@2461
  1377
                sqlite3_finalize(session->replace_main_user_fpr);                
krista@2461
  1378
            if (session->get_main_user_fpr)
krista@2461
  1379
                sqlite3_finalize(session->get_main_user_fpr);
krista@2461
  1380
            if (session->refresh_userid_default_key)
krista@2461
  1381
                sqlite3_finalize(session->refresh_userid_default_key);
vb@517
  1382
            if (session->blacklist_add)
vb@517
  1383
                sqlite3_finalize(session->blacklist_add);
vb@517
  1384
            if (session->blacklist_delete)
vb@517
  1385
                sqlite3_finalize(session->blacklist_delete);
vb@517
  1386
            if (session->blacklist_is_listed)
vb@517
  1387
                sqlite3_finalize(session->blacklist_is_listed);
vb@517
  1388
            if (session->blacklist_retrieve)
vb@517
  1389
                sqlite3_finalize(session->blacklist_retrieve);
krista@957
  1390
            if (session->own_key_is_listed)
krista@957
  1391
                sqlite3_finalize(session->own_key_is_listed);
roker@1002
  1392
            if (session->own_identities_retrieve)
roker@1002
  1393
                sqlite3_finalize(session->own_identities_retrieve);
edouard@1394
  1394
            if (session->own_keys_retrieve)
edouard@1394
  1395
                sqlite3_finalize(session->own_keys_retrieve);
krista@2461
  1396
            // if (session->set_own_key)
krista@2461
  1397
            //     sqlite3_finalize(session->set_own_key);
krista@957
  1398
            if (session->sequence_value1)
krista@957
  1399
                sqlite3_finalize(session->sequence_value1);
krista@957
  1400
            if (session->sequence_value2)
krista@960
  1401
                sqlite3_finalize(session->sequence_value2);
vb@1085
  1402
            if (session->sequence_value3)
vb@1085
  1403
                sqlite3_finalize(session->sequence_value3);
krista@957
  1404
            if (session->set_revoked)
krista@957
  1405
                sqlite3_finalize(session->set_revoked);
krista@957
  1406
            if (session->get_revoked)
krista@957
  1407
                sqlite3_finalize(session->get_revoked);
vb@26
  1408
krista@2471
  1409
            if (session->add_mistrusted_key)
krista@2471
  1410
                sqlite3_finalize(session->add_mistrusted_key);
krista@2471
  1411
            if (session->delete_mistrusted_key)
krista@2471
  1412
                sqlite3_finalize(session->delete_mistrusted_key);
krista@2471
  1413
            if (session->is_mistrusted_key)
krista@2471
  1414
                sqlite3_finalize(session->is_mistrusted_key);
krista@2471
  1415
vb@65
  1416
            if (session->db)
vb@65
  1417
                sqlite3_close_v2(session->db);
vb@65
  1418
            if (session->system_db)
vb@65
  1419
                sqlite3_close_v2(session->system_db);
roker@529
  1420
        }
vb@65
  1421
vb@65
  1422
        release_transport_system(session, out_last);
vb@65
  1423
        release_cryptotech(session, out_last);
vb@65
  1424
roker@1722
  1425
#ifdef DEBUG_ERRORSTACK
roker@1722
  1426
        free_stringlist(session->errorstack);
roker@1722
  1427
#endif
vb@65
  1428
        free(session);
vb@62
  1429
    }
vb@0
  1430
}
vb@0
  1431
vb@467
  1432
DYNAMIC_API void config_passive_mode(PEP_SESSION session, bool enable)
vb@464
  1433
{
vb@464
  1434
    assert(session);
vb@467
  1435
    session->passive_mode = enable;
vb@464
  1436
}
vb@464
  1437
vb@467
  1438
DYNAMIC_API void config_unencrypted_subject(PEP_SESSION session, bool enable)
vb@464
  1439
{
vb@464
  1440
    assert(session);
vb@467
  1441
    session->unencrypted_subject = enable;
vb@464
  1442
}
vb@464
  1443
vb@1110
  1444
DYNAMIC_API void config_keep_sync_msg(PEP_SESSION session, bool enable)
vb@1109
  1445
{
vb@1109
  1446
    assert(session);
vb@1110
  1447
    session->keep_sync_msg = enable;
vb@1109
  1448
}
vb@1109
  1449
vb@1819
  1450
DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable)
vb@1819
  1451
{
vb@1819
  1452
    assert(session);
vb@1819
  1453
    session->service_log = enable;
vb@1819
  1454
}
vb@1819
  1455
vb@0
  1456
DYNAMIC_API PEP_STATUS log_event(
vb@450
  1457
        PEP_SESSION session,
vb@451
  1458
        const char *title,
vb@451
  1459
        const char *entity,
vb@451
  1460
        const char *description,
vb@451
  1461
        const char *comment
vb@0
  1462
    )
vb@0
  1463
{
roker@529
  1464
    PEP_STATUS status = PEP_STATUS_OK;
roker@529
  1465
    int result;
vb@0
  1466
roker@529
  1467
    assert(session);
roker@529
  1468
    assert(title);
roker@529
  1469
    assert(entity);
vb@0
  1470
vb@191
  1471
    if (!(session && title && entity))
vb@191
  1472
        return PEP_ILLEGAL_VALUE;
vb@191
  1473
roker@529
  1474
    sqlite3_reset(session->log);
roker@529
  1475
    sqlite3_bind_text(session->log, 1, title, -1, SQLITE_STATIC);
roker@529
  1476
    sqlite3_bind_text(session->log, 2, entity, -1, SQLITE_STATIC);
roker@529
  1477
    if (description)
vb@46
  1478
        sqlite3_bind_text(session->log, 3, description, -1, SQLITE_STATIC);
roker@529
  1479
    else
roker@529
  1480
        sqlite3_bind_null(session->log, 3);
roker@529
  1481
    if (comment)
roker@529
  1482
        sqlite3_bind_text(session->log, 4, comment, -1, SQLITE_STATIC);
roker@529
  1483
    else
roker@529
  1484
        sqlite3_bind_null(session->log, 4);
roker@529
  1485
    do {
roker@529
  1486
        result = sqlite3_step(session->log);
roker@529
  1487
        assert(result == SQLITE_DONE || result == SQLITE_BUSY);
roker@529
  1488
        if (result != SQLITE_DONE && result != SQLITE_BUSY)
roker@529
  1489
            status = PEP_UNKNOWN_ERROR;
roker@529
  1490
    } while (result == SQLITE_BUSY);
roker@529
  1491
    sqlite3_reset(session->log);
vb@0
  1492
roker@1853
  1493
    return ADD_TO_LOG(status);
vb@0
  1494
}
vb@0
  1495
vb@1819
  1496
DYNAMIC_API PEP_STATUS log_service(
vb@1819
  1497
        PEP_SESSION session,
vb@1819
  1498
        const char *title,
vb@1819
  1499
        const char *entity,
vb@1819
  1500
        const char *description,
vb@1819
  1501
        const char *comment
vb@1819
  1502
    )
vb@1819
  1503
{
vb@1819
  1504
    assert(session);
vb@1819
  1505
    if (!session)
vb@1819
  1506
        return PEP_ILLEGAL_VALUE;
vb@1819
  1507
vb@1819
  1508
    if (session->service_log)
vb@1819
  1509
        return log_event(session, title, entity, description, comment);
vb@1819
  1510
    else
vb@1819
  1511
        return PEP_STATUS_OK;
vb@1819
  1512
}
vb@1819
  1513
vb@233
  1514
DYNAMIC_API PEP_STATUS trustword(
vb@0
  1515
            PEP_SESSION session, uint16_t value, const char *lang,
vb@0
  1516
            char **word, size_t *wsize
vb@0
  1517
        )
vb@0
  1518
{
roker@529
  1519
    PEP_STATUS status = PEP_STATUS_OK;
vb@0
  1520
roker@529
  1521
    assert(session);
roker@529
  1522
    assert(word);
roker@529
  1523
    assert(wsize);
vb@0
  1524
vb@191
  1525
    if (!(session && word && wsize))
vb@191
  1526
        return PEP_ILLEGAL_VALUE;
vb@191
  1527
roker@529
  1528
    *word = NULL;
roker@529
  1529
    *wsize = 0;
vb@0
  1530
roker@529
  1531
    if (lang == NULL)
roker@529
  1532
        lang = "en";
vb@0
  1533
roker@529
  1534
    assert((lang[0] >= 'A' && lang[0] <= 'Z')
vb@0
  1535
            || (lang[0] >= 'a' && lang[0] <= 'z'));
roker@529
  1536
    assert((lang[1] >= 'A' && lang[1] <= 'Z')
vb@0
  1537
            || (lang[1] >= 'a' && lang[1] <= 'z'));
roker@529
  1538
    assert(lang[2] == 0);
vb@0
  1539
roker@529
  1540
    sqlite3_reset(session->trustword);
vb@233
  1541
    sqlite3_bind_text(session->trustword, 1, lang, -1, SQLITE_STATIC);
roker@529
  1542
    sqlite3_bind_int(session->trustword, 2, value);
vb@0
  1543
roker@877
  1544
    const int result = sqlite3_step(session->trustword);
roker@529
  1545
    if (result == SQLITE_ROW) {
vb@233
  1546
        *word = strdup((const char *) sqlite3_column_text(session->trustword,
vb@0
  1547
                    1));
roker@529
  1548
        if (*word)
vb@233
  1549
            *wsize = sqlite3_column_bytes(session->trustword, 1);
roker@529
  1550
        else
Edouard@693
  1551
            status = PEP_OUT_OF_MEMORY;
roker@529
  1552
    } else
roker@529
  1553
        status = PEP_TRUSTWORD_NOT_FOUND;
vb@0
  1554
roker@529
  1555
    sqlite3_reset(session->trustword);
roker@529
  1556
    return status;
vb@0
  1557
}
vb@0
  1558
vb@233
  1559
DYNAMIC_API PEP_STATUS trustwords(
vb@0
  1560
        PEP_SESSION session, const char *fingerprint, const char *lang,
vb@0
  1561
        char **words, size_t *wsize, int max_words
vb@0
  1562
    )
vb@0
  1563
{
roker@529
  1564
    const char *source = fingerprint;
vb@0
  1565
roker@529
  1566
    assert(session);
roker@529
  1567
    assert(fingerprint);
roker@529
  1568
    assert(words);
roker@529
  1569
    assert(wsize);
roker@529
  1570
    assert(max_words >= 0);
vb@0
  1571
vb@191
  1572
    if (!(session && fingerprint && words && wsize && max_words >= 0))
vb@191
  1573
        return PEP_ILLEGAL_VALUE;
vb@191
  1574
roker@529
  1575
    *words = NULL;
roker@529
  1576
    *wsize = 0;
vb@0
  1577
roker@1559
  1578
    char *buffer = calloc(1, MAX_TRUSTWORDS_SPACE);
vb@0
  1579
    assert(buffer);
vb@0
  1580
    if (buffer == NULL)
vb@0
  1581
        return PEP_OUT_OF_MEMORY;
roker@1559
  1582
    char *dest = buffer;
vb@0
  1583
roker@1559
  1584
    const size_t fsize = strlen(fingerprint);
vb@0
  1585
roker@529
  1586
    if (!lang || !lang[0])
roker@529
  1587
        lang = "en";
vb@0
  1588
roker@529
  1589
    assert((lang[0] >= 'A' && lang[0] <= 'Z')
vb@0
  1590
            || (lang[0] >= 'a' && lang[0] <= 'z'));
roker@529
  1591
    assert((lang[1] >= 'A' && lang[1] <= 'Z')
vb@0
  1592
            || (lang[1] >= 'a' && lang[1] <= 'z'));
roker@529
  1593
    assert(lang[2] == 0);
vb@0
  1594
roker@529
  1595
    int n_words = 0;
roker@529
  1596
    while (source < fingerprint + fsize) {
vb@939
  1597
        PEP_STATUS _status;
roker@529
  1598
        uint16_t value;
roker@1559
  1599
        char *word = NULL;
roker@1559
  1600
        size_t _wsize = 0;
roker@529
  1601
        int j;
vb@0
  1602
vb@0
  1603
        for (value=0, j=0; j < 4 && source < fingerprint + fsize; ) {
roker@529
  1604
            if (*source >= 'a' && *source <= 'f')
roker@529
  1605
                value += (*source - 'a' + 10) << (3 - j++) * 4;
roker@529
  1606
            else if (*source >= 'A' && *source <= 'F')
roker@529
  1607
                value += (*source - 'A' + 10) << (3 - j++) * 4;
roker@529
  1608
            else if (*source >= '0' && *source <= '9')
roker@529
  1609
                value += (*source - '0') << (3 - j++) * 4;
roker@529
  1610
            
roker@529
  1611
            source++;
roker@529
  1612
        }
vb@0
  1613
roker@529
  1614
        _status = trustword(session, value, lang, &word, &_wsize);
vb@0
  1615
        if (_status == PEP_OUT_OF_MEMORY) {
vb@0
  1616
            free(buffer);
vb@0
  1617
            return PEP_OUT_OF_MEMORY;
vb@0
  1618
        }
roker@529
  1619
        if (word == NULL) {
vb@0
  1620
            free(buffer);
roker@529
  1621
            return PEP_TRUSTWORD_NOT_FOUND;
vb@0
  1622
        }
vb@0
  1623
roker@529
  1624
        if (dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1) {
roker@529
  1625
            strncpy(dest, word, _wsize);
vb@0
  1626
            free(word);
roker@529
  1627
            dest += _wsize;
roker@529
  1628
        }
roker@529
  1629
        else {
vb@0
  1630
            free(word);
roker@529
  1631
            break; // buffer full
vb@0
  1632
        }
vb@0
  1633
roker@529
  1634
        if (source < fingerprint + fsize
vb@251
  1635
                && dest + _wsize < buffer + MAX_TRUSTWORDS_SPACE - 1)
roker@529
  1636
            *dest++ = ' ';
vb@0
  1637
roker@529
  1638
        ++n_words;
roker@529
  1639
        if (max_words && n_words >= max_words)
roker@529
  1640
            break;
roker@529
  1641
    }
vb@0
  1642
roker@529
  1643
    *words = buffer;
roker@529
  1644
    *wsize = dest - buffer;
roker@529
  1645
    return PEP_STATUS_OK;
vb@0
  1646
}
vb@0
  1647
vb@0
  1648
pEp_identity *new_identity(
vb@0
  1649
        const char *address, const char *fpr, const char *user_id,
vb@0
  1650
        const char *username
vb@0
  1651
    )
vb@0
  1652
{
vb@0
  1653
    pEp_identity *result = calloc(1, sizeof(pEp_identity));
vb@0
  1654
    assert(result);
vb@0
  1655
    if (result) {
vb@0
  1656
        if (address) {
vb@0
  1657
            result->address = strdup(address);
vb@0
  1658
            assert(result->address);
vb@0
  1659
            if (result->address == NULL) {
vb@0
  1660
                free(result);
vb@0
  1661
                return NULL;
vb@0
  1662
            }
vb@0
  1663
        }
vb@0
  1664
        if (fpr) {
vb@0
  1665
            result->fpr = strdup(fpr);
vb@0
  1666
            assert(result->fpr);
vb@0
  1667
            if (result->fpr == NULL) {
vb@0
  1668
                free_identity(result);
vb@0
  1669
                return NULL;
vb@0
  1670
            }
vb@0
  1671
        }
vb@0
  1672
        if (user_id) {
vb@0
  1673
            result->user_id = strdup(user_id);
vb@0
  1674
            assert(result->user_id);
vb@0
  1675
            if (result->user_id == NULL) {
vb@0
  1676
                free_identity(result);
vb@0
  1677
                return NULL;
vb@0
  1678
            }
vb@0
  1679
        }
vb@0
  1680
        if (username) {
vb@0
  1681
            result->username = strdup(username);
vb@0
  1682
            assert(result->username);
vb@0
  1683
            if (result->username == NULL) {
vb@0
  1684
                free_identity(result);
vb@0
  1685
                return NULL;
vb@0
  1686
            }
vb@0
  1687
        }
vb@0
  1688
    }
vb@0
  1689
    return result;
vb@0
  1690
}
vb@0
  1691
vb@37
  1692
pEp_identity *identity_dup(const pEp_identity *src)
vb@37
  1693
{
vb@37
  1694
    assert(src);
vb@37
  1695
vb@951
  1696
    pEp_identity *dup = new_identity(src->address, src->fpr, src->user_id,
vb@951
  1697
            src->username);
vb@37
  1698
    assert(dup);
vb@37
  1699
    if (dup == NULL)
vb@37
  1700
        return NULL;
vb@37
  1701
    
vb@37
  1702
    dup->comm_type = src->comm_type;
vb@37
  1703
    dup->lang[0] = src->lang[0];
vb@37
  1704
    dup->lang[1] = src->lang[1];
vb@37
  1705
    dup->lang[2] = 0;
vb@930
  1706
    dup->flags = src->flags;
krista@2461
  1707
    dup->me = src->me;
krista@2461
  1708
    
vb@37
  1709
    return dup;
vb@37
  1710
}
vb@37
  1711
vb@0
  1712
void free_identity(pEp_identity *identity)
vb@0
  1713
{
vb@0
  1714
    if (identity) {
vb@0
  1715
        free(identity->address);
vb@0
  1716
        free(identity->fpr);
vb@0
  1717
        free(identity->user_id);
vb@0
  1718
        free(identity->username);
vb@0
  1719
        free(identity);
vb@0
  1720
    }
vb@0
  1721
}
vb@0
  1722
krista@2461
  1723
DYNAMIC_API PEP_STATUS get_default_own_userid(
krista@2461
  1724
        PEP_SESSION session, 
krista@2461
  1725
        char** userid
krista@2461
  1726
    )
krista@2461
  1727
{
krista@2461
  1728
    assert(session);
krista@2461
  1729
    assert(userid);
krista@2461
  1730
    
krista@2461
  1731
    if (!session || !userid)
krista@2461
  1732
        return PEP_ILLEGAL_VALUE;
krista@2461
  1733
        
krista@2461
  1734
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
  1735
    char* retval = NULL;
krista@2461
  1736
    
krista@2461
  1737
    sqlite3_reset(session->get_default_own_userid);
krista@2461
  1738
krista@2461
  1739
    const int result = sqlite3_step(session->get_default_own_userid);
krista@2461
  1740
    const char* id;
krista@2461
  1741
    
krista@2461
  1742
    switch (result) {
krista@2461
  1743
        case SQLITE_ROW:
krista@2461
  1744
            id = (const char *) sqlite3_column_text(session->get_default_own_userid, 0);
krista@2461
  1745
            if (!id) {
krista@2461
  1746
                // Shouldn't happen.
krista@2461
  1747
                status = PEP_UNKNOWN_ERROR;
krista@2461
  1748
            }
krista@2461
  1749
            else {
krista@2461
  1750
                retval = strdup(id);
krista@2461
  1751
                if (!retval)
krista@2461
  1752
                    status = PEP_OUT_OF_MEMORY;
krista@2461
  1753
            }
krista@2461
  1754
            break;
krista@2461
  1755
        default:
krista@2461
  1756
            // Technically true, given how we find it, but FIXME we need a more descriptive error
krista@2461
  1757
            status = PEP_CANNOT_FIND_IDENTITY;
krista@2461
  1758
            *userid = NULL;
krista@2461
  1759
    }
krista@2461
  1760
krista@2461
  1761
    *userid = retval;
krista@2461
  1762
krista@2461
  1763
    sqlite3_reset(session->get_default_own_userid);
krista@2461
  1764
    
krista@2461
  1765
    return status;
krista@2461
  1766
}
krista@2461
  1767
krista@2461
  1768
DYNAMIC_API PEP_STATUS get_userid_alias_default(
krista@2461
  1769
        PEP_SESSION session, 
krista@2461
  1770
        const char* alias_id,
krista@2461
  1771
        char** default_id) {
krista@2461
  1772
            
krista@2461
  1773
    assert(session);
krista@2461
  1774
    assert(alias_id);
krista@2461
  1775
    assert(alias_id[0]);
krista@2461
  1776
    assert(default_id);
krista@2461
  1777
krista@2461
  1778
    if (!(session && alias_id && alias_id[0] && default_id))
krista@2461
  1779
        return PEP_ILLEGAL_VALUE;
krista@2461
  1780
krista@2461
  1781
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
  1782
    char* retval = NULL;
krista@2461
  1783
krista@2461
  1784
    sqlite3_reset(session->get_userid_alias_default);
krista@2461
  1785
    sqlite3_bind_text(session->get_userid_alias_default, 1, alias_id, -1, SQLITE_STATIC);
krista@2461
  1786
krista@2461
  1787
    const char* tempid;
krista@2461
  1788
    
krista@2461
  1789
    const int result = sqlite3_step(session->get_userid_alias_default);
krista@2461
  1790
    switch (result) {
krista@2461
  1791
    case SQLITE_ROW:
krista@2461
  1792
        tempid = (const char *) sqlite3_column_text(session->get_userid_alias_default, 0);
krista@2461
  1793
        if (tempid) {
krista@2461
  1794
            retval = strdup(tempid);
krista@2461
  1795
            assert(retval);
krista@2461
  1796
            if (retval == NULL)
krista@2461
  1797
                return PEP_OUT_OF_MEMORY;
krista@2461
  1798
        }
krista@2461
  1799
    
krista@2461
  1800
        *default_id = retval;
krista@2461
  1801
        break;
krista@2461
  1802
    default:
krista@2461
  1803
        status = PEP_CANNOT_FIND_ALIAS;
krista@2461
  1804
        *default_id = NULL;
krista@2461
  1805
    }
krista@2461
  1806
krista@2461
  1807
    sqlite3_reset(session->get_userid_alias_default);
krista@2461
  1808
    return status;            
krista@2461
  1809
}
krista@2461
  1810
krista@2461
  1811
DYNAMIC_API PEP_STATUS set_userid_alias (
krista@2461
  1812
        PEP_SESSION session, 
krista@2461
  1813
        const char* default_id,
krista@2461
  1814
        const char* alias_id) {
krista@2461
  1815
            
krista@2461
  1816
    int result;
krista@2461
  1817
krista@2461
  1818
    assert(session);
krista@2461
  1819
    assert(default_id);
krista@2461
  1820
    assert(alias_id);
krista@2461
  1821
krista@2461
  1822
    if (!(session && default_id && alias_id && 
krista@2461
  1823
          default_id[0] != '\0' && alias_id[0] != '\0'))
krista@2461
  1824
        return PEP_ILLEGAL_VALUE;
krista@2478
  1825
    
krista@2479
  1826
    sqlite3_exec(session->db, "BEGIN TRANSACTION ;", NULL, NULL, NULL);
krista@2461
  1827
krista@2461
  1828
    sqlite3_reset(session->add_userid_alias);
krista@2461
  1829
    sqlite3_bind_text(session->add_userid_alias, 1, default_id, -1,
krista@2461
  1830
            SQLITE_STATIC);
krista@2461
  1831
    sqlite3_bind_text(session->add_userid_alias, 2, alias_id, -1,
krista@2461
  1832
            SQLITE_STATIC);
krista@2461
  1833
        
krista@2461
  1834
    result = sqlite3_step(session->add_userid_alias);
krista@2461
  1835
krista@2461
  1836
    sqlite3_reset(session->add_userid_alias);
krista@2478
  1837
    if (result != SQLITE_DONE) {
krista@2478
  1838
        sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);        
krista@2461
  1839
        return PEP_CANNOT_SET_ALIAS;
krista@2478
  1840
    }
krista@2478
  1841
    sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
krista@2478
  1842
        
krista@2478
  1843
krista@2461
  1844
    return PEP_STATUS_OK;
krista@2461
  1845
}
krista@2461
  1846
vb@0
  1847
DYNAMIC_API PEP_STATUS get_identity(
Edouard@559
  1848
        PEP_SESSION session,
Edouard@559
  1849
        const char *address,
Edouard@559
  1850
        const char *user_id,
vb@0
  1851
        pEp_identity **identity
vb@0
  1852
    )
vb@0
  1853
{
roker@529
  1854
    PEP_STATUS status = PEP_STATUS_OK;
roker@529
  1855
    static pEp_identity *_identity;
vb@0
  1856
roker@529
  1857
    assert(session);
roker@529
  1858
    assert(address);
vb@8
  1859
    assert(address[0]);
vb@632
  1860
    assert(identity);
vb@0
  1861
vb@632
  1862
    if (!(session && address && address[0] && identity))
vb@191
  1863
        return PEP_ILLEGAL_VALUE;
vb@191
  1864
vb@632
  1865
    *identity = NULL;
vb@632
  1866
vb@46
  1867
    sqlite3_reset(session->get_identity);
vb@46
  1868
    sqlite3_bind_text(session->get_identity, 1, address, -1, SQLITE_STATIC);
Edouard@559
  1869
    sqlite3_bind_text(session->get_identity, 2, user_id, -1, SQLITE_STATIC);
vb@0
  1870
roker@876
  1871
    const int result = sqlite3_step(session->get_identity);
roker@529
  1872
    switch (result) {
roker@529
  1873
    case SQLITE_ROW:
vb@0
  1874
        _identity = new_identity(
vb@0
  1875
                address,
vb@46
  1876
                (const char *) sqlite3_column_text(session->get_identity, 0),
Edouard@559
  1877
                user_id,
Edouard@559
  1878
                (const char *) sqlite3_column_text(session->get_identity, 1)
vb@0
  1879
                );
vb@0
  1880
        assert(_identity);
vb@0
  1881
        if (_identity == NULL)
vb@0
  1882
            return PEP_OUT_OF_MEMORY;
vb@0
  1883
vb@951
  1884
        _identity->comm_type = (PEP_comm_type)
vb@951
  1885
            sqlite3_column_int(session->get_identity, 2);
vb@951
  1886
        const char* const _lang = (const char *)
vb@951
  1887
            sqlite3_column_text(session->get_identity, 3);
vb@0
  1888
        if (_lang && _lang[0]) {
roker@529
  1889
            assert(_lang[0] >= 'a' && _lang[0] <= 'z');
roker@529
  1890
            assert(_lang[1] >= 'a' && _lang[1] <= 'z');
roker@529
  1891
            assert(_lang[2] == 0);
roker@529
  1892
            _identity->lang[0] = _lang[0];
roker@529
  1893
            _identity->lang[1] = _lang[1];
vb@0
  1894
            _identity->lang[2] = 0;
roker@529
  1895
        }
vb@951
  1896
        _identity->flags = (unsigned int)
vb@951
  1897
            sqlite3_column_int(session->get_identity, 4);
krista@2461
  1898
        _identity->me = (unsigned int)
krista@2461
  1899
            sqlite3_column_int(session->get_identity, 5);
krista@2461
  1900
    
roker@529
  1901
        *identity = _identity;
roker@529
  1902
        break;
roker@529
  1903
    default:
vb@0
  1904
        status = PEP_CANNOT_FIND_IDENTITY;
roker@529
  1905
        *identity = NULL;
roker@529
  1906
    }
vb@0
  1907
vb@46
  1908
    sqlite3_reset(session->get_identity);
roker@529
  1909
    return status;
vb@0
  1910
}
vb@0
  1911
krista@2461
  1912
PEP_STATUS get_identity_without_trust_check(
krista@2461
  1913
        PEP_SESSION session,
krista@2461
  1914
        const char *address,
krista@2461
  1915
        const char *user_id,
krista@2461
  1916
        pEp_identity **identity
krista@2461
  1917
    )
krista@2461
  1918
{
krista@2461
  1919
    PEP_STATUS status = PEP_STATUS_OK;
krista@2461
  1920
    static pEp_identity *_identity;
krista@2461
  1921
krista@2461
  1922
    assert(session);
krista@2461
  1923
    assert(address);
krista@2461
  1924
    assert(address[0]);
krista@2461
  1925
    assert(identity);
krista@2461
  1926
krista@2461
  1927
    if (!(session && address && address[0] && identity))
krista@2461
  1928
        return PEP_ILLEGAL_VALUE;
krista@2461
  1929
krista@2461
  1930
    *identity = NULL;
krista@2461
  1931
krista@2461
  1932
    sqlite3_reset(session->get_identity_without_trust_check);
krista@2461
  1933
    sqlite3_bind_text(session->get_identity_without_trust_check, 1, address, -1, SQLITE_STATIC);
krista@2461
  1934
    sqlite3_bind_text(session->get_identity_without_trust_check, 2, user_id, -1, SQLITE_STATIC);
krista@2461
  1935
krista@2461
  1936
    const int result = sqlite3_step(session->get_identity_without_trust_check);
krista@2461
  1937
    switch (result) {
krista@2461
  1938
    case SQLITE_ROW:
krista@2461
  1939
        _identity = new_identity(
krista@2461
  1940
                address,
krista@2461
  1941
                (const char *) sqlite3_column_text(session->get_identity_without_trust_check, 0),
krista@2461
  1942
                user_id,
krista@2461
  1943
                (const char *) sqlite3_column_text(session->get_identity_without_trust_check, 1)
krista@2461
  1944
                );
krista@2461
  1945
        assert(_identity);
krista@2461
  1946
        if (_identity == NULL)
krista@2461
  1947
            return PEP_OUT_OF_MEMORY;
krista@2461
  1948
krista@2461
  1949
        _identity->comm_type = PEP_ct_unknown;
krista@2461
  1950
        const char* const _lang = (const char *)
krista@2461
  1951
            sqlite3_column_text(session->get_identity_without_trust_check, 2);
krista@2461
  1952
        if (_lang && _lang[0]) {
krista@2461
  1953
            assert(_lang[0] >= 'a' && _lang[0] <= 'z');
krista@2461
  1954
            assert(_lang[1] >= 'a' && _lang[1] <= 'z');
krista@2461
  1955
            assert(_lang[2] == 0);
krista@2461
  1956
            _identity->lang[0] = _lang[0];
krista@2461
  1957
            _identity->lang[1] = _lang[1];
krista@2461
  1958
            _identity->lang[2] = 0;
krista@2461
  1959
        }
krista@2461
  1960
        _identity->flags = (unsigned int)
krista@2461
  1961
            sqlite3_column_int(session->get_identity_without_trust_check, 3);
krista@2461
  1962
        _identity->me = (unsigned int)
krista@2461
  1963
            sqlite3_column_int(session->get_identity_without_trust_check, 4);
krista@2461
  1964
    
krista@2461
  1965
        *identity = _identity;
krista@2461
  1966
        break;
krista@2461
  1967
    default:
krista@2461
  1968
        status = PEP_CANNOT_FIND_IDENTITY;
krista@2461
  1969
        *identity = NULL;
krista@2461
  1970
    }
krista@2461
  1971
krista@2461
  1972
    sqlite3_reset(session->get_identity_without_trust_check);
krista@2461
  1973
    return status;
krista@2461
  1974
}
krista@2461
  1975
krista@2461
  1976
PEP_STATUS get_identities_by_address(
krista@2461
  1977
        PEP_SESSION session,
krista@2461
  1978
        const char *address,
krista@2461
  1979
        identity_list** id_list
krista@2461
  1980
    )
krista@2461
  1981
{
krista@2461
  1982
    pEp_identity* ident;
krista@2461
  1983
krista@2461
  1984
    assert(session);
krista@2461
  1985
    assert(address);
krista@2461
  1986
    assert(address[0]);
krista@2461
  1987
    assert(id_list);
krista@2461
  1988
krista@2461
  1989
    if (!(session && address && address[0] && id_list))
krista@2461
  1990
        return PEP_ILLEGAL_VALUE;
krista@2461
  1991
krista@2461
  1992
    *id_list = NULL;
krista@2461
  1993
    identity_list* ident_list = NULL;
krista@2461
  1994
krista@2461
  1995
    sqlite3_reset(session->get_identities_by_address);
krista@2461
  1996
    sqlite3_bind_text(session->get_identities_by_address, 1, address, -1, SQLITE_STATIC);
krista@2461
  1997
    int result;
krista@2461
  1998
krista@2461
  1999
    while ((result = sqlite3_step(session->get_identities_by_address)) == SQLITE_ROW) {
krista@2461
  2000
        //"select user_id, main_key_id, username, comm_type, lang,"
krista@2461
  2001
        //"   identity.flags, is_own"
krista@2461
  2002
        ident = new_identity(
krista@2461
  2003
                address,
krista@2461
  2004
                (const char *) sqlite3_column_text(session->get_identities_by_address, 1),
krista@2461
  2005
                (const char *) sqlite3_column_text(session->get_identities_by_address, 0),
krista@2461
  2006
                (const char *) sqlite3_column_text(session->get_identities_by_address, 2)
krista@2461
  2007
                );
krista@2461
  2008
        assert(ident);
krista@2461
  2009
        if (ident == NULL)
krista@2461
  2010
            return PEP_OUT_OF_MEMORY;
krista@2461
  2011
krista@2461
  2012
        ident->comm_type = PEP_ct_unknown;
krista@2461
  2013
        
krista@2461
  2014
        const char* const _lang = (const char *)
krista@2461
  2015
            sqlite3_column_text(session->get_identities_by_address, 3);
krista@2461
  2016
        if (_lang && _lang[0]) {
krista@2461
  2017
            assert(_lang[0] >= 'a' && _lang[0] <= 'z');
krista@2461
  2018
            assert(_lang[1] >= 'a' && _lang[1] <= 'z');
krista@2461
  2019
            assert(_lang[2] == 0);
krista@2461
  2020
            ident->lang[0] = _lang[0];
krista@2461
  2021
            ident->lang[1] = _lang[1];
krista@2461
  2022
            ident->lang[2] = 0;
krista@2461
  2023
        }
krista@2461
  2024
        ident->flags = (unsigned int)
krista@2461
  2025
            sqlite3_column_int(session->get_identities_by_address, 4);
krista@2461
  2026
        ident->me = (unsigned int)
krista@2461
  2027
            sqlite3_column_int(session->get_identities_by_address, 5);
krista@2461
  2028
    
krista@2461
  2029
        if (ident_list)
krista@2461
  2030
            identity_list_add(ident_list, ident);
krista@2461
  2031
        else
krista@2461
  2032
            ident_list = new_identity_list(ident);
krista@2461
  2033
    }
krista@2461
  2034
krista@2461
  2035
    sqlite3_reset(session->get_identities_by_address);
krista@2461
  2036
    
krista@2461
  2037
    *id_list = ident_list;
krista@2461
  2038
    
krista@2461
  2039
    if (!ident_list)
krista@2461
  2040
        return PEP_CANNOT_FIND_IDENTITY;
krista@2461
  2041
    
krista@2461
  2042
    return PEP_STATUS_OK;
krista@2461
  2043
}
krista@2461
  2044
krista@2480
  2045
PEP_STATUS exists_identity_entry(PEP_SESSION session, pEp_identity* identity,
krista@2480
  2046
                                 bool* exists) {
krista@2480
  2047
    assert(session);
krista@2480
  2048
    assert(identity);
krista@2480
  2049
    assert(!EMPTYSTR(identity->user_id));        
krista@2480
  2050
    assert(!EMPTYSTR(identity->address));
krista@2480
  2051
    if (!session || !exists || EMPTYSTR(identity->user_id) || EMPTYSTR(identity->address))
krista@2480
  2052
        return PEP_ILLEGAL_VALUE;
krista@2480
  2053
    
krista@2480
  2054
    *exists = false;
krista@2480
  2055
    
krista@2480
  2056
    sqlite3_reset(session->exists_identity_entry);
krista@2480
  2057
    sqlite3_bind_text(session->exists_identity_entry, 1, identity->address, -1,
krista@2480
  2058
                      SQLITE_STATIC);
krista@2480
  2059
    sqlite3_bind_text(session->exists_identity_entry, 2, identity->user_id, -1,
krista@2480
  2060
                      SQLITE_STATIC);
krista@2480
  2061
                  
krista@2480
  2062
    int result = sqlite3_step(session->exists_identity_entry);
krista@2480
  2063
    switch (result) {
krista@2480
  2064
        case SQLITE_ROW: {
krista@2480
  2065
            // yeah yeah, I know, we could be lazy here, but it looks bad.
krista@2480
  2066
            *exists = (sqlite3_column_int(session->exists_identity_entry, 0) != 0);
krista@2480
  2067
            break;
krista@2480
  2068
        }
krista@2480
  2069
        default:
krista@2480
  2070
            return PEP_UNKNOWN_ERROR;
krista@2480
  2071
    }
krista@2480
  2072
krista@2480
  2073
    return PEP_STATUS_OK;
krista@2480
  2074
}
krista@2480
  2075
krista@2480
  2076
PEP_STATUS exists_trust_entry(PEP_SESSION session, pEp_identity* identity,
krista@2480
  2077
                              bool* exists) {
krista@2480
  2078
    assert(session);
krista@2480
  2079
    assert(identity);
krista@2480
  2080
    assert(!EMPTYSTR(identity->user_id));        
krista@2480
  2081
    assert(!EMPTYSTR(identity->fpr));
krista@2480
  2082
    if (!session || !exists || EMPTYSTR(identity->user_id) || EMPTYSTR(identity->fpr))
krista@2480
  2083
        return PEP_ILLEGAL_VALUE;
krista@2480
  2084
    
krista@2480
  2085
    *exists = false;
krista@2480
  2086
    
krista@2480
  2087
    sqlite3_reset(session->exists_trust_entry);
krista@2480
  2088
    sqlite3_bind_text(session->exists_trust_entry, 1, identity->user_id, -1,
krista@2480
  2089
                      SQLITE_STATIC);
krista@2480
  2090
    sqlite3_bind_text(session->exists_trust_entry, 2, identity->fpr, -1,
krista@2480
  2091
                      SQLITE_STATIC);
krista@2480
  2092
                  
krista@2480
  2093
    int result = sqlite3_step(session->exists_trust_entry);
krista@2480
  2094
    switch (result) {
krista@2480
  2095
        case SQLITE_ROW: {
krista@2480
  2096
            // yeah yeah, I know, we could be lazy here, but it looks bad.
krista@2480
  2097
            *exists = (sqlite3_column_int(session->exists_trust_entry, 0) != 0);
krista@2480
  2098
            break;
krista@2480
  2099
        }
krista@2480
  2100
        default:
krista@2480
  2101
            return PEP_UNKNOWN_ERROR;
krista@2480
  2102
    }
krista@2480
  2103
krista@2480
  2104
    return PEP_STATUS_OK;
krista@2480
  2105
}
krista@2480
  2106
krista@2477
  2107
// FIXME: We can rollback in set_identity on the return status,
krista@2477
  2108
// so we should probably do that.
krista@2477
  2109
PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr) {
krista@2477
  2110
    if (!session || EMPTYSTR(fpr))
krista@2477
  2111
        return PEP_ILLEGAL_VALUE;
krista@2477
  2112
        
krista@2477
  2113
    int result;
krista@2477
  2114
    
krista@2477
  2115
    sqlite3_reset(session->set_pgp_keypair);
krista@2477
  2116
    sqlite3_bind_text(session->set_pgp_keypair, 1, fpr, -1,
krista@2477
  2117
            SQLITE_STATIC);
krista@2477
  2118
    result = sqlite3_step(session->set_pgp_keypair);
krista@2477
  2119
    sqlite3_reset(session->set_pgp_keypair);
krista@2477
  2120
    if (result != SQLITE_DONE) {
krista@2477
  2121
        return PEP_CANNOT_SET_PGP_KEYPAIR;
krista@2477
  2122
    }
krista@2477
  2123
    
krista@2477
  2124
    return PEP_STATUS_OK;
krista@2477
  2125
}
krista@2461
  2126
krista@2478
  2127
static PEP_STATUS _set_or_update_trust(PEP_SESSION session,
krista@2480
  2128
                                       pEp_identity* identity,
krista@2478
  2129
                                       sqlite3_stmt* set_or_update) {
krista@2478
  2130
krista@2478
  2131
    assert(session);
krista@2478
  2132
    assert(identity);
krista@2478
  2133
    assert(identity->user_id);
krista@2478
  2134
    assert(identity->fpr);
krista@2478
  2135
    
krista@2478
  2136
    if (!session || !identity || EMPTYSTR(identity->user_id) || EMPTYSTR(identity->fpr))
krista@2478
  2137
        return PEP_ILLEGAL_VALUE;
krista@2478
  2138
        
krista@2478
  2139
    int result;
krista@2478
  2140
                
krista@2478
  2141
    sqlite3_reset(set_or_update);
krista@2478
  2142
    sqlite3_bind_text(set_or_update, 1, identity->user_id, -1,
krista@2478
  2143
            SQLITE_STATIC);
krista@2478
  2144
    sqlite3_bind_text(set_or_update, 2, identity->fpr, -1,
krista@2478
  2145
            SQLITE_STATIC);
krista@2478
  2146
    sqlite3_bind_int(set_or_update, 3, identity->comm_type);
krista@2478
  2147
    result = sqlite3_step(set_or_update);
krista@2478
  2148
    assert(result == SQLITE_DONE);
krista@2478
  2149
    sqlite3_reset(set_or_update);
krista@2478
  2150
    if (result != SQLITE_DONE)
krista@2478
  2151
        return PEP_CANNOT_SET_TRUST;
krista@2478
  2152
krista@2478
  2153
    return PEP_STATUS_OK;
krista@2478
  2154
}
krista@2478
  2155
krista@2478
  2156
static PEP_STATUS _set_or_update_identity_entry(PEP_SESSION session,
krista@2480
  2157
                                                pEp_identity* identity,
krista@2478
  2158
                                                sqlite3_stmt* set_or_update) {
krista@2478
  2159
    assert(session);
krista@2478
  2160
    assert(identity);
krista@2478
  2161
    assert(set_or_update);
krista@2478
  2162
                      
krista@2478
  2163
    if (!session || !identity || !identity->user_id || !identity->address)
krista@2478
  2164
        return PEP_ILLEGAL_VALUE;
krista@2478
  2165
                                              
krista@2478
  2166
    sqlite3_reset(set_or_update);
krista@2478
  2167
    sqlite3_bind_text(set_or_update, 1, identity->address, -1,
krista@2478
  2168
            SQLITE_STATIC);
krista@2478
  2169
    sqlite3_bind_text(set_or_update, 2, identity->fpr, -1,
krista@2478
  2170
            SQLITE_STATIC);
krista@2478
  2171
    sqlite3_bind_text(set_or_update, 3, identity->user_id, -1,
krista@2478
  2172
            SQLITE_STATIC);
krista@2478
  2173
    sqlite3_bind_int(set_or_update, 4, identity->flags);
krista@2478
  2174
    sqlite3_bind_int(set_or_update, 5, identity->me);
krista@2478
  2175
    int result = sqlite3_step(set_or_update);
krista@2478
  2176
    sqlite3_reset(set_or_update);
krista@2478
  2177
    if (result != SQLITE_DONE)
krista@2478
  2178
        return PEP_CANNOT_SET_IDENTITY;
krista@2478
  2179
    
krista@2478
  2180
    return PEP_STATUS_OK;
krista@2478
  2181
}
krista@2478
  2182
krista@2478
  2183
static PEP_STATUS _set_or_update_person(PEP_SESSION session, 
krista@2480
  2184
                                        pEp_identity* identity,
krista@2478
  2185
                                        sqlite3_stmt* set_or_update) {
krista@2478
  2186
    assert(session);
krista@2478
  2187
    assert(identity);
krista@2478
  2188
    assert(set_or_update);
krista@2478
  2189
                        
krista@2478
  2190
    if (!session || !identity || !identity->user_id || !identity->username)
krista@2478
  2191
        return PEP_ILLEGAL_VALUE;
krista@2478
  2192
        
krista@2478
  2193
    sqlite3_reset(set_or_update);
krista@2478
  2194
    sqlite3_bind_text(set_or_update, 1, identity->user_id, -1,
krista@2478
  2195
            SQLITE_STATIC);
krista@2478
  2196
    sqlite3_bind_text(set_or_update, 2, identity->username, -1,
krista@2478
  2197
            SQLITE_STATIC);
krista@2478
  2198
    if (identity->lang[0])
krista@2478
  2199
        sqlite3_bind_text(set_or_update, 3, identity->lang, 2,
krista@2478
  2200
                SQLITE_STATIC);
krista@2478
  2201
    else
krista@2478
  2202
        sqlite3_bind_null(set_or_update, 3);
krista@2478
  2203
    sqlite3_bind_text(set_or_update, 4, identity->fpr, -1,
krista@2478
  2204
                      SQLITE_STATIC);
krista@2478
  2205
    int result = sqlite3_step(set_or_update);
krista@2478
  2206
    sqlite3_reset(set_or_update);
krista@2478
  2207
    
krista@2478
  2208
    if (result != SQLITE_DONE)
krista@2478
  2209
        return PEP_CANNOT_SET_PERSON;
krista@2478
  2210
    
krista@2478
  2211
    return PEP_STATUS_OK;                                         
krista@2478
  2212
}
krista@2478
  2213
krista@2478
  2214
PEP_STATUS set_or_update_with_identity(PEP_SESSION session,
krista@2480
  2215
                                       pEp_identity* identity,
krista@2480
  2216
                                       PEP_STATUS (* set_function)(PEP_SESSION, pEp_identity*, sqlite3_stmt*),
krista@2480
  2217
                                       PEP_STATUS (* exists_function)(PEP_SESSION, pEp_identity*, bool*),                                       
krista@2479
  2218
                                       sqlite3_stmt* update_query,
krista@2478
  2219
                                       sqlite3_stmt* set_query,
krista@2478
  2220
                                       bool guard_transaction) {
krista@2478
  2221
krista@2478
  2222
    if (guard_transaction) {
krista@2479
  2223
        sqlite3_exec(session->db, "BEGIN TRANSACTION ;", NULL, NULL, NULL);
krista@2480
  2224
    }
krista@2480
  2225
    bool exists = false;
krista@2480
  2226
    PEP_STATUS status = exists_function(session, identity, &exists);
krista@2480
  2227
    
krista@2480
  2228
    if (status == PEP_STATUS_OK) {
krista@2480
  2229
        if (exists) {
krista@2480
  2230
            status = set_function(session, identity, update_query);
krista@2480
  2231
        }
krista@2480
  2232
        else {
krista@2480
  2233
            status = set_function(session, identity, set_query);                                              
krista@2480
  2234
        }                    
krista@2480
  2235
    }   
krista@2480
  2236
    if (guard_transaction) {        
krista@2480
  2237
        if (status != PEP_STATUS_OK)
krista@2478
  2238
            sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
krista@2480
  2239
        else 
krista@2480
  2240
            sqlite3_exec(session->db, "COMMIT ;", NULL, NULL, NULL);
krista@2478
  2241
    }                      
krista@2478
  2242
    return status;
krista@2478
  2243
}
krista@2478
  2244
krista@2480
  2245
PEP_STATUS _set_trust_internal(PEP_SESSION session, pEp_identity* identity,
krista@2478
  2246
                               bool guard_transaction) {
krista@2478
  2247
    return set_or_update_with_identity(session, identity,
krista@2478
  2248
                                       _set_or_update_trust,
krista@2480
  2249
                                       exists_trust_entry,
krista@2478
  2250
                                       session->update_trust,
krista@2478
  2251
                                       session->set_trust,
krista@2478
  2252
                                       guard_transaction);
krista@2478
  2253
}
krista@2480
  2254
PEP_STATUS set_trust(PEP_SESSION session, pEp_identity* identity) {
krista@2478
  2255
    return _set_trust_internal(session, identity, true);
krista@2478
  2256
}
krista@2478
  2257
krista@2480
  2258
PEP_STATUS set_person(PEP_SESSION session, pEp_identity* identity,
krista@2478
  2259
                      bool guard_transaction) {
krista@2478
  2260
    return set_or_update_with_identity(session, identity,
krista@2478
  2261
                                       _set_or_update_person,
krista@2480
  2262
                                       exists_person,
krista@2478
  2263
                                       session->update_person,
krista@2478
  2264
                                       session->set_person,
krista@2478
  2265
                                       guard_transaction);
krista@2478
  2266
}
krista@2478
  2267
krista@2480
  2268
PEP_STATUS set_identity_entry(PEP_SESSION session, pEp_identity* identity,
krista@2478
  2269
                              bool guard_transaction) {
krista@2478
  2270
    return set_or_update_with_identity(session, identity,
krista@2478
  2271
                                       _set_or_update_identity_entry,
krista@2480
  2272
                                       exists_identity_entry,
krista@2478
  2273
                                       session->update_identity_entry,
krista@2478
  2274
                                       session->set_identity_entry,
krista@2478
  2275
                                       guard_transaction);
krista@2478
  2276
}
krista@2478
  2277
vb@0
  2278
DYNAMIC_API PEP_STATUS set_identity(
vb@0
  2279
        PEP_SESSION session, const pEp_identity *identity
vb@0
  2280
    )
vb@0
  2281
{
roker@529
  2282
    int result;
vb@0
  2283
roker@529
  2284
    assert(session);
roker@529
  2285
    assert(identity);
roker@529
  2286
    assert(identity->address);
roker@529
  2287
    assert(identity->user_id);
roker@529
  2288
    assert(identity->username);
vb@0
  2289
krista@1223
  2290
    if (!(session && identity && identity->address &&
vb@191
  2291
                identity->user_id && identity->username))
vb@191
  2292
        return PEP_ILLEGAL_VALUE;
vb@191
  2293
krista@1791
  2294
    PEP_STATUS status = PEP_STATUS_OK;
krista@1791
  2295
    
vb@515
  2296
    bool listed;
krista@1449
  2297
krista@2480
  2298
    bool has_fpr = (!EMPTYSTR(identity->fpr));
krista@1222
  2299
    
krista@1449
  2300
    if (has_fpr) {    
krista@2461
  2301
        // blacklist check - FIXME: ENGINE-294 will remove
krista@1791
  2302
        status = blacklist_is_listed(session, identity->fpr, &listed);
krista@1223
  2303
        assert(status == PEP_STATUS_OK);
krista@1223
  2304
        if (status != PEP_STATUS_OK)
krista@1223
  2305
            return status;
vb@515
  2306
krista@1223
  2307
        if (listed)
krista@1223
  2308
            return PEP_KEY_BLACKLISTED;
krista@1223
  2309
    }
vb@515
  2310
krista@2479
  2311
    sqlite3_exec(session->db, "BEGIN TRANSACTION ;", NULL, NULL, NULL);
vb@0
  2312
vb@1079
  2313
    if (identity->lang[0]) {
vb@1079
  2314
        assert(identity->lang[0] >= 'a' && identity->lang[0] <= 'z');
vb@1079
  2315
        assert(identity->lang[1] >= 'a' && identity->lang[1] <= 'z');
vb@1079
  2316
        assert(identity->lang[2] == 0);
vb@1079
  2317
    }
vb@1079
  2318
krista@2468
  2319
    if (has_fpr) {
krista@2468
  2320
        sqlite3_reset(session->set_pgp_keypair);
krista@2468
  2321
        sqlite3_bind_text(session->set_pgp_keypair, 1, identity->fpr, -1,
krista@2468
  2322
                SQLITE_STATIC);
krista@2468
  2323
        result = sqlite3_step(session->set_pgp_keypair);
krista@2468
  2324
        sqlite3_reset(session->set_pgp_keypair);
krista@2468
  2325
        if (result != SQLITE_DONE) {
krista@2468
  2326
            sqlite3_exec(session->db, "ROLLBACK ;", NULL, NULL, NULL);
krista@2468
  2327
            return PEP_CANNOT_SET_PGP_KEYPAIR;
krista@2468
  2328
        }
krista@2468
  2329
    }
krista@2468
  2330
krista@2480
  2331
    // We do this because there are checks in set_person for
krista@2480
  2332
    // aliases, which modify the identity object on return.
krista@2480
  2333
    pEp_identity* ident_copy = identity_dup(identity); 
krista@2480
  2334
    if (!ident_copy)
krista@2480
  2335
        return PEP_OUT_OF_MEMORY;
krista@2480
  2336
krista@2480
  2337
    status = set_person(session, ident_copy, false);
krista@2478
  2338
    if (status != PEP_STATUS_OK) {