Commit 86593dc3 authored by JC Brand's avatar JC Brand

Don't render http (i.e. non-TLS) resources

Causes "Mixed Content" TLS errors
parent e07bb52d
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
## 4.0.6 (unreleased) ## 4.0.6 (unreleased)
- Don't render http (i.e. non-TLS) resources
- #1331 Fix missing checkmarks in old muc messages - #1331 Fix missing checkmarks in old muc messages
## 4.0.5 (2018-11-15) ## 4.0.5 (2018-11-15)
......
...@@ -94990,7 +94990,7 @@ _headless_utils_core__WEBPACK_IMPORTED_MODULE_16__["default"].isAudioURL = funct ...@@ -94990,7 +94990,7 @@ _headless_utils_core__WEBPACK_IMPORTED_MODULE_16__["default"].isAudioURL = funct
const filename = url.filename().toLowerCase(); const filename = url.filename().toLowerCase();
if (!_headless_lodash_noconflict__WEBPACK_IMPORTED_MODULE_1___default.a.includes(["https", "http"], url.protocol().toLowerCase())) { if (url.protocol().toLowerCase() !== "https") {
return false; return false;
} }
...@@ -95004,7 +95004,7 @@ _headless_utils_core__WEBPACK_IMPORTED_MODULE_16__["default"].isImageURL = funct ...@@ -95004,7 +95004,7 @@ _headless_utils_core__WEBPACK_IMPORTED_MODULE_16__["default"].isImageURL = funct
const filename = url.filename().toLowerCase(); const filename = url.filename().toLowerCase();
if (!_headless_lodash_noconflict__WEBPACK_IMPORTED_MODULE_1___default.a.includes(["https", "http"], url.protocol().toLowerCase())) { if (url.protocol().toLowerCase() !== "https") {
return false; return false;
} }
...@@ -95018,7 +95018,7 @@ _headless_utils_core__WEBPACK_IMPORTED_MODULE_16__["default"].isVideoURL = funct ...@@ -95018,7 +95018,7 @@ _headless_utils_core__WEBPACK_IMPORTED_MODULE_16__["default"].isVideoURL = funct
const filename = url.filename().toLowerCase(); const filename = url.filename().toLowerCase();
if (!_headless_lodash_noconflict__WEBPACK_IMPORTED_MODULE_1___default.a.includes(["https", "http"], url.protocol().toLowerCase())) { if (url.protocol().toLowerCase() !== "https") {
return false; return false;
} }
...@@ -271,6 +271,8 @@ ...@@ -271,6 +271,8 @@
it("is uploaded and sent out", mock.initConverseWithAsync( it("is uploaded and sent out", mock.initConverseWithAsync(
async function (done, _converse) { async function (done, _converse) {
const base_url = 'https://conversejs.org';
await test_utils.waitUntilDiscoConfirmed( await test_utils.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],
...@@ -310,7 +312,6 @@ ...@@ -310,7 +312,6 @@
`xmlns="urn:xmpp:http:upload:0"/>`+ `xmlns="urn:xmpp:http:upload:0"/>`+
`</iq>`); `</iq>`);
var base_url = document.URL.split(window.location.pathname)[0];
var message = base_url+"/logo/conversejs-filled.svg"; var message = base_url+"/logo/conversejs-filled.svg";
var stanza = Strophe.xmlHtmlNode( var stanza = Strophe.xmlHtmlNode(
...@@ -366,8 +367,8 @@ ...@@ -366,8 +367,8 @@
// Check that the image renders // Check that the image renders
expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual( expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual(
`<!-- src/templates/image.html -->\n`+ `<!-- src/templates/image.html -->\n`+
`<a href="${window.location.origin}/logo/conversejs-filled.svg" target="_blank" rel="noopener">`+ `<a href="${base_url}/logo/conversejs-filled.svg" target="_blank" rel="noopener">`+
`<img class="chat-image img-thumbnail" src="${window.location.origin}/logo/conversejs-filled.svg">`+ `<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg">`+
`</a>`); `</a>`);
XMLHttpRequest.prototype.send = send_backup; XMLHttpRequest.prototype.send = send_backup;
done(); done();
...@@ -376,6 +377,7 @@ ...@@ -376,6 +377,7 @@
it("is uploaded and sent out from a groupchat", mock.initConverseWithAsync( it("is uploaded and sent out from a groupchat", mock.initConverseWithAsync(
async function (done, _converse) { async function (done, _converse) {
const base_url = 'https://conversejs.org';
await test_utils.waitUntilDiscoConfirmed( await test_utils.waitUntilDiscoConfirmed(
_converse, _converse.domain, _converse, _converse.domain,
[{'category': 'server', 'type':'IM'}], [{'category': 'server', 'type':'IM'}],
...@@ -412,7 +414,6 @@ ...@@ -412,7 +414,6 @@
`xmlns="urn:xmpp:http:upload:0"/>`+ `xmlns="urn:xmpp:http:upload:0"/>`+
`</iq>`); `</iq>`);
var base_url = document.URL.split(window.location.pathname)[0];
var message = base_url+"/logo/conversejs-filled.svg"; var message = base_url+"/logo/conversejs-filled.svg";
var stanza = Strophe.xmlHtmlNode( var stanza = Strophe.xmlHtmlNode(
...@@ -469,8 +470,8 @@ ...@@ -469,8 +470,8 @@
// Check that the image renders // Check that the image renders
expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual( expect(view.el.querySelector('.chat-msg .chat-msg__media').innerHTML.trim()).toEqual(
`<!-- src/templates/image.html -->\n`+ `<!-- src/templates/image.html -->\n`+
`<a href="${window.location.origin}/logo/conversejs-filled.svg" target="_blank" rel="noopener">`+ `<a href="${base_url}/logo/conversejs-filled.svg" target="_blank" rel="noopener">`+
`<img class="chat-image img-thumbnail" src="${window.location.origin}/logo/conversejs-filled.svg">`+ `<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg">`+
`</a>`); `</a>`);
XMLHttpRequest.prototype.send = send_backup; XMLHttpRequest.prototype.send = send_backup;
done(); done();
...@@ -642,7 +643,7 @@ ...@@ -642,7 +643,7 @@
`xmlns="urn:xmpp:http:upload:0"/>`+ `xmlns="urn:xmpp:http:upload:0"/>`+
`</iq>`); `</iq>`);
const base_url = document.URL.split(window.location.pathname)[0]; const base_url = 'https://conversejs.org';
const message = base_url+"/logo/conversejs-filled.svg"; const message = base_url+"/logo/conversejs-filled.svg";
const stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
"<iq from='upload.montague.tld'"+ "<iq from='upload.montague.tld'"+
......
...@@ -967,7 +967,7 @@ ...@@ -967,7 +967,7 @@
test_utils.createContacts(_converse, 'current', 1); test_utils.createContacts(_converse, 'current', 1);
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const base_url = document.URL.split(window.location.pathname)[0]; let base_url = 'https://conversejs.org';
let message = base_url+"/logo/conversejs-filled.svg"; let message = base_url+"/logo/conversejs-filled.svg";
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
await test_utils.openChatBoxFor(_converse, contact_jid); await test_utils.openChatBoxFor(_converse, contact_jid);
...@@ -999,6 +999,13 @@ ...@@ -999,6 +999,13 @@
msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text'); msg = $(view.el).find('.chat-content').find('.chat-msg').last().find('.chat-msg__text');
expect(msg[0].textContent.trim()).toEqual('hello world'); expect(msg[0].textContent.trim()).toEqual('hello world');
expect(msg[0].querySelectorAll('img').length).toEqual(2); expect(msg[0].querySelectorAll('img').length).toEqual(2);
// Non-https images aren't rendered
base_url = document.URL.split(window.location.pathname)[0];
message = base_url+"/logo/conversejs-filled.svg";
expect(view.el.querySelectorAll('img').length).toBe(4);
test_utils.sendMessage(view, message);
expect(view.el.querySelectorAll('img').length).toBe(4);
done(); done();
})); }));
...@@ -1795,7 +1802,7 @@ ...@@ -1795,7 +1802,7 @@
" type='chat'"+ " type='chat'"+
" to='dummy@localhost/resource'>"+ " to='dummy@localhost/resource'>"+
" <body>Have you heard this funny audio?</body>"+ " <body>Have you heard this funny audio?</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>"+ " <x xmlns='jabber:x:oob'><url>https://localhost/audio.mp3</url></x>"+
"</message>").firstChild "</message>").firstChild
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await new Promise((resolve, reject) => view.once('messageInserted', resolve));
...@@ -1805,16 +1812,16 @@ ...@@ -1805,16 +1812,16 @@
let media = view.el.querySelector('.chat-msg .chat-msg__media'); let media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/audio.html -->'+ '<!-- src/templates/audio.html -->'+
'<audio controls="" src="http://localhost/audio.mp3"></audio>'+ '<audio controls="" src="https://localhost/audio.mp3"></audio>'+
'<a target="_blank" rel="noopener" href="http://localhost/audio.mp3">Download audio file "audio.mp3"</a>'); '<a target="_blank" rel="noopener" href="https://localhost/audio.mp3">Download audio file "audio.mp3"</a>');
// If the <url> and <body> contents is the same, don't duplicate. // If the <url> and <body> contents is the same, don't duplicate.
stanza = Strophe.xmlHtmlNode( stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+ "<message from='"+contact_jid+"'"+
" type='chat'"+ " type='chat'"+
" to='dummy@localhost/resource'>"+ " to='dummy@localhost/resource'>"+
" <body>http://localhost/audio.mp3</body>"+ " <body>https://localhost/audio.mp3</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/audio.mp3</url></x>"+ " <x xmlns='jabber:x:oob'><url>https://localhost/audio.mp3</url></x>"+
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await new Promise((resolve, reject) => view.once('messageInserted', resolve));
...@@ -1823,8 +1830,8 @@ ...@@ -1823,8 +1830,8 @@
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media'); media = view.el.querySelector('.chat-msg:last-child .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/audio.html -->'+ '<!-- src/templates/audio.html -->'+
'<audio controls="" src="http://localhost/audio.mp3"></audio>'+ '<audio controls="" src="https://localhost/audio.mp3"></audio>'+
'<a target="_blank" rel="noopener" href="http://localhost/audio.mp3">Download audio file "audio.mp3"</a>' '<a target="_blank" rel="noopener" href="https://localhost/audio.mp3">Download audio file "audio.mp3"</a>'
); );
done(); done();
})); }));
...@@ -1846,7 +1853,7 @@ ...@@ -1846,7 +1853,7 @@
" type='chat'"+ " type='chat'"+
" to='dummy@localhost/resource'>"+ " to='dummy@localhost/resource'>"+
" <body>Have you seen this funny video?</body>"+ " <body>Have you seen this funny video?</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>"+ " <x xmlns='jabber:x:oob'><url>https://localhost/video.mp4</url></x>"+
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg video').length, 2000) await test_utils.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg video').length, 2000)
...@@ -1855,16 +1862,16 @@ ...@@ -1855,16 +1862,16 @@
let media = view.el.querySelector('.chat-msg .chat-msg__media'); let media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/video.html -->'+ '<!-- src/templates/video.html -->'+
'<video controls="" src="http://localhost/video.mp4" style="max-height: 50vh"></video>'+ '<video controls="" src="https://localhost/video.mp4" style="max-height: 50vh"></video>'+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file "video.mp4"</a>'); '<a target="_blank" rel="noopener" href="https://localhost/video.mp4">Download video file "video.mp4"</a>');
// If the <url> and <body> contents is the same, don't duplicate. // If the <url> and <body> contents is the same, don't duplicate.
stanza = Strophe.xmlHtmlNode( stanza = Strophe.xmlHtmlNode(
"<message from='"+contact_jid+"'"+ "<message from='"+contact_jid+"'"+
" type='chat'"+ " type='chat'"+
" to='dummy@localhost/resource'>"+ " to='dummy@localhost/resource'>"+
" <body>http://localhost/video.mp4</body>"+ " <body>https://localhost/video.mp4</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/video.mp4</url></x>"+ " <x xmlns='jabber:x:oob'><url>https://localhost/video.mp4</url></x>"+
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await new Promise((resolve, reject) => view.once('messageInserted', resolve));
...@@ -1873,8 +1880,8 @@ ...@@ -1873,8 +1880,8 @@
media = view.el.querySelector('.chat-msg:last-child .chat-msg__media'); media = view.el.querySelector('.chat-msg:last-child .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/video.html -->'+ '<!-- src/templates/video.html -->'+
'<video controls="" src="http://localhost/video.mp4" style="max-height: 50vh"></video>'+ '<video controls="" src="https://localhost/video.mp4" style="max-height: 50vh"></video>'+
'<a target="_blank" rel="noopener" href="http://localhost/video.mp4">Download video file "video.mp4"</a>'); '<a target="_blank" rel="noopener" href="https://localhost/video.mp4">Download video file "video.mp4"</a>');
done(); done();
})); }));
...@@ -1894,7 +1901,7 @@ ...@@ -1894,7 +1901,7 @@
" type='chat'"+ " type='chat'"+
" to='dummy@localhost/resource'>"+ " to='dummy@localhost/resource'>"+
" <body>Have you downloaded this funny file?</body>"+ " <body>Have you downloaded this funny file?</body>"+
" <x xmlns='jabber:x:oob'><url>http://localhost/funny.pdf</url></x>"+ " <x xmlns='jabber:x:oob'><url>https://localhost/funny.pdf</url></x>"+
"</message>").firstChild; "</message>").firstChild;
_converse.connection._dataRecv(test_utils.createRequest(stanza)); _converse.connection._dataRecv(test_utils.createRequest(stanza));
await new Promise((resolve, reject) => view.once('messageInserted', resolve)); await new Promise((resolve, reject) => view.once('messageInserted', resolve));
...@@ -1904,7 +1911,7 @@ ...@@ -1904,7 +1911,7 @@
const media = view.el.querySelector('.chat-msg .chat-msg__media'); const media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
'<!-- src/templates/file.html -->'+ '<!-- src/templates/file.html -->'+
'<a target="_blank" rel="noopener" href="http://localhost/funny.pdf">Download file "funny.pdf"</a>'); '<a target="_blank" rel="noopener" href="https://localhost/funny.pdf">Download file "funny.pdf"</a>');
done(); done();
})); }));
...@@ -1913,6 +1920,7 @@ ...@@ -1913,6 +1920,7 @@
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
function (done, _converse) { function (done, _converse) {
const base_url = 'https://conversejs.org';
test_utils.createContacts(_converse, 'current'); test_utils.createContacts(_converse, 'current');
_converse.emit('rosterContactsFetched'); _converse.emit('rosterContactsFetched');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
...@@ -1921,7 +1929,6 @@ ...@@ -1921,7 +1929,6 @@
.then(() => { .then(() => {
view = _converse.chatboxviews.get(contact_jid); view = _converse.chatboxviews.get(contact_jid);
spyOn(view.model, 'sendMessage').and.callThrough(); spyOn(view.model, 'sendMessage').and.callThrough();
const base_url = document.URL.split(window.location.pathname)[0];
const url = base_url+"/logo/conversejs-filled.svg"; const url = base_url+"/logo/conversejs-filled.svg";
const stanza = Strophe.xmlHtmlNode( const stanza = Strophe.xmlHtmlNode(
...@@ -1939,8 +1946,8 @@ ...@@ -1939,8 +1946,8 @@
const media = view.el.querySelector('.chat-msg .chat-msg__media'); const media = view.el.querySelector('.chat-msg .chat-msg__media');
expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual( expect(media.innerHTML.replace(/(\r\n|\n|\r)/gm, "")).toEqual(
`<!-- src/templates/image.html -->`+ `<!-- src/templates/image.html -->`+
`<a href="${window.location.origin}/logo/conversejs-filled.svg" target="_blank" rel="noopener">`+ `<a href="${base_url}/logo/conversejs-filled.svg" target="_blank" rel="noopener">`+
`<img class="chat-image img-thumbnail" src="${window.location.origin}/logo/conversejs-filled.svg">`+ `<img class="chat-image img-thumbnail" src="${base_url}/logo/conversejs-filled.svg">`+
`</a>`); `</a>`);
done(); done();
}).catch(_.partial(console.error, _)); }).catch(_.partial(console.error, _));
......
...@@ -78,7 +78,7 @@ u.isAudioURL = function (url) { ...@@ -78,7 +78,7 @@ u.isAudioURL = function (url) {
url = new URI(url); url = new URI(url);
} }
const filename = url.filename().toLowerCase(); const filename = url.filename().toLowerCase();
if (!_.includes(["https", "http"], url.protocol().toLowerCase())) { if (url.protocol().toLowerCase() !== "https") {
return false; return false;
} }
return filename.endsWith('.ogg') || filename.endsWith('.mp3') || filename.endsWith('.m4a'); return filename.endsWith('.ogg') || filename.endsWith('.mp3') || filename.endsWith('.m4a');
...@@ -90,7 +90,7 @@ u.isImageURL = function (url) { ...@@ -90,7 +90,7 @@ u.isImageURL = function (url) {
url = new URI(url); url = new URI(url);
} }
const filename = url.filename().toLowerCase(); const filename = url.filename().toLowerCase();
if (!_.includes(["https", "http"], url.protocol().toLowerCase())) { if (url.protocol().toLowerCase() !== "https") {
return false; return false;
} }
return filename.endsWith('.jpg') || filename.endsWith('.jpeg') || return filename.endsWith('.jpg') || filename.endsWith('.jpeg') ||
...@@ -105,7 +105,7 @@ u.isVideoURL = function (url) { ...@@ -105,7 +105,7 @@ u.isVideoURL = function (url) {
url = new URI(url); url = new URI(url);
} }
const filename = url.filename().toLowerCase(); const filename = url.filename().toLowerCase();
if (!_.includes(["https", "http"], url.protocol().toLowerCase())) { if (url.protocol().toLowerCase() !== "https") {
return false; return false;
} }
return filename.endsWith('.mp4') || filename.endsWith('.webm'); return filename.endsWith('.mp4') || filename.endsWith('.webm');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment