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 <hcas...@collabora.com> AuthorDate: Sat Aug 18 20:37:51 2018 -0400 Commit: Jan Holesovsky <ke...@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 <hcas...@collabora.com> AuthorDate: Sat Aug 18 20:17:25 2018 -0400 Commit: Jan Holesovsky <ke...@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 <t...@collabora.com> AuthorDate: Wed Jul 18 17:54:45 2018 +0300 Commit: Jan Holesovsky <ke...@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 <t...@collabora.com> AuthorDate: Thu Jul 12 18:31:36 2018 +0300 Commit: Jan Holesovsky <ke...@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 <t...@collabora.com> Tested-by: Tor Lillqvist <t...@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 <t...@collabora.com> AuthorDate: Tue Jul 10 22:50:11 2018 +0300 Commit: Jan Holesovsky <ke...@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.me...@collabora.com> AuthorDate: Sun May 13 12:32:05 2018 +0100 Commit: Jan Holesovsky <ke...@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 <selim...@gmail.com> AuthorDate: Mon May 14 16:36:03 2018 +0300 Commit: Jan Holesovsky <ke...@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.me...@collabora.com> Tested-by: Michael Meeks <michael.me...@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.me...@collabora.com> AuthorDate: Sun May 13 13:35:32 2018 +0100 Commit: Jan Holesovsky <ke...@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....@gmail.com> AuthorDate: Wed Dec 13 13:31:29 2017 +0800 Commit: Jan Holesovsky <ke...@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 <pran...@collabora.co.uk> Tested-by: pranavk <pran...@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 <hcas...@collabora.com> AuthorDate: Sat Aug 18 11:44:07 2018 -0400 Commit: Jan Holesovsky <ke...@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 <hcas...@collabora.com> AuthorDate: Fri Aug 17 17:33:15 2018 -0400 Commit: Jan Holesovsky <ke...@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 <ke...@collabora.com> AuthorDate: Fri Aug 3 05:15:19 2018 +0200 Commit: Jan Holesovsky <ke...@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 <hcas...@collabora.com> AuthorDate: Sat Jul 14 12:43:45 2018 -0400 Commit: Jan Holesovsky <ke...@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}); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits