mirror of
https://github.com/thelounge/thelounge
synced 2024-11-11 07:04:18 +00:00
Fix protocol-aware urls, add better link validation in previews
This commit is contained in:
parent
15c14c6dea
commit
629ae8bfa4
5 changed files with 78 additions and 9 deletions
|
@ -25,11 +25,18 @@ function findLinks(text) {
|
|||
return [];
|
||||
}
|
||||
|
||||
return matches.map((url) => ({
|
||||
start: url.index,
|
||||
end: url.lastIndex,
|
||||
link: url.url,
|
||||
}));
|
||||
return matches.map((url) => {
|
||||
// Prefix protocol to protocol-aware urls
|
||||
if (url.schema === "//") {
|
||||
url.url = `http:${url.url}`;
|
||||
}
|
||||
|
||||
return {
|
||||
start: url.index,
|
||||
end: url.lastIndex,
|
||||
link: url.url,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = findLinks;
|
||||
|
|
|
@ -11,7 +11,6 @@ const findLinks = require("../../../client/js/libs/handlebars/ircmessageparser/f
|
|||
const storage = require("../storage");
|
||||
|
||||
const mediaTypeRegex = /^(audio|video)\/.+/;
|
||||
const linkRegex = /^https?:\/\//;
|
||||
|
||||
// Fix ECDH curve client compatibility in Node v8/v9
|
||||
// This is fixed in Node 10, but The Lounge supports LTS versions
|
||||
|
@ -34,7 +33,7 @@ module.exports = function(client, chan, msg) {
|
|||
const cleanText = cleanIrcMessage(msg.text);
|
||||
|
||||
// We will only try to prefetch http(s) links
|
||||
const links = findLinks(cleanText).filter((w) => linkRegex.test(w.link));
|
||||
const links = findLinks(cleanText).filter((w) => isValidLink(w.link));
|
||||
|
||||
if (links.length === 0) {
|
||||
return;
|
||||
|
@ -99,7 +98,7 @@ function parseHtml(preview, res, client) {
|
|||
}
|
||||
|
||||
// Make sure thumbnail is a valid url
|
||||
if (!linkRegex.test(preview.thumb)) {
|
||||
if (!isValidLink(preview.thumb)) {
|
||||
preview.thumb = "";
|
||||
}
|
||||
|
||||
|
@ -364,3 +363,24 @@ function fetch(uri, headers, cb) {
|
|||
function normalizeURL(header) {
|
||||
return URI(header).normalize().toString();
|
||||
}
|
||||
|
||||
function isValidLink(link) {
|
||||
try {
|
||||
const uri = URI(link);
|
||||
const protocol = uri.protocol();
|
||||
|
||||
// Only fetch http and https links
|
||||
if (protocol !== "http" && protocol !== "https") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do not fetch links without hostname or ones that contain authorization
|
||||
if (!uri.hostname() || uri.username() || uri.password()) {
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -290,4 +290,17 @@ describe("findLinks", () => {
|
|||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should add protocol to protocol-aware urls", () => {
|
||||
const input = "//example.com";
|
||||
const expected = [{
|
||||
link: "http://example.com",
|
||||
start: 0,
|
||||
end: 13,
|
||||
}];
|
||||
|
||||
const actual = findLinks(input);
|
||||
|
||||
expect(actual).to.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ describe("parse Handlebars helper", () => {
|
|||
it("should not introduce xss", () => {
|
||||
const testCases = [{
|
||||
input: "<img onerror='location.href=\"//youtube.com\"'>",
|
||||
expected: "<img onerror='location.href="<a href=\"//youtube.com\" target=\"_blank\" rel=\"noopener\">//youtube.com</a>"'>",
|
||||
expected: "<img onerror='location.href="<a href=\"http://youtube.com\" target=\"_blank\" rel=\"noopener\">//youtube.com</a>"'>",
|
||||
}, {
|
||||
input: '#&">bug',
|
||||
expected: '<span class="inline-channel" role="button" tabindex="0" data-chan="#&">bug">#&">bug</span>',
|
||||
|
|
|
@ -371,4 +371,33 @@ describe("Link plugin", function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should fetch protocol-aware links", function(done) {
|
||||
const message = this.irc.createMessage({
|
||||
text: "//localhost:9002",
|
||||
});
|
||||
|
||||
link(this.irc, this.network.channels[0], message);
|
||||
|
||||
this.irc.once("msg:preview", function(data) {
|
||||
expect(data.preview.link).to.equal("http://localhost:9002");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("should not try to fetch links with wrong protocol", function() {
|
||||
const message = this.irc.createMessage({
|
||||
text: "ssh://example.com ftp://example.com irc://example.com http:////////example.com",
|
||||
});
|
||||
|
||||
expect(message.previews).to.be.empty;
|
||||
});
|
||||
|
||||
it("should not try to fetch links with username or password", function() {
|
||||
const message = this.irc.createMessage({
|
||||
text: "http://root:'some%pass'@hostname/database http://a:%p@c http://a:%p@example.com http://test@example.com",
|
||||
});
|
||||
|
||||
expect(message.previews).to.be.empty;
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue