Skip to content

Commit 6127160

Browse files
committed
add attachment decryption
1 parent 07a96bf commit 6127160

File tree

4 files changed

+49
-29
lines changed

4 files changed

+49
-29
lines changed

extension/js/common/browser/browser-msg.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Ui } from './ui.js';
2020
import { AuthRes } from '../api/authentication/generic/oauth.js';
2121
import { GlobalStore } from '../platform/store/global-store.js';
2222
import { BgUtils } from '../../service_worker/bgutils.js';
23+
import { Attachment } from '../core/attachment.js';
2324

2425
export type GoogleAuthWindowResult$result = 'Success' | 'Denied' | 'Error' | 'Closed';
2526
export type ScreenDimensions = { width: number; height: number; availLeft: number; availTop: number };
@@ -98,7 +99,7 @@ export namespace Bm {
9899
export type PgpBlockRetry = { frameId: string; messageSender: Dest };
99100
export type PgpBlockReady = { frameId: string; messageSender: Dest };
100101
export type ThunderbirdOpenPassphraseDialog = { acctEmail: string; longids: string };
101-
export type ThunderbirdAttachmentDownload = { attachment: messenger.messages.MessageAttachment };
102+
export type ThunderbirdGetDownloadableAttachment = { attachment: messenger.messages.MessageAttachment };
102103

103104
export namespace Res {
104105
export type GetActiveTabInfo = {
@@ -115,7 +116,7 @@ export namespace Bm {
115116
export type ExpirationCacheGet<V> = Promise<V | undefined>;
116117
export type ExpirationCacheSet = Promise<void>;
117118
export type ExpirationCacheDeleteExpired = Promise<void>;
118-
export type ThunderbirdAttachmentDownload = Promise<void>;
119+
export type ThunderbirdGetDownloadableAttachment = Attachment | undefined;
119120
export type ThunderbirdGetCurrentUser = string | undefined;
120121
export type ThunderbirdMsgGet = { attachments: messenger.messages.MessageAttachment[]; messagePart: messenger.messages.MessagePart };
121122
export type ThunderbirdOpenPassphraseDialog = Promise<void>;
@@ -136,7 +137,7 @@ export namespace Bm {
136137
| ExpirationCacheDeleteExpired
137138
| AjaxGmailAttachmentGetChunk
138139
| ConfirmationResult
139-
| ThunderbirdAttachmentDownload
140+
| ThunderbirdGetDownloadableAttachment
140141
| ThunderbirdMsgGet;
141142
}
142143

@@ -178,7 +179,7 @@ export namespace Bm {
178179
| PgpBlockReady
179180
| PgpBlockRetry
180181
| ConfirmationResult
181-
| ThunderbirdAttachmentDownload
182+
| ThunderbirdGetDownloadableAttachment
182183
| ThunderbirdOpenPassphraseDialog
183184
| Ajax;
184185

@@ -243,8 +244,8 @@ export class BrowserMsg {
243244
BrowserMsg.sendAwait(undefined, 'expirationCacheSet', bm, true) as Promise<Bm.Res.ExpirationCacheSet>,
244245
expirationCacheDeleteExpired: (bm: Bm.ExpirationCacheDeleteExpired) =>
245246
BrowserMsg.sendAwait(undefined, 'expirationCacheDeleteExpired', bm, true) as Promise<Bm.Res.ExpirationCacheDeleteExpired>,
246-
thunderbirdAttachmentDownload: (bm: Bm.ThunderbirdAttachmentDownload) =>
247-
BrowserMsg.sendAwait(undefined, 'thunderbirdAttachmentDownload', bm, true) as Promise<Bm.Res.ThunderbirdAttachmentDownload>,
247+
thunderbirdGetDownloadableAttachment: (bm: Bm.ThunderbirdGetDownloadableAttachment) =>
248+
BrowserMsg.sendAwait(undefined, 'thunderbirdGetDownloadableAttachment', bm, true) as Promise<Bm.Res.ThunderbirdGetDownloadableAttachment>,
248249
thunderbirdGetCurrentUser: () =>
249250
BrowserMsg.sendAwait(undefined, 'thunderbirdGetCurrentUser', undefined, true) as Promise<Bm.Res.ThunderbirdGetCurrentUser>,
250251
thunderbirdMsgGet: () => BrowserMsg.sendAwait(undefined, 'thunderbirdMsgGet', undefined, true) as Promise<Bm.Res.ThunderbirdMsgGet>,

extension/js/content_scripts/webmail/thunderbird/thunderbird-element-replacer.ts

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
1919
public reinsertReplyBox: (replyMsgId: string) => void;
2020
public scrollToReplyBox: (replyMsgId: string) => void;
2121
public scrollToCursorInReplyBox: (replyMsgId: string, cursorOffsetTop: number) => void;
22+
private acctEmail: string;
2223
private emailBodyFromThunderbirdMail: string;
2324
private thunderbirdEmailSelector = $('div.moz-text-plain');
2425

@@ -32,12 +33,13 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
3233
if (!messagePart) {
3334
return;
3435
} else {
35-
const acctEmail = await BrowserMsg.send.bg.await.thunderbirdGetCurrentUser();
36-
const parsedPubs = (await ContactStore.getOneWithAllPubkeys(undefined, String(acctEmail)))?.sortedPubkeys ?? [];
36+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
37+
this.acctEmail = (await BrowserMsg.send.bg.await.thunderbirdGetCurrentUser())!;
38+
const parsedPubs = (await ContactStore.getOneWithAllPubkeys(undefined, this.acctEmail))?.sortedPubkeys ?? [];
3739
const signerKeys = parsedPubs.map(key => KeyUtil.armor(key.pubkey));
3840
if (this.isPublicKeyEncryptedMsg()) {
3941
const result = await MsgUtil.decryptMessage({
40-
kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(String(acctEmail)),
42+
kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(this.acctEmail),
4143
encryptedData: this.emailBodyFromThunderbirdMail,
4244
verificationPubs: signerKeys,
4345
});
@@ -70,6 +72,15 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
7072
const pgpBlock = this.generatePgpBlockTemplate(decryptionErrorMsg, 'not signed', this.emailBodyFromThunderbirdMail);
7173
$('body').html(pgpBlock); // xss-sanitized
7274
}
75+
if (!attachments.length) {
76+
return;
77+
} else {
78+
for (const attachment of attachments) {
79+
const generatedPgpTemplate = this.generatePgpAttachmentTemplate(attachment);
80+
$('.pgp_attachments_block').append(generatedPgpTemplate); // xss-sanitized
81+
// todo: detached signed message via https://github.com/FlowCrypt/flowcrypt-browser/issues/5668
82+
}
83+
}
7384
} else if (this.isCleartextMsg()) {
7485
const message = await openpgp.readCleartextMessage({ cleartextMessage: this.emailBodyFromThunderbirdMail });
7586
const result = await OpenPGPKey.verify(message, await ContactStore.getPubkeyInfos(undefined, signerKeys));
@@ -85,15 +96,6 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
8596
$('body').html(pgpBlock); // xss-sanitized
8697
}
8798
}
88-
if (!attachments.length) {
89-
return;
90-
} else {
91-
for (const attachment of attachments) {
92-
const generatedPgpTemplate = this.generatePgpAttachmentTemplate(attachment);
93-
$('.pgp_attachments_block').append(generatedPgpTemplate); // xss-sanitized
94-
// todo: detached signed message via https://github.com/FlowCrypt/flowcrypt-browser/issues/5668
95-
}
96-
}
9799
}
98100
};
99101

@@ -129,7 +131,25 @@ export class ThunderbirdElementReplacer extends WebmailElementReplacer {
129131
};
130132

131133
private downloadThunderbirdAttachmentHandler = async (attachment: messenger.messages.MessageAttachment) => {
132-
await BrowserMsg.send.bg.await.thunderbirdAttachmentDownload({ attachment });
134+
const flowCryptAttachment = await BrowserMsg.send.bg.await.thunderbirdGetDownloadableAttachment({ attachment });
135+
if (flowCryptAttachment) {
136+
const result = await MsgUtil.decryptMessage({
137+
kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(this.acctEmail),
138+
encryptedData: this.emailBodyFromThunderbirdMail,
139+
verificationPubs: [], // todo: #4158 signature verification of attachments
140+
});
141+
if (result.success && result.content) {
142+
console.log('debug: download me');
143+
// todo - create separate background message for download prompt and file download
144+
// const fileUrl = URL.createObjectURL(rawAttachment);
145+
// await browser.downloads.download({
146+
// url: fileUrl,
147+
// filename: r.attachment.name,
148+
// saveAs: true,
149+
// });
150+
// URL.revokeObjectURL(fileUrl);
151+
}
152+
}
133153
};
134154

135155
private isCleartextMsg = (): boolean => {

extension/js/service_worker/background.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ console.info('background.js service worker starting');
7575
await BgHandlers.thunderbirdContentScriptRegistration();
7676
BrowserMsg.bgAddListener('thunderbirdGetCurrentUser', BgHandlers.thunderbirdGetCurrentUserHandler);
7777
BrowserMsg.bgAddListener('thunderbirdMsgGet', BgHandlers.thunderbirdMsgGetHandler);
78-
BrowserMsg.bgAddListener('thunderbirdAttachmentDownload', BgHandlers.thunderbirdAttachmentDownload);
78+
BrowserMsg.bgAddListener('thunderbirdGetDownloadableAttachment', BgHandlers.thunderbirdGetDownloadableAttachment);
7979
BrowserMsg.bgAddListener('thunderbirdOpenPassphraseDialog', BgHandlers.thunderbirdOpenPassphraseDialog);
8080
}
8181
})().catch(Catch.reportErr);

extension/js/service_worker/bg-handlers.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { GoogleOAuth } from '../common/api/authentication/google/google-oauth.js
1313
import { AcctStore } from '../common/platform/store/acct-store.js';
1414
import { ConfiguredIdpOAuth } from '../common/api/authentication/configured-idp-oauth.js';
1515
import { Url, Str } from '../common/core/common.js';
16+
import { Attachment } from '../common/core/attachment.js';
1617

1718
export class BgHandlers {
1819
public static openSettingsPageHandler: Bm.AsyncResponselessHandler = async ({ page, path, pageUrlParams, addNewAcct, acctEmail }: Bm.Settings) => {
@@ -162,18 +163,16 @@ export class BgHandlers {
162163
});
163164
};
164165

165-
public static thunderbirdAttachmentDownload = async (r: Bm.ThunderbirdAttachmentDownload): Promise<Bm.Res.ThunderbirdAttachmentDownload> => {
166+
public static thunderbirdGetDownloadableAttachment = async (
167+
r: Bm.ThunderbirdGetDownloadableAttachment
168+
): Promise<Bm.Res.ThunderbirdGetDownloadableAttachment> => {
166169
const [tab] = await messenger.mailTabs.query({ active: true, currentWindow: true });
167170
if (tab.id) {
168-
const downloadableAttachment = await messenger.messages.getAttachmentFile(tab.id, r.attachment.partName);
169-
const fileUrl = URL.createObjectURL(downloadableAttachment);
170-
await browser.downloads.download({
171-
url: fileUrl,
172-
filename: r.attachment.name,
173-
saveAs: true,
174-
});
175-
URL.revokeObjectURL(fileUrl);
171+
const rawAttachment = await messenger.messages.getAttachmentFile(tab.id, r.attachment.partName);
172+
const data = new Uint8Array(await rawAttachment.arrayBuffer());
173+
return new Attachment({ data });
176174
}
175+
return;
177176
};
178177

179178
public static thunderbirdGetCurrentUserHandler = async (): Promise<Bm.Res.ThunderbirdGetCurrentUser> => {

0 commit comments

Comments
 (0)