ENGINE-538: added DB repair to default - no use risking it.
authorKrista 'DarthMama' Bennett <krista@pep.foundation>
Tue, 09 Apr 2019 09:26:27 +0200
changeset 34739cd6a0ad3c74
parent 3472 df00e438b8c4
child 3942 3453d05cbe9a
child 4204 e278385af49d
ENGINE-538: added DB repair to default - no use risking it.
src/keymanagement.c
src/message_api.c
src/pEpEngine.c
     1.1 --- a/src/keymanagement.c	Tue Apr 09 09:07:10 2019 +0200
     1.2 +++ b/src/keymanagement.c	Tue Apr 09 09:26:27 2019 +0200
     1.3 @@ -1581,7 +1581,7 @@
     1.4          }
     1.5      }    
     1.6  
     1.7 -pep_free:
     1.8 +//pep_free:
     1.9      free(ident_default_fpr);
    1.10      free(cached_fpr);
    1.11      free_identity(tmp_id);
     2.1 --- a/src/message_api.c	Tue Apr 09 09:07:10 2019 +0200
     2.2 +++ b/src/message_api.c	Tue Apr 09 09:26:27 2019 +0200
     2.3 @@ -1406,30 +1406,6 @@
     2.4             );
     2.5  }
     2.6  
     2.7 -static void remove_attached_keys(message *msg)
     2.8 -{
     2.9 -    if (msg) {
    2.10 -        bloblist_t *last = NULL;
    2.11 -        for (bloblist_t *bl = msg->attachments; bl && bl->value; ) {
    2.12 -            bloblist_t *next = bl->next;
    2.13 -
    2.14 -            if (is_key(bl)) {
    2.15 -                if (last) {
    2.16 -                    last->next = next;
    2.17 -                }
    2.18 -                else {
    2.19 -                    msg->attachments = next;
    2.20 -                }
    2.21 -                free_bl_entry(bl);
    2.22 -            }
    2.23 -            else {
    2.24 -                last = bl;
    2.25 -            }
    2.26 -            bl = next;
    2.27 -        }
    2.28 -    }
    2.29 -}
    2.30 -
    2.31  static bool compare_first_n_bytes(const char* first, const char* second, size_t n) {
    2.32      int i;
    2.33      for (i = 0; i < n; i++) {
     3.1 --- a/src/pEpEngine.c	Tue Apr 09 09:07:10 2019 +0200
     3.2 +++ b/src/pEpEngine.c	Tue Apr 09 09:26:27 2019 +0200
     3.3 @@ -518,6 +518,193 @@
     3.4      return retval;
     3.5  }
     3.6  
     3.7 +// N.B. In default, there are two tables in this check which are not 
     3.8 +//      in the default branch; since this code is executed rarely, 
     3.9 +//      we'll leave the checks in anyway (they're harmless), as 
    3.10 +//      this'll prevent merge conflicts when we do the final merge from 
    3.11 +//      default to sync; once 2.0.0 is released and we are then only 
    3.12 +//      doing backports to this branch, we should remove these in this 
    3.13 +//      branch.
    3.14 +static PEP_STATUS repair_altered_tables(PEP_SESSION session) {
    3.15 +    PEP_STATUS status = PEP_STATUS_OK;
    3.16 +    
    3.17 +    const unsigned int _PEP_MAX_AFFECTED = 5;
    3.18 +    char** table_names = calloc(_PEP_MAX_AFFECTED, sizeof(char*));
    3.19 +    if (!table_names)
    3.20 +        return PEP_OUT_OF_MEMORY;
    3.21 +
    3.22 +    const char* sql_query = "select tbl_name from sqlite_master WHERE sql LIKE '%REFERENCES%' AND sql LIKE '%_old%';";
    3.23 +    sqlite3_stmt *stmt; 
    3.24 +    sqlite3_prepare_v2(session->db, sql_query, -1, &stmt, NULL);
    3.25 +    int i = 0;
    3.26 +    int int_result = 0;
    3.27 +    while ((int_result = sqlite3_step(stmt)) == SQLITE_ROW && i < _PEP_MAX_AFFECTED) {
    3.28 +        table_names[i++] = strdup((const char*)(sqlite3_column_text(stmt, 0)));
    3.29 +    }
    3.30 +    
    3.31 +    sqlite3_finalize(stmt);      
    3.32 +
    3.33 +    if ((int_result != SQLITE_DONE && int_result != SQLITE_OK) || i > (_PEP_MAX_AFFECTED + 1)) {
    3.34 +        status = PEP_UNKNOWN_ERROR;
    3.35 +        goto pEp_free;
    3.36 +    }
    3.37 +        
    3.38 +    for (i = 0; i < _PEP_MAX_AFFECTED; i++) {
    3.39 +        const char* table_name = table_names[i];
    3.40 +        if (!table_name)
    3.41 +            break;
    3.42 +            
    3.43 +        if (strcmp(table_name, "identity") == 0) {
    3.44 +            int_result = sqlite3_exec(session->db,
    3.45 +                "PRAGMA foreign_keys=off;\n"
    3.46 +                "BEGIN TRANSACTION;\n"
    3.47 +                "create table _identity_new (\n"
    3.48 +                "   address text,\n"
    3.49 +                "   user_id text\n"
    3.50 +                "       references person (id)\n"
    3.51 +                "       on delete cascade on update cascade,\n"
    3.52 +                "   main_key_id text\n"
    3.53 +                "       references pgp_keypair (fpr)\n"
    3.54 +                "       on delete set null,\n"
    3.55 +                "   comment text,\n"
    3.56 +                "   flags integer default 0,\n"
    3.57 +                "   is_own integer default 0,\n"
    3.58 +                "   timestamp integer default (datetime('now')),\n"
    3.59 +                "   primary key (address, user_id)\n"
    3.60 +                ");\n"
    3.61 +                "INSERT INTO _identity_new SELECT * from identity;\n"
    3.62 +                "DROP TABLE identity;\n"
    3.63 +                "ALTER TABLE _identity_new RENAME TO identity;\n"
    3.64 +                "COMMIT;\n"
    3.65 +                "PRAGMA foreign_keys=on;"
    3.66 +                ,
    3.67 +                NULL,
    3.68 +                NULL,
    3.69 +                NULL
    3.70 +            );
    3.71 +            assert(int_result == PEP_STATUS_OK);
    3.72 +        }
    3.73 +        else if (strcmp(table_name, "trust") == 0) {
    3.74 +            int_result = sqlite3_exec(session->db,
    3.75 +                "PRAGMA foreign_keys=off;\n"
    3.76 +                "BEGIN TRANSACTION;\n"
    3.77 +                "create table _trust_new (\n"
    3.78 +                "   user_id text not null\n"
    3.79 +                "       references person (id)\n"
    3.80 +                "       on delete cascade on update cascade,\n"
    3.81 +                "   pgp_keypair_fpr text not null\n"
    3.82 +                "       references pgp_keypair (fpr)\n"
    3.83 +                "       on delete cascade,\n"
    3.84 +                "   comm_type integer not null,\n"
    3.85 +                "   comment text,\n"
    3.86 +                "   primary key (user_id, pgp_keypair_fpr)\n"
    3.87 +                ");\n"
    3.88 +                "INSERT INTO _trust_new SELECT * from trust;\n"
    3.89 +                "DROP TABLE trust;\n"
    3.90 +                "ALTER TABLE _trust_new RENAME TO trust;\n"
    3.91 +                "COMMIT;\n"
    3.92 +                "PRAGMA foreign_keys=on;"
    3.93 +                ,
    3.94 +                NULL,
    3.95 +                NULL,
    3.96 +                NULL
    3.97 +            );             
    3.98 +            assert(int_result == PEP_STATUS_OK);                       
    3.99 +        }
   3.100 +        else if (strcmp(table_name, "alternate_user_id") == 0) {
   3.101 +            int_result = sqlite3_exec(session->db,
   3.102 +                "PRAGMA foreign_keys=off;\n"
   3.103 +                "BEGIN TRANSACTION;\n"
   3.104 +                "create table _alternate_user_id_new (\n"
   3.105 +                "    default_id text references person (id)\n"
   3.106 +                "       on delete cascade on update cascade,\n"
   3.107 +                "    alternate_id text primary key\n"
   3.108 +                ");\n"
   3.109 +                "INSERT INTO _alternate_user_id_new SELECT * from alternate_user_id;\n"
   3.110 +                "DROP TABLE alternate_user_id;\n"
   3.111 +                "ALTER TABLE _alternate_user_id_new RENAME TO alternate_user_id;\n"
   3.112 +                "COMMIT;\n"
   3.113 +                "PRAGMA foreign_keys=on;"                
   3.114 +                ,
   3.115 +                NULL,
   3.116 +                NULL,
   3.117 +                NULL
   3.118 +            );
   3.119 +            assert(int_result == PEP_STATUS_OK);
   3.120 +        }
   3.121 +        else if (strcmp(table_name, "revocation_contact_list") == 0) {
   3.122 +            int_result = sqlite3_exec(session->db,
   3.123 +                "PRAGMA foreign_keys=off;\n"
   3.124 +                "BEGIN TRANSACTION;\n"
   3.125 +                "create table _revocation_contact_list_new (\n"
   3.126 +                "   fpr text not null references pgp_keypair (fpr)\n"
   3.127 +                "       on delete cascade,\n"
   3.128 +                "   contact_id text not null references person (id)\n"
   3.129 +                "       on delete cascade on update cascade,\n"
   3.130 +                "   timestamp integer default (datetime('now')),\n"
   3.131 +                "   PRIMARY KEY(fpr, contact_id)\n"            
   3.132 +                ");\n"
   3.133 +                "INSERT INTO _revocation_contact_list_new SELECT * from revocation_contact_list;\n"
   3.134 +                "DROP TABLE revocation_contact_list;\n"
   3.135 +                "ALTER TABLE _revocation_contact_list_new RENAME TO revocation_contact_list;\n"
   3.136 +                "COMMIT;\n"
   3.137 +                "PRAGMA foreign_keys=on;"                
   3.138 +                ,
   3.139 +                NULL,
   3.140 +                NULL,
   3.141 +                NULL
   3.142 +            );      
   3.143 +            assert(int_result == PEP_STATUS_OK);                              
   3.144 +        }
   3.145 +        else if (strcmp(table_name, "social_graph")) {
   3.146 +            int_result = sqlite3_exec(session->db,
   3.147 +                "PRAGMA foreign_keys=off;\n"
   3.148 +                "BEGIN TRANSACTION;\n"
   3.149 +                "create table _social_new (\n"
   3.150 +                "    own_userid text,\n"
   3.151 +                "    own_address text,\n"
   3.152 +                "    contact_userid text,\n"
   3.153 +                "    CONSTRAINT fk_own_identity\n"
   3.154 +                "       FOREIGN KEY(own_address, own_userid)\n" 
   3.155 +                "       REFERENCES identity(address, user_id)\n"
   3.156 +                "       ON DELETE CASCADE ON UPDATE CASCADE\n"
   3.157 +                ");\n"
   3.158 +                "INSERT INTO _social_graph_new SELECT * from social_graph;\n"
   3.159 +                "DROP TABLE social_graph;\n"
   3.160 +                "ALTER TABLE _social_graph_new RENAME TO social_graph;\n"
   3.161 +                "COMMIT;\n"
   3.162 +                "PRAGMA foreign_keys=on;"                
   3.163 +                ,
   3.164 +                NULL,
   3.165 +                NULL,
   3.166 +                NULL
   3.167 +            );
   3.168 +            assert(int_result == PEP_STATUS_OK);                                    
   3.169 +        }        
   3.170 +    }
   3.171 +    
   3.172 +    int_result = sqlite3_exec(
   3.173 +        session->db,
   3.174 +        "PRAGMA foreign_key_check;\n"
   3.175 +        ,
   3.176 +        NULL,
   3.177 +        NULL,
   3.178 +        NULL
   3.179 +    );
   3.180 +    assert(int_result == SQLITE_OK);
   3.181 +
   3.182 +pEp_free:
   3.183 +    for (i = 0; i < _PEP_MAX_AFFECTED; i++) {
   3.184 +        if (table_names[i])
   3.185 +            free(table_names[i]);
   3.186 +        else
   3.187 +            break;
   3.188 +    }
   3.189 +    free(table_names);
   3.190 +    return status;
   3.191 +}
   3.192 +
   3.193 +
   3.194  void errorLogCallback(void *pArg, int iErrCode, const char *zMsg){
   3.195    fprintf(stderr, "(%d) %s\n", iErrCode, zMsg);
   3.196  }
   3.197 @@ -835,7 +1022,6 @@
   3.198              }
   3.199          }
   3.200  
   3.201 -
   3.202          if(version != 0) { 
   3.203              // Version has been already set
   3.204  
   3.205 @@ -1074,6 +1260,12 @@
   3.206              assert(int_result == SQLITE_OK);
   3.207          }
   3.208          
   3.209 +        // We just do this universally at this point on this branch.
   3.210 +        // It's one quick DB query at init and should only 
   3.211 +        // result in actual full function execution once.
   3.212 +        status = repair_altered_tables(_session);
   3.213 +        assert(status == PEP_STATUS_OK);
   3.214 +        
   3.215          // We need to init a few globals for message id that we'd rather not
   3.216          // calculate more than once.
   3.217          _init_globals();