1 import { splitExtension } from '@proton/shared/lib/helpers/file';
2 import isTruthy from '@proton/utils/isTruthy';
4 import type { EncryptedLink } from './interface';
6 export const WINDOWS_FORBIDDEN_CHARACTERS = /[<>:"|?*]/;
7 // eslint-disable-next-line no-control-regex
8 export const GLOBAL_FORBIDDEN_CHARACTERS = /\/|\\|[\u0000-\u001F]|[\u2000-\u200F]|[\u202E-\u202F]/;
9 export const WINDOWS_RESERVED_NAMES = [
34 export const formatLinkName = (str: string) => str.trim();
36 export const splitLinkName = (linkName: string) => {
37 if (linkName.endsWith('.')) {
38 return [linkName, ''];
40 return splitExtension(linkName);
43 export const adjustWindowsLinkName = (fileName: string) => {
44 let adjustedFileName = fileName.replaceAll(RegExp(WINDOWS_FORBIDDEN_CHARACTERS, 'g'), '_');
46 if (WINDOWS_RESERVED_NAMES.includes(fileName.toUpperCase())) {
47 adjustedFileName = `_${fileName}`;
50 if (adjustedFileName.endsWith('.')) {
51 adjustedFileName = `${adjustedFileName.slice(0, -1)}_`;
54 return adjustedFileName;
57 export const adjustName = (index: number, namePart: string, extension?: string) => {
59 return extension ? `${namePart}.${extension}` : namePart;
63 return [`.${extension}`, `(${index})`].join(' ');
66 const newNamePart = [namePart, `(${index})`].filter(isTruthy).join(' ');
67 return [newNamePart, extension].filter(isTruthy).join('.');
71 * isEncryptedLinkSame returns whether the encrypted content and keys are
72 * the same, so we might clear signature issues and try decryption again,
75 export function isEncryptedLinkSame(original: EncryptedLink, newLink: EncryptedLink): boolean {
77 original.nodeKey === newLink.nodeKey &&
78 original.nodePassphrase === newLink.nodePassphrase &&
79 original.nodePassphraseSignature === newLink.nodePassphraseSignature &&
80 original.nodeHashKey === newLink.nodeHashKey &&
81 original.contentKeyPacket === newLink.contentKeyPacket &&
82 original.contentKeyPacketSignature === newLink.contentKeyPacketSignature &&
83 original.signatureAddress === newLink.signatureAddress &&
84 isDecryptedLinkSame(original, newLink)
89 * isDecryptedLinkSame returns whether the encrypted content (not keys) is
90 * the same and thus we can say decrypted content is also the same, so we
91 * might skip decryption if we already have decrypted content, for example.
93 export function isDecryptedLinkSame(original: EncryptedLink, newLink: EncryptedLink): boolean {
95 original.parentLinkId === newLink.parentLinkId &&
96 original.name === newLink.name &&
97 original.xAttr === newLink.xAttr