Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions extension/chrome/elements/add_pubkey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ View.run(class AddPubkeyView extends View {
private readonly parentTabId: string;
private readonly missingPubkeyEmails: string[];
private readonly fetchKeyUi = new FetchKeyUI();
private readonly attUI = new AttachmentUI(() => Promise.resolve({ size_mb: 5, size: 5 * 1024 * 1024, count: 1 }));
private readonly attachmentUI = new AttachmentUI(() => Promise.resolve({ size_mb: 5, size: 5 * 1024 * 1024, count: 1 }));

constructor() {
super();
Expand All @@ -45,9 +45,9 @@ View.run(class AddPubkeyView extends View {
}

public setHandlers = () => {
this.attUI.initAttDialog('fineuploader', 'fineuploader_button', {
attAdded: async (file) => {
this.attUI.clearAllAtts();
this.attachmentUI.initAttachmentDialog('fineuploader', 'fineuploader_button', {
attachmentAdded: async (file) => {
this.attachmentUI.clearAllAttachments();
const { keys, errs } = await KeyUtil.readMany(file.getData());
if (keys.length) {
if (errs.length) {
Expand Down
28 changes: 14 additions & 14 deletions extension/chrome/elements/attachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ export class AttachmentDownloadView extends View {
private downloadButton = $('#download');
private header = $('#header');
private originalButtonHTML: string | undefined;
private canClickOnAtt: boolean = false;
private canClickOnAttachment: boolean = false;
private downloadInProgress = false;
private tabId!: string;

constructor() {
super();
const uncheckedUrlParams = Url.parse(['acctEmail', 'msgId', 'attId', 'name', 'type', 'size', 'url', 'parentTabId', 'content', 'decrypted', 'frameId', 'isEncrypted']);
const uncheckedUrlParams = Url.parse(['acctEmail', 'msgId', 'attachmentId', 'name', 'type', 'size', 'url', 'parentTabId', 'content', 'decrypted', 'frameId', 'isEncrypted']);
this.acctEmail = Assert.urlParamRequire.string(uncheckedUrlParams, 'acctEmail');
this.parentTabId = Assert.urlParamRequire.string(uncheckedUrlParams, 'parentTabId');
this.frameId = Assert.urlParamRequire.string(uncheckedUrlParams, 'frameId');
Expand All @@ -53,7 +53,7 @@ export class AttachmentDownloadView extends View {
this.size = uncheckedUrlParams.size ? parseInt(String(uncheckedUrlParams.size)) : undefined;
this.type = Assert.urlParamRequire.optionalString(uncheckedUrlParams, 'type');
this.msgId = Assert.urlParamRequire.optionalString(uncheckedUrlParams, 'msgId');
this.id = Assert.urlParamRequire.optionalString(uncheckedUrlParams, 'attId');
this.id = Assert.urlParamRequire.optionalString(uncheckedUrlParams, 'attachmentId');
this.name = Assert.urlParamRequire.optionalString(uncheckedUrlParams, 'name');
// url contains either actual url of remote content or objectUrl for direct content, either way needs to be downloaded
this.url = Assert.urlParamRequire.optionalString(uncheckedUrlParams, 'url');
Expand Down Expand Up @@ -82,7 +82,7 @@ export class AttachmentDownloadView extends View {
}).catch(ApiErr.reportIfSignificant);
}
try {
this.canClickOnAtt = ! await this.processAsPublicKeyAndHideAttIfAppropriate();
this.canClickOnAttachment = ! await this.processAsPublicKeyAndHideAttachmentIfAppropriate();
} catch (e) {
this.renderErr(e);
}
Expand All @@ -91,7 +91,7 @@ export class AttachmentDownloadView extends View {

public setHandlers = () => {
Ui.event.protect();
if (this.canClickOnAtt) {
if (this.canClickOnAttachment) {
this.downloadButton.click(this.setHandlerPrevent('double', () => this.downloadButtonClickedHandler()));
this.downloadButton.click((e) => e.stopPropagation());
$('body').click(this.setHandlerPrevent('double', async () => {
Expand Down Expand Up @@ -119,7 +119,7 @@ export class AttachmentDownloadView extends View {
if (this.attachment.url) { // when content was downloaded and decrypted
this.attachment.setData(await Api.download(this.attachment.url, this.renderProgress));
} else if (this.attachment.id && this.attachment.msgId) { // gmail attId
const { data } = await this.gmail.attGet(this.attachment.msgId, this.attachment.id, this.renderProgress);
const { data } = await this.gmail.attachmentGet(this.attachment.msgId, this.attachment.id, this.renderProgress);
this.attachment.setData(data);
} else {
throw new Error('File is missing both id and url - this should be fixed');
Expand Down Expand Up @@ -189,9 +189,9 @@ export class AttachmentDownloadView extends View {
});
}

private processAsPublicKeyAndHideAttIfAppropriate = async () => {
private processAsPublicKeyAndHideAttachmentIfAppropriate = async () => {
if (this.attachment.msgId && this.attachment.id && this.attachment.treatAs() === 'publicKey') { // this is encrypted public key - download && decrypt & parse & render
const { data } = await this.gmail.attGet(this.attachment.msgId, this.attachment.id);
const { data } = await this.gmail.attachmentGet(this.attachment.msgId, this.attachment.id);
const decrRes = await MsgUtil.decryptMessage({ kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(this.acctEmail), encryptedData: data });
if (decrRes.success && decrRes.content) {
const openpgpType = await MsgUtil.type({ data: decrRes.content });
Expand All @@ -215,12 +215,12 @@ export class AttachmentDownloadView extends View {
try {
this.originalButtonHTML = this.downloadButton.html();
Xss.sanitizeRender(this.header, `${Ui.spinner('green', 'large_spinner')}<span class="download_progress"></span>`);
await this.recoverMissingAttIdIfNeeded();
await this.recoverMissingAttachmentIdIfNeeded();
await this.downloadDataIfNeeded();
if (!this.isEncrypted) {
Browser.saveToDownloads(this.attachment);
} else {
await this.decryptAndSaveAttToDownloads();
await this.decryptAndSaveAttachmentToDownloads();
}
this.renderHeader();
} catch (e) {
Expand All @@ -236,11 +236,11 @@ export class AttachmentDownloadView extends View {
this.attachment.length = this.size!;
}
const factory = new XssSafeFactory(this.acctEmail, this.parentTabId);
const iframeUrl = factory.srcPgpAttIframe(this.attachment, this.isEncrypted, undefined, 'chrome/elements/attachment_preview.htm');
const iframeUrl = factory.srcPgpAttachmentIframe(this.attachment, this.isEncrypted, undefined, 'chrome/elements/attachment_preview.htm');
BrowserMsg.send.showAttachmentPreview(this.parentTabId, { iframeUrl });
}

private decryptAndSaveAttToDownloads = async () => {
private decryptAndSaveAttachmentToDownloads = async () => {
const result = await MsgUtil.decryptMessage({ kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(this.acctEmail), encryptedData: this.attachment.getData() });
Xss.sanitizeRender(this.downloadButton, this.originalButtonHTML || '');
if (result.success) {
Expand All @@ -253,7 +253,7 @@ export class AttachmentDownloadView extends View {
if (! await PassphraseStore.waitUntilPassphraseChanged(this.acctEmail, result.longids.needPassphrase, 1000, this.ppChangedPromiseCancellation)) {
return;
}
await this.decryptAndSaveAttToDownloads();
await this.decryptAndSaveAttachmentToDownloads();
} else {
delete result.message;
console.info(result);
Expand All @@ -273,7 +273,7 @@ export class AttachmentDownloadView extends View {
}
}

private recoverMissingAttIdIfNeeded = async () => {
private recoverMissingAttachmentIdIfNeeded = async () => {
if (!this.attachment.url && !this.attachment.id && this.attachment.msgId) {
const result = await this.gmail.msgGet(this.attachment.msgId, 'full');
if (result && result.payload && result.payload.parts) {
Expand Down
4 changes: 2 additions & 2 deletions extension/chrome/elements/attachment_preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ View.run(class AttachmentPreviewView extends AttachmentDownloadView {
const blob = new Blob([result], { type: this.type });
const url = window.URL.createObjectURL(blob);
const attachmentType = this.getAttachmentType(this.origNameBasedOnFilename);
const attForSave = new Attachment({ name: this.origNameBasedOnFilename, type: this.type, data: result });
const attachmentForSave = new Attachment({ name: this.origNameBasedOnFilename, type: this.type, data: result });
if (attachmentType) {
if (attachmentType === 'img') { // image
this.attachmentPreviewContainer.html(`<img src="${url}" class="attachment-preview-img" alt="${Xss.escape(this.origNameBasedOnFilename)}">`); // xss-escaped
Expand All @@ -60,7 +60,7 @@ View.run(class AttachmentPreviewView extends AttachmentDownloadView {
});
$('#attachment-preview-download').css('display', 'flex').click((e) => {
e.stopPropagation();
Browser.saveToDownloads(attForSave);
Browser.saveToDownloads(attachmentForSave);
});
}
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@

'use strict';

import { AttLimits, AttachmentUI } from '../../../js/common/ui/attachment-ui.js';
import { AttachmentLimits, AttachmentUI } from '../../../js/common/ui/attachment-ui.js';
import { BrowserMsg } from '../../../js/common/browser/browser-msg.js';
import { OrgRules } from '../../../js/common/org-rules.js';
import { Ui } from '../../../js/common/browser/ui.js';
import { ViewModule } from '../../../js/common/view-module.js';
import { ComposeView } from '../compose.js';
import { AcctStore } from '../../../js/common/platform/store/acct-store.js';

export class ComposeAttsModule extends ViewModule<ComposeView> {
export class ComposeAttachmentsModule extends ViewModule<ComposeView> {

public attach: AttachmentUI;
public attachment: AttachmentUI;

constructor(view: ComposeView) {
super(view);
this.attach = new AttachmentUI(() => this.getMaxAttSizeAndOversizeNotice());
this.attachment = new AttachmentUI(() => this.getMaxAttachmentSizeAndOversizeNotice());
}

public setHandlers = () => {
this.view.S.cached('body').bind({ drop: Ui.event.stop(), dragover: Ui.event.stop() }); // prevents files dropped out of the intended drop area to interfere
this.attach.initAttDialog('fineuploader', 'fineuploader_button', {
this.attachment.initAttachmentDialog('fineuploader', 'fineuploader_button', {
uiChanged: () => {
this.view.sizeModule.setInputTextHeightManuallyIfNeeded();
this.view.sizeModule.resizeComposeBox();
}
});
}

private getMaxAttSizeAndOversizeNotice = async (): Promise<AttLimits> => {
private getMaxAttachmentSizeAndOversizeNotice = async (): Promise<AttachmentLimits> => {
const subscription = await AcctStore.getSubscription(this.view.acctEmail);
if (!subscription.active && !OrgRules.isPublicEmailProviderDomain(this.view.senderModule.getSender())) {
return {
Expand Down
24 changes: 12 additions & 12 deletions extension/chrome/elements/compose-modules/compose-quote-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class ComposeQuoteModule extends ViewModule<ComposeView> {
}
if (method === 'forward' && this.messageToReplyOrForward.decryptedFiles.length) {
for (const file of this.messageToReplyOrForward.decryptedFiles) {
this.view.attsModule.attach.addFile(file);
this.view.attachmentsModule.attachment.addFile(file);
}
}
}
Expand Down Expand Up @@ -95,8 +95,8 @@ export class ComposeQuoteModule extends ViewModule<ComposeView> {
const readableBlockTypes = ['encryptedMsg', 'plainText', 'plainHtml', 'signedMsg'];
const decryptedBlockTypes = ['decryptedHtml'];
if (method === 'forward') {
readableBlockTypes.push(...['encryptedAtt', 'plainAtt']);
decryptedBlockTypes.push('decryptedAtt');
readableBlockTypes.push(...['encryptedAttachment', 'plainAttachment']);
decryptedBlockTypes.push('decryptedAttachment');
}
const readableBlocks: MsgBlock[] = [];
for (const block of message.blocks.filter(b => readableBlockTypes.includes(b.type))) {
Expand All @@ -118,20 +118,20 @@ export class ComposeQuoteModule extends ViewModule<ComposeView> {
decryptedAndFormatedContent.push(Xss.htmlUnescape(htmlParsed));
} else if (block.type === 'plainHtml') {
decryptedAndFormatedContent.push(Xss.htmlUnescape(Xss.htmlSanitizeAndStripAllTags(stringContent, '\n')));
} else if (['encryptedAtt', 'decryptedAtt', 'plainAtt'].includes(block.type)) {
if (block.attMeta?.data) {
let attMeta: { content: Buf, filename?: string } | undefined;
if (block.type === 'encryptedAtt') {
} else if (['encryptedAttachment', 'decryptedAttachment', 'plainAttachment'].includes(block.type)) {
if (block.attachmentMeta?.data) {
let attachmentMeta: { content: Buf, filename?: string } | undefined;
if (block.type === 'encryptedAttachment') {
this.setQuoteLoaderProgress('decrypting...');
const result = await MsgUtil.decryptMessage({ kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(this.view.acctEmail), encryptedData: block.attMeta.data });
const result = await MsgUtil.decryptMessage({ kisWithPp: await KeyStore.getAllWithOptionalPassPhrase(this.view.acctEmail), encryptedData: block.attachmentMeta.data });
if (result.success) {
attMeta = { content: result.content, filename: result.filename };
attachmentMeta = { content: result.content, filename: result.filename };
}
} else {
attMeta = { content: Buf.fromUint8(block.attMeta.data), filename: block.attMeta.name };
attachmentMeta = { content: Buf.fromUint8(block.attachmentMeta.data), filename: block.attachmentMeta.name };
}
if (attMeta) {
const file = new File([attMeta.content], attMeta.filename || '');
if (attachmentMeta) {
const file = new File([attachmentMeta.content], attachmentMeta.filename || '');
decryptedFiles.push(file);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ export class ComposeRenderModule extends ViewModule<ComposeView> {
if (this.view.inputModule.isRichText()) {
const sanitized = Xss.htmlSanitizeKeepBasicTags(this.view.inputModule.extract('html', 'input_text', 'SKIP-ADDONS'), 'IMG-KEEP');
Xss.setElementContentDANGEROUSLY(repliedBodyEl.get(0), sanitized); // xss-sanitized
this.renderReplySuccessMimeAtts(this.view.inputModule.extractAttachments());
this.renderReplySuccessMimeAttachments(this.view.inputModule.extractAttachments());
} else {
Xss.sanitizeRender(repliedBodyEl, Str.escapeTextAsRenderableHtml(this.view.inputModule.extract('text', 'input_text', 'SKIP-ADDONS')));
this.renderReplySuccessAtts(msg.attachments, msgId, this.view.sendBtnModule.popover.choices.encrypt);
this.renderReplySuccessAttachments(msg.attachments, msgId, this.view.sendBtnModule.popover.choices.encrypt);
}
const t = new Date();
const time = ((t.getHours() !== 12) ? (t.getHours() % 12) : 12) + ':' + (t.getMinutes() < 10 ? '0' : '') + t.getMinutes() + ((t.getHours() >= 12) ? ' PM ' : ' AM ') + '(0 minutes ago)';
Expand Down Expand Up @@ -208,8 +208,8 @@ export class ComposeRenderModule extends ViewModule<ComposeView> {
<br><br>My current public key is attached below. Please update your records and send me a new encrypted message.
<br><br>Thank you</div>`);
const primaryKi = await KeyStore.getFirstRequired(this.view.acctEmail);
const attachment = Attachment.keyinfoAsPubkeyAtt(primaryKi);
this.view.attsModule.attach.addFile(new File([attachment.getData()], attachment.name));
const attachment = Attachment.keyinfoAsPubkeyAttachment(primaryKi);
this.view.attachmentsModule.attachment.addFile(new File([attachment.getData()], attachment.name));
this.view.sendBtnModule.popover.toggleItemTick($('.action-toggle-encrypt-sending-option'), 'encrypt', false); // don't encrypt
this.view.sendBtnModule.popover.toggleItemTick($('.action-toggle-sign-sending-option'), 'sign', false); // don't sign
}
Expand Down Expand Up @@ -336,18 +336,18 @@ export class ComposeRenderModule extends ViewModule<ComposeView> {
$('body').attr('data-test-state', 'ready'); // set as ready so that automated tests can evaluate results
}

private renderReplySuccessAtts = (attachments: Attachment[], msgId: string, isEncrypted: boolean) => {
const hideAttTypes = this.view.sendBtnModule.popover.choices.richtext ? ['hidden', 'encryptedMsg', 'signature', 'publicKey'] : ['publicKey'];
const renderableAtts = attachments.filter(attachment => !hideAttTypes.includes(attachment.treatAs()));
if (renderableAtts.length) {
this.view.S.cached('replied_attachments').html(renderableAtts.map(attachment => { // xss-safe-factory
private renderReplySuccessAttachments = (attachments: Attachment[], msgId: string, isEncrypted: boolean) => {
const hideAttachmentTypes = this.view.sendBtnModule.popover.choices.richtext ? ['hidden', 'encryptedMsg', 'signature', 'publicKey'] : ['publicKey'];
const renderableAttachments = attachments.filter(attachment => !hideAttachmentTypes.includes(attachment.treatAs()));
if (renderableAttachments.length) {
this.view.S.cached('replied_attachments').html(renderableAttachments.map(attachment => { // xss-safe-factory
attachment.msgId = msgId;
return this.view.factory!.embeddedAtta(attachment, isEncrypted, this.view.parentTabId);
return this.view.factory!.embeddedAttachment(attachment, isEncrypted, this.view.parentTabId);
}).join('')).css('display', 'block');
}
}

private renderReplySuccessMimeAtts = (attachmentsFilenames: string[]) => {
private renderReplySuccessMimeAttachments = (attachmentsFilenames: string[]) => {
const attachments = $('<div id="attachments"></div>');
for (const index in attachmentsFilenames) {
if (attachmentsFilenames.hasOwnProperty(index)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export class ComposeSendBtnModule extends ViewModule<ComposeView> {
}

public renderUploadProgress = (progress: number | undefined, progressRepresents: 'FIRST-HALF' | 'SECOND-HALF' | 'EVERYTHING') => {
if (progress && this.view.attsModule.attach.hasAtt()) {
if (progress && this.view.attachmentsModule.attachment.hasAttachment()) {
if (progressRepresents === 'FIRST-HALF') {
progress = Math.floor(progress / 2); // show 0-50% instead of 0-100%
} else if (progressRepresents === 'SECOND-HALF') {
Expand Down Expand Up @@ -149,7 +149,7 @@ export class ComposeSendBtnModule extends ViewModule<ComposeView> {
msg.attachments.push(...imgAttachments);
}
if (this.view.myPubkeyModule.shouldAttach()) {
msg.attachments.push(Attachment.keyinfoAsPubkeyAtt(senderKi));
msg.attachments.push(Attachment.keyinfoAsPubkeyAttachment(senderKi));
}
await this.addNamesToMsg(msg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ export class ComposeSizeModule extends ViewModule<ComposeView> {
if (updateRefBodyHeight || !this.refBodyHeight) {
this.refBodyHeight = this.view.S.cached('body').height() || 605;
}
const attListHeight = this.view.S.cached('fineuploader').height() || 0;
const attachmentListHeight = this.view.S.cached('fineuploader').height() || 0;
const inputTextVerticalPadding = parseInt(this.view.S.cached('input_text').css('padding-top')) + parseInt(this.view.S.cached('input_text').css('padding-bottom'));
const iconShowPrevMsgHeight = this.view.S.cached('triple_dot').outerHeight(true) || 0;
this.view.S.cached('input_text').css('height', this.refBodyHeight - cellHeightExceptText - attListHeight - inputTextVerticalPadding - iconShowPrevMsgHeight);
this.view.S.cached('input_text').css('height', this.refBodyHeight - cellHeightExceptText - attachmentListHeight - inputTextVerticalPadding - iconShowPrevMsgHeight);
}
}

Expand Down
Loading