diff --git a/SignalServiceKit/MessageBackup/Archivers/ChatItem/MessageBackupTSIncomingMessageArchiver.swift b/SignalServiceKit/MessageBackup/Archivers/ChatItem/MessageBackupTSIncomingMessageArchiver.swift index 8fddd1e291..2adc6f67a4 100644 --- a/SignalServiceKit/MessageBackup/Archivers/ChatItem/MessageBackupTSIncomingMessageArchiver.swift +++ b/SignalServiceKit/MessageBackup/Archivers/ChatItem/MessageBackupTSIncomingMessageArchiver.swift @@ -126,10 +126,32 @@ extension MessageBackupTSIncomingMessageArchiver: MessageBackupTSMessageEditHist return errorResult } - let incomingMessageDetails: BackupProto_ChatItem.IncomingMessageDetails = buildIncomingMessageDetails( - incomingMessage, - editRecord: editRecord - ) + let directionalDetails: BackupProto_ChatItem.OneOf_DirectionalDetails + if author == context.recipientContext.localRecipientId { + // Incoming messages from self are not allowed in backups + // but have been observed in real-world databases. + // If we encounter these, fudge them a bit and pretend + // they were outgoing messages. + var outgoingDetails = BackupProto_ChatItem.OutgoingMessageDetails() + var sendStatus = BackupProto_SendStatus() + sendStatus.recipientID = context.recipientContext.localRecipientId.value + sendStatus.timestamp = incomingMessage.receivedAtTimestamp + var viewedStatus = BackupProto_SendStatus.Viewed() + viewedStatus.sealedSender = incomingMessage.wasReceivedByUD + sendStatus.deliveryStatus = .viewed(viewedStatus) + outgoingDetails.sendStatus = [sendStatus] + directionalDetails = .outgoing(outgoingDetails) + partialErrors.append(.archiveFrameError( + .incomingMessageFromSelf, + incomingMessage.uniqueInteractionId + )) + } else { + let incomingMessageDetails: BackupProto_ChatItem.IncomingMessageDetails = buildIncomingMessageDetails( + incomingMessage, + editRecord: editRecord + ) + directionalDetails = .incoming(incomingMessageDetails) + } let expireStartDate: UInt64? if incomingMessage.expireStartedAt > 0 { @@ -140,7 +162,7 @@ extension MessageBackupTSIncomingMessageArchiver: MessageBackupTSMessageEditHist let details = Details( author: author, - directionalDetails: .incoming(incomingMessageDetails), + directionalDetails: directionalDetails, dateCreated: incomingMessage.timestamp, expireStartDate: expireStartDate, expiresInMs: UInt64(incomingMessage.expiresInSeconds) * 1000, diff --git a/SignalServiceKit/MessageBackup/Archivers/MessageBackupErrors.swift b/SignalServiceKit/MessageBackup/Archivers/MessageBackupErrors.swift index 3b9de62f07..c2804d5a50 100644 --- a/SignalServiceKit/MessageBackup/Archivers/MessageBackupErrors.swift +++ b/SignalServiceKit/MessageBackup/Archivers/MessageBackupErrors.swift @@ -60,6 +60,8 @@ extension MessageBackup { /// An incoming message has an invalid or missing author address information, /// causing the message to be skipped. case invalidIncomingMessageAuthor + /// An incoming message came from the self recipient. + case incomingMessageFromSelf /// An outgoing message has an invalid or missing recipient address information, /// causing the message to be skipped. case invalidOutgoingMessageRecipient @@ -257,6 +259,7 @@ extension MessageBackup { .distributionListMissingDeletionTimestamp, .invalidDistributionListMemberAddress, .invalidIncomingMessageAuthor, + .incomingMessageFromSelf, .invalidOutgoingMessageRecipient, .invalidQuoteAuthor, .linkPreviewMissingUrl, @@ -374,6 +377,10 @@ extension MessageBackup { // We've seen real world databases with invalid link previews; we // just drop these on export and just issue a warning. return .warning + case .incomingMessageFromSelf: + // We've seen real world databases with messages from self; we + // fudge these into outgoing messages on export and issue a warning. + return .warning } } }