[Libreoffice-commits] online.git: Branch 'distro/collabora/collabora-online-3' - 13 commits - kit/ChildSession.cpp loleaflet/dist loleaflet/src loolwsd.xml.in net/ServerSocket.hpp net/Socket.hpp wsd/DocumentBroker.cpp wsd/LOOLWSD.cpp wsd/protocol.txt wsd/Storage.cpp wsd/Storage.hpp

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Sep 11 18:36:42 UTC 2018


 kit/ChildSession.cpp                          |   13 ++++++--
 loleaflet/dist/toolbar/toolbar.js             |   14 ++++++++
 loleaflet/src/control/Control.Menubar.js      |   12 +++++++
 loleaflet/src/control/Toolbar.js              |    4 ++
 loleaflet/src/map/handler/Map.FileInserter.js |   29 +++++++++++++++++
 loleaflet/src/map/handler/Map.WOPI.js         |    9 +++++
 loolwsd.xml.in                                |    7 ++++
 net/ServerSocket.hpp                          |   31 +++++++++++++++++--
 net/Socket.hpp                                |    6 +++
 wsd/DocumentBroker.cpp                        |    2 +
 wsd/LOOLWSD.cpp                               |   42 ++++++++++++++++++++++++++
 wsd/Storage.cpp                               |    6 +++
 wsd/Storage.hpp                               |    8 ++++
 wsd/protocol.txt                              |    8 ++++
 14 files changed, 181 insertions(+), 10 deletions(-)

New commits:
commit 6d50bdf9f7d910e60800e33d8402bbba7857ace2
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sat Aug 18 20:37:51 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    loleaflet: wopi: add EnableShare
    
    Change-Id: I1a2a86e671f97891855cc2bd8d8047829e819508

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index e10501ae9..5fe17ada1 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -17,6 +17,7 @@ L.Control.Menubar = L.Control.extend({
 			{name: _UNO('.uno:PickList', 'text'), id: 'file', type: 'menu', menu: [
 				{name: _UNO('.uno:Save', 'text'), id: 'save', type: 'action'},
 				{name: _UNO('.uno:SaveAs', 'text'), id: 'saveas', type: 'action'},
+				{name: _('Share...'), id:'shareas', type: 'action'},
 				{name: _UNO('.uno:Print', 'text'), id: 'print', type: 'action'},
 				{name: _('See revision history'), id: 'rev-history', type: 'action'},
 				{name: _('Download as'), id: 'downloadas', type: 'menu', menu: [
@@ -666,6 +667,8 @@ L.Control.Menubar = L.Control.extend({
 			map.save(true, true);
 		} else if (id === 'saveas') {
 			map.fire('postMessage', {msgId: 'UI_SaveAs'});
+		} else if (id === 'shareas') {
+			map.fire('postMessage', {msgId: 'UI_Share'});
 		} else if (id === 'print') {
 			map.print();
 		} else if (id.startsWith('downloadas-')) {
@@ -805,6 +808,9 @@ L.Control.Menubar = L.Control.extend({
 			if (menu[i].id === 'saveas' && this._map['wopi'].UserCanNotWriteRelative)
 				continue;
 
+			if (menu[i].id === 'shareas' && !this._map['wopi'].EnableShare)
+				continue;
+
 			if (menu[i].id === 'insertgraphicremote' && !this._map['wopi'].EnableInsertRemoteImage)
 				continue;
 
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index cd31fce22..d291ae71f 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -20,6 +20,7 @@ L.Map.WOPI = L.Handler.extend({
 	DisableInactiveMessages: false,
 	UserCanNotWriteRelative: true,
 	EnableInsertRemoteImage: false,
+	EnableShare: false,
 	CallPythonScriptSource: null,
 
 	_appLoadedConditions: {
@@ -76,6 +77,7 @@ L.Map.WOPI = L.Handler.extend({
 		this.DisableInactiveMessages = !!wopiInfo['DisableInactiveMessages'];
 		this.UserCanNotWriteRelative = !!wopiInfo['UserCanNotWriteRelative'];
 		this.EnableInsertRemoteImage = !!wopiInfo['EnableInsertRemoteImage'];
+		this.EnableShare = !!wopiInfo['EnableShare'];
 
 		this._map.fire('postMessage', {
 			msgId: 'App_LoadingStatus',
commit 113071182ea85f9df001b9c59d57f9d79036d366
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sat Aug 18 20:17:25 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    wsd: wopi: introduce a "EnableShare" entry in the CheckFileInfo
    
    Change-Id: Ia47d7e8f5c8cd8ae1eb314467c664b27b50e7fd3

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 67c73c112..e01af9069 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -510,6 +510,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
         wopiInfo->set("DisableInactiveMessages", wopifileinfo->_disableInactiveMessages);
         wopiInfo->set("UserCanNotWriteRelative", wopifileinfo->_userCanNotWriteRelative);
         wopiInfo->set("EnableInsertRemoteImage", wopifileinfo->_enableInsertRemoteImage);
+        wopiInfo->set("EnableShare", wopifileinfo->_enableShare);
         if (wopifileinfo->_hideChangeTrackingControls != WopiStorage::WOPIFileInfo::TriState::Unset)
             wopiInfo->set("HideChangeTrackingControls", wopifileinfo->_hideChangeTrackingControls == WopiStorage::WOPIFileInfo::TriState::True);
 
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index acfc18408..3e2e23ad6 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -464,6 +464,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
     std::string lastModifiedTime;
     bool userCanNotWriteRelative = true;
     bool enableInsertRemoteImage = false;
+    bool enableShare = false;
     WOPIFileInfo::TriState disableChangeTrackingRecord = WOPIFileInfo::TriState::Unset;
     WOPIFileInfo::TriState disableChangeTrackingShow = WOPIFileInfo::TriState::Unset;
     WOPIFileInfo::TriState hideChangeTrackingControls = WOPIFileInfo::TriState::Unset;
@@ -543,6 +544,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
         JsonUtil::findJSONValue(object, "LastModifiedTime", lastModifiedTime);
         JsonUtil::findJSONValue(object, "UserCanNotWriteRelative", userCanNotWriteRelative);
         JsonUtil::findJSONValue(object, "EnableInsertRemoteImage", enableInsertRemoteImage);
+        JsonUtil::findJSONValue(object, "EnableShare", enableShare);
         bool booleanFlag = false;
         if (JsonUtil::findJSONValue(object, "DisableChangeTrackingRecord", booleanFlag))
             disableChangeTrackingRecord = (booleanFlag ? WOPIFileInfo::TriState::True : WOPIFileInfo::TriState::False);
@@ -570,7 +572,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
         {userId, obfuscatedUserId, userName, userExtraInfo, watermarkText, canWrite,
          postMessageOrigin, hidePrintOption, hideSaveOption, hideExportOption,
          enableOwnerTermination, disablePrint, disableExport, disableCopy,
-         disableInactiveMessages, userCanNotWriteRelative, enableInsertRemoteImage,
+         disableInactiveMessages, userCanNotWriteRelative, enableInsertRemoteImage, enableShare,
          disableChangeTrackingShow, disableChangeTrackingRecord,
          hideChangeTrackingControls, callDuration}));
 }
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index f1361996e..f061f818b 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -285,6 +285,7 @@ public:
                      const bool disableInactiveMessages,
                      const bool userCanNotWriteRelative,
                      const bool enableInsertRemoteImage,
+                     const bool enableShare,
                      const TriState disableChangeTrackingShow,
                      const TriState disableChangeTrackingRecord,
                      const TriState hideChangeTrackingControls,
@@ -305,6 +306,7 @@ public:
               _disableInactiveMessages(disableInactiveMessages),
               _userCanNotWriteRelative(userCanNotWriteRelative),
               _enableInsertRemoteImage(enableInsertRemoteImage),
+              _enableShare(enableShare),
               _disableChangeTrackingShow(disableChangeTrackingShow),
               _disableChangeTrackingRecord(disableChangeTrackingRecord),
               _hideChangeTrackingControls(hideChangeTrackingControls),
@@ -347,6 +349,8 @@ public:
         bool _userCanNotWriteRelative;
         /// if set to true, users can access the insert remote image functionality
         bool _enableInsertRemoteImage;
+        /// if set to true, users can access the file share functionality
+        bool _enableShare;
         /// If we should disable change-tracking visibility by default (meaningful at loading).
         TriState _disableChangeTrackingShow;
         /// If we should disable change-tracking ability by default (meaningful at loading).
commit 2fb4b0fb5a7add2d200ce72ae64504c6c3b49a67
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Wed Jul 18 17:54:45 2018 +0300
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    Allow also the IPv6 loopback address ::1
    
    Change-Id: I4e079095d0a599f36b1d48d7a1311db75e3d79bf

diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index de50d0b02..587452ba4 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -74,6 +74,7 @@
         <host desc="Ditto, but as IPv4-mapped IPv6 addresses">::ffff:192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
         <host desc="The IPv4 loopback (localhost) address.">127\.0\.0\.1</host>
         <host desc="Ditto, but as IPv4-mapped IPv6 address">::ffff:127\.0\.0\.1</host>
+        <host desc="The IPv6 loopback (localhost) address.">::1</host>
       </post_allow>
     </net>
 
commit 5a47102d75f7c2247fc8aca9b2c4c6f4d4967bd1
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Thu Jul 12 18:31:36 2018 +0300
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    Accept also localhost and IPv4-mapped IPv6 addresses
    
    Change-Id: Ifc295d164276c0dd17592ff27066a522482fe04a
    Reviewed-on: https://gerrit.libreoffice.org/57351
    Reviewed-by: Tor Lillqvist <tml at collabora.com>
    Tested-by: Tor Lillqvist <tml at collabora.com>

diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index b11966d7d..de50d0b02 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -70,7 +70,10 @@
       <proto type="string" default="all" desc="Protocol to use IPv4, IPv6 or all for both">all</proto>
       <service_root type="path" default="" desc="Prefix all the pages, websockets, etc. with this path."></service_root>
       <post_allow desc="Allow/deny client IP address for POST(REST)." allow="true">
-        <host desc="Regex pattern of ip address to allow.">192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
+        <host desc="The IPv4 private 192.168 block as plain IPv4 dotted decimal addresses.">192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
+        <host desc="Ditto, but as IPv4-mapped IPv6 addresses">::ffff:192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
+        <host desc="The IPv4 loopback (localhost) address.">127\.0\.0\.1</host>
+        <host desc="Ditto, but as IPv4-mapped IPv6 address">::ffff:127\.0\.0\.1</host>
       </post_allow>
     </net>
 
commit 3e3295c00cd587f42f521b104b4c25cb814e8285
Author:     Tor Lillqvist <tml at collabora.com>
AuthorDate: Tue Jul 10 22:50:11 2018 +0300
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    Fis our use of inet_ntop() etc
    
    We had:
        auto ipv4 = (struct sockaddr_in *)&clientInfo.sin_addr
    even if the clientInfo variable itself was a struct sockaddr_in.
    
    And then we also had:
        auto ipv6 = (struct sockaddr_in6 *)&clientInfo.sin_addr
    which makes even less sense.
    
    Instead, make clientInfo into a struct sockaddr_in6, which is big
    enough to also to be interpreted as a sockaddr_in. Pass the address of
    the correct field, either sin_addr or sin6_addr, to inet_ntop(). (Note
    that sin_addr in sockaddr_in has a different offset than sin6_addr in
    sockaddr_in6.)
    
    At least on my Fedora 28, when I connect using IPv4, accept4() still
    returns the client address as an IPv4 mapped IPv6 address, that is
    ::ffff:192.168.1.113 for 192.168.1.113. So the sample
    net.post_allow.host value in loolwsd.xml.in should probably be changed
    to have that ::ffff: prefix, too.
    
    Change-Id: I0ad774616b210d94b904982e2f7dc928adc879ed

diff --git a/net/ServerSocket.hpp b/net/ServerSocket.hpp
index afd4b97f4..f0ad38ad3 100644
--- a/net/ServerSocket.hpp
+++ b/net/ServerSocket.hpp
@@ -61,8 +61,8 @@ public:
     {
         // Accept a connection (if any) and set it to non-blocking.
         // There still need the client's address to filter request from POST(call from REST) here.
-        struct sockaddr_in clientInfo;
-        socklen_t addrlen = sizeof(struct sockaddr_in);
+        struct sockaddr_in6 clientInfo;
+        socklen_t addrlen = sizeof(clientInfo);
         const int rc = ::accept4(getFD(), (struct sockaddr *)&clientInfo, &addrlen, SOCK_NONBLOCK);
         LOG_DBG("Accepted socket #" << rc << ", creating socket object.");
         try
@@ -73,21 +73,21 @@ public:
                 char addrstr[INET6_ADDRSTRLEN];
 
                 const void *inAddr;
-                if (clientInfo.sin_family == AF_INET)
+                if (clientInfo.sin6_family == AF_INET)
                 {
-                    auto ipv4 = (struct sockaddr_in *)&clientInfo.sin_addr;
+                    auto ipv4 = (struct sockaddr_in *)&clientInfo;
                     inAddr = &(ipv4->sin_addr);
                 }
                 else
                 {
-                    auto ipv6 = (struct sockaddr_in6 *)&clientInfo.sin_addr;
+                    auto ipv6 = (struct sockaddr_in6 *)&clientInfo;
                     inAddr = &(ipv6->sin6_addr);
                 }
 
-                inet_ntop(clientInfo.sin_family, inAddr, addrstr, sizeof(addrstr));
+                inet_ntop(clientInfo.sin6_family, inAddr, addrstr, sizeof(addrstr));
                 std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
                 _socket->_clientAddress = addrstr;
-                LOG_DBG("Accepted socket has family " << clientInfo.sin_family <<
+                LOG_DBG("Accepted socket has family " << clientInfo.sin6_family <<
                         " address " << _socket->_clientAddress);
                 return _socket;
             }
commit 57d7bdfcf8cbb4699638e7d7852c3e6858b7586f
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Sun May 13 12:32:05 2018 +0100
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    Use inet_ntop for ipv6 address names.
    
    Change-Id: Ic52b69eb2dc86b6532a78d770531b2fac928fb28

diff --git a/net/ServerSocket.hpp b/net/ServerSocket.hpp
index abc018678..afd4b97f4 100644
--- a/net/ServerSocket.hpp
+++ b/net/ServerSocket.hpp
@@ -70,9 +70,25 @@ public:
             // Create a socket object using the factory.
             if (rc != -1)
             {
-                std::string ip = inet_ntoa(clientInfo.sin_addr);
+                char addrstr[INET6_ADDRSTRLEN];
+
+                const void *inAddr;
+                if (clientInfo.sin_family == AF_INET)
+                {
+                    auto ipv4 = (struct sockaddr_in *)&clientInfo.sin_addr;
+                    inAddr = &(ipv4->sin_addr);
+                }
+                else
+                {
+                    auto ipv6 = (struct sockaddr_in6 *)&clientInfo.sin_addr;
+                    inAddr = &(ipv6->sin6_addr);
+                }
+
+                inet_ntop(clientInfo.sin_family, inAddr, addrstr, sizeof(addrstr));
                 std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
-                _socket->_clientAddress = ip;
+                _socket->_clientAddress = addrstr;
+                LOG_DBG("Accepted socket has family " << clientInfo.sin_family <<
+                        " address " << _socket->_clientAddress);
                 return _socket;
             }
             return std::shared_ptr<Socket>(nullptr);
commit cd11971f92ae12fd3972344233c3d480c85076f8
Author:     Safir Depo <selimzcn at gmail.com>
AuthorDate: Mon May 14 16:36:03 2018 +0300
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    bugfix for commit:910ae80-'wsd: to filter clientAddress before POST action.'
    
    Change-Id: I48e6d89fc62c6a656d9e8a74f9f5f8be1d687940
    Reviewed-on: https://gerrit.libreoffice.org/54325
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 3850875c7..eca0644f6 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1797,7 +1797,7 @@ public:
             // Parse the host allow settings.
             for (size_t i = 0; ; ++i)
             {
-                const std::string path = "post_allow.host[" + std::to_string(i) + "]";
+                const std::string path = "net.post_allow.host[" + std::to_string(i) + "]";
                 const auto host = app.config().getString(path, "");
                 if (!host.empty())
                 {
commit 45d4b08ac0a7afbb158a4ce003dd69fb416b9d28
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Sun May 13 13:35:32 2018 +0100
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    Restrict convert-to to known hosts - not all insert / downloads.
    
    Change-Id: Ief26c80bf7e9e96f3c5dce0d8739a825f6fac629

diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index fe4ca7004..3850875c7 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1786,6 +1786,33 @@ public:
         StaticFileContentCache["discovery.xml"] = getDiscoveryXML();
     }
 
+    /// Does this address feature in the allowed hosts list.
+    bool allowPostFrom(const std::string &address)
+    {
+        static bool init = false;
+        static Util::RegexListMatcher hosts;
+        if (!init)
+        {
+            const auto& app = Poco::Util::Application::instance();
+            // Parse the host allow settings.
+            for (size_t i = 0; ; ++i)
+            {
+                const std::string path = "post_allow.host[" + std::to_string(i) + "]";
+                const auto host = app.config().getString(path, "");
+                if (!host.empty())
+                {
+                    LOG_INF("Adding trusted POST_ALLOW host: [" << host << "].");
+                    hosts.allow(host);
+                }
+                else if (!app.config().has(path))
+                {
+                    break;
+                }
+            }
+        }
+        return hosts.match(address);
+    }
+
 private:
 
     /// Set the socket associated with this ResponseClient.
@@ -1870,42 +1897,8 @@ private:
                 if (!(request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0) &&
                     reqPathTokens.count() > 0 && reqPathTokens[0] == "lool")
                 {
-                    // allow/deny for POST
-                    const auto& app = Poco::Util::Application::instance();
-                    Util::RegexListMatcher hosts;
-                    // Parse the host allow settings.
-                    for (size_t i = 0; ; ++i)
-                    {
-                        const std::string path = "post_allow.host[" + std::to_string(i) + "]";
-                        const auto host = app.config().getString(path, "");
-                        if (!host.empty())
-                        {
-                            LOG_INF("Adding trusted POST_ALLOW host: [" << host << "].");
-                            hosts.allow(host);
-                        }
-                        else if (!app.config().has(path))
-                        {
-                            break;
-                        }
-                    }
-                    if (!hosts.match(socket->clientAddress()))
-                    {
-                        LOG_ERR("client address DENY: " << socket->clientAddress().c_str());
-
-                        std::ostringstream oss;
-                        oss << "HTTP/1.1 403\r\n"
-                            << "Date: " << Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT) << "\r\n"
-                            << "User-Agent: " << HTTP_AGENT_STRING << "\r\n"
-                            << "Content-Length: 0\r\n"
-                            << "\r\n";
-                        socket->send(oss.str());
-                        socket->shutdown();
-                    }
-                    else
-                    {
-                        // All post requests have url prefix 'lool'.
-                        handlePostRequest(request, message, disposition);
-                    }
+                    // All post requests have url prefix 'lool'.
+                    handlePostRequest(request, message, disposition);
                 }
                 else if (reqPathTokens.count() > 2 && reqPathTokens[0] == "lool" && reqPathTokens[2] == "ws" &&
                          request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0)
@@ -2103,6 +2096,21 @@ private:
 
             std::string format = (form.has("format") ? form.get("format") : "");
 
+            if (!allowPostFrom(socket->clientAddress()))
+            {
+                LOG_ERR("client address DENY: " << socket->clientAddress().c_str());
+
+                std::ostringstream oss;
+                oss << "HTTP/1.1 403\r\n"
+                    << "Date: " << Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT) << "\r\n"
+                    << "User-Agent: " << HTTP_AGENT_STRING << "\r\n"
+                    << "Content-Length: 0\r\n"
+                    << "\r\n";
+                socket->send(oss.str());
+                socket->shutdown();
+                return;
+            }
+
             // prefer what is in the URI
             if (tokens.count() > 3)
                 format = tokens[3];
commit 94a870f57d13d49cb586365a565110245a868046
Author:     YiiChang Yen <sadwind.yan at gmail.com>
AuthorDate: Wed Dec 13 13:31:29 2017 +0800
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    wsd: to filter clientAddress before POST action.
    
    Change-Id: I293580f041bc46b36c57f63fe4a2c0131763b3c1
    Reviewed-on: https://gerrit.libreoffice.org/50977
    Reviewed-by: pranavk <pranavk at collabora.co.uk>
    Tested-by: pranavk <pranavk at collabora.co.uk>

diff --git a/loolwsd.xml.in b/loolwsd.xml.in
index 74414de97..b11966d7d 100644
--- a/loolwsd.xml.in
+++ b/loolwsd.xml.in
@@ -69,6 +69,9 @@
     <net desc="Network settings">
       <proto type="string" default="all" desc="Protocol to use IPv4, IPv6 or all for both">all</proto>
       <service_root type="path" default="" desc="Prefix all the pages, websockets, etc. with this path."></service_root>
+      <post_allow desc="Allow/deny client IP address for POST(REST)." allow="true">
+        <host desc="Regex pattern of ip address to allow.">192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
+      </post_allow>
     </net>
 
     <ssl desc="SSL settings">
diff --git a/net/ServerSocket.hpp b/net/ServerSocket.hpp
index 7ae7e7141..abc018678 100644
--- a/net/ServerSocket.hpp
+++ b/net/ServerSocket.hpp
@@ -60,13 +60,22 @@ public:
     std::shared_ptr<Socket> accept()
     {
         // Accept a connection (if any) and set it to non-blocking.
-        // We don't care about the client's address, so ignored.
-        const int rc = ::accept4(getFD(), nullptr, nullptr, SOCK_NONBLOCK);
+        // There still need the client's address to filter request from POST(call from REST) here.
+        struct sockaddr_in clientInfo;
+        socklen_t addrlen = sizeof(struct sockaddr_in);
+        const int rc = ::accept4(getFD(), (struct sockaddr *)&clientInfo, &addrlen, SOCK_NONBLOCK);
         LOG_DBG("Accepted socket #" << rc << ", creating socket object.");
         try
         {
             // Create a socket object using the factory.
-            return rc != -1 ? _sockFactory->create(rc) : std::shared_ptr<Socket>(nullptr);
+            if (rc != -1)
+            {
+                std::string ip = inet_ntoa(clientInfo.sin_addr);
+                std::shared_ptr<Socket> _socket = _sockFactory->create(rc);
+                _socket->_clientAddress = ip;
+                return _socket;
+            }
+            return std::shared_ptr<Socket>(nullptr);
         }
         catch (const std::exception& ex)
         {
diff --git a/net/Socket.hpp b/net/Socket.hpp
index 421222302..ce30a28c9 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -98,6 +98,7 @@ public:
     static const int DefaultSendBufferSize = 16 * 1024;
     static const int MaximumSendBufferSize = 128 * 1024;
     static std::atomic<bool> InhibitThreadChecks;
+    std::string _clientAddress;
 
     enum Type { IPv4, IPv6, All };
 
@@ -879,6 +880,11 @@ public:
         recv = _bytesRecvd;
     }
 
+    const std::string clientAddress()
+    {
+        return _clientAddress;
+    }
+
 protected:
 
     /// Called when a polling event is received.
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index ecc3d4fd1..fe4ca7004 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1870,8 +1870,42 @@ private:
                 if (!(request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0) &&
                     reqPathTokens.count() > 0 && reqPathTokens[0] == "lool")
                 {
-                    // All post requests have url prefix 'lool'.
-                    handlePostRequest(request, message, disposition);
+                    // allow/deny for POST
+                    const auto& app = Poco::Util::Application::instance();
+                    Util::RegexListMatcher hosts;
+                    // Parse the host allow settings.
+                    for (size_t i = 0; ; ++i)
+                    {
+                        const std::string path = "post_allow.host[" + std::to_string(i) + "]";
+                        const auto host = app.config().getString(path, "");
+                        if (!host.empty())
+                        {
+                            LOG_INF("Adding trusted POST_ALLOW host: [" << host << "].");
+                            hosts.allow(host);
+                        }
+                        else if (!app.config().has(path))
+                        {
+                            break;
+                        }
+                    }
+                    if (!hosts.match(socket->clientAddress()))
+                    {
+                        LOG_ERR("client address DENY: " << socket->clientAddress().c_str());
+
+                        std::ostringstream oss;
+                        oss << "HTTP/1.1 403\r\n"
+                            << "Date: " << Poco::DateTimeFormatter::format(Poco::Timestamp(), Poco::DateTimeFormat::HTTP_FORMAT) << "\r\n"
+                            << "User-Agent: " << HTTP_AGENT_STRING << "\r\n"
+                            << "Content-Length: 0\r\n"
+                            << "\r\n";
+                        socket->send(oss.str());
+                        socket->shutdown();
+                    }
+                    else
+                    {
+                        // All post requests have url prefix 'lool'.
+                        handlePostRequest(request, message, disposition);
+                    }
                 }
                 else if (reqPathTokens.count() > 2 && reqPathTokens[0] == "lool" && reqPathTokens[2] == "ws" &&
                          request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0)
commit 828ed669e3b6c90f5226b9e5003d6c22e3db886b
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sat Aug 18 11:44:07 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    loleaflet: wopi: add EnableInsertRemoteImage
    
    Change-Id: I806c3a79813e77cba85e837aa188453a5b63cacc

diff --git a/loleaflet/dist/toolbar/toolbar.js b/loleaflet/dist/toolbar/toolbar.js
index d9a5e8712..e7b4ed8b4 100644
--- a/loleaflet/dist/toolbar/toolbar.js
+++ b/loleaflet/dist/toolbar/toolbar.js
@@ -161,9 +161,12 @@ function onClick(e, id, item, subItem) {
 	else if (id === 'insertpage') {
 		$('#spreadsheet-tab-scroll').scrollLeft($('#spreadsheet-tab-scroll').prop('scrollWidth'));
 	}
-	else if (id === 'insertgraphic') {
+	else if (id === 'insertgraphic' || item.id === 'localgraphic') {
 		L.DomUtil.get('insertgraphic').click();
 	}
+	else if (item.id === 'remotegraphic') {
+		map.fire('postMessage', {msgId: 'UI_InsertGraphic'});
+	}
 	else if (id === 'fontcolor' && typeof e.color !== 'undefined') {
 		onColorPick(id, e.color);
 	}
@@ -467,6 +470,11 @@ $(function () {
 			{type: 'button',  id: 'insertobjectchart',  img: 'insertobjectchart', hint: _UNO('.uno:InsertObjectChart', '', true), uno: 'InsertObjectChart'},
 			{type: 'button',  id: 'insertannotation', img: 'annotation', hint: _UNO('.uno:InsertAnnotation', '', true)},
 			{type: 'button',  id: 'insertgraphic',  img: 'insertgraphic', hint: _UNO('.uno:InsertGraphic', '', true)},
+			{type: 'menu', id: 'menugraphic', img: 'insertgraphic', hint: _UNO('.uno:InsertGraphic', '', true), hidden: true,
+				items: [
+					{id: 'localgraphic', text: _UNO('.uno:InsertGraphic', '', true), icon: 'insertgraphic'},
+					{id: 'remotegraphic', text: _('Remote Image...'), icon: 'insertgraphic'}
+				]},
 			{type: 'button',  id: 'specialcharacter', img: 'specialcharacter', hint: _UNO('.uno:InsertSymbol', '', true), uno: '.uno:InsertSymbol'}
 		],
 		onClick: function (e) {
@@ -959,6 +967,10 @@ map.on('wopiprops', function(e) {
 		$('#document-name-input').removeClass('editable');
 		$('#document-name-input').off('keypress', onDocumentNameKeyPress);
 	}
+	if (e.EnableInsertRemoteImage === true) {
+		w2ui['toolbar-up'].hide('insertgraphic');
+		w2ui['toolbar-up'].show('menugraphic');
+	}
 });
 
 map.on('doclayerinit', function () {
diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 75f782dc0..e10501ae9 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -805,6 +805,9 @@ L.Control.Menubar = L.Control.extend({
 			if (menu[i].id === 'saveas' && this._map['wopi'].UserCanNotWriteRelative)
 				continue;
 
+			if (menu[i].id === 'insertgraphicremote' && !this._map['wopi'].EnableInsertRemoteImage)
+				continue;
+
 			if (menu[i].id && menu[i].id.startsWith('fullscreen-presentation') && this._map['wopi'].HideExportOption)
 				continue;
 
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index f9135762e..cd31fce22 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -19,6 +19,7 @@ L.Map.WOPI = L.Handler.extend({
 	DisableCopy: false,
 	DisableInactiveMessages: false,
 	UserCanNotWriteRelative: true,
+	EnableInsertRemoteImage: false,
 	CallPythonScriptSource: null,
 
 	_appLoadedConditions: {
@@ -74,6 +75,7 @@ L.Map.WOPI = L.Handler.extend({
 		this.DisableCopy = !!wopiInfo['DisableCopy'];
 		this.DisableInactiveMessages = !!wopiInfo['DisableInactiveMessages'];
 		this.UserCanNotWriteRelative = !!wopiInfo['UserCanNotWriteRelative'];
+		this.EnableInsertRemoteImage = !!wopiInfo['EnableInsertRemoteImage'];
 
 		this._map.fire('postMessage', {
 			msgId: 'App_LoadingStatus',
commit c2e37224d6467ae4eeafe40040b2dfb45dc0b6af
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Fri Aug 17 17:33:15 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    wsd: wopi: introduce a "EnableInsertRemoteImage" entry in the CheckFileInfo
    
    Change-Id: I66e5f12fbd49509ce8e82ea07ae7a2cc75ddc665

diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp
index 38b4d682d..67c73c112 100644
--- a/wsd/DocumentBroker.cpp
+++ b/wsd/DocumentBroker.cpp
@@ -509,6 +509,7 @@ bool DocumentBroker::load(const std::shared_ptr<ClientSession>& session, const s
         wopiInfo->set("DisableCopy", wopifileinfo->_disableCopy);
         wopiInfo->set("DisableInactiveMessages", wopifileinfo->_disableInactiveMessages);
         wopiInfo->set("UserCanNotWriteRelative", wopifileinfo->_userCanNotWriteRelative);
+        wopiInfo->set("EnableInsertRemoteImage", wopifileinfo->_enableInsertRemoteImage);
         if (wopifileinfo->_hideChangeTrackingControls != WopiStorage::WOPIFileInfo::TriState::Unset)
             wopiInfo->set("HideChangeTrackingControls", wopifileinfo->_hideChangeTrackingControls == WopiStorage::WOPIFileInfo::TriState::True);
 
diff --git a/wsd/Storage.cpp b/wsd/Storage.cpp
index e4ab5462c..acfc18408 100644
--- a/wsd/Storage.cpp
+++ b/wsd/Storage.cpp
@@ -463,6 +463,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
     bool disableInactiveMessages = false;
     std::string lastModifiedTime;
     bool userCanNotWriteRelative = true;
+    bool enableInsertRemoteImage = false;
     WOPIFileInfo::TriState disableChangeTrackingRecord = WOPIFileInfo::TriState::Unset;
     WOPIFileInfo::TriState disableChangeTrackingShow = WOPIFileInfo::TriState::Unset;
     WOPIFileInfo::TriState hideChangeTrackingControls = WOPIFileInfo::TriState::Unset;
@@ -541,6 +542,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
         JsonUtil::findJSONValue(object, "DisableInactiveMessages", disableInactiveMessages);
         JsonUtil::findJSONValue(object, "LastModifiedTime", lastModifiedTime);
         JsonUtil::findJSONValue(object, "UserCanNotWriteRelative", userCanNotWriteRelative);
+        JsonUtil::findJSONValue(object, "EnableInsertRemoteImage", enableInsertRemoteImage);
         bool booleanFlag = false;
         if (JsonUtil::findJSONValue(object, "DisableChangeTrackingRecord", booleanFlag))
             disableChangeTrackingRecord = (booleanFlag ? WOPIFileInfo::TriState::True : WOPIFileInfo::TriState::False);
@@ -568,7 +570,7 @@ std::unique_ptr<WopiStorage::WOPIFileInfo> WopiStorage::getWOPIFileInfo(const Au
         {userId, obfuscatedUserId, userName, userExtraInfo, watermarkText, canWrite,
          postMessageOrigin, hidePrintOption, hideSaveOption, hideExportOption,
          enableOwnerTermination, disablePrint, disableExport, disableCopy,
-         disableInactiveMessages, userCanNotWriteRelative,
+         disableInactiveMessages, userCanNotWriteRelative, enableInsertRemoteImage,
          disableChangeTrackingShow, disableChangeTrackingRecord,
          hideChangeTrackingControls, callDuration}));
 }
diff --git a/wsd/Storage.hpp b/wsd/Storage.hpp
index 1e9544c2e..f1361996e 100644
--- a/wsd/Storage.hpp
+++ b/wsd/Storage.hpp
@@ -284,6 +284,7 @@ public:
                      const bool disableCopy,
                      const bool disableInactiveMessages,
                      const bool userCanNotWriteRelative,
+                     const bool enableInsertRemoteImage,
                      const TriState disableChangeTrackingShow,
                      const TriState disableChangeTrackingRecord,
                      const TriState hideChangeTrackingControls,
@@ -303,6 +304,7 @@ public:
               _disableCopy(disableCopy),
               _disableInactiveMessages(disableInactiveMessages),
               _userCanNotWriteRelative(userCanNotWriteRelative),
+              _enableInsertRemoteImage(enableInsertRemoteImage),
               _disableChangeTrackingShow(disableChangeTrackingShow),
               _disableChangeTrackingRecord(disableChangeTrackingRecord),
               _hideChangeTrackingControls(hideChangeTrackingControls),
@@ -343,6 +345,8 @@ public:
         bool _disableInactiveMessages;
         /// If set to false, users can access the save-as functionality
         bool _userCanNotWriteRelative;
+        /// if set to true, users can access the insert remote image functionality
+        bool _enableInsertRemoteImage;
         /// If we should disable change-tracking visibility by default (meaningful at loading).
         TriState _disableChangeTrackingShow;
         /// If we should disable change-tracking ability by default (meaningful at loading).
commit 1ded82e9027a744ac4f981cd963be474f07a788f
Author:     Jan Holesovsky <kendy at collabora.com>
AuthorDate: Fri Aug 3 05:15:19 2018 +0200
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    Insert graphic: Pass the remote url to the core for download & insertion.
    
    Change-Id: I871de173c255dcb7b184582e486328d7f66a2fae

diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp
index f63e2643e..678ea0f5a 100644
--- a/kit/ChildSession.cpp
+++ b/kit/ChildSession.cpp
@@ -755,20 +755,27 @@ bool ChildSession::insertFile(const char* /*buffer*/, int /*length*/, const std:
         return false;
     }
 
-    if (type == "graphic")
+    if (type == "graphic" || type == "graphicurl")
     {
-        std::string fileName = "file://" + std::string(JAILED_DOCUMENT_ROOT) + "insertfile/" + name;
+        std::string url;
+        if (type == "graphic")
+            url = "file://" + std::string(JAILED_DOCUMENT_ROOT) + "insertfile/" + name;
+        else if (type == "graphicurl")
+            URI::decode(name, url);
+
         std::string command = ".uno:InsertGraphic";
         std::string arguments = "{"
             "\"FileName\":{"
                 "\"type\":\"string\","
-                "\"value\":\"" + fileName + "\""
+                "\"value\":\"" + url + "\""
             "}}";
 
         std::unique_lock<std::mutex> lock(_docManager.getDocumentMutex());
 
         getLOKitDocument()->setView(_viewId);
 
+        LOG_TRC("Inserting graphic: '" << arguments.c_str() << "', '");
+
         getLOKitDocument()->postUnoCommand(command.c_str(), arguments.c_str(), false);
     }
 
diff --git a/loleaflet/src/control/Toolbar.js b/loleaflet/src/control/Toolbar.js
index c6c4fc4ba..b9d7dacb1 100644
--- a/loleaflet/src/control/Toolbar.js
+++ b/loleaflet/src/control/Toolbar.js
@@ -156,6 +156,10 @@ L.Map.include({
 		this.fire('insertfile', {file: file});
 	},
 
+	insertURL: function (url) {
+		this.fire('inserturl', {url: url});
+	},
+
 	cellEnterString: function (string) {
 		var command = {
 			'StringName': {
diff --git a/loleaflet/src/map/handler/Map.FileInserter.js b/loleaflet/src/map/handler/Map.FileInserter.js
index 756ee4744..aa7a53745 100644
--- a/loleaflet/src/map/handler/Map.FileInserter.js
+++ b/loleaflet/src/map/handler/Map.FileInserter.js
@@ -12,6 +12,7 @@ L.Map.FileInserter = L.Handler.extend({
 		this._map = map;
 		this._childId = null;
 		this._toInsert = {};
+		this._toInsertURL = {};
 		var parser = document.createElement('a');
 		parser.href = map.options.server;
 		var wopiSrc = '';
@@ -24,11 +25,13 @@ L.Map.FileInserter = L.Handler.extend({
 
 	addHooks: function () {
 		this._map.on('insertfile', this._onInsertFile, this);
+		this._map.on('inserturl', this._onInsertURL, this);
 		this._map.on('childid', this._onChildIdMsg, this);
 	},
 
 	removeHooks: function () {
 		this._map.off('insertfile', this._onInsertFile, this);
+		this._map.off('inserturl', this._onInsertURL, this);
 		this._map.off('childid', this._onChildIdMsg, this);
 	},
 
@@ -42,12 +45,27 @@ L.Map.FileInserter = L.Handler.extend({
 		}
 	},
 
+	_onInsertURL: function (e) {
+		if (!this._childId) {
+			this._map._socket.sendMessage('getchildid');
+			this._toInsertURL[Date.now()] = e.url;
+		}
+		else {
+			this._sendURL(Date.now(), e.url);
+		}
+	},
+
 	_onChildIdMsg: function (e) {
 		this._childId = e.id;
 		for (var name in this._toInsert) {
 			this._sendFile(name, this._toInsert[name]);
 		}
 		this._toInsert = {};
+
+		for (name in this._toInsertURL) {
+			this._sendURL(name, this._toInsertURL[name]);
+		}
+		this._toInsertURL = {};
 	},
 
 	_sendFile: function (name, file) {
@@ -73,6 +91,10 @@ L.Map.FileInserter = L.Handler.extend({
 			formData.append('file', file);
 		}
 		xmlHttp.send(formData);
+	},
+
+	_sendURL: function (name, url) {
+		this._map._socket.sendMessage('insertfile name=' + encodeURIComponent(url) + ' type=graphicurl');
 	}
 });
 
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index 78e79f1ec..f9135762e 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -217,7 +217,7 @@ L.Map.WOPI = L.Handler.extend({
 		}
 		else if (msg.MessageId == 'Action_InsertGraphic') {
 			if (msg.Values) {
-				this._map.insertFile(msg.Values);
+				this._map.insertURL(msg.Values.url);
 			}
 		}
 		else if (msg.MessageId === 'Action_ShowBusy') {
diff --git a/wsd/protocol.txt b/wsd/protocol.txt
index 159bf1516..ead37a067 100644
--- a/wsd/protocol.txt
+++ b/wsd/protocol.txt
@@ -60,7 +60,13 @@ paste mimetype=<mimeType>
 
 insertfile name=<name> type=<type>
 
-    Inserts the file with the name <name> into the document, we currently support type = 'graphic'
+    Inserts the file with the name <name> into the document, we currently
+    support:
+
+        type = 'graphic': The file has been previously uploaded using insertfile POST
+
+        type = 'graphicurl': The file is supposed to be downloaded by the core
+	                     itself; it does so from the URL provided in 'name'
 
 key type=<type> char=<charcode> key=<keycode>
 
commit ef8974463294433e22307819b46598553c3d24ee
Author:     Henry Castro <hcastro at collabora.com>
AuthorDate: Sat Jul 14 12:43:45 2018 -0400
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Tue Sep 11 20:24:13 2018 +0200

    loleaflet: add action to insert graphic
    
    Change-Id: If3ab2de89625f44c4178da1146ca3834702a62ec

diff --git a/loleaflet/src/control/Control.Menubar.js b/loleaflet/src/control/Control.Menubar.js
index 808fe0e18..75f782dc0 100644
--- a/loleaflet/src/control/Control.Menubar.js
+++ b/loleaflet/src/control/Control.Menubar.js
@@ -62,6 +62,7 @@ L.Control.Menubar = L.Control.extend({
 			},
 			{name: _UNO('.uno:InsertMenu', 'text'), type: 'menu', menu: [
 				{name: _UNO('.uno:InsertGraphic', 'text'), id: 'insertgraphic', type: 'action'},
+				{name: _('Remote Image...'), id: 'insertgraphicremote', type: 'action'},
 				{name: _UNO('.uno:InsertAnnotation', 'text'), id: 'insertcomment', type: 'action'},
 				{uno: '.uno:InsertObjectChart'},
 				{type: 'separator'},
@@ -677,6 +678,8 @@ L.Control.Menubar = L.Control.extend({
 			map.insertComment();
 		} else if (id === 'insertgraphic') {
 			L.DomUtil.get('insertgraphic').click();
+		} else if (id === 'insertgraphicremote') {
+			map.fire('postMessage', {msgId: 'UI_InsertGraphic'});
 		} else if (id === 'zoomin' && map.getZoom() < map.getMaxZoom()) {
 			map.zoomIn(1);
 		} else if (id === 'zoomout' && map.getZoom() > map.getMinZoom()) {
diff --git a/loleaflet/src/map/handler/Map.FileInserter.js b/loleaflet/src/map/handler/Map.FileInserter.js
index 153e821a3..756ee4744 100644
--- a/loleaflet/src/map/handler/Map.FileInserter.js
+++ b/loleaflet/src/map/handler/Map.FileInserter.js
@@ -66,7 +66,12 @@ L.Map.FileInserter = L.Handler.extend({
 		var formData = new FormData();
 		formData.append('name', name);
 		formData.append('childid', this._childId);
-		formData.append('file', file);
+		if (file.filename && file.url) {
+			formData.append('url', file.url);
+			formData.append('filename', file.filename);
+		} else {
+			formData.append('file', file);
+		}
 		xmlHttp.send(formData);
 	}
 });
diff --git a/loleaflet/src/map/handler/Map.WOPI.js b/loleaflet/src/map/handler/Map.WOPI.js
index 9a55fd577..78e79f1ec 100644
--- a/loleaflet/src/map/handler/Map.WOPI.js
+++ b/loleaflet/src/map/handler/Map.WOPI.js
@@ -215,6 +215,11 @@ L.Map.WOPI = L.Handler.extend({
 				this._map.downloadAs(filename + '.' + format, format);
 			}
 		}
+		else if (msg.MessageId == 'Action_InsertGraphic') {
+			if (msg.Values) {
+				this._map.insertFile(msg.Values);
+			}
+		}
 		else if (msg.MessageId === 'Action_ShowBusy') {
 			if (msg.Values && msg.Values.Label) {
 				this._map.fire('showbusy', {label: msg.Values.Label});


More information about the Libreoffice-commits mailing list