Only inline image paths referenced via cid: in <img src=“”>

This commit is contained in:
Ben Gotow 2022-10-09 20:49:13 -05:00
parent 35e35c034c
commit 17363b4442
2 changed files with 16 additions and 16 deletions

View file

@ -18,6 +18,9 @@ import { BrowserWindow } from '@electron/remote';
const TransparentPixel =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNikAQAACIAHF/uBd8AAAAASUVORK5CYII=';
const SpinnerImg =
'<img alt="spinner.gif" src="mailspring://message-list/assets/spinner.gif" style="-webkit-user-drag: none;">';
class ConditionalQuotedTextControl extends React.Component<{ body: string; onClick?: () => void }> {
static displayName = 'ConditionalQuotedTextControl';
@ -134,7 +137,7 @@ export default class MessageItemBody extends React.Component<
win.loadURL(`file://${filepath}`);
};
_mergeBodyWithFiles(body) {
_mergeBodyWithFiles(body: string) {
let merged = body;
// Replace cid: references with the paths to downloaded files
@ -146,21 +149,18 @@ export default class MessageItemBody extends React.Component<
// Note: I don't like doing this with RegExp before the body is inserted into
// the DOM, but we want to avoid "could not load cid://" in the console.
if (download && download.state !== 'finished') {
const inlineImgRegexp = new RegExp(
`<\\s*img.*src=['"]cid:${safeContentId}['"][^>]*>`,
`<\\s*img[^>/]*src=['"]cid:${safeContentId}['"][^>]*>`,
'gi'
);
if (download && download.state !== 'finished') {
// Render a spinner
merged = merged.replace(
inlineImgRegexp,
() =>
'<img alt="spinner.gif" src="mailspring://message-list/assets/spinner.gif" style="-webkit-user-drag: none;">'
);
merged = merged.replace(inlineImgRegexp, () => SpinnerImg);
} else {
const cidRegexp = new RegExp(`cid:${safeContentId}(@[^'"]+)?`, 'gi');
merged = merged.replace(cidRegexp, `file://${AttachmentStore.pathForFile(file)}`);
merged = merged.replace(inlineImgRegexp, match =>
match.replace(`cid:${file.contentId}`, `file://${AttachmentStore.pathForFile(file)}`)
);
}
});

View file

@ -45,7 +45,7 @@ Any `props` added to the <EventedIFrame> are passed to the iFrame it renders.
Section: Component Kit
*/
export class EventedIFrame extends React.Component<
EventedIFrameProps & React.HTMLProps<HTMLDivElement>
EventedIFrameProps & React.HTMLProps<HTMLIFrameElement>
> {
static displayName = 'EventedIFrame';
@ -354,14 +354,14 @@ export class EventedIFrame extends React.Component<
new MenuItem({
label: localized('Save Image') + '...',
click() {
AppEnv.showSaveDialog({ defaultPath: srcFilename }, function (path) {
AppEnv.showSaveDialog({ defaultPath: srcFilename }, function(path) {
if (!path) {
return;
}
const oReq = new XMLHttpRequest();
oReq.open('GET', src, true);
oReq.responseType = 'arraybuffer';
oReq.onload = function () {
oReq.onload = function() {
const buffer = Buffer.from(new Uint8Array(oReq.response));
fs.writeFile(path, buffer, err => shell.showItemInFolder(path));
};
@ -377,7 +377,7 @@ export class EventedIFrame extends React.Component<
const img = new Image();
img.addEventListener(
'load',
function () {
function() {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;