Add option to disable media preview.

This disables image previews iff prefetchStorage is disabled. This
stops the client from making any requests to third-party sites.
This commit is contained in:
Dexter Chua 2020-07-12 10:04:04 +08:00
parent 0ac1fcb471
commit 2f434be75d
3 changed files with 103 additions and 5 deletions

View file

@ -110,6 +110,18 @@ module.exports = {
// This value is set to `false` by default.
prefetch: false,
// ### `disableMediaPreview`
//
// When set to `true`, The Lounge will not preview media (images, video and
// audio) hosted on third-party sites. This ensures the client does not
// make any requests to external sites. If `prefetchStorage` is enabled,
// images proxied via the The Lounge will be previewed.
//
// This has no effect if `prefetch` is set to `false`.
//
// This value is set to `false` by default.
disableMediaPreview: false,
// ### `prefetchStorage`
// When set to `true`, The Lounge will store and proxy prefetched images and

View file

@ -84,11 +84,6 @@ function parseHtml(preview, res, client) {
$('meta[property="og:description"]').attr("content") ||
$('meta[name="description"]').attr("content") ||
"";
let thumb =
$('meta[property="og:image"]').attr("content") ||
$('meta[name="twitter:image:src"]').attr("content") ||
$('link[rel="image_src"]').attr("href") ||
"";
if (preview.head.length) {
preview.head = preview.head.substr(0, 100);
@ -98,6 +93,17 @@ function parseHtml(preview, res, client) {
preview.body = preview.body.substr(0, 300);
}
if (!Helper.config.prefetchStorage && Helper.config.disableMediaPreview) {
resolve(res);
return;
}
let thumb =
$('meta[property="og:image"]').attr("content") ||
$('meta[name="twitter:image:src"]').attr("content") ||
$('link[rel="image_src"]').attr("href") ||
"";
// Make sure thumbnail is a valid and absolute url
if (thumb.length) {
thumb = normalizeURL(thumb, preview.link) || "";
@ -127,6 +133,10 @@ function parseHtml(preview, res, client) {
function parseHtmlMedia($, preview, client) {
return new Promise((resolve, reject) => {
if (Helper.config.disableMediaPreview) {
reject();
}
let foundMedia = false;
["video", "audio"].forEach((type) => {
@ -203,6 +213,10 @@ function parse(msg, chan, preview, res, client) {
case "image/jpg":
case "image/jpeg":
case "image/webp":
if (!Helper.config.prefetchStorage && Helper.config.disableMediaPreview) {
return removePreview(msg, preview);
}
if (res.size > Helper.config.prefetchMaxImageSize * 1024) {
preview.type = "error";
preview.error = "image-too-big";
@ -228,6 +242,10 @@ function parse(msg, chan, preview, res, client) {
break;
}
if (Helper.config.disableMediaPreview) {
return removePreview(msg, preview);
}
preview.type = "audio";
preview.media = preview.link;
preview.mediaType = res.type;
@ -241,6 +259,10 @@ function parse(msg, chan, preview, res, client) {
break;
}
if (Helper.config.disableMediaPreview) {
return removePreview(msg, preview);
}
preview.type = "video";
preview.media = preview.link;
preview.mediaType = res.type;

View file

@ -222,6 +222,70 @@ Vivamus bibendum vulputate tincidunt. Sed vitae ligula felis.`;
});
});
describe("test disableMediaPreview", function () {
beforeEach(function (done) {
Helper.config.disableMediaPreview = true;
done();
});
afterEach(function (done) {
Helper.config.disableMediaPreview = false;
done();
});
it("should ignore og:image if disableMediaPreview", function (done) {
const port = this.port;
app.get("/nonexistent-test-image.png", function () {
throw "Should not fetch image";
});
app.get("/thumb", function (req, res) {
res.send(
"<title>Google</title><meta property='og:image' content='http://localhost:" +
port +
"/nonexistent-test-image.png'>"
);
});
const message = this.irc.createMessage({
text: "http://localhost:" + port + "/thumb",
});
link(this.irc, this.network.channels[0], message);
this.irc.once("msg:preview", function (data) {
expect(data.preview.head).to.equal("Google");
expect(data.preview.type).to.equal("link");
expect(data.preview.thumb).to.equal("");
done();
});
});
it("should ignore og:video if disableMediaPreview", function (done) {
const port = this.port;
app.get("/nonexistent-video.mpr", function () {
throw "Should not fetch video";
});
app.get("/thumb", function (req, res) {
res.send(
"<title>Google</title><meta property='og:video:type' content='video/mp4'><meta property='og:video' content='http://localhost:" +
port +
"/nonexistent-video.mp4'>"
);
});
const message = this.irc.createMessage({
text: "http://localhost:" + port + "/thumb",
});
link(this.irc, this.network.channels[0], message);
this.irc.once("msg:preview", function (data) {
expect(data.preview.head).to.equal("Google");
expect(data.preview.type).to.equal("link");
done();
});
});
});
it("should find image_src", function (done) {
const port = this.port;
const message = this.irc.createMessage({