From 7a105ab84f4674ac3fa28c5d109a323dfcfc046b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 10 Mar 2023 11:07:23 +0000 Subject: [PATCH 1/2] fix --- .../chrome/elements/compose-modules/compose-quote-module.ts | 2 +- extension/js/common/core/buf.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/extension/chrome/elements/compose-modules/compose-quote-module.ts b/extension/chrome/elements/compose-modules/compose-quote-module.ts index fa1861db283..40178a71d7d 100644 --- a/extension/chrome/elements/compose-modules/compose-quote-module.ts +++ b/extension/chrome/elements/compose-modules/compose-quote-module.ts @@ -119,7 +119,7 @@ export class ComposeQuoteModule extends ViewModule { for (const block of readableBlocks) { const stringContent = block.content.toString(); if (block.type === 'decryptedHtml') { - const htmlParsed = Xss.htmlSanitizeAndStripAllTags(block ? block.content.toString() : 'No Content', '\n', false); + const htmlParsed = Xss.htmlSanitizeAndStripAllTags(stringContent || 'No Content', '\n', false); decryptedAndFormatedContent.push(Xss.htmlUnescape(htmlParsed)); } else if (block.type === 'plainHtml') { decryptedAndFormatedContent.push(Xss.htmlUnescape(Xss.htmlSanitizeAndStripAllTags(stringContent, '\n', false))); diff --git a/extension/js/common/core/buf.ts b/extension/js/common/core/buf.ts index 5d7ca87cb68..14bb37cdc9b 100644 --- a/extension/js/common/core/buf.ts +++ b/extension/js/common/core/buf.ts @@ -97,6 +97,7 @@ export class Buf extends Uint8Array { return Buf.fromBase64Str(b64UrlStr.replace(/-/g, '+').replace(/_/g, '/')); }; + // todo: deprecate public toString = (mode: 'strict' | 'inform' | 'ignore' = 'inform'): string => { // mimic Node api return this.toUtfStr(mode); From 89a67ad7744a042d210fed1a58dba0aa4836d54c Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 16 Mar 2023 09:30:03 +0000 Subject: [PATCH 2/2] refactorings --- extension/chrome/elements/attachment_preview.ts | 2 +- .../compose-modules/compose-draft-module.ts | 2 +- .../compose-modules/compose-quote-module.ts | 2 +- .../inbox-modules/inbox-active-thread-module.ts | 4 ++-- extension/js/common/api/key-server/attester.ts | 2 +- extension/js/common/core/buf.ts | 4 ++-- extension/js/common/core/crypto/key.ts | 4 ++-- extension/js/common/core/mime.ts | 4 ++-- extension/js/common/core/msg-block-parser.ts | 2 +- extension/js/common/ui/key-import-ui.ts | 2 +- extension/js/common/xss-safe-factory.ts | 14 +++++++------- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/extension/chrome/elements/attachment_preview.ts b/extension/chrome/elements/attachment_preview.ts index b26fe6a4300..ec17d8a14e0 100644 --- a/extension/chrome/elements/attachment_preview.ts +++ b/extension/chrome/elements/attachment_preview.ts @@ -58,7 +58,7 @@ View.run( this.attachmentPreviewContainer.html(`${Xss.escape(this.origNameBasedOnFilename)}`); // xss-escaped } else if (attachmentType === 'txt') { // text - this.attachmentPreviewContainer.html(`
${Xss.escape(result.toString()).replace(/\n/g, '
')}
`); // xss-escaped + this.attachmentPreviewContainer.html(`
${Xss.escape(result.toUtfStr()).replace(/\n/g, '
')}
`); // xss-escaped } else if (attachmentType === 'pdf') { // PDF pdfjsLib.getDocument({ data: result }).promise.then(async (pdf: PDFDocumentProxy) => { diff --git a/extension/chrome/elements/compose-modules/compose-draft-module.ts b/extension/chrome/elements/compose-modules/compose-draft-module.ts index fe217ff88b2..f19d498382e 100644 --- a/extension/chrome/elements/compose-modules/compose-draft-module.ts +++ b/extension/chrome/elements/compose-modules/compose-draft-module.ts @@ -331,7 +331,7 @@ export class ComposeDraftModule extends ViewModule { if (isRichText) { this.view.sendBtnModule.popover.toggleItemTick($('.action-toggle-richtext-sending-option'), 'richtext', true); } - this.view.inputModule.inputTextHtmlSetSafely(sanitizedContent.toString()); + this.view.inputModule.inputTextHtmlSetSafely(Str.with(sanitizedContent)); this.view.inputModule.squire.focus(); }; diff --git a/extension/chrome/elements/compose-modules/compose-quote-module.ts b/extension/chrome/elements/compose-modules/compose-quote-module.ts index 40178a71d7d..eee74fa4f3b 100644 --- a/extension/chrome/elements/compose-modules/compose-quote-module.ts +++ b/extension/chrome/elements/compose-modules/compose-quote-module.ts @@ -117,7 +117,7 @@ export class ComposeQuoteModule extends ViewModule { const decryptedAndFormatedContent: string[] = []; const decryptedFiles: File[] = []; for (const block of readableBlocks) { - const stringContent = block.content.toString(); + const stringContent = Str.with(block.content); if (block.type === 'decryptedHtml') { const htmlParsed = Xss.htmlSanitizeAndStripAllTags(stringContent || 'No Content', '\n', false); decryptedAndFormatedContent.push(Xss.htmlUnescape(htmlParsed)); diff --git a/extension/chrome/settings/inbox/inbox-modules/inbox-active-thread-module.ts b/extension/chrome/settings/inbox/inbox-modules/inbox-active-thread-module.ts index 1d8dc3e9096..9c0e3d655ca 100644 --- a/extension/chrome/settings/inbox/inbox-modules/inbox-active-thread-module.ts +++ b/extension/chrome/settings/inbox/inbox-modules/inbox-active-thread-module.ts @@ -5,7 +5,7 @@ import { Bm, BrowserMsg } from '../../../../js/common/browser/browser-msg.js'; import { FactoryReplyParams, XssSafeFactory } from '../../../../js/common/xss-safe-factory.js'; import { GmailParser, GmailRes } from '../../../../js/common/api/email-provider/gmail/gmail-parser.js'; -import { Url, UrlParams } from '../../../../js/common/core/common.js'; +import { Str, Url, UrlParams } from '../../../../js/common/core/common.js'; import { ApiErr } from '../../../../js/common/api/shared/api-error.js'; import { BrowserMsgCommonHandlers } from '../../../../js/common/browser/browser-msg-common-handlers.js'; @@ -128,7 +128,7 @@ export class InboxActiveThreadModule extends ViewModule { this.view.storage.sendAs && !!this.view.storage.sendAs[from] ); } else if (this.view.showOriginal) { - r += Xss.escape(block.content.toString()).replace(/\n/g, '
'); + r += Xss.escape(Str.with(block.content)).replace(/\n/g, '
'); } else { r += XssSafeFactory.renderableMsgBlock(this.view.factory, block, message.id, from, this.view.storage.sendAs && !!this.view.storage.sendAs[from]); } diff --git a/extension/js/common/api/key-server/attester.ts b/extension/js/common/api/key-server/attester.ts index de08ae63e61..867241b0619 100644 --- a/extension/js/common/api/key-server/attester.ts +++ b/extension/js/common/api/key-server/attester.ts @@ -107,7 +107,7 @@ export class Attester extends Api { private getPubKeysSearchResult = async (r: PubCallRes): Promise => { const { blocks } = MsgBlockParser.detectBlocks(r.responseText); - const pubkeys = blocks.filter(block => block.type === 'publicKey').map(block => block.content.toString()); + const pubkeys = blocks.filter(block => block.type === 'publicKey').map(block => Str.with(block.content)); return { pubkeys }; }; diff --git a/extension/js/common/core/buf.ts b/extension/js/common/core/buf.ts index 14bb37cdc9b..58e6da8bc31 100644 --- a/extension/js/common/core/buf.ts +++ b/extension/js/common/core/buf.ts @@ -97,9 +97,9 @@ export class Buf extends Uint8Array { return Buf.fromBase64Str(b64UrlStr.replace(/-/g, '+').replace(/_/g, '/')); }; - // todo: deprecate + /** @deprecated use toUtfStr() instead */ public toString = (mode: 'strict' | 'inform' | 'ignore' = 'inform'): string => { - // mimic Node api + // mimic Buffer.toString() return this.toUtfStr(mode); }; diff --git a/extension/js/common/core/crypto/key.ts b/extension/js/common/core/crypto/key.ts index 3c4d1e1cfc5..4b712c3c793 100644 --- a/extension/js/common/core/crypto/key.ts +++ b/extension/js/common/core/crypto/key.ts @@ -11,7 +11,7 @@ import { OpenPGPKey } from './pgp/openpgp-key.js'; import type * as OpenPGP from 'openpgp'; import { SmimeKey } from './smime/smime-key.js'; import { MsgBlock } from '../msg-block.js'; -import { EmailParts } from '../common.js'; +import { EmailParts, Str } from '../common.js'; /** * This is a common Key interface for both OpenPGP and X.509 keys. @@ -158,7 +158,7 @@ export class KeyUtil { const pushKeysAndErrs = async (content: string | Buf, isArmored: boolean) => { try { if (isArmored) { - allKeys.push(...(await KeyUtil.parseMany(content.toString()))); + allKeys.push(...(await KeyUtil.parseMany(Str.with(content)))); } else { const buf = typeof content === 'string' ? Buf.fromUtfStr(content) : content; const { keys, err } = await KeyUtil.readBinary(buf); diff --git a/extension/js/common/core/mime.ts b/extension/js/common/core/mime.ts index b40568cf0c5..ec1c879b940 100644 --- a/extension/js/common/core/mime.ts +++ b/extension/js/common/core/mime.ts @@ -259,7 +259,7 @@ export class Mime { contentNode = new MimeBuilder('multipart/alternative'); for (const [type, content] of Object.entries(body)) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - contentNode.appendChild(Mime.newContentNode(MimeBuilder, type, content!.toString())); // already present, that's why part of for loop + contentNode.appendChild(Mime.newContentNode(MimeBuilder, type, Str.with(content!))); // already present, that's why part of for loop } } rootNode.appendChild(contentNode); @@ -307,7 +307,7 @@ export class Mime { const bodyNodes = new MimeBuilder('multipart/alternative'); for (const [type, content] of Object.entries(body)) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - bodyNodes.appendChild(Mime.newContentNode(MimeBuilder, type, content!.toString())); + bodyNodes.appendChild(Mime.newContentNode(MimeBuilder, type, Str.with(content!))); } const signedContentNode = new MimeBuilder('multipart/mixed'); signedContentNode.appendChild(bodyNodes); diff --git a/extension/js/common/core/msg-block-parser.ts b/extension/js/common/core/msg-block-parser.ts index b1bc7be7d22..f077cd70915 100644 --- a/extension/js/common/core/msg-block-parser.ts +++ b/extension/js/common/core/msg-block-parser.ts @@ -132,7 +132,7 @@ export class MsgBlockParser { let { blocks, normalized } = MsgBlockParser.detectBlocks(decryptedContent); for (const block of blocks) { if (block.type === 'publicKey') { - const armored = block.content.toString(); + const armored = Str.with(block.content); foundPublicKeys.push(armored); normalized = normalized.replace(armored, ''); } diff --git a/extension/js/common/ui/key-import-ui.ts b/extension/js/common/ui/key-import-ui.ts index df473db28e3..67c0bc4a480 100644 --- a/extension/js/common/ui/key-import-ui.ts +++ b/extension/js/common/ui/key-import-ui.ts @@ -165,7 +165,7 @@ export class KeyImportUi { const firstPrv = MsgBlockParser.detectBlocks(utf).blocks.filter(b => b.type === 'privateKey')[0]; if (firstPrv) { // filter out all content except for the first encountered private key (GPGKeychain compatibility) - prv = await KeyUtil.parse(firstPrv.content.toString()); + prv = await KeyUtil.parse(Str.with(firstPrv.content)); } } else { try { diff --git a/extension/js/common/xss-safe-factory.ts b/extension/js/common/xss-safe-factory.ts index 3dd51f0c5b6..d36fcad36c2 100644 --- a/extension/js/common/xss-safe-factory.ts +++ b/extension/js/common/xss-safe-factory.ts @@ -61,25 +61,25 @@ export class XssSafeFactory { */ public static renderableMsgBlock = (factory: XssSafeFactory, block: MsgBlock, msgId: string, senderEmail: string, isOutgoing?: boolean) => { if (block.type === 'plainText') { - return Xss.escape(block.content.toString()).replace(/\n/g, '
') + '

'; + return Xss.escape(Str.with(block.content)).replace(/\n/g, '
') + '

'; } else if (block.type === 'plainHtml') { - return Xss.htmlSanitizeAndStripAllTags(block.content.toString(), '
') + '

'; + return Xss.htmlSanitizeAndStripAllTags(Str.with(block.content), '
') + '

'; } else if (block.type === 'encryptedMsg') { return factory.embeddedMsg( 'encryptedMsg', - block.complete ? PgpArmor.normalize(block.content.toString(), 'encryptedMsg') : '', + block.complete ? PgpArmor.normalize(Str.with(block.content), 'encryptedMsg') : '', msgId, isOutgoing, senderEmail ); } else if (block.type === 'signedMsg') { - return factory.embeddedMsg('signedMsg', block.content.toString(), msgId, isOutgoing, senderEmail); + return factory.embeddedMsg('signedMsg', Str.with(block.content), msgId, isOutgoing, senderEmail); } else if (block.type === 'publicKey') { - return factory.embeddedPubkey(PgpArmor.normalize(block.content.toString(), 'publicKey'), isOutgoing); + return factory.embeddedPubkey(PgpArmor.normalize(Str.with(block.content), 'publicKey'), isOutgoing); } else if (block.type === 'privateKey') { - return factory.embeddedBackup(PgpArmor.normalize(block.content.toString(), 'privateKey')); + return factory.embeddedBackup(PgpArmor.normalize(Str.with(block.content), 'privateKey')); } else if (block.type === 'certificate') { - return factory.embeddedPubkey(block.content.toString()); + return factory.embeddedPubkey(Str.with(block.content)); } else if (['encryptedAttachment', 'plainAttachment'].includes(block.type)) { return block.attachmentMeta ? factory.embeddedAttachment(new Attachment(block.attachmentMeta), block.type === 'encryptedAttachment')