diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/AdHocCallArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/AdHocCallArchiveExporter.kt index a946a3423d..a11ceb3273 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/AdHocCallArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/AdHocCallArchiveExporter.kt @@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.backup.v2.database import android.database.Cursor import org.signal.core.util.requireLong import org.thoughtcrime.securesms.backup.v2.proto.AdHocCall +import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange import org.thoughtcrime.securesms.database.CallTable import java.io.Closeable @@ -31,7 +32,7 @@ class AdHocCallArchiveExporter(private val cursor: Cursor) : Iterator callId = callId, recipientId = cursor.requireLong(CallTable.PEER), state = AdHocCall.State.GENERIC, - callTimestamp = cursor.requireLong(CallTable.TIMESTAMP) + callTimestamp = cursor.requireLong(CallTable.TIMESTAMP).clampToValidBackupRange() ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatArchiveExporter.kt index 46fa3b8ed8..83814917d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ChatArchiveExporter.kt @@ -13,6 +13,7 @@ import org.signal.core.util.requireInt import org.signal.core.util.requireLong import org.thoughtcrime.securesms.backup.v2.proto.Chat import org.thoughtcrime.securesms.backup.v2.util.ChatStyleConverter +import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange import org.thoughtcrime.securesms.conversation.colors.ChatColors import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.SignalDatabase @@ -57,7 +58,7 @@ class ChatArchiveExporter(private val cursor: Cursor, private val db: SignalData pinnedOrder = cursor.requireInt(ThreadTable.PINNED), expirationTimerMs = cursor.requireLong(RecipientTable.MESSAGE_EXPIRATION_TIME).seconds.inWholeMilliseconds.takeIf { it > 0 }, expireTimerVersion = cursor.requireInt(RecipientTable.MESSAGE_EXPIRATION_TIME_VERSION), - muteUntilMs = cursor.requireLong(RecipientTable.MUTE_UNTIL).takeIf { it > 0 }, + muteUntilMs = cursor.requireLong(RecipientTable.MUTE_UNTIL).takeIf { it > 0 }?.clampToValidBackupRange(), markedUnread = ThreadTable.ReadStatus.deserialize(cursor.requireInt(ThreadTable.READ)) == ThreadTable.ReadStatus.FORCED_UNREAD, dontNotifyForMentionsIfMuted = RecipientTable.MentionSetting.DO_NOT_NOTIFY.id == cursor.requireInt(RecipientTable.MENTION_SETTING), style = ChatStyleConverter.constructRemoteChatStyle( 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 305a1ee060..2081359d9d 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 @@ -53,6 +53,7 @@ import org.thoughtcrime.securesms.backup.v2.proto.StickerMessage import org.thoughtcrime.securesms.backup.v2.proto.Text import org.thoughtcrime.securesms.backup.v2.proto.ThreadMergeChatUpdate import org.thoughtcrime.securesms.backup.v2.proto.ViewOnceMessage +import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange import org.thoughtcrime.securesms.backup.v2.util.toRemoteFilePointer import org.thoughtcrime.securesms.contactshare.Contact import org.thoughtcrime.securesms.database.AttachmentTable @@ -431,7 +432,7 @@ private fun BackupMessageRecord.toBasicChatItemBuilder(selfRecipientId: Recipien val builder = ChatItem.Builder().apply { chatId = record.threadId authorId = fromRecipientId - dateSent = record.dateSent + dateSent = record.dateSent.clampToValidBackupRange() expireStartDate = record.expireStarted.takeIf { it > 0 } expiresInMs = record.expiresIn.takeIf { it > 0 } revisions = emptyList() @@ -603,8 +604,8 @@ private fun CallTable.Call.toRemoteCallUpdate(db: SignalDatabase, messageRecord: }, ringerRecipientId = this.ringerRecipient?.toLong(), startedCallRecipientId = ACI.parseOrNull(groupCallUpdateDetails.startedCallUuid)?.let { db.recipientTable.getByAci(it).getOrNull()?.toLong() }, - startedCallTimestamp = this.timestamp, - endedCallTimestamp = groupCallUpdateDetails.endedCallTimestamp, + startedCallTimestamp = this.timestamp.clampToValidBackupRange(), + endedCallTimestamp = groupCallUpdateDetails.endedCallTimestamp.clampToValidBackupRange(), read = messageRecord.read ) ) @@ -634,7 +635,7 @@ private fun CallTable.Call.toRemoteCallUpdate(db: SignalDatabase, messageRecord: return null } }, - startedCallTimestamp = this.timestamp, + startedCallTimestamp = this.timestamp.clampToValidBackupRange(), read = messageRecord.read ) ) @@ -720,7 +721,7 @@ private fun BackupMessageRecord.toRemoteLinkPreviews(attachments: List Text( @@ -981,9 +982,9 @@ private fun PaymentTable.PaymentTransaction.toRemoteTransactionDetails(): Paymen return PaymentNotification.TransactionDetails( transaction = PaymentNotification.TransactionDetails.Transaction( status = this.state.toRemote(), - timestamp = this.timestamp, + timestamp = this.timestamp.clampToValidBackupRange(), blockIndex = this.blockIndex, - blockTimestamp = this.blockTimestamp, + blockTimestamp = this.blockTimestamp.clampToValidBackupRange(), mobileCoinIdentification = this.paymentMetaData.mobileCoinTxoIdentification?.let { PaymentNotification.TransactionDetails.MobileCoinTxoIdentification( publicKey = it.publicKey.takeIf { this.direction.isReceived } ?: emptyList(), @@ -1065,7 +1066,7 @@ private fun List?.toRemote(): List { Reaction( emoji = it.emoji, authorId = it.author.toLong(), - sentTimestamp = it.dateSent, + sentTimestamp = it.dateSent.clampToValidBackupRange(), sortOrder = it.dateReceived ) } ?: emptyList() @@ -1298,9 +1299,9 @@ private fun Cursor.toBackupMessageRecord(pastIds: Set, backupStartTime: Lo return BackupMessageRecord( id = id, - dateSent = this.requireLong(MessageTable.DATE_SENT), - dateReceived = this.requireLong(MessageTable.DATE_RECEIVED), - dateServer = this.requireLong(MessageTable.DATE_SERVER), + dateSent = this.requireLong(MessageTable.DATE_SENT).clampToValidBackupRange(), + dateReceived = this.requireLong(MessageTable.DATE_RECEIVED).clampToValidBackupRange(), + dateServer = this.requireLong(MessageTable.DATE_SERVER).clampToValidBackupRange(), type = this.requireLong(MessageTable.TYPE), threadId = this.requireLong(MessageTable.THREAD_ID), body = this.requireString(MessageTable.BODY), @@ -1313,7 +1314,7 @@ private fun Cursor.toBackupMessageRecord(pastIds: Set, backupStartTime: Lo sealedSender = this.requireBoolean(MessageTable.UNIDENTIFIED), linkPreview = this.requireString(MessageTable.LINK_PREVIEWS), sharedContacts = this.requireString(MessageTable.SHARED_CONTACTS), - quoteTargetSentTimestamp = this.requireLong(MessageTable.QUOTE_ID), + quoteTargetSentTimestamp = this.requireLong(MessageTable.QUOTE_ID).clampToValidBackupRange(), quoteAuthor = this.requireLong(MessageTable.QUOTE_AUTHOR), quoteBody = this.requireString(MessageTable.QUOTE_BODY), quoteMissing = this.requireBoolean(MessageTable.QUOTE_MISSING), diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt index ee93df4213..a67acee845 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/ContactArchiveExporter.kt @@ -17,6 +17,7 @@ import org.signal.core.util.requireString import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient import org.thoughtcrime.securesms.backup.v2.proto.Contact import org.thoughtcrime.securesms.backup.v2.proto.Self +import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange import org.thoughtcrime.securesms.database.IdentityTable import org.thoughtcrime.securesms.database.RecipientTable import org.thoughtcrime.securesms.database.RecipientTableCursorUtil @@ -80,7 +81,7 @@ class ContactArchiveExporter(private val cursor: Cursor, private val selfId: Lon if (registeredState == RecipientTable.RegisteredState.REGISTERED) { contactBuilder.registered = Contact.Registered() } else { - contactBuilder.notRegistered = Contact.NotRegistered(unregisteredTimestamp = cursor.requireLong(RecipientTable.UNREGISTERED_TIMESTAMP)) + contactBuilder.notRegistered = Contact.NotRegistered(unregisteredTimestamp = cursor.requireLong(RecipientTable.UNREGISTERED_TIMESTAMP).clampToValidBackupRange()) } return ArchiveRecipient( diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/DistributionListArchiveExporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/DistributionListArchiveExporter.kt index 4e29525946..bfefa354d7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/DistributionListArchiveExporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/exporters/DistributionListArchiveExporter.kt @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.backup.v2.ArchiveRecipient import org.thoughtcrime.securesms.backup.v2.database.getMembersForBackup import org.thoughtcrime.securesms.backup.v2.proto.DistributionList import org.thoughtcrime.securesms.backup.v2.proto.DistributionListItem +import org.thoughtcrime.securesms.backup.v2.util.clampToValidBackupRange import org.thoughtcrime.securesms.database.DistributionListTables import org.thoughtcrime.securesms.database.model.DistributionListId import org.thoughtcrime.securesms.database.model.DistributionListPrivacyMode @@ -49,7 +50,7 @@ class DistributionListArchiveExporter( allowsReplies = cursor.requireBoolean(DistributionListTables.ListTable.ALLOWS_REPLIES), rawMembers = distributionListTables.getRawMembers(id, privacyMode), members = distributionListTables.getMembersForBackup(id), - deletedAtTimestamp = cursor.requireLong(DistributionListTables.ListTable.DELETION_TIMESTAMP), + deletedAtTimestamp = cursor.requireLong(DistributionListTables.ListTable.DELETION_TIMESTAMP).clampToValidBackupRange(), isUnknown = cursor.requireBoolean(DistributionListTables.ListTable.IS_UNKNOWN), privacyMode = privacyMode ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/util/ArchiveConverterExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/util/ArchiveConverterExtensions.kt index 62350038bf..276a3eff2b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/util/ArchiveConverterExtensions.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/util/ArchiveConverterExtensions.kt @@ -62,7 +62,7 @@ fun FilePointer?.toLocalAttachment( isGif = gif, caption = Optional.ofNullable(this.caption), blurHash = Optional.ofNullable(this.blurHash), - uploadTimestamp = this.attachmentLocator.uploadTimestamp ?: 0, + uploadTimestamp = this.attachmentLocator.uploadTimestamp?.clampToValidBackupRange() ?: 0, uuid = UuidUtil.fromByteStringOrNull(uuid) ) return PointerAttachment.forPointer( @@ -165,10 +165,14 @@ fun DatabaseAttachment.toRemoteFilePointer(mediaArchiveEnabled: Boolean, content builder.attachmentLocator = FilePointer.AttachmentLocator( cdnKey = this.remoteLocation, cdnNumber = this.cdn.cdnNumber, - uploadTimestamp = this.uploadTimestamp.takeIf { it > 0 }, + uploadTimestamp = this.uploadTimestamp.takeIf { it > 0 }?.clampToValidBackupRange(), key = Base64.decode(remoteKey).toByteString(), size = this.size.toInt(), digest = this.remoteDigest.toByteString() ) return builder.build() } + +fun Long.clampToValidBackupRange(): Long { + return this.coerceIn(0, 8640000000000000) +}