Browse Source

adds option to whitelist image domains

Ariel Fuggini 4 năm trước cách đây
mục cha
commit
6adec9a8d2
4 tập tin đã thay đổi với 46 bổ sung21 xóa
  1. 3 0
      docs/source/configuration.rst
  2. 26 1
      spec/messages.js
  3. 3 3
      src/templates/directives/body.js
  4. 14 17
      src/utils/html.js

+ 3 - 0
docs/source/configuration.rst

@@ -1692,6 +1692,9 @@ show_images_inline
 
 If set to ``false``, images won't be rendered in chats, instead only their links will be shown.
 
+It also accepts an array strings of whitelisted domain names to only render images that belong to those domains.
+
+E.g. ``['imgur.com', 'imgbb.com']``
 
 show_retraction_warning
 -----------------------

+ 26 - 1
spec/messages.js

@@ -974,6 +974,7 @@ describe("A Chat Message", function () {
         expect(msg.textContent.trim()).toEqual('hello world');
         expect(msg.querySelectorAll('img').length).toEqual(2);
 
+        // @XXX This test isn't really testing anything - needs revisiting
         // Non-https images aren't rendered
         message = base_url+"/logo/conversejs-filled.svg";
         expect(view.content.querySelectorAll('img').length).toBe(4);
@@ -985,7 +986,31 @@ describe("A Chat Message", function () {
         message = 'http://imgur.com/xxxxxxx';
         mock.sendMessage(view, message);
         await u.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length === 5, 1000);
-        expect(view.content.querySelectorAll('img').length).toBe(5);
+        expect(view.content.querySelectorAll('.chat-content .chat-image').length).toBe(5);
+
+        done();
+    }));
+
+    it("will render images from approved URLs only",
+        mock.initConverse(
+            ['rosterGroupsFetched', 'chatBoxesFetched'], {},
+            async function (done, _converse) {
+
+        await mock.waitForRoster(_converse, 'current');
+        const base_url = 'https://conversejs.org';
+        let message = 'http://wrongdomain.com/xxxxxxx.png';
+        const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
+        await mock.openChatBoxFor(_converse, contact_jid);
+        _converse.api.settings.set('show_images_inline', ['conversejs.org']);
+        const view = _converse.api.chatviews.get(contact_jid);
+        spyOn(view.model, 'sendMessage').and.callThrough();
+        mock.sendMessage(view, message);
+        message = base_url+"/logo/conversejs-filled.svg";
+        mock.sendMessage(view, message);
+        await u.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-msg').length === 2, 1000);
+        await u.waitUntil(() => view.el.querySelectorAll('.chat-content .chat-image').length === 1, 1000)
+        expect(view.content.querySelectorAll('.chat-content .chat-image').length).toBe(1);
+
         done();
     }));
 

+ 3 - 3
src/templates/directives/body.js

@@ -120,9 +120,9 @@ function addHyperlinks (text, onImgLoad, onImgClick) {
         text.addTemplateResult(
             url_obj.start,
             url_obj.end,
-            show_images && u.isImageURL(url_text) ?
-                u.convertToImageTag(url_text, onImgLoad, onImgClick) :
-                u.convertUrlToHyperlink(url_text),
+            show_images && u.isImageURL(url_text) && u.isImageDomainAllowed(url_text)
+                ? u.convertToImageTag(url_text, onImgLoad, onImgClick)
+                : u.convertUrlToHyperlink(url_text)
         );
     });
 }

+ 14 - 17
src/utils/html.js

@@ -82,6 +82,18 @@ u.isImageURL = url => {
         ? regex.test(url)
         : checkFileTypes(['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.svg'], url);
 }
+u.isImageDomainAllowed = url => {
+    try {
+        const show_images_inline = api.settings.get('show_images_inline');
+        const is_domains_array = Array.isArray(show_images_inline);
+        if (!is_domains_array) return true;
+        const image_domain = getURI(url).domain();
+        return show_images_inline.includes(image_domain);
+    } catch (error) {
+        log.debug(error);
+        return true;
+    }
+}
 
 function getFileName (uri) {
     try {
@@ -294,24 +306,9 @@ u.escapeHTML = function (string) {
         .replace(/"/g, """);
 };
 
-
 u.convertToImageTag = function (url, onLoad, onClick) {
-    const uri = getURI(url);
-    const img_url_without_ext = ['imgur.com', 'pbs.twimg.com'].includes(uri.hostname());
-    if (u.isImageURL(url) || img_url_without_ext) {
-        if (img_url_without_ext) {
-            const format = (uri.hostname() === 'pbs.twimg.com') ? uri.search(true).format : 'png';
-            return tpl_image({
-                onClick,
-                onLoad,
-                'url': uri.removeSearch(/.*/).toString() + `.${format}`
-            });
-        } else {
-            return tpl_image({url, onClick, onLoad});
-        }
-    }
-}
-
+    return tpl_image({url, onClick, onLoad});
+};
 
 u.convertURIoHyperlink = function (uri, urlAsTyped) {
     let normalized_url = uri.normalize()._string;