Skip to content

Commit

Permalink
Merge branch 'master' into issue-5668-add-thunderbird-attachments-sup…
Browse files Browse the repository at this point in the history
…port
  • Loading branch information
martgil authored Dec 16, 2024
2 parents e3a9756 + 132dafd commit 211be40
Show file tree
Hide file tree
Showing 21 changed files with 672 additions and 351 deletions.
4 changes: 3 additions & 1 deletion conf/tsconfig.content_scripts.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"openpgp": ["../node_modules/openpgp/openpgp.d.ts"],
"@openpgp/web-stream-tools": ["../node_modules/@openpgp/web-stream-tools/lib/index.d.ts"],
"squire-rte": ["../node_modules/squire-rte/dist/types/Squire.d.ts"],
"undici-types": ["../node_modules/undici-types/index.d.ts", "COMMENT"]
"undici-types": ["../node_modules/undici-types/index.d.ts", "COMMENT"],
"linkifyHtml": ["../node_modules/linkify-html/dist/linkify-html.es.d.ts", "COMMENT"],
"linkifyjs": ["../node_modules/linkifyjs/dist/linkify.es.d.ts", "COMMENT"]
},
"typeRoots": ["../extension/types", "../extension/js/common/core/types"]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { ViewModule } from '../../../js/common/view-module.js';
import { ComposeView } from '../compose.js';
import { AjaxErrMsgs } from '../../../js/common/api/shared/api-error.js';
import { Lang } from '../../../js/common/lang.js';
import linkifyHtml from 'linkifyHtml';
import { MsgUtil } from '../../../js/common/core/crypto/pgp/msg-util.js';

export class ComposerUserError extends Error {}
class ComposerNotReadyError extends ComposerUserError {}
Expand Down Expand Up @@ -160,6 +162,11 @@ export class ComposeErrModule extends ViewModule<ComposeView> {
};

public throwIfEncryptionPasswordInvalidOrDisabled = async ({ subject, pwd }: { subject: string; pwd?: string }) => {
const disallowedPasswordMessageTerms = this.view.clientConfiguration.getDisallowPasswordMessagesForTerms();
const disallowedPasswordMessageErrorText = this.view.clientConfiguration.getDisallowPasswordMessagesErrorText();
if (disallowedPasswordMessageErrorText && disallowedPasswordMessageTerms && !MsgUtil.isPasswordMessageEnabled(subject, disallowedPasswordMessageTerms)) {
throw new ComposerUserError(linkifyHtml(disallowedPasswordMessageErrorText, { target: '_blank' }));
}
// When DISABLE_FLOWCRYPT_HOSTED_PASSWORD_MESSAGES present, and recipients are missing a public key, and the user is using flowcrypt.com/shared-tenant-fes (not FES)
if (this.view.clientConfiguration.shouldDisableFlowCryptHostedPasswordMessages() && !this.view.isCustomerUrlFesUsed()) {
throw new ComposerUserError(Lang.compose.addMissingRecipientPubkeys);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export class ComposeStorageModule extends ViewModule<ComposeView> {
// re-query the storage, which is now updated
const updatedContact = await ContactStore.getOneWithAllPubkeys(undefined, email);
this.view.errModule.debug(`getUpToDatePubkeys.updatedContact.sortedPubkeys.length(${updatedContact?.sortedPubkeys.length})`);
this.view.errModule.debug(`getUpToDatePubkeys.updatedContact(${updatedContact})`);
this.view.errModule.debug(`getUpToDatePubkeys.updatedContact(${JSON.stringify(updatedContact)})`);
return updatedContact;
};

Expand Down
2 changes: 2 additions & 0 deletions extension/chrome/elements/compose.htm
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ <h1 id="header_title" data-test="header-title">New Secure Message</h1>
<script src="/lib/zxcvbn.js"></script>
<script src="/lib/iso-8859-2.js"></script>
<script src="/lib/forge.js"></script>
<script src="/lib/linkify.min.js"></script>
<script src="/lib/linkify-html.min.js"></script>
<script src="compose.js" type="module"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion extension/js/common/api/email-provider/gmail/gmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ export class Gmail extends EmailProviderApi implements EmailProviderInterface {
// Depending on your needs, you might throw an error or handle this scenario differently.
throw new Error('Failed to meet the minimum byte requirement or condition.');
})
// eslint-disable-next-line @typescript-eslint/use-unknown-in-catch-callback-variable

.catch(reject);
});
};
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/api/shared/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ export class Api {
.then(data => {
resolve(data as FetchResult<T, RT>);
})
// eslint-disable-next-line @typescript-eslint/use-unknown-in-catch-callback-variable

.catch(reject);
});
} catch (e) {
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/browser/browser-extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class BrowserExtension {
try {
bugReport.details = JSON.stringify(details, undefined, 2);
} catch (e) {
bugReport.details_as_string = String(details);
bugReport.details_as_string = String(details as unknown);
bugReport.details_serialization_error = String(e);
}
let result = '';
Expand Down
17 changes: 17 additions & 0 deletions extension/js/common/client-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export type ClientConfigurationJson = {
enforce_keygen_expire_months?: number;
in_memory_pass_phrase_session_length?: number;
prv_backup_to_designated_mailbox?: string;
disallow_password_messages_for_terms?: string[];
disallow_password_messages_error_text?: string;
};
/* eslint-enable @typescript-eslint/naming-convention */

Expand Down Expand Up @@ -110,6 +112,21 @@ export class ClientConfiguration {
return this.clientConfigurationJson.enforce_keygen_expire_months;
};

/**
* An array of strings to check against the subject of the composed password-protected message.
* If any string in this array is found in the subject, an error alert must be displayed.
*/
public getDisallowPasswordMessagesForTerms = (): string[] | undefined => {
return this.clientConfigurationJson.disallow_password_messages_for_terms?.filter(term => !!term);
};

/**
* The text to be displayed in the password message terms error alert
*/
public getDisallowPasswordMessagesErrorText = (): string | undefined => {
return this.clientConfigurationJson.disallow_password_messages_error_text;
};

/**
* pass phrase session length to be configurable with client configuraiton
* default 4 hours
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/core/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export class Str {
};

public static prettyPrint = (obj: unknown) => {
return typeof obj === 'object' ? JSON.stringify(obj, undefined, 2).replace(/ /g, '&nbsp;').replace(/\n/g, '<br />') : String(obj);
return typeof obj === 'object' ? JSON.stringify(obj, undefined, 2).replace(/ /g, '&nbsp;').replace(/\n/g, '<br />') : String(obj as unknown);
};

public static normalizeSpaces = (str: string) => {
Expand Down
25 changes: 25 additions & 0 deletions extension/js/common/core/crypto/pgp/msg-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,31 @@ export class MsgUtil {
return diagnosis;
}

public static isPasswordMessageEnabled(subject: string, disallowTerms: string[]) {
if (!subject || !Array.isArray(disallowTerms)) {
return true; // If no subject or no terms to disallow, assume enabled
}

const lowerSubject = subject.toLowerCase();

for (const term of disallowTerms) {
// Escape term for regex
const escapedTerm = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Use regex to ensure the term appears as a separate token
// (^|\W) ensures the term is at start or preceded by non-word char
// (\W|$) ensures the term is followed by non-word char or end
const regex = new RegExp(`(^|\\W)${escapedTerm}(\\W|$)`, 'i');

if (regex.test(lowerSubject)) {
// Found a disallowed term as a separate token
return false;
}
}

// No disallowed terms found as exact matches
return true;
}

private static async getSortedKeys(kiWithPp: KeyInfoWithIdentityAndOptionalPp[], msg: OpenPGP.Message<OpenPGP.Data>): Promise<SortedKeysForDecrypt> {
const keys: SortedKeysForDecrypt = {
encryptedFor: [],
Expand Down
2 changes: 1 addition & 1 deletion extension/js/common/platform/catch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ export class Catch {
private static formExceptionFromThrown(thrown: unknown, errMsg?: string, url?: string, line?: number, col?: number, isManuallyCalled?: boolean): Error {
let exception: Error;
if (typeof thrown !== 'object') {
exception = new Error(`THROWN_NON_OBJECT[${typeof thrown}]: ${String(thrown)}`);
exception = new Error(`THROWN_NON_OBJECT[${typeof thrown}]: ${String(thrown as unknown)}`);
} else if (errMsg && url && typeof line !== 'undefined' && !col && !thrown && !isManuallyCalled) {
exception = new Error(`LIMITED_ERROR: ${errMsg}`);
} else if (thrown instanceof Error) {
Expand Down
Loading

0 comments on commit 211be40

Please sign in to comment.