Update attachment handling

This commit is contained in:
trevor-signal 2024-12-11 14:56:41 -05:00 committed by GitHub
parent 6f7faf4be8
commit 6c348e2db7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 34 additions and 22 deletions

View file

@ -1,6 +1,6 @@
// Copyright 2024 Signal Messenger, LLC // Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import { debounce, noop, omit } from 'lodash'; import { noop, omit, throttle } from 'lodash';
import * as durations from '../util/durations'; import * as durations from '../util/durations';
import * as log from '../logging/log'; import * as log from '../logging/log';
@ -46,7 +46,10 @@ import {
import type { MIMEType } from '../types/MIME'; import type { MIMEType } from '../types/MIME';
import { AttachmentDownloadSource } from '../sql/Interface'; import { AttachmentDownloadSource } from '../sql/Interface';
import { drop } from '../util/drop'; import { drop } from '../util/drop';
import { getAttachmentCiphertextLength } from '../AttachmentCrypto'; import {
getAttachmentCiphertextLength,
type ReencryptedAttachmentV2,
} from '../AttachmentCrypto';
import { safeParsePartial } from '../util/schemas'; import { safeParsePartial } from '../util/schemas';
import { createBatcher } from '../util/batcher'; import { createBatcher } from '../util/batcher';
@ -522,11 +525,15 @@ export async function runDownloadAttachmentJobInner({
try { try {
let totalDownloaded = 0; let totalDownloaded = 0;
let downloadedAttachment: ReencryptedAttachmentV2 | undefined;
const onSizeUpdate = async (totalBytes: number) => { const onSizeUpdate = async (totalBytes: number) => {
if (abortSignal.aborted) { if (abortSignal.aborted) {
return; return;
} }
if (downloadedAttachment) {
return;
}
totalDownloaded = Math.min(totalBytes, attachment.size); totalDownloaded = Math.min(totalBytes, attachment.size);
await addAttachmentToMessage( await addAttachmentToMessage(
@ -537,18 +544,18 @@ export async function runDownloadAttachmentJobInner({
); );
}; };
const downloaded = await dependencies.downloadAttachment({ downloadedAttachment = await dependencies.downloadAttachment({
attachment, attachment,
options: { options: {
variant: AttachmentVariant.Default, variant: AttachmentVariant.Default,
onSizeUpdate: debounce(onSizeUpdate, 200), onSizeUpdate: throttle(onSizeUpdate, 200),
abortSignal, abortSignal,
}, },
}); });
const upgradedAttachment = await dependencies.processNewAttachment({ const upgradedAttachment = await dependencies.processNewAttachment({
...omit(attachment, ['error', 'pending', 'downloadPath']), ...omit(attachment, ['error', 'pending', 'downloadPath']),
...downloaded, ...downloadedAttachment,
}); });
await addAttachmentToMessage(messageId, upgradedAttachment, logId, { await addAttachmentToMessage(messageId, upgradedAttachment, logId, {

View file

@ -5,7 +5,7 @@ import * as Bytes from '../Bytes';
import type { AttachmentDownloadJobTypeType } from '../types/AttachmentDownload'; import type { AttachmentDownloadJobTypeType } from '../types/AttachmentDownload';
import type { AttachmentType } from '../types/Attachment'; import type { AttachmentType } from '../types/Attachment';
import { getAttachmentSignature, isDownloaded } from '../types/Attachment'; import { getAttachmentSignatureSafe, isDownloaded } from '../types/Attachment';
import { __DEPRECATED$getMessageById } from '../messages/getMessageById'; import { __DEPRECATED$getMessageById } from '../messages/getMessageById';
export async function addAttachmentToMessage( export async function addAttachmentToMessage(
@ -21,7 +21,10 @@ export async function addAttachmentToMessage(
return; return;
} }
const attachmentSignature = getAttachmentSignature(attachment); const attachmentSignature = getAttachmentSignatureSafe(attachment);
if (!attachmentSignature) {
log.error(`${logPrefix}: Attachment did not have valid signature (digest)`);
}
if (type === 'long-message') { if (type === 'long-message') {
let handledAnywhere = false; let handledAnywhere = false;
@ -45,7 +48,8 @@ export async function addAttachmentToMessage(
} }
// This attachment isn't destined for this edit // This attachment isn't destined for this edit
if ( if (
getAttachmentSignature(edit.bodyAttachment) !== attachmentSignature getAttachmentSignatureSafe(edit.bodyAttachment) !==
attachmentSignature
) { ) {
return edit; return edit;
} }
@ -79,7 +83,8 @@ export async function addAttachmentToMessage(
return; return;
} }
if ( if (
getAttachmentSignature(existingBodyAttachment) !== attachmentSignature getAttachmentSignatureSafe(existingBodyAttachment) !==
attachmentSignature
) { ) {
return; return;
} }
@ -116,7 +121,7 @@ export async function addAttachmentToMessage(
return existing; return existing;
} }
if (attachmentSignature !== getAttachmentSignature(existing)) { if (attachmentSignature !== getAttachmentSignatureSafe(existing)) {
return existing; return existing;
} }
@ -322,7 +327,7 @@ export async function addAttachmentToMessage(
message.set({ message.set({
sticker: { sticker: {
...sticker, ...sticker,
data: attachment, data: sticker.data ? maybeReplaceAttachment(sticker.data) : attachment,
}, },
}); });
return; return;

View file

@ -1105,6 +1105,16 @@ export function getAttachmentSignature(attachment: AttachmentType): string {
return attachment.digest; return attachment.digest;
} }
export function getAttachmentSignatureSafe(
attachment: AttachmentType
): string | undefined {
try {
return getAttachmentSignature(attachment);
} catch {
return undefined;
}
}
type RequiredPropertiesForDecryption = 'key' | 'digest'; type RequiredPropertiesForDecryption = 'key' | 'digest';
type RequiredPropertiesForReencryption = 'path' | 'key' | 'digest' | 'iv'; type RequiredPropertiesForReencryption = 'path' | 'key' | 'digest' | 'iv';

View file

@ -21,7 +21,7 @@ import type {
} from '../model-types.d'; } from '../model-types.d';
import * as Errors from '../types/errors'; import * as Errors from '../types/errors';
import { import {
getAttachmentSignature, getAttachmentSignatureSafe,
isDownloading, isDownloading,
isDownloaded, isDownloaded,
} from '../types/Attachment'; } from '../types/Attachment';
@ -44,16 +44,6 @@ export type MessageAttachmentsDownloadedType = {
sticker?: StickerType; sticker?: StickerType;
}; };
function getAttachmentSignatureSafe(
attachment: AttachmentType
): string | undefined {
try {
return getAttachmentSignature(attachment);
} catch {
return undefined;
}
}
function getLogger(source: AttachmentDownloadSource) { function getLogger(source: AttachmentDownloadSource) {
const verbose = source !== AttachmentDownloadSource.BACKUP_IMPORT; const verbose = source !== AttachmentDownloadSource.BACKUP_IMPORT;
const log = verbose ? logger : { ...logger, info: () => null }; const log = verbose ? logger : { ...logger, info: () => null };