Merge branch 'feat/inda-383-daily-stat' into 'main'
[ProtonMail-WebClient.git] / applications / drive / src / app / store / _links / link.ts
blobcb420ec249c4dfae0f72be7338da1c3ab902bf26
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 = [
10     'CON',
11     'PRN',
12     'AUX',
13     'NUL',
14     'COM1',
15     'COM2',
16     'COM3',
17     'COM4',
18     'COM5',
19     'COM6',
20     'COM7',
21     'COM8',
22     'COM9',
23     'LPT1',
24     'LPT2',
25     'LPT3',
26     'LPT4',
27     'LPT5',
28     'LPT6',
29     'LPT7',
30     'LPT8',
31     'LPT9',
34 export const formatLinkName = (str: string) => str.trim();
36 export const splitLinkName = (linkName: string) => {
37     if (linkName.endsWith('.')) {
38         return [linkName, ''];
39     }
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}`;
48     }
50     if (adjustedFileName.endsWith('.')) {
51         adjustedFileName = `${adjustedFileName.slice(0, -1)}_`;
52     }
54     return adjustedFileName;
57 export const adjustName = (index: number, namePart: string, extension?: string) => {
58     if (index === 0) {
59         return extension ? `${namePart}.${extension}` : namePart;
60     }
62     if (!namePart) {
63         return [`.${extension}`, `(${index})`].join(' ');
64     }
66     const newNamePart = [namePart, `(${index})`].filter(isTruthy).join(' ');
67     return [newNamePart, extension].filter(isTruthy).join('.');
70 /**
71  * isEncryptedLinkSame returns whether the encrypted content and keys are
72  * the same, so we might clear signature issues and try decryption again,
73  * for example.
74  */
75 export function isEncryptedLinkSame(original: EncryptedLink, newLink: EncryptedLink): boolean {
76     return (
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)
85     );
88 /**
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.
92  */
93 export function isDecryptedLinkSame(original: EncryptedLink, newLink: EncryptedLink): boolean {
94     return (
95         original.parentLinkId === newLink.parentLinkId &&
96         original.name === newLink.name &&
97         original.xAttr === newLink.xAttr
98     );