diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveValidator.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveValidator.kt index 5dd9f0b2f4..91c47bad21 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveValidator.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveValidator.kt @@ -23,13 +23,18 @@ object ArchiveValidator { /** * Validates the provided [backupFile] that is encrypted with the provided [backupKey]. */ - fun validate(backupFile: File, backupKey: MessageBackupKey): ValidationResult { + fun validate(backupFile: File, backupKey: MessageBackupKey, forTransfer: Boolean): ValidationResult { return try { val backupId = backupKey.deriveBackupId(SignalStore.account.requireAci()) val libSignalBackupKey = LibSignalBackupKey(backupKey.value) val backupKey = LibSignalMessageBackupKey(libSignalBackupKey, backupId.value) - MessageBackup.validate(backupKey, MessageBackup.Purpose.REMOTE_BACKUP, { backupFile.inputStream() }, backupFile.length()) + MessageBackup.validate( + backupKey, + if (forTransfer) MessageBackup.Purpose.DEVICE_TRANSFER else MessageBackup.Purpose.REMOTE_BACKUP, + { backupFile.inputStream() }, + backupFile.length() + ) ValidationResult.Success } catch (e: IOException) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt index 4e75e4c7e5..277c5d0621 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/BackupRepository.kt @@ -460,6 +460,7 @@ object BackupRepository { plaintext: Boolean = false, currentTime: Long = System.currentTimeMillis(), mediaBackupEnabled: Boolean = SignalStore.backup.backsUpMedia, + forTransfer: Boolean = false, progressEmitter: ExportProgressListener? = null, cancellationSignal: () -> Boolean = { false }, exportExtras: ((SignalDatabase) -> Unit)? = null @@ -481,6 +482,7 @@ object BackupRepository { writer = writer, progressEmitter = progressEmitter, mediaBackupEnabled = mediaBackupEnabled, + forTransfer = forTransfer, cancellationSignal = cancellationSignal, exportExtras = exportExtras ) @@ -500,6 +502,7 @@ object BackupRepository { isLocal: Boolean, writer: BackupExportWriter, mediaBackupEnabled: Boolean = SignalStore.backup.backsUpMedia, + forTransfer: Boolean = false, progressEmitter: ExportProgressListener? = null, cancellationSignal: () -> Boolean = { false }, exportExtras: ((SignalDatabase) -> Unit)? = null @@ -515,7 +518,7 @@ object BackupRepository { val signalStoreSnapshot: SignalStore = createSignalStoreSnapshot(keyValueDbName) eventTimer.emit("store-db-snapshot") - val exportState = ExportState(backupTime = currentTime, mediaBackupEnabled = mediaBackupEnabled) + val exportState = ExportState(backupTime = currentTime, mediaBackupEnabled = mediaBackupEnabled, forTransfer = forTransfer) val selfAci = signalStoreSnapshot.accountValues.aci!! val selfRecipientId = dbSnapshot.recipientTable.getByAci(selfAci).get().toLong().let { RecipientId.from(it) } @@ -1521,7 +1524,11 @@ data class ResumableMessagesBackupUploadSpec( data class ArchivedMediaObject(val mediaId: String, val cdn: Int) -class ExportState(val backupTime: Long, val mediaBackupEnabled: Boolean) { +class ExportState( + val backupTime: Long, + val mediaBackupEnabled: Boolean, + val forTransfer: Boolean +) { val recipientIds: MutableSet = hashSetOf() val threadIds: MutableSet = hashSetOf() val contactRecipientIds: MutableSet = hashSetOf() diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatItemArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatItemArchiveExporter.kt index 3e2b68fde0..7f22673a10 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatItemArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatItemArchiveExporter.kt @@ -562,9 +562,14 @@ private fun BackupMessageRecord.toBasicChatItemBuilder(selfRecipientId: Recipien } } - if (!MessageTypes.isExpirationTimerUpdate(record.type) && builder.expiresInMs != null && builder.expireStartDate != null && builder.expireStartDate!! + builder.expiresInMs!! < backupStartTime + 1.days.inWholeMilliseconds) { - Log.w(TAG, ExportSkips.messageExpiresTooSoon(record.dateSent)) - return null + if (!MessageTypes.isExpirationTimerUpdate(record.type) && builder.expiresInMs != null && builder.expireStartDate != null) { + val expiresAt = builder.expireStartDate!! + builder.expiresInMs!! + val threshold = if (exportState.forTransfer) backupStartTime else backupStartTime + 1.days.inWholeMilliseconds + + if (expiresAt < threshold) { + Log.w(TAG, ExportSkips.messageExpiresTooSoon(record.dateSent)) + return null + } } if (builder.expireStartDate != null && builder.expiresInMs == null) { @@ -1500,10 +1505,6 @@ private fun Cursor.toBackupMessageRecord(pastIds: Set, backupStartTime: Lo val expiresIn = this.requireLong(MessageTable.EXPIRES_IN) val expireStarted = this.requireLong(MessageTable.EXPIRE_STARTED) - if (expireStarted != 0L && expireStarted + expiresIn < backupStartTime + 1.days.inWholeMilliseconds) { - return null - } - return BackupMessageRecord( id = id, dateSent = this.requireLong(MessageTable.DATE_SENT).clampToValidBackupRange(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/backup/InternalBackupPlaygroundViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/backup/InternalBackupPlaygroundViewModel.kt index c387858ffe..d30f94a296 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/backup/InternalBackupPlaygroundViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/backup/InternalBackupPlaygroundViewModel.kt @@ -143,7 +143,7 @@ class InternalBackupPlaygroundViewModel : ViewModel() { append = { bytes -> tempFile.appendBytes(bytes) } ) _state.value = _state.value.copy(statusMessage = "Export complete! Validating...") - ArchiveValidator.validate(tempFile, SignalStore.backup.messageBackupKey) + ArchiveValidator.validate(tempFile, SignalStore.backup.messageBackupKey, forTransfer = false) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt index 0f40dd54e1..0f06cc23c7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/BackupMessagesJob.kt @@ -215,7 +215,7 @@ class BackupMessagesJob private constructor( stopwatch.split("export") - when (val result = ArchiveValidator.validate(tempBackupFile, backupKey)) { + when (val result = ArchiveValidator.validate(tempBackupFile, backupKey, forTransfer = false)) { ArchiveValidator.ValidationResult.Success -> { Log.d(TAG, "Successfully passed validation.") } diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt index ff8338d624..9b8b295779 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/linkdevice/LinkDeviceRepository.kt @@ -254,6 +254,7 @@ object LinkDeviceRepository { append = { tempBackupFile.appendBytes(it) }, messageBackupKey = ephemeralMessageBackupKey, mediaBackupEnabled = false, + forTransfer = true, cancellationSignal = cancellationSignal ) } catch (e: Exception) { @@ -268,7 +269,7 @@ object LinkDeviceRepository { return LinkUploadArchiveResult.BackupCreationCancelled } - when (val result = ArchiveValidator.validate(tempBackupFile, ephemeralMessageBackupKey)) { + when (val result = ArchiveValidator.validate(tempBackupFile, ephemeralMessageBackupKey, forTransfer = true)) { ArchiveValidator.ValidationResult.Success -> { Log.d(TAG, "[createAndUploadArchive] Successfully passed validation.") }