diff --git a/ts/test-both/processDataMessage_test.ts b/ts/test-both/processDataMessage_test.ts index 88576ce18a..bc39de0907 100644 --- a/ts/test-both/processDataMessage_test.ts +++ b/ts/test-both/processDataMessage_test.ts @@ -23,22 +23,42 @@ const CLIENT_UUID = generateUuid(); const UNPROCESSED_ATTACHMENT: Proto.IAttachmentPointer = { cdnId: Long.fromNumber(123), + cdnKey: 'cdnKey', + cdnNumber: 2, + blurHash: 'blurHash', + caption: 'caption', clientUuid: uuidToBytes(CLIENT_UUID), key: new Uint8Array([1, 2, 3]), digest: new Uint8Array([4, 5, 6]), contentType: IMAGE_GIF, - incrementalMac: new Uint8Array(), + incrementalMac: new Uint8Array([12, 12, 12]), + chunkSize: 24, + uploadTimestamp: Long.fromNumber(456), size: 34, + height: 64, + width: 128, + flags: 1, + fileName: 'fileName', }; const PROCESSED_ATTACHMENT: ProcessedAttachment = { cdnId: '123', + cdnKey: 'cdnKey', + cdnNumber: 2, + blurHash: 'blurHash', + caption: 'caption', clientUuid: CLIENT_UUID, key: 'AQID', digest: 'BAUG', contentType: IMAGE_GIF, - incrementalMac: undefined, + incrementalMac: 'DAwM', + chunkSize: 24, size: 34, + uploadTimestamp: 456, + height: 64, + width: 128, + flags: 1, + fileName: 'fileName', }; describe('processDataMessage', () => { diff --git a/ts/textsecure/Types.d.ts b/ts/textsecure/Types.d.ts index a41c753849..1a6e1efcde 100644 --- a/ts/textsecure/Types.d.ts +++ b/ts/textsecure/Types.d.ts @@ -118,6 +118,7 @@ export type ProcessedAttachment = { cdnNumber?: number; textAttachment?: Omit; backupLocator?: AttachmentType['backupLocator']; + uploadTimestamp?: number; downloadPath?: string; incrementalMac?: string; chunkSize?: number; diff --git a/ts/textsecure/processDataMessage.ts b/ts/textsecure/processDataMessage.ts index e7e2815eba..dcb16ddaab 100644 --- a/ts/textsecure/processDataMessage.ts +++ b/ts/textsecure/processDataMessage.ts @@ -49,22 +49,48 @@ export function processAttachment( export function processAttachment( attachment?: Proto.IAttachmentPointer | null ): ProcessedAttachment | undefined { - if (!attachment) { + const attachmentWithoutNulls = shallowDropNull(attachment); + if (!attachmentWithoutNulls) { return undefined; } - const { cdnId } = attachment; + const { + cdnId, + cdnKey, + cdnNumber, + clientUuid, + key, + size, + contentType, + digest, + incrementalMac, + chunkSize, + fileName, + flags, + width, + height, + caption, + blurHash, + uploadTimestamp, + } = attachmentWithoutNulls; + const hasCdnId = Long.isLong(cdnId) ? !cdnId.isZero() : Boolean(cdnId); - const { clientUuid, contentType, digest, incrementalMac, key, size } = - attachment; if (!isNumber(size)) { throw new Error('Missing size on incoming attachment!'); } return { - ...shallowDropNull(attachment), - + cdnKey, + cdnNumber, + chunkSize, + fileName, + flags, + width, + height, + caption, + blurHash, + uploadTimestamp: uploadTimestamp?.toNumber(), cdnId: hasCdnId ? String(cdnId) : undefined, clientUuid: Bytes.isNotEmpty(clientUuid) ? bytesToUuid(clientUuid) diff --git a/ts/util/attachments.ts b/ts/util/attachments.ts index 3cf59e7c6b..0360db904c 100644 --- a/ts/util/attachments.ts +++ b/ts/util/attachments.ts @@ -88,6 +88,7 @@ export type CdnFieldsType = Pick< | 'iv' | 'key' | 'plaintextHash' + | 'uploadTimestamp' >; export function copyCdnFields( @@ -109,5 +110,6 @@ export function copyCdnFields( iv: Bytes.toBase64(uploaded.iv), key: Bytes.toBase64(uploaded.key), plaintextHash: uploaded.plaintextHash, + uploadTimestamp: uploaded.uploadTimestamp?.toNumber(), }; } diff --git a/ts/util/uploadAttachment.ts b/ts/util/uploadAttachment.ts index 0615b1cd54..8bf22f54f3 100644 --- a/ts/util/uploadAttachment.ts +++ b/ts/util/uploadAttachment.ts @@ -1,5 +1,6 @@ // Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only +import Long from 'long'; import { createReadStream } from 'fs'; import type { AttachmentWithHydratedData, @@ -33,6 +34,7 @@ export async function uploadAttachment( const keys = getRandomBytes(64); const needIncrementalMac = supportsIncrementalMac(attachment.contentType); + const uploadTimestamp = Date.now(); const { cdnKey, cdnNumber, encrypted } = await encryptAndUploadAttachment({ keys, needIncrementalMac, @@ -54,6 +56,7 @@ export async function uploadAttachment( plaintextHash: encrypted.plaintextHash, incrementalMac: encrypted.incrementalMac, chunkSize: encrypted.chunkSize, + uploadTimestamp: Long.fromNumber(uploadTimestamp), contentType: MIMETypeToString(attachment.contentType), fileName,