That fuck shit the fascists are using
at master 545 lines 21 kB view raw
1package org.tm.archive.database 2 3import android.app.Application 4import android.content.Context 5import androidx.annotation.VisibleForTesting 6import com.tm.androidcopysdk.api.IArchiveMessageDao 7import com.tm.androidcopysdk.api.IDatabase 8import net.zetetic.database.sqlcipher.SQLiteOpenHelper 9import org.archiver.data.TeleAttachmentTable 10import org.archiver.data.TeleMessageTable 11import org.signal.core.util.SqlUtil 12import org.signal.core.util.logging.Log 13import org.signal.core.util.withinTransaction 14import org.tm.archive.crypto.AttachmentSecret 15import org.tm.archive.crypto.DatabaseSecret 16import org.tm.archive.crypto.MasterSecret 17import org.tm.archive.database.helpers.ClassicOpenHelper 18import org.tm.archive.database.helpers.PreKeyMigrationHelper 19import org.tm.archive.database.helpers.SQLCipherMigrationHelper 20import org.tm.archive.database.helpers.SessionStoreMigrationHelper 21import org.tm.archive.database.helpers.SignalDatabaseMigrations 22import org.tm.archive.database.model.AvatarPickerDatabase 23import org.tm.archive.jobs.PreKeysSyncJob 24import org.tm.archive.migrations.LegacyMigrationJob 25import org.tm.archive.migrations.LegacyMigrationJob.DatabaseUpgradeListener 26import org.tm.archive.service.KeyCachingService 27import org.tm.archive.util.TextSecurePreferences 28import java.io.File 29 30open class SignalDatabase(private val context: Application, databaseSecret: DatabaseSecret, attachmentSecret: AttachmentSecret) : 31 SQLiteOpenHelper( 32 context, 33 DATABASE_NAME, 34 databaseSecret.asString(), 35 null, 36 SignalDatabaseMigrations.DATABASE_VERSION, 37 0, 38 SqlCipherErrorHandler(DATABASE_NAME), 39 SqlCipherDatabaseHook(), 40 true 41 ), 42 SignalDatabaseOpenHelper, IDatabase<Long> { // TM_SA implement IDatabase 43 44 val messageTable: MessageTable = TeleMessageTable(context, this) // TM_SA TeleMessageTable 45 val attachmentTable: AttachmentTable = TeleAttachmentTable(context, this, attachmentSecret) // TM_SA TeleAttachmentTable 46 val mediaTable: MediaTable = MediaTable(context, this) 47 val threadTable: ThreadTable = ThreadTable(context, this) 48 val identityTable: IdentityTable = IdentityTable(context, this) 49 val draftTable: DraftTable = DraftTable(context, this) 50 val groupTable: GroupTable = GroupTable(context, this) 51 val recipientTable: RecipientTable = RecipientTable(context, this) 52 val groupReceiptTable: GroupReceiptTable = GroupReceiptTable(context, this) 53 val preKeyDatabase: OneTimePreKeyTable = OneTimePreKeyTable(context, this) 54 val signedPreKeyTable: SignedPreKeyTable = SignedPreKeyTable(context, this) 55 val sessionTable: SessionTable = SessionTable(context, this) 56 val senderKeyTable: SenderKeyTable = SenderKeyTable(context, this) 57 val senderKeySharedTable: SenderKeySharedTable = SenderKeySharedTable(context, this) 58 val pendingRetryReceiptTable: PendingRetryReceiptTable = PendingRetryReceiptTable(context, this) 59 val searchTable: SearchTable = SearchTable(context, this) 60 val stickerTable: StickerTable = StickerTable(context, this, attachmentSecret) 61 val storageIdDatabase: UnknownStorageIdTable = UnknownStorageIdTable(context, this) 62 val remappedRecordTables: RemappedRecordTables = RemappedRecordTables(context, this) 63 val mentionTable: MentionTable = MentionTable(context, this) 64 val paymentTable: PaymentTable = PaymentTable(context, this) 65 val chatColorsTable: ChatColorsTable = ChatColorsTable(context, this) 66 val emojiSearchTable: EmojiSearchTable = EmojiSearchTable(context, this) 67 val messageSendLogTables: MessageSendLogTables = MessageSendLogTables(context, this) 68 val avatarPickerDatabase: AvatarPickerDatabase = AvatarPickerDatabase(context, this) 69 val reactionTable: ReactionTable = ReactionTable(context, this) 70 val notificationProfileDatabase: NotificationProfileDatabase = NotificationProfileDatabase(context, this) 71 val donationReceiptTable: DonationReceiptTable = DonationReceiptTable(context, this) 72 val distributionListTables: DistributionListTables = DistributionListTables(context, this) 73 val storySendTable: StorySendTable = StorySendTable(context, this) 74 val cdsTable: CdsTable = CdsTable(context, this) 75 val remoteMegaphoneTable: RemoteMegaphoneTable = RemoteMegaphoneTable(context, this) 76 val pendingPniSignatureMessageTable: PendingPniSignatureMessageTable = PendingPniSignatureMessageTable(context, this) 77 val callTable: CallTable = CallTable(context, this) 78 val kyberPreKeyTable: KyberPreKeyTable = KyberPreKeyTable(context, this) 79 val callLinkTable: CallLinkTable = CallLinkTable(context, this) 80 81 override fun onOpen(db: net.zetetic.database.sqlcipher.SQLiteDatabase) { 82 db.setForeignKeyConstraintsEnabled(true) 83 } 84 85 override fun onCreate(db: net.zetetic.database.sqlcipher.SQLiteDatabase) { 86 db.execSQL(MessageTable.CREATE_TABLE) 87 db.execSQL(AttachmentTable.CREATE_TABLE) 88 db.execSQL(ThreadTable.CREATE_TABLE) 89 db.execSQL(IdentityTable.CREATE_TABLE) 90 db.execSQL(DraftTable.CREATE_TABLE) 91 executeStatements(db, GroupTable.CREATE_TABLES) 92 db.execSQL(RecipientTable.CREATE_TABLE) 93 db.execSQL(GroupReceiptTable.CREATE_TABLE) 94 db.execSQL(OneTimePreKeyTable.CREATE_TABLE) 95 db.execSQL(SignedPreKeyTable.CREATE_TABLE) 96 db.execSQL(SessionTable.CREATE_TABLE) 97 db.execSQL(SenderKeyTable.CREATE_TABLE) 98 db.execSQL(SenderKeySharedTable.CREATE_TABLE) 99 db.execSQL(PendingRetryReceiptTable.CREATE_TABLE) 100 db.execSQL(StickerTable.CREATE_TABLE) 101 db.execSQL(UnknownStorageIdTable.CREATE_TABLE) 102 db.execSQL(MentionTable.CREATE_TABLE) 103 db.execSQL(PaymentTable.CREATE_TABLE) 104 db.execSQL(ChatColorsTable.CREATE_TABLE) 105 db.execSQL(EmojiSearchTable.CREATE_TABLE) 106 db.execSQL(AvatarPickerDatabase.CREATE_TABLE) 107 db.execSQL(ReactionTable.CREATE_TABLE) 108 db.execSQL(DonationReceiptTable.CREATE_TABLE) 109 db.execSQL(StorySendTable.CREATE_TABLE) 110 db.execSQL(CdsTable.CREATE_TABLE) 111 db.execSQL(RemoteMegaphoneTable.CREATE_TABLE) 112 db.execSQL(PendingPniSignatureMessageTable.CREATE_TABLE) 113 db.execSQL(CallLinkTable.CREATE_TABLE) 114 db.execSQL(CallTable.CREATE_TABLE) 115 db.execSQL(KyberPreKeyTable.CREATE_TABLE) 116 executeStatements(db, SearchTable.CREATE_TABLE) 117 executeStatements(db, RemappedRecordTables.CREATE_TABLE) 118 executeStatements(db, MessageSendLogTables.CREATE_TABLE) 119 executeStatements(db, NotificationProfileDatabase.CREATE_TABLE) 120 executeStatements(db, DistributionListTables.CREATE_TABLE) 121 122 executeStatements(db, RecipientTable.CREATE_INDEXS) 123 executeStatements(db, MessageTable.CREATE_INDEXS) 124 executeStatements(db, AttachmentTable.CREATE_INDEXS) 125 executeStatements(db, ThreadTable.CREATE_INDEXS) 126 executeStatements(db, DraftTable.CREATE_INDEXS) 127 executeStatements(db, GroupTable.CREATE_INDEXS) 128 executeStatements(db, GroupReceiptTable.CREATE_INDEXES) 129 executeStatements(db, StickerTable.CREATE_INDEXES) 130 executeStatements(db, UnknownStorageIdTable.CREATE_INDEXES) 131 executeStatements(db, MentionTable.CREATE_INDEXES) 132 executeStatements(db, PaymentTable.CREATE_INDEXES) 133 executeStatements(db, MessageSendLogTables.CREATE_INDEXES) 134 executeStatements(db, NotificationProfileDatabase.CREATE_INDEXES) 135 executeStatements(db, DonationReceiptTable.CREATE_INDEXS) 136 executeStatements(db, StorySendTable.CREATE_INDEXS) 137 executeStatements(db, DistributionListTables.CREATE_INDEXES) 138 executeStatements(db, PendingPniSignatureMessageTable.CREATE_INDEXES) 139 executeStatements(db, CallTable.CREATE_INDEXES) 140 executeStatements(db, ReactionTable.CREATE_INDEXES) 141 executeStatements(db, KyberPreKeyTable.CREATE_INDEXES) 142 143 executeStatements(db, SearchTable.CREATE_TRIGGERS) 144 executeStatements(db, MessageSendLogTables.CREATE_TRIGGERS) 145 146 DistributionListTables.insertInitialDistributionListAtCreationTime(db) 147 148 if (context.getDatabasePath(ClassicOpenHelper.NAME).exists()) { 149 val legacyHelper = ClassicOpenHelper(context) 150 val legacyDb = legacyHelper.writableDatabase 151 SQLCipherMigrationHelper.migratePlaintext(context, legacyDb, db) 152 val masterSecret = KeyCachingService.getMasterSecret(context) 153 if (masterSecret != null) SQLCipherMigrationHelper.migrateCiphertext(context, masterSecret, legacyDb, db, null) else TextSecurePreferences.setNeedsSqlCipherMigration(context, true) 154 if (!PreKeyMigrationHelper.migratePreKeys(context, db)) { 155 PreKeysSyncJob.enqueue() 156 } 157 SessionStoreMigrationHelper.migrateSessions(context, db) 158 PreKeyMigrationHelper.cleanUpPreKeys(context) 159 } 160 } 161 162 override fun onUpgrade(db: net.zetetic.database.sqlcipher.SQLiteDatabase, oldVersion: Int, newVersion: Int) { 163 // The caller of onUpgrade starts a transaction, which prevents us from turning off foreign keys. 164 // At this point it hasn't done anything, so we can just end it and then start it again ourselves. 165 db.endTransaction() 166 167 Log.i(TAG, "Upgrading database: $oldVersion, $newVersion") 168 val startTime = System.currentTimeMillis() 169 db.setForeignKeyConstraintsEnabled(false) 170 try { 171 // Transactions and version bumps are handled in the migrate method 172 SignalDatabaseMigrations.migrate(context, db, oldVersion, newVersion) 173 } finally { 174 db.setForeignKeyConstraintsEnabled(true) 175 176 // We have to re-begin the transaction for the calling code (see comment at start of method) 177 db.beginTransaction() 178 } 179 180 SignalDatabaseMigrations.migratePostTransaction(context, oldVersion) 181 Log.i(TAG, "Upgrade complete. Took " + (System.currentTimeMillis() - startTime) + " ms.") 182 } 183 184 override fun getReadableDatabase(): net.zetetic.database.sqlcipher.SQLiteDatabase { 185 throw UnsupportedOperationException("Call getSignalReadableDatabase() instead!") 186 } 187 188 override fun getWritableDatabase(): net.zetetic.database.sqlcipher.SQLiteDatabase { 189 throw UnsupportedOperationException("Call getSignalWritableDatabase() instead!") 190 } 191 192 open val rawReadableDatabase: net.zetetic.database.sqlcipher.SQLiteDatabase 193 get() = super.getReadableDatabase() 194 195 open val rawWritableDatabase: net.zetetic.database.sqlcipher.SQLiteDatabase 196 get() = super.getWritableDatabase() 197 198 open val signalReadableDatabase: SQLiteDatabase 199 get() = SQLiteDatabase(super.getReadableDatabase()) 200 201 open val signalWritableDatabase: SQLiteDatabase 202 get() = SQLiteDatabase(super.getWritableDatabase()) 203 204 override fun getSqlCipherDatabase(): net.zetetic.database.sqlcipher.SQLiteDatabase { 205 return super.getWritableDatabase() 206 } 207 208 open fun markCurrent(db: net.zetetic.database.sqlcipher.SQLiteDatabase) { 209 db.version = SignalDatabaseMigrations.DATABASE_VERSION 210 } 211 212 private fun executeStatements(db: net.zetetic.database.sqlcipher.SQLiteDatabase, statements: Array<String>) { 213 for (statement in statements) db.execSQL(statement) 214 } 215 216 companion object { 217 private val TAG = Log.tag(SignalDatabase::class.java) 218 private const val DATABASE_NAME = "signal.db" 219 220 @JvmStatic 221 @Volatile 222 var instance: SignalDatabase? = null 223 private set 224 225 @JvmStatic 226 fun init(application: Application, databaseSecret: DatabaseSecret, attachmentSecret: AttachmentSecret) { 227 if (instance == null) { 228 synchronized(SignalDatabase::class.java) { 229 if (instance == null) { 230 instance = SignalDatabase(application, databaseSecret, attachmentSecret) 231 } 232 } 233 } 234 } 235 236 @JvmStatic 237 @VisibleForTesting 238 fun setSignalDatabaseInstanceForTesting(signalDatabase: SignalDatabase) { 239 this.instance = signalDatabase 240 } 241 242 @JvmStatic 243 val rawDatabase: net.zetetic.database.sqlcipher.SQLiteDatabase 244 get() = instance!!.rawWritableDatabase 245 246 @JvmStatic 247 val backupDatabase: net.zetetic.database.sqlcipher.SQLiteDatabase 248 get() = instance!!.rawReadableDatabase 249 250 @JvmStatic 251 @get:JvmName("inTransaction") 252 val inTransaction: Boolean 253 get() = instance!!.rawWritableDatabase.inTransaction() 254 255 @JvmStatic 256 fun runPostSuccessfulTransaction(dedupeKey: String, task: Runnable) { 257 instance!!.signalWritableDatabase.runPostSuccessfulTransaction(dedupeKey, task) 258 } 259 260 @JvmStatic 261 fun runPostSuccessfulTransaction(task: Runnable) { 262 instance!!.signalWritableDatabase.runPostSuccessfulTransaction(task) 263 } 264 265 @JvmStatic 266 fun databaseFileExists(context: Context): Boolean { 267 return context.getDatabasePath(DATABASE_NAME).exists() 268 } 269 270 @JvmStatic 271 fun getDatabaseFile(context: Context): File { 272 return context.getDatabasePath(DATABASE_NAME) 273 } 274 275 /** 276 * After restoring a backup, we want to make sure that we run all of the onUpgrade logic necessary to bring the databases up to our current versions. 277 * There's also some cleanup we wan tto do to remove any possibly bad/stale data. 278 */ 279 @JvmStatic 280 fun runPostBackupRestoreTasks(database: net.zetetic.database.sqlcipher.SQLiteDatabase) { 281 synchronized(SignalDatabase::class.java) { 282 database.setForeignKeyConstraintsEnabled(false) 283 database.beginTransaction() 284 try { 285 instance!!.onUpgrade(database, database.getVersion(), -1) 286 instance!!.markCurrent(database) 287 instance!!.messageTable.deleteAbandonedMessages() 288 instance!!.messageTable.trimEntriesForExpiredMessages() 289 instance!!.reactionTable.deleteAbandonedReactions() 290 instance!!.searchTable.fullyResetTables() 291 instance!!.rawWritableDatabase.execSQL("DROP TABLE IF EXISTS key_value") 292 instance!!.rawWritableDatabase.execSQL("DROP TABLE IF EXISTS megaphone") 293 instance!!.rawWritableDatabase.execSQL("DROP TABLE IF EXISTS job_spec") 294 instance!!.rawWritableDatabase.execSQL("DROP TABLE IF EXISTS constraint_spec") 295 instance!!.rawWritableDatabase.execSQL("DROP TABLE IF EXISTS dependency_spec") 296 database.setTransactionSuccessful() 297 } finally { 298 database.endTransaction() 299 database.setForeignKeyConstraintsEnabled(true) 300 } 301 302 instance!!.rawWritableDatabase.close() 303 triggerDatabaseAccess() 304 } 305 } 306 307 @JvmStatic 308 fun hasTable(table: String): Boolean { 309 return SqlUtil.tableExists(instance!!.rawReadableDatabase, table) 310 } 311 312 @JvmStatic 313 fun triggerDatabaseAccess() { 314 instance!!.signalWritableDatabase 315 } 316 317 @Deprecated("Only used for a legacy migration.") 318 @JvmStatic 319 fun onApplicationLevelUpgrade( 320 context: Context, 321 masterSecret: MasterSecret, 322 fromVersion: Int, 323 listener: DatabaseUpgradeListener? 324 ) { 325 instance!!.signalWritableDatabase 326 var legacyOpenHelper: ClassicOpenHelper? = null 327 if (fromVersion < LegacyMigrationJob.ASYMMETRIC_MASTER_SECRET_FIX_VERSION) { 328 legacyOpenHelper = ClassicOpenHelper(context) 329 legacyOpenHelper.onApplicationLevelUpgrade(context, masterSecret, fromVersion, listener) 330 } 331 332 if (fromVersion < LegacyMigrationJob.SQLCIPHER && TextSecurePreferences.getNeedsSqlCipherMigration(context)) { 333 if (legacyOpenHelper == null) { 334 legacyOpenHelper = ClassicOpenHelper(context) 335 } 336 337 SQLCipherMigrationHelper.migrateCiphertext( 338 context, 339 masterSecret, 340 legacyOpenHelper.writableDatabase, 341 instance!!.rawWritableDatabase, 342 listener 343 ) 344 } 345 } 346 347 @JvmStatic 348 fun <T> runInTransaction(block: (SQLiteDatabase) -> T): T { 349 return instance!!.signalWritableDatabase.withinTransaction { 350 block(it) 351 } 352 } 353 354 @get:JvmStatic 355 @get:JvmName("attachments") 356 val attachments: AttachmentTable 357 get() = instance!!.attachmentTable 358 359 @get:JvmStatic 360 @get:JvmName("avatarPicker") 361 val avatarPicker: AvatarPickerDatabase 362 get() = instance!!.avatarPickerDatabase 363 364 @get:JvmStatic 365 @get:JvmName("cds") 366 val cds: CdsTable 367 get() = instance!!.cdsTable 368 369 @get:JvmStatic 370 @get:JvmName("chatColors") 371 val chatColors: ChatColorsTable 372 get() = instance!!.chatColorsTable 373 374 @get:JvmStatic 375 @get:JvmName("distributionLists") 376 val distributionLists: DistributionListTables 377 get() = instance!!.distributionListTables 378 379 @get:JvmStatic 380 @get:JvmName("donationReceipts") 381 val donationReceipts: DonationReceiptTable 382 get() = instance!!.donationReceiptTable 383 384 @get:JvmStatic 385 @get:JvmName("drafts") 386 val drafts: DraftTable 387 get() = instance!!.draftTable 388 389 @get:JvmStatic 390 @get:JvmName("emojiSearch") 391 val emojiSearch: EmojiSearchTable 392 get() = instance!!.emojiSearchTable 393 394 @get:JvmStatic 395 @get:JvmName("groupReceipts") 396 val groupReceipts: GroupReceiptTable 397 get() = instance!!.groupReceiptTable 398 399 @get:JvmStatic 400 @get:JvmName("groups") 401 val groups: GroupTable 402 get() = instance!!.groupTable 403 404 @get:JvmStatic 405 @get:JvmName("identities") 406 val identities: IdentityTable 407 get() = instance!!.identityTable 408 409 @get:JvmStatic 410 @get:JvmName("kyberPreKeys") 411 val kyberPreKeys: KyberPreKeyTable 412 get() = instance!!.kyberPreKeyTable 413 414 @get:JvmStatic 415 @get:JvmName("media") 416 val media: MediaTable 417 get() = instance!!.mediaTable 418 419 @get:JvmStatic 420 @get:JvmName("mentions") 421 val mentions: MentionTable 422 get() = instance!!.mentionTable 423 424 @get:JvmStatic 425 @get:JvmName("messages") 426 val messages: MessageTable 427 get() = instance!!.messageTable 428 429 @get:JvmStatic 430 @get:JvmName("messageLog") 431 val messageLog: MessageSendLogTables 432 get() = instance!!.messageSendLogTables 433 434 @get:JvmStatic 435 @get:JvmName("messageSearch") 436 val messageSearch: SearchTable 437 get() = instance!!.searchTable 438 439 @get:JvmStatic 440 @get:JvmName("notificationProfiles") 441 val notificationProfiles: NotificationProfileDatabase 442 get() = instance!!.notificationProfileDatabase 443 444 @get:JvmStatic 445 @get:JvmName("payments") 446 val payments: PaymentTable 447 get() = instance!!.paymentTable 448 449 @get:JvmStatic 450 @get:JvmName("pendingRetryReceipts") 451 val pendingRetryReceipts: PendingRetryReceiptTable 452 get() = instance!!.pendingRetryReceiptTable 453 454 @get:JvmStatic 455 @get:JvmName("oneTimePreKeys") 456 val oneTimePreKeys: OneTimePreKeyTable 457 get() = instance!!.preKeyDatabase 458 459 @get:JvmStatic 460 @get:JvmName("pendingPniSignatureMessages") 461 val pendingPniSignatureMessages: PendingPniSignatureMessageTable 462 get() = instance!!.pendingPniSignatureMessageTable 463 464 @get:JvmStatic 465 @get:JvmName("recipients") 466 val recipients: RecipientTable 467 get() = instance!!.recipientTable 468 469 @get:JvmStatic 470 @get:JvmName("signedPreKeys") 471 val signedPreKeys: SignedPreKeyTable 472 get() = instance!!.signedPreKeyTable 473 474 @get:JvmStatic 475 @get:JvmName("threads") 476 val threads: ThreadTable 477 get() = instance!!.threadTable 478 479 @get:JvmStatic 480 @get:JvmName("reactions") 481 val reactions: ReactionTable 482 get() = instance!!.reactionTable 483 484 @get:JvmStatic 485 @get:JvmName("remappedRecords") 486 val remappedRecords: RemappedRecordTables 487 get() = instance!!.remappedRecordTables 488 489 @get:JvmStatic 490 @get:JvmName("senderKeys") 491 val senderKeys: SenderKeyTable 492 get() = instance!!.senderKeyTable 493 494 @get:JvmStatic 495 @get:JvmName("senderKeyShared") 496 val senderKeyShared: SenderKeySharedTable 497 get() = instance!!.senderKeySharedTable 498 499 @get:JvmStatic 500 @get:JvmName("sessions") 501 val sessions: SessionTable 502 get() = instance!!.sessionTable 503 504 @get:JvmStatic 505 @get:JvmName("stickers") 506 val stickers: StickerTable 507 get() = instance!!.stickerTable 508 509 @get:JvmStatic 510 @get:JvmName("storySends") 511 val storySends: StorySendTable 512 get() = instance!!.storySendTable 513 514 @get:JvmStatic 515 @get:JvmName("unknownStorageIds") 516 val unknownStorageIds: UnknownStorageIdTable 517 get() = instance!!.storageIdDatabase 518 519 @get:JvmStatic 520 @get:JvmName("remoteMegaphones") 521 val remoteMegaphones: RemoteMegaphoneTable 522 get() = instance!!.remoteMegaphoneTable 523 524 @get:JvmStatic 525 @get:JvmName("calls") 526 val calls: CallTable 527 get() = instance!!.callTable 528 529 @get:JvmStatic 530 @get:JvmName("callLinks") 531 val callLinks: CallLinkTable 532 get() = instance!!.callLinkTable 533 } 534 // TM_SA implement IDatabase start 535 override fun beginTransaction() {} 536 537 override fun endTransaction() {} 538 539 override fun isInTransaction(): Boolean = false 540 541 override fun messageDao(): IArchiveMessageDao<Long> = messageTable as TeleMessageTable 542 543 override fun setTransactionSuccessful() {} 544 // TM_SA implement IDatabase end 545}