| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882 |
- /* _____ _
- * |_ _| |_ _ _ ___ ___ _ __ __ _
- * | | | ' \| '_/ -_) -_) ' \/ _` |_
- * |_| |_||_|_| \___\___|_|_|_\__,_(_)
- *
- * Threema for Android
- * Copyright (c) 2015-2023 Threema GmbH
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- package ch.threema.storage;
- import android.content.Context;
- import android.text.format.DateUtils;
- import android.widget.Toast;
- import androidx.annotation.MainThread;
- import net.sqlcipher.database.SQLiteDatabase;
- import net.sqlcipher.database.SQLiteDatabaseHook;
- import net.sqlcipher.database.SQLiteException;
- import net.sqlcipher.database.SQLiteOpenHelper;
- import org.slf4j.Logger;
- import java.io.File;
- import java.io.IOException;
- import androidx.annotation.NonNull;
- import ch.threema.app.exceptions.DatabaseMigrationFailedException;
- import ch.threema.app.exceptions.DatabaseMigrationLockedException;
- import ch.threema.app.services.UpdateSystemService;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion10;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion11;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion12;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion13;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion14;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion15;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion16;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion17;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion19;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion20;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion21;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion24;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion25;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion27;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion28;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion31;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion32;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion33;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion34;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion35;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion36;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion37;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion38;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion39;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion4;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion40;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion41;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion42;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion43;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion44;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion45;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion46;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion47;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion48;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion49;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion50;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion51;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion52;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion53;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion54;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion55;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion56;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion58;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion59;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion6;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion60;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion61;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion62;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion63;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion64;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion65;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion66;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion67;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion68;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion69;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion7;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion70;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion71;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion72;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion73;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion74;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion75;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion76;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion77;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion78;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion79;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion8;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion80;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion81;
- import ch.threema.app.services.systemupdate.SystemUpdateToVersion9;
- import ch.threema.app.utils.FileUtil;
- import ch.threema.app.utils.RuntimeUtil;
- import ch.threema.app.utils.TestUtil;
- import ch.threema.base.utils.LoggingUtil;
- import ch.threema.storage.factories.BallotChoiceModelFactory;
- import ch.threema.storage.factories.BallotModelFactory;
- import ch.threema.storage.factories.BallotVoteModelFactory;
- import ch.threema.storage.factories.ContactModelFactory;
- import ch.threema.storage.factories.ConversationTagFactory;
- import ch.threema.storage.factories.DistributionListMemberModelFactory;
- import ch.threema.storage.factories.DistributionListMessageModelFactory;
- import ch.threema.storage.factories.DistributionListModelFactory;
- import ch.threema.storage.factories.GroupBallotModelFactory;
- import ch.threema.storage.factories.GroupCallModelFactory;
- import ch.threema.storage.factories.GroupInviteModelFactory;
- import ch.threema.storage.factories.GroupMemberModelFactory;
- import ch.threema.storage.factories.GroupMessageModelFactory;
- import ch.threema.storage.factories.GroupMessagePendingMessageIdModelFactory;
- import ch.threema.storage.factories.GroupModelFactory;
- import ch.threema.storage.factories.GroupRequestSyncLogModelFactory;
- import ch.threema.storage.factories.IdentityBallotModelFactory;
- import ch.threema.storage.factories.IncomingGroupJoinRequestModelFactory;
- import ch.threema.storage.factories.MessageModelFactory;
- import ch.threema.storage.factories.ModelFactory;
- import ch.threema.storage.factories.OutgoingGroupJoinRequestModelFactory;
- import ch.threema.storage.factories.ServerMessageModelFactory;
- import ch.threema.storage.factories.WebClientSessionModelFactory;
- public class DatabaseServiceNew extends SQLiteOpenHelper {
- private static final Logger logger = LoggingUtil.getThreemaLogger("DatabaseServiceNew");
- public static final String DATABASE_NAME = "threema.db";
- public static final String DATABASE_NAME_V4 = "threema4.db";
- public static final String DATABASE_BACKUP_EXT = ".backup";
- private static final int DATABASE_VERSION = SystemUpdateToVersion81.VERSION;
- private final Context context;
- private final String key;
- private final UpdateSystemService updateSystemService;
- private ContactModelFactory contactModelFactory;
- private MessageModelFactory messageModelFactory;
- private GroupModelFactory groupModelFactory;
- private GroupMemberModelFactory groupMemberModelFactory;
- private GroupMessageModelFactory groupMessageModelFactory;
- private DistributionListModelFactory distributionListModelFactory;
- private DistributionListMemberModelFactory distributionListMemberModelFactory;
- private DistributionListMessageModelFactory distributionListMessageModelFactory;
- private GroupRequestSyncLogModelFactory groupRequestSyncLogModelFactory;
- private BallotModelFactory ballotModelFactory;
- private BallotChoiceModelFactory ballotChoiceModelFactory;
- private BallotVoteModelFactory ballotVoteModelFactory;
- private IdentityBallotModelFactory identityBallotModelFactory;
- private GroupBallotModelFactory groupBallotModelFactory;
- private GroupMessagePendingMessageIdModelFactory groupMessagePendingMessageIdModelFactory;
- private WebClientSessionModelFactory webClientSessionModelFactory;
- private ConversationTagFactory conversationTagFactory;
- private GroupInviteModelFactory groupInviteModelFactory;
- private OutgoingGroupJoinRequestModelFactory outgoingGroupJoinRequestModelFactory;
- private IncomingGroupJoinRequestModelFactory incomingGroupJoinRequestModelFactory;
- private GroupCallModelFactory groupCallModelFactory;
- private ServerMessageModelFactory serverMessageModelFactory;
- public DatabaseServiceNew(final Context context,
- final String databaseKey,
- UpdateSystemService updateSystemService,
- int sqlcipherVersion) {
- super(
- context,
- sqlcipherVersion == 4 ? DATABASE_NAME_V4 : DATABASE_NAME,
- null,
- DATABASE_VERSION,
- new SQLiteDatabaseHook() {
- @Override
- public void preKey(SQLiteDatabase sqLiteDatabase) {
- if (sqlcipherVersion == 4) {
- sqLiteDatabase.rawExecSQL("PRAGMA cipher_default_kdf_iter = 1;");
- } else {
- sqLiteDatabase.rawExecSQL(
- "PRAGMA cipher_default_page_size = 1024;" +
- "PRAGMA cipher_default_kdf_iter = 4000;" +
- "PRAGMA cipher_default_hmac_algorithm = HMAC_SHA1;" +
- "PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA1;");
- }
- }
- @Override
- public void postKey(SQLiteDatabase sqLiteDatabase) {
- if (sqlcipherVersion == 4) {
- sqLiteDatabase.rawExecSQL("PRAGMA kdf_iter = 1;");
- // turn off memory wiping for now due to https://github.com/sqlcipher/android-database-sqlcipher/issues/411
- sqLiteDatabase.rawExecSQL("PRAGMA cipher_memory_security = OFF;");
- } else {
- sqLiteDatabase.rawExecSQL(
- "PRAGMA cipher_page_size = 1024;" +
- "PRAGMA kdf_iter = 4000;" +
- "PRAGMA cipher_hmac_algorithm = HMAC_SHA1;" +
- "PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;");
- }
- }
- }
- ,
- sqLiteDatabase -> {
- logger.error("Database corrupted");
- RuntimeUtil.runOnUiThread(() -> {
- if (context != null) {
- Toast.makeText(context, "Database corrupted. Please save all data!", Toast.LENGTH_LONG).show();
- }
- });
- // close database
- if (sqLiteDatabase.isOpen()) {
- try {
- sqLiteDatabase.close();
- } catch (Exception e) {
- logger.error("Exception while closing database", e);
- }
- }
- System.exit(2);
- }
- );
- logger.info("instantiated");
- this.updateSystemService = updateSystemService;
- this.context = context;
- SQLiteDatabase.loadLibs(context);
- this.key = databaseKey;
- }
- public synchronized SQLiteDatabase getWritableDatabase() throws SQLiteException {
- return super.getWritableDatabase(this.key);
- }
- public synchronized SQLiteDatabase getReadableDatabase() {
- return super.getReadableDatabase(this.key);
- }
- @Override
- public void onCreate(SQLiteDatabase sqLiteDatabase) {
- for(ModelFactory f: new ModelFactory[] {
- this.getContactModelFactory(),
- this.getMessageModelFactory(),
- this.getGroupModelFactory(),
- this.getGroupMemberModelFactory(),
- this.getGroupMessageModelFactory(),
- this.getDistributionListModelFactory(),
- this.getDistributionListMemberModelFactory(),
- this.getDistributionListMessageModelFactory(),
- this.getGroupRequestSyncLogModelFactory(),
- this.getBallotModelFactory(),
- this.getBallotChoiceModelFactory(),
- this.getBallotVoteModelFactory(),
- this.getIdentityBallotModelFactory(),
- this.getGroupBallotModelFactory(),
- this.getGroupMessagePendingMessageIdModelFactory(),
- this.getWebClientSessionModelFactory(),
- this.getConversationTagFactory(),
- this.getGroupInviteModelFactory(),
- this.getIncomingGroupJoinRequestModelFactory(),
- this.getOutgoingGroupJoinRequestModelFactory(),
- this.getGroupCallModelFactory(),
- this.getServerMessageModelFactory(),
- }) {
- String[] createTableStatement = f.getStatements();
- if(createTableStatement != null) {
- for (String statement : createTableStatement) {
- if (!TestUtil.empty(statement)) {
- sqLiteDatabase.execSQL(statement);
- }
- }
- }
- }
- }
- @NonNull
- public ContactModelFactory getContactModelFactory() {
- if(this.contactModelFactory == null) {
- this.contactModelFactory = new ContactModelFactory(this);
- }
- return this.contactModelFactory;
- }
- @NonNull
- public MessageModelFactory getMessageModelFactory() {
- if(this.messageModelFactory == null) {
- this.messageModelFactory = new MessageModelFactory(this);
- }
- return this.messageModelFactory;
- }
- @NonNull
- public GroupModelFactory getGroupModelFactory() {
- if(this.groupModelFactory == null) {
- this.groupModelFactory = new GroupModelFactory(this);
- }
- return this.groupModelFactory;
- }
- @NonNull
- public GroupMemberModelFactory getGroupMemberModelFactory() {
- if(this.groupMemberModelFactory == null) {
- this.groupMemberModelFactory = new GroupMemberModelFactory(this);
- }
- return this.groupMemberModelFactory;
- }
- @NonNull
- public GroupMessageModelFactory getGroupMessageModelFactory() {
- if(this.groupMessageModelFactory == null) {
- this.groupMessageModelFactory = new GroupMessageModelFactory(this);
- }
- return this.groupMessageModelFactory;
- }
- @NonNull
- public DistributionListModelFactory getDistributionListModelFactory() {
- if(this.distributionListModelFactory == null) {
- this.distributionListModelFactory = new DistributionListModelFactory(this);
- }
- return this.distributionListModelFactory;
- }
- @NonNull
- public DistributionListMemberModelFactory getDistributionListMemberModelFactory() {
- if(this.distributionListMemberModelFactory == null) {
- this.distributionListMemberModelFactory = new DistributionListMemberModelFactory(this);
- }
- return this.distributionListMemberModelFactory;
- }
- @NonNull
- public DistributionListMessageModelFactory getDistributionListMessageModelFactory() {
- if(this.distributionListMessageModelFactory == null) {
- this.distributionListMessageModelFactory = new DistributionListMessageModelFactory(this);
- }
- return this.distributionListMessageModelFactory;
- }
- @NonNull
- public GroupRequestSyncLogModelFactory getGroupRequestSyncLogModelFactory() {
- if(this.groupRequestSyncLogModelFactory == null) {
- this.groupRequestSyncLogModelFactory = new GroupRequestSyncLogModelFactory(this);
- }
- return this.groupRequestSyncLogModelFactory;
- }
- @NonNull
- public BallotModelFactory getBallotModelFactory() {
- if(this.ballotModelFactory == null) {
- this.ballotModelFactory = new BallotModelFactory(this);
- }
- return this.ballotModelFactory;
- }
- @NonNull
- public BallotChoiceModelFactory getBallotChoiceModelFactory() {
- if (this.ballotChoiceModelFactory == null) {
- this.ballotChoiceModelFactory = new BallotChoiceModelFactory(this);
- }
- return this.ballotChoiceModelFactory;
- }
- @NonNull
- public BallotVoteModelFactory getBallotVoteModelFactory() {
- if(this.ballotVoteModelFactory == null) {
- this.ballotVoteModelFactory = new BallotVoteModelFactory(this);
- }
- return this.ballotVoteModelFactory;
- }
- @NonNull
- public IdentityBallotModelFactory getIdentityBallotModelFactory() {
- if(this.identityBallotModelFactory == null) {
- this.identityBallotModelFactory = new IdentityBallotModelFactory(this);
- }
- return this.identityBallotModelFactory;
- }
- @NonNull
- public GroupBallotModelFactory getGroupBallotModelFactory() {
- if(this.groupBallotModelFactory == null) {
- this.groupBallotModelFactory = new GroupBallotModelFactory(this);
- }
- return this.groupBallotModelFactory;
- }
- @NonNull
- public GroupMessagePendingMessageIdModelFactory getGroupMessagePendingMessageIdModelFactory() {
- if(this.groupMessagePendingMessageIdModelFactory == null) {
- this.groupMessagePendingMessageIdModelFactory = new GroupMessagePendingMessageIdModelFactory(this);
- }
- return this.groupMessagePendingMessageIdModelFactory;
- }
- @NonNull
- public WebClientSessionModelFactory getWebClientSessionModelFactory() {
- if(this.webClientSessionModelFactory == null) {
- this.webClientSessionModelFactory = new WebClientSessionModelFactory(this);
- }
- return this.webClientSessionModelFactory;
- }
- @NonNull
- public ConversationTagFactory getConversationTagFactory() {
- if(this.conversationTagFactory == null) {
- this.conversationTagFactory = new ConversationTagFactory(this);
- }
- return this.conversationTagFactory;
- }
- @NonNull
- public GroupInviteModelFactory getGroupInviteModelFactory() {
- if(this.groupInviteModelFactory == null) {
- this.groupInviteModelFactory = new GroupInviteModelFactory(this);
- }
- return this.groupInviteModelFactory;
- }
- @NonNull
- public IncomingGroupJoinRequestModelFactory getIncomingGroupJoinRequestModelFactory() {
- if (this.incomingGroupJoinRequestModelFactory == null) {
- this.incomingGroupJoinRequestModelFactory = new IncomingGroupJoinRequestModelFactory(this);
- }
- return this.incomingGroupJoinRequestModelFactory;
- }
- @NonNull
- public OutgoingGroupJoinRequestModelFactory getOutgoingGroupJoinRequestModelFactory() {
- if (this.outgoingGroupJoinRequestModelFactory == null) {
- this.outgoingGroupJoinRequestModelFactory = new OutgoingGroupJoinRequestModelFactory(this);
- }
- return this.outgoingGroupJoinRequestModelFactory;
- }
- @NonNull
- public GroupCallModelFactory getGroupCallModelFactory() {
- if (this.groupCallModelFactory == null) {
- this.groupCallModelFactory = new GroupCallModelFactory(this);
- }
- return this.groupCallModelFactory;
- }
- @NonNull
- public ServerMessageModelFactory getServerMessageModelFactory() {
- if (this.serverMessageModelFactory == null) {
- this.serverMessageModelFactory = new ServerMessageModelFactory(this);
- }
- return this.serverMessageModelFactory;
- }
- // Note: Enable this to allow database downgrades.
- //
- //@Override
- //public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- // logger.info("onDowngrade, version {} -> {}", oldVersion, newVersion);
- //}
- @Override
- public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
- logger.info("onUpgrade, version {} -> {}", oldVersion, newVersion);
- if (oldVersion < 4) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion4(sqLiteDatabase));
- }
- if (oldVersion < 6) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion6(this.context, sqLiteDatabase));
- }
- if (oldVersion < 7) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion7(sqLiteDatabase));
- }
- if (oldVersion < 8) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion8(this, sqLiteDatabase));
- }
- if (oldVersion < 9) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion9(sqLiteDatabase));
- }
- if (oldVersion < 10) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion10(sqLiteDatabase));
- }
- if (oldVersion < 11) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion11(sqLiteDatabase));
- }
- if (oldVersion < 12) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion12(this.context, sqLiteDatabase));
- }
- if (oldVersion < 13) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion13(sqLiteDatabase));
- }
- if (oldVersion < 14) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion14());
- }
- if (oldVersion < 15) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion15(this, sqLiteDatabase));
- }
- if (oldVersion < 16) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion16(sqLiteDatabase));
- }
- if (oldVersion < 17) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion17(sqLiteDatabase));
- }
- if (oldVersion < 19) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion19(sqLiteDatabase));
- }
- if (oldVersion < 20) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion20(sqLiteDatabase));
- }
- if (oldVersion < 21) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion21(this, sqLiteDatabase));
- }
- if (oldVersion < 24) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion24(sqLiteDatabase));
- }
- if (oldVersion < 25) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion25(this, sqLiteDatabase));
- }
- if (oldVersion < 27) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion27(sqLiteDatabase));
- }
- if (oldVersion < 28) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion28(sqLiteDatabase));
- }
- if (oldVersion < 31) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion31(this.context));
- }
- if (oldVersion < 32) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion32(sqLiteDatabase));
- }
- if (oldVersion < 33) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion33(this, sqLiteDatabase));
- }
- if (oldVersion < 34) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion34(sqLiteDatabase));
- }
- if (oldVersion < 35) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion35(sqLiteDatabase));
- }
- if (oldVersion < 36) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion36(sqLiteDatabase));
- }
- if (oldVersion < 37) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion37(this, sqLiteDatabase));
- }
- if (oldVersion < 38) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion38(this, sqLiteDatabase));
- }
- if (oldVersion < 39) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion39());
- }
- if (oldVersion < 40) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion40(sqLiteDatabase));
- }
- if (oldVersion < 41) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion41(sqLiteDatabase));
- }
- if (oldVersion < 42) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion42(sqLiteDatabase));
- }
- if (oldVersion < 43) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion43(sqLiteDatabase));
- }
- if (oldVersion < 44) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion44(sqLiteDatabase));
- }
- if (oldVersion < 45) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion45(this, sqLiteDatabase));
- }
- if (oldVersion < 46) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion46());
- }
- if (oldVersion < 47) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion47(sqLiteDatabase));
- }
- if (oldVersion < 48) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion48(this.context));
- }
- if (oldVersion < 49) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion49(sqLiteDatabase));
- }
- if (oldVersion < 50) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion50(sqLiteDatabase));
- }
- if (oldVersion < 51) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion51(sqLiteDatabase));
- }
- if (oldVersion < 52) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion52(sqLiteDatabase));
- }
- if (oldVersion < 53) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion53());
- }
- if (oldVersion < 54) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion54(this.context));
- }
- if (oldVersion < 55) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion55());
- }
- if (oldVersion < 56) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion56(sqLiteDatabase));
- }
- if (oldVersion < 58) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion58(sqLiteDatabase));
- }
- if (oldVersion < 59) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion59(sqLiteDatabase));
- }
- if (oldVersion < 60) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion60(sqLiteDatabase));
- }
- if (oldVersion < 61) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion61(sqLiteDatabase));
- }
- if (oldVersion < 62) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion62(sqLiteDatabase));
- }
- if (oldVersion < 63) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion63(this.context));
- }
- if (oldVersion < 64) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion64(this.context));
- }
- if (oldVersion < SystemUpdateToVersion65.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion65(this, sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion66.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion66(this.context));
- }
- if (oldVersion < SystemUpdateToVersion67.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion67(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion68.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion68(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion69.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion69(this, sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion70.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion70(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion71.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion71(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion72.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion72(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion73.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion73(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion74.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion74(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion75.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion75(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion76.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion76(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion77.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion77(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion78.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion78(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion79.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion79(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion80.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion80(sqLiteDatabase));
- }
- if (oldVersion < SystemUpdateToVersion81.VERSION) {
- this.updateSystemService.addUpdate(new SystemUpdateToVersion81(sqLiteDatabase));
- }
- }
- public void executeNull() throws SQLiteException {
- this.getWritableDatabase().rawExecSQL("SELECT NULL");
- }
- @MainThread
- public static synchronized void tryMigrateToV4(Context context, final String databaseKey) throws DatabaseMigrationFailedException, DatabaseMigrationLockedException {
- File oldDatabaseFile = context.getDatabasePath(DATABASE_NAME);
- File newDatabaseFile = context.getDatabasePath(DATABASE_NAME_V4);
- final boolean[] migrateSuccess = {false};
- logger.info("check if v4 database migration is necessary");
- if (oldDatabaseFile.exists()) {
- File lockfile = new File(context.getFilesDir(), ".dbv4-lock");
- if (lockfile.exists()) {
- long lastModified = lockfile.lastModified();
- long now = System.currentTimeMillis();
- if ((now - lastModified) > (5 * DateUtils.MINUTE_IN_MILLIS)) {
- FileUtil.deleteFileOrWarn(lockfile, "Lockfile", logger);
- if (newDatabaseFile.exists()) {
- FileUtil.deleteFileOrWarn(newDatabaseFile, "New Database File", logger);
- }
- } else {
- logger.info("Lockfile exists...exiting");
- throw new DatabaseMigrationLockedException();
- }
- }
- try {
- FileUtil.createNewFileOrLog(lockfile, logger);
- } catch (IOException e) {
- logger.error("IOException when creating lockfile", e);
- }
- if (!newDatabaseFile.exists()) {
- logger.info("Database migration to v4 required");
- long usableSpace = oldDatabaseFile.getUsableSpace();
- long fileSize = oldDatabaseFile.length();
- if (usableSpace < (fileSize * 2)) {
- FileUtil.deleteFileOrWarn(lockfile, "Lockfile", logger);
- throw new DatabaseMigrationFailedException("Not enough space left on device");
- }
- Thread migrateThread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // migrate
- SQLiteDatabase.loadLibs(context);
- SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
- @Override
- public void preKey(SQLiteDatabase sqLiteDatabase) {}
- @Override
- public void postKey(SQLiteDatabase sqLiteDatabase) {
- // old settings
- sqLiteDatabase.rawExecSQL(
- "PRAGMA cipher_page_size = 1024;" +
- "PRAGMA kdf_iter = 4000;" +
- "PRAGMA cipher_hmac_algorithm = HMAC_SHA1;" +
- "PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;");
- }
- };
- final int databaseVersion;
- try (SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(oldDatabaseFile.getAbsolutePath(), databaseKey, null, hook)) {
- if (database.isOpen()) {
- databaseVersion = database.getVersion();
- logger.info("Original database version: {}", databaseVersion);
- database.rawExecSQL(
- "PRAGMA key = '" + databaseKey + "';" +
- "PRAGMA cipher_page_size = 1024;" +
- "PRAGMA kdf_iter = 4000;" +
- "PRAGMA cipher_hmac_algorithm = HMAC_SHA1;" +
- "PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;" +
- "ATTACH DATABASE '" + newDatabaseFile.getAbsolutePath() + "' AS threema4 KEY '" + databaseKey + "';" +
- "PRAGMA threema4.kdf_iter = 1;" +
- "PRAGMA threema4.cipher_memory_security = OFF;" +
- "SELECT sqlcipher_export('threema4');" +
- "PRAGMA threema4.user_version = " + databaseVersion + ";" +
- "DETACH DATABASE threema4;");
- database.close();
- logger.info("Database successfully migrated");
- if (checkNewDatabase(newDatabaseFile, databaseKey, databaseVersion)) {
- migrateSuccess[0] = true;
- }
- }
- }
- } catch (Exception e) {
- logger.info("Database migration FAILED");
- logger.error("Exception while migrating", e);
- FileUtil.deleteFileOrWarn(newDatabaseFile, "New Database File", logger);
- }
- }
- });
- migrateThread.start();
- try {
- migrateThread.join();
- } catch (InterruptedException e) {
- logger.error("InterruptedException while waiting for migrateThread", e);
- migrateSuccess[0] = false;
- }
- if (migrateSuccess[0]) {
- Toast.makeText(context, "Database successfully migrated", Toast.LENGTH_LONG).show();
- logger.info("Migration finished");
- } else {
- logger.info("Migration failed");
- FileUtil.deleteFileOrWarn(newDatabaseFile, "New Database File", logger);
- FileUtil.deleteFileOrWarn(lockfile, "New Database File", logger);
- throw new DatabaseMigrationFailedException();
- }
- } else {
- try {
- SQLiteDatabase.loadLibs(context);
- if (checkNewDatabase(newDatabaseFile, databaseKey, DATABASE_VERSION)) {
- logger.info("Delete old format database");
- FileUtil.deleteFileOrWarn(oldDatabaseFile, "Old Database File", logger);
- } else {
- throw new Exception();
- }
- } catch (Exception e) {
- logger.info("Database checking FAILED");
- FileUtil.deleteFileOrWarn(newDatabaseFile, "New Database File", logger);
- FileUtil.deleteFileOrWarn(lockfile, "Lockfile", logger);
- throw new DatabaseMigrationFailedException();
- }
- }
- FileUtil.deleteFileOrWarn(lockfile, "Lockfile", logger);
- } else {
- logger.info("No old database file found. No migration necessary");
- logger.info("New database file exists = {}", newDatabaseFile.exists());
- }
- }
- private static boolean checkNewDatabase(File newDatabaseFile, String databaseKey, int databaseVersion) {
- // test new database
- try (SQLiteDatabase newDatabase = SQLiteDatabase.openDatabase(newDatabaseFile.getAbsolutePath(), databaseKey, null, 0, new SQLiteDatabaseHook() {
- @Override
- public void preKey(SQLiteDatabase sqLiteDatabase) {
- sqLiteDatabase.rawExecSQL("PRAGMA cipher_default_kdf_iter = 1;");
- }
- @Override
- public void postKey(SQLiteDatabase sqLiteDatabase) {
- sqLiteDatabase.rawExecSQL(
- "PRAGMA kdf_iter = 1;" +
- "PRAGMA cipher_memory_security = OFF;");
- }
- })) {
- if (newDatabase.isOpen()) {
- if (newDatabase.getVersion() == databaseVersion) {
- newDatabase.rawExecSQL("SELECT NULL;");
- logger.info("New database successfully checked. Version set to {}", databaseVersion);
- return true;
- } else {
- logger.info("Database version mismatch. old = {} new = {}", databaseVersion, newDatabase.getVersion());
- }
- } else {
- logger.info("Could not open new database");
- }
- }
- return false;
- }
- }
|