diff --git a/ts/models/conversations.ts b/ts/models/conversations.ts index 3bea5962f3..5964370686 100644 --- a/ts/models/conversations.ts +++ b/ts/models/conversations.ts @@ -5469,7 +5469,7 @@ export class ConversationModel { async #getTemporaryAvatarPath(): Promise { const { - copyIntoTempDirectory, + copyAttachmentIntoTempDirectory, deleteAttachmentData, getAbsoluteAttachmentPath, getAbsoluteTempPath, @@ -5505,7 +5505,7 @@ export class ConversationModel { }); try { - const { path: tempPath } = await copyIntoTempDirectory( + const { path: tempPath } = await copyAttachmentIntoTempDirectory( getAbsoluteAttachmentPath(plaintextPath) ); return getAbsoluteTempPath(tempPath); diff --git a/ts/signal.ts b/ts/signal.ts index dda19da8bd..7eae264309 100644 --- a/ts/signal.ts +++ b/ts/signal.ts @@ -64,10 +64,10 @@ type EncryptedWriter = (data: Uint8Array) => Promise; type MigrationsModuleType = { attachmentsPath: string; - copyIntoAttachmentsDirectory: ( + copyStickerIntoAttachmentsDirectory: ( path: string ) => Promise<{ path: string; size: number }>; - copyIntoTempDirectory: ( + copyAttachmentIntoTempDirectory: ( path: string ) => Promise<{ path: string; size: number }>; deleteAttachmentData: (path: string) => Promise; @@ -241,8 +241,6 @@ export function initializeMigrations({ const getAbsoluteAttachmentPath = createAbsolutePathGetter(attachmentsPath); const deleteOnDisk = Attachments.createDeleter(attachmentsPath); const writeNewAttachmentData = createEncryptedWriterForNew(attachmentsPath); - const copyIntoAttachmentsDirectory = - Attachments.copyIntoAttachmentsDirectory(attachmentsPath); const doesAttachmentExist = createDoesExist(attachmentsPath); const stickersPath = getStickersPath(userDataPath); @@ -250,6 +248,11 @@ export function initializeMigrations({ const writeNewStickerData = createEncryptedWriterForNew(stickersPath); const deleteSticker = Attachments.createDeleter(stickersPath); const readStickerData = createEncryptedReader(stickersPath); + const copyStickerIntoAttachmentsDirectory = + Attachments.copyIntoAttachmentsDirectory({ + sourceDir: stickersPath, + targetDir: attachmentsPath, + }); const badgesPath = getBadgesPath(userDataPath); const getAbsoluteBadgeImageFilePath = createAbsolutePathGetter(badgesPath); @@ -261,8 +264,11 @@ export function initializeMigrations({ const writeNewPlaintextTempData = createWriterForNew(tempPath); const deleteTempFile = Attachments.createDeleter(tempPath); const readTempData = createEncryptedReader(tempPath); - const copyIntoTempDirectory = - Attachments.copyIntoAttachmentsDirectory(tempPath); + const copyAttachmentIntoTempDirectory = + Attachments.copyIntoAttachmentsDirectory({ + sourceDir: attachmentsPath, + targetDir: tempPath, + }); const draftPath = getDraftPath(userDataPath); const getAbsoluteDraftPath = createAbsolutePathGetter(draftPath); @@ -282,8 +288,8 @@ export function initializeMigrations({ return { attachmentsPath, - copyIntoAttachmentsDirectory, - copyIntoTempDirectory, + copyStickerIntoAttachmentsDirectory, + copyAttachmentIntoTempDirectory, deleteAttachmentData: deleteOnDisk, deleteAvatar, deleteDownloadData: deleteDownloadOnDisk, @@ -390,9 +396,10 @@ type AttachmentsModuleType = { root: string ) => (relativePath: string) => Promise; - copyIntoAttachmentsDirectory: ( - root: string - ) => (sourcePath: string) => Promise<{ path: string; size: number }>; + copyIntoAttachmentsDirectory: (options: { + sourceDir: string; + targetDir: string; + }) => (sourcePath: string) => Promise<{ path: string; size: number }>; createWriterForNew: ( root: string, diff --git a/ts/state/ducks/lightbox.ts b/ts/state/ducks/lightbox.ts index 626a59ae0b..e4378f088f 100644 --- a/ts/state/ducks/lightbox.ts +++ b/ts/state/ducks/lightbox.ts @@ -195,11 +195,12 @@ function showLightboxForViewOnceMedia( ); } - const { copyIntoTempDirectory, getAbsoluteAttachmentPath } = + const { copyAttachmentIntoTempDirectory, getAbsoluteAttachmentPath } = window.Signal.Migrations; const absolutePath = getAbsoluteAttachmentPath(firstAttachment.path); - const { path: tempPath } = await copyIntoTempDirectory(absolutePath); + const { path: tempPath } = + await copyAttachmentIntoTempDirectory(absolutePath); const tempAttachment = { ...firstAttachment, path: tempPath, diff --git a/ts/test-electron/windows/attachments_test.ts b/ts/test-electron/windows/attachments_test.ts index 20c54d8d7b..a3175ecf60 100644 --- a/ts/test-electron/windows/attachments_test.ts +++ b/ts/test-electron/windows/attachments_test.ts @@ -55,24 +55,32 @@ describe('Attachments', () => { it('throws if passed a non-string', () => { assert.throws(() => { - Attachments.copyIntoAttachmentsDirectory(1234 as unknown as string); + Attachments.copyIntoAttachmentsDirectory({ + targetDir: 1234 as unknown as string, + sourceDir: 1234 as unknown as string, + }); }, TypeError); assert.throws(() => { - Attachments.copyIntoAttachmentsDirectory(null as unknown as string); + Attachments.copyIntoAttachmentsDirectory({ + targetDir: null as unknown as string, + sourceDir: null as unknown as string, + }); }, TypeError); }); it('returns a function that rejects if the source path is not a string', async () => { - const copier = Attachments.copyIntoAttachmentsDirectory( - await getFakeAttachmentsDirectory() - ); + const copier = Attachments.copyIntoAttachmentsDirectory({ + sourceDir: await getFakeAttachmentsDirectory(), + targetDir: await getFakeAttachmentsDirectory(), + }); await assert.isRejected(copier(123 as unknown as string)); }); it('returns a function that rejects if the source path is not in the user config directory', async () => { - const copier = Attachments.copyIntoAttachmentsDirectory( - await getFakeAttachmentsDirectory() - ); + const copier = Attachments.copyIntoAttachmentsDirectory({ + sourceDir: await getFakeAttachmentsDirectory(), + targetDir: await getFakeAttachmentsDirectory(), + }); await assert.isRejected( copier(path.join(tempRootDirectory, 'hello.txt')), "'sourcePath' must be relative to the user config directory" @@ -85,7 +93,10 @@ describe('Attachments', () => { await fse.outputFile(someOtherPath, 'hello world'); filesToRemove.push(someOtherPath); - const copier = Attachments.copyIntoAttachmentsDirectory(attachmentsPath); + const copier = Attachments.copyIntoAttachmentsDirectory({ + sourceDir: USER_DATA, + targetDir: attachmentsPath, + }); const { path: relativePath, size } = await copier(someOtherPath); const absolutePath = path.join(attachmentsPath, relativePath); diff --git a/ts/types/Stickers.ts b/ts/types/Stickers.ts index b79ac1c2b8..4c2ce6f6b4 100644 --- a/ts/types/Stickers.ts +++ b/ts/types/Stickers.ts @@ -1087,7 +1087,9 @@ export async function copyStickerToAttachments( const absolutePath = window.Signal.Migrations.getAbsoluteStickerPath(stickerPath); const { path, size } = - await window.Signal.Migrations.copyIntoAttachmentsDirectory(absolutePath); + await window.Signal.Migrations.copyStickerIntoAttachmentsDirectory( + absolutePath + ); const newSticker: AttachmentType = { ...sticker, diff --git a/ts/windows/main/attachments.ts b/ts/windows/main/attachments.ts index cec14fb6a1..860388999e 100644 --- a/ts/windows/main/attachments.ts +++ b/ts/windows/main/attachments.ts @@ -59,14 +59,19 @@ export const createPlaintextReader = ( }; }; -export const copyIntoAttachmentsDirectory = ( - root: string -): ((sourcePath: string) => Promise<{ path: string; size: number }>) => { - if (!isString(root)) { - throw new TypeError("'root' must be a path"); +export const copyIntoAttachmentsDirectory = ({ + sourceDir, + targetDir, +}: { + sourceDir: string; + targetDir: string; +}): ((sourcePath: string) => Promise<{ path: string; size: number }>) => { + if (!isString(sourceDir)) { + throw new TypeError("'sourceDir' must be a path"); + } + if (!isString(targetDir)) { + throw new TypeError("'targetDir' must be a path"); } - - const userDataPath = window.SignalContext.getPath('userData'); return async ( sourcePath: string @@ -75,7 +80,7 @@ export const copyIntoAttachmentsDirectory = ( throw new TypeError('sourcePath must be a string'); } - if (!isPathInside(sourcePath, userDataPath)) { + if (!isPathInside(sourcePath, sourceDir)) { throw new Error( "'sourcePath' must be relative to the user config directory" ); @@ -83,9 +88,9 @@ export const copyIntoAttachmentsDirectory = ( const name = createName(); const relativePath = getRelativePath(name); - const absolutePath = join(root, relativePath); + const absolutePath = join(targetDir, relativePath); const normalized = normalize(absolutePath); - if (!isPathInside(normalized, root)) { + if (!isPathInside(normalized, targetDir)) { throw new Error('Invalid relative path'); }