mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-02-14 23:18:54 +00:00
Support symlinked stickers.noindex folder
This commit is contained in:
@@ -5469,7 +5469,7 @@ export class ConversationModel {
|
||||
|
||||
async #getTemporaryAvatarPath(): Promise<string | undefined> {
|
||||
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);
|
||||
|
||||
29
ts/signal.ts
29
ts/signal.ts
@@ -64,10 +64,10 @@ type EncryptedWriter = (data: Uint8Array) => Promise<LocalAttachmentV2Type>;
|
||||
|
||||
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<void>;
|
||||
@@ -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<Uint8Array>;
|
||||
|
||||
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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user