[Libreoffice-commits] online.git: 2 commits - loleaflet/js net/WebSocketHandler.hpp tools/WebSocketDump.cpp wsd/Admin.cpp wsd/ClientSession.cpp wsd/LOOLWSD.cpp wsd/TileCache.cpp

Michael Meeks (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 24 13:39:36 UTC 2020


 loleaflet/js/global.js   |   27 ++++++++++++
 net/WebSocketHandler.hpp |   19 ++++----
 tools/WebSocketDump.cpp  |    6 ++
 wsd/Admin.cpp            |    5 ++
 wsd/ClientSession.cpp    |    4 +
 wsd/LOOLWSD.cpp          |  100 +++++++++++++++++++++++++++++------------------
 wsd/TileCache.cpp        |    4 +
 7 files changed, 116 insertions(+), 49 deletions(-)

New commits:
commit 5b9f0927488243b6af8a6d9e0f88c1dcc100b41e
Author:     Michael Meeks <michael.meeks at collabora.com>
AuthorDate: Fri Mar 20 19:05:48 2020 +0000
Commit:     Jan Holesovsky <kendy at collabora.com>
CommitDate: Fri Apr 24 15:39:25 2020 +0200

    Proxy: re-write css image URLs to handle the proxy.
    
    Change-Id: I09f3dea2f5e3a51869d5b0aa3f473d8f3ba75f44
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92808
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
    Reviewed-by: Jan Holesovsky <kendy at collabora.com>

diff --git a/loleaflet/js/global.js b/loleaflet/js/global.js
index f5c038b91..023a8bf7c 100644
--- a/loleaflet/js/global.js
+++ b/loleaflet/js/global.js
@@ -335,6 +335,33 @@
 		}, 250);
 	};
 
+	if (global.socketProxy)
+	{
+		// re-write relative URLs in CSS - somewhat grim.
+		window.addEventListener('load', function() {
+			var sheets = document.styleSheets;
+			for (var i = 0; i < sheets.length; ++i) {
+				var relBases = sheets[i].href.split('/');
+				relBases.pop(); // bin last - css name.
+				var replaceBase = 'url("' + relBases.join('/') + '/images/';
+
+				var rules = sheets[i].cssRules || sheets[i].rules;
+				for (var r = 0; r < rules.length; ++r) {
+					if (!rules[r] || !rules[r].style)
+						continue;
+					var img = rules[r].style.backgroundImage;
+					if (img === '' || img === undefined)
+						continue;
+					if (img.startsWith('url("images/'))
+					{
+						rules[r].style.backgroundImage =
+							img.replace('url("images/', replaceBase);
+					}
+				}
+			}
+		}, false);
+	}
+
 	global.createWebSocket = function(uri) {
 		if (global.socketProxy) {
 			return new global.ProxySocket(uri);
commit df6d942d08dfb5e8fffed015edf4c0eb5ce6f65e
Author:     Ashod Nakashian <ashod.nakashian at collabora.co.uk>
AuthorDate: Sun Apr 19 14:46:01 2020 -0400
Commit:     Ashod Nakashian <ashnakash at gmail.com>
CommitDate: Fri Apr 24 15:39:17 2020 +0200

    wsd: harden socket weakptr
    
    Weak pointers can be null and must be
    checked before using. This fixes at least
    one segfault and prevents a number of others.
    
    Also, minimizes locking of weak pointers
    in the message handlers.
    
    Change-Id: I306501c26c3441d7bd6812d51fa17e7356126f32
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/92828
    Reviewed-by: Michael Meeks <michael.meeks at collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>

diff --git a/net/WebSocketHandler.hpp b/net/WebSocketHandler.hpp
index 46a2916a7..a329e7711 100644
--- a/net/WebSocketHandler.hpp
+++ b/net/WebSocketHandler.hpp
@@ -122,7 +122,7 @@ public:
     void sendCloseFrame(const StatusCodes statusCode = StatusCodes::NORMAL_CLOSE, const std::string& statusMessage = "")
     {
         std::shared_ptr<StreamSocket> socket = _socket.lock();
-        if (socket == nullptr)
+        if (!socket)
         {
             LOG_ERR("No socket associated with WebSocketHandler " << this);
             return;
@@ -404,23 +404,21 @@ public:
     /// Implementation of the ProtocolHandlerInterface.
     virtual void handleIncomingMessage(SocketDisposition&) override
     {
-        // LOG_TRC("***** WebSocketHandler::handleIncomingMessage()");
-
         std::shared_ptr<StreamSocket> socket = _socket.lock();
 
 #if MOBILEAPP
         // No separate "upgrade" is going on
-        if (socket != nullptr && !socket->isWebSocket())
+        if (socket && !socket->isWebSocket())
             socket->setWebSocket();
 #endif
 
-        if (socket == nullptr)
+        if (!socket)
         {
             LOG_ERR("No socket associated with WebSocketHandler " << this);
         }
 #if !MOBILEAPP
         else if (_isClient && !socket->isWebSocket())
-            handleClientUpgrade();
+            handleClientUpgrade(socket);
 #endif
         else
         {
@@ -694,7 +692,7 @@ protected:
     void upgradeToWebSocket(const Poco::Net::HTTPRequest& req)
     {
         std::shared_ptr<StreamSocket> socket = _socket.lock();
-        if (socket == nullptr)
+        if (!socket)
             throw std::runtime_error("Invalid socket while upgrading to WebSocket. Request: " + req.getURI());
 
         LOG_TRC("#" << socket->getFD() << ": Upgrading to WebSocket.");
@@ -730,9 +728,9 @@ protected:
 
 #if !MOBILEAPP
     // Handle incoming upgrade to full socket as client WS.
-    void handleClientUpgrade()
+    void handleClientUpgrade(const std::shared_ptr<StreamSocket>& socket)
     {
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
+        assert(socket && "socket must be valid");
 
         LOG_TRC("Incoming client websocket upgrade response: "
                 << std::string(&socket->getInBuffer()[0], socket->getInBuffer().size()));
@@ -800,7 +798,8 @@ protected:
     void setWebSocket()
     {
         std::shared_ptr<StreamSocket> socket = _socket.lock();
-        socket->setWebSocket();
+        if (socket)
+            socket->setWebSocket();
 
         // No need to ping right upon connection/upgrade,
         // but do reset the time to avoid pinging immediately after.
diff --git a/tools/WebSocketDump.cpp b/tools/WebSocketDump.cpp
index 81e034a67..711cbaca9 100644
--- a/tools/WebSocketDump.cpp
+++ b/tools/WebSocketDump.cpp
@@ -70,6 +70,12 @@ private:
     void handleIncomingMessage(SocketDisposition &disposition) override
     {
         std::shared_ptr<StreamSocket> socket = _socket.lock();
+        if (!socket)
+        {
+            LOG_ERR("Invalid socket while reading client message.");
+            return;
+        }
+
         std::vector<char>& in = socket->getInBuffer();
         LOG_TRC("#" << socket->getFD() << " handling incoming " << in.size() << " bytes.");
 
diff --git a/wsd/Admin.cpp b/wsd/Admin.cpp
index ca84c5c6c..8f98cce64 100644
--- a/wsd/Admin.cpp
+++ b/wsd/Admin.cpp
@@ -330,6 +330,11 @@ bool AdminSocketHandler::handleInitialRequest(
     }
 
     std::shared_ptr<StreamSocket> socket = socketWeak.lock();
+    if (!socket)
+    {
+        LOG_ERR("Invalid socket while reading initial request.");
+        return false;
+    }
 
     const std::string& requestURI = request.getURI();
     StringVector pathTokens(LOOLProtocol::tokenize(requestURI, '/'));
diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp
index c9dc7827a..a73749352 100644
--- a/wsd/ClientSession.cpp
+++ b/wsd/ClientSession.cpp
@@ -1358,12 +1358,16 @@ bool ClientSession::handleKitToClientMessage(const char* buffer, const int lengt
                 << "X-Content-Type-Options: nosniff\r\n"
                 << "\r\n";
             auto socket = it.lock();
+            if (!socket)
+                continue;
+
             if (!empty)
             {
                 oss.write(&payload->data()[header], payload->size() - header);
                 socket->setSocketBufferSize(std::min(payload->size() + 256,
                                                      size_t(Socket::MaximumSendBufferSize)));
             }
+
             socket->send(oss.str());
             socket->shutdown();
             LOG_INF("Queued " << (empty?"empty":"clipboard") << " response for send.");
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index c58430509..7607facef 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1937,7 +1937,6 @@ private:
     /// Called after successful socket reads.
     void handleIncomingMessage(SocketDisposition &disposition) override
     {
-        // LOG_TRC("***** PrisonerRequestDispatcher::handleIncomingMessage()");
         if (_childProcess.lock())
         {
             // FIXME: inelegant etc. - derogate to websocket code
@@ -1946,6 +1945,11 @@ private:
         }
 
         std::shared_ptr<StreamSocket> socket = getSocket().lock();
+        if (!socket)
+        {
+            LOG_ERR("Invalid socket while reading incoming message.");
+            return;
+        }
 
         Poco::MemoryInputStream message(&socket->getInBuffer()[0],
                                         socket->getInBuffer().size());;
@@ -2194,6 +2198,11 @@ private:
     void handleIncomingMessage(SocketDisposition &disposition) override
     {
         std::shared_ptr<StreamSocket> socket = _socket.lock();
+        if (!socket)
+        {
+            LOG_ERR("Invalid socket while handling incoming client request");
+            return;
+        }
 
 #if !MOBILEAPP
         if (!LOOLWSD::isSSLEnabled() && socket->sniffSSL())
@@ -2247,7 +2256,7 @@ private:
             else if (reqPathSegs.size() >= 1 && reqPathSegs[0] == "loleaflet")
             {
                 // File server
-                handleFileServerRequest(request, message);
+                handleFileServerRequest(request, message, socket);
             }
             else if (reqPathSegs.size() >= 2 && reqPathSegs[0] == "lool" && reqPathSegs[1] == "adminws")
             {
@@ -2308,23 +2317,23 @@ private:
                       request.getMethod() == HTTPRequest::HTTP_HEAD) &&
                      request.getURI() == "/")
             {
-                handleRootRequest(request);
+                handleRootRequest(request, socket);
             }
             else if (request.getMethod() == HTTPRequest::HTTP_GET && request.getURI() == "/favicon.ico")
             {
-                handleFaviconRequest(request);
+                handleFaviconRequest(request, socket);
             }
             else if (request.getMethod() == HTTPRequest::HTTP_GET && (request.getURI() == "/hosting/discovery" || request.getURI() == "/hosting/discovery/"))
             {
-                handleWopiDiscoveryRequest(request);
+                handleWopiDiscoveryRequest(request, socket);
             }
             else if (request.getMethod() == HTTPRequest::HTTP_GET && request.getURI() == CAPABILITIES_END_POINT)
             {
-                handleCapabilitiesRequest(request);
+                handleCapabilitiesRequest(request, socket);
             }
             else if (request.getMethod() == HTTPRequest::HTTP_GET && request.getURI() == "/robots.txt")
             {
-                handleRobotsTxtRequest(request);
+                handleRobotsTxtRequest(request, socket);
             }
             else
             {
@@ -2332,7 +2341,7 @@ private:
                 if (reqPathTokens.count() > 1 && reqPathTokens[0] == "lool" && reqPathTokens[1] == "clipboard")
                 {
 //                    Util::dumpHex(std::cerr, "clipboard:\n", "", socket->getInBuffer()); // lots of data ...
-                    handleClipboardRequest(request, message, disposition);
+                    handleClipboardRequest(request, message, disposition, socket);
                 }
                 else if (request.has("ProxyPrefix") && reqPathTokens.count() > 2 &&
                          (reqPathTokens[reqPathTokens.count()-2] == "ws"))
@@ -2345,14 +2354,14 @@ private:
                     reqPathTokens.count() > 0 && reqPathTokens[0] == "lool")
                 {
                     // All post requests have url prefix 'lool'.
-                    handlePostRequest(request, message, disposition);
+                    handlePostRequest(request, message, disposition, socket);
                 }
                 else if (reqPathTokens.count() > 2 && reqPathTokens[0] == "lool" && reqPathTokens[2] == "ws" &&
                          request.find("Upgrade") != request.end() && Poco::icompare(request["Upgrade"], "websocket") == 0)
                 {
                     std::string decodedUri; // WOPISrc
                     Poco::URI::decode(reqPathTokens[1], decodedUri);
-                    handleClientWsUpgrade(request, decodedUri, disposition);
+                    handleClientWsUpgrade(request, decodedUri, disposition, socket);
                 }
                 else
                 {
@@ -2396,7 +2405,9 @@ private:
         Poco::Net::HTTPRequest request;
         // The 2nd parameter is the response to the HULLO message (which we
         // respond with the path of the document)
-        handleClientWsUpgrade(request, std::string(socket->getInBuffer().data(), socket->getInBuffer().size()), disposition);
+        handleClientWsUpgrade(
+            request, std::string(socket->getInBuffer().data(), socket->getInBuffer().size()),
+            disposition, socket);
         socket->getInBuffer().clear();
 #endif
     }
@@ -2412,15 +2423,20 @@ private:
     }
 
 #if !MOBILEAPP
-    void handleFileServerRequest(const Poco::Net::HTTPRequest& request, Poco::MemoryInputStream& message)
+    void handleFileServerRequest(const Poco::Net::HTTPRequest& request,
+                                 Poco::MemoryInputStream& message,
+                                 const std::shared_ptr<StreamSocket>& socket)
     {
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
+        assert(socket && "Must have a valid socket");
         FileServerRequestHandler::handleRequest(request, message, socket);
         socket->shutdown();
     }
 
-    void handleRootRequest(const Poco::Net::HTTPRequest& request)
+    void handleRootRequest(const Poco::Net::HTTPRequest& request,
+                           const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_DBG("HTTP request: " << request.getURI());
         const std::string mimeType = "text/plain";
         const std::string responseString = "OK";
@@ -2438,14 +2454,16 @@ private:
             oss << responseString;
         }
 
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
         socket->send(oss.str());
         socket->shutdown();
         LOG_INF("Sent / response successfully.");
     }
 
-    void handleFaviconRequest(const Poco::Net::HTTPRequest& request)
+    void handleFaviconRequest(const Poco::Net::HTTPRequest& request,
+                              const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_DBG("Favicon request: " << request.getURI());
         std::string mimeType = "image/vnd.microsoft.icon";
         std::string faviconPath = Path(Application::instance().commandPath()).parent().toString() + "favicon.ico";
@@ -2454,14 +2472,16 @@ private:
             faviconPath = LOOLWSD::FileServerRoot + "/favicon.ico";
         }
 
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
         Poco::Net::HTTPResponse response;
         HttpHelper::sendFile(socket, faviconPath, mimeType, response);
         socket->shutdown();
     }
 
-    void handleWopiDiscoveryRequest(const Poco::Net::HTTPRequest& request)
+    void handleWopiDiscoveryRequest(const Poco::Net::HTTPRequest& request,
+                                    const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_DBG("Wopi discovery request: " << request.getURI());
 
         std::string xml = getFileContent("discovery.xml");
@@ -2479,17 +2499,19 @@ private:
             "\r\n"
             << xml;
 
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
         socket->send(oss.str());
         socket->shutdown();
         LOG_INF("Sent discovery.xml successfully.");
     }
 
-    void handleCapabilitiesRequest(const Poco::Net::HTTPRequest& request)
+    void handleCapabilitiesRequest(const Poco::Net::HTTPRequest& request,
+                                   const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_DBG("Wopi capabilities request: " << request.getURI());
 
-        std::string capabilities = getCapabilitiesJson(request);
+        const std::string capabilities = getCapabilitiesJson(request, socket);
 
         std::ostringstream oss;
         oss << "HTTP/1.1 200 OK\r\n"
@@ -2501,7 +2523,6 @@ private:
             "\r\n"
             << capabilities;
 
-        auto socket = _socket.lock();
         socket->send(oss.str());
         socket->shutdown();
         LOG_INF("Sent capabilities.json successfully.");
@@ -2509,8 +2530,11 @@ private:
 
     void handleClipboardRequest(const Poco::Net::HTTPRequest& request,
                                 Poco::MemoryInputStream& message,
-                                SocketDisposition &disposition)
+                                SocketDisposition &disposition,
+                                const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_DBG("Clipboard " << ((request.getMethod() == HTTPRequest::HTTP_GET) ? "GET" : "POST") <<
                 " request: " << request.getURI());
 
@@ -2579,7 +2603,7 @@ private:
             LOG_TRC("queued clipboard command " << type << " on docBroker fetch");
         }
         // fallback to persistent clipboards if we can
-        else if (!DocumentBroker::lookupSendClipboardTag(_socket.lock(), tag, false))
+        else if (!DocumentBroker::lookupSendClipboardTag(socket, tag, false))
         {
             LOG_ERR("Invalid clipboard request: " << serverId << " with tag " << tag <<
                     " and broker: " << (docBroker ? "" : "not ") << "found");
@@ -2598,14 +2622,16 @@ private:
                 << "Content-Length: 0\r\n"
                 << "\r\n"
                 << errMsg;
-            auto socket = _socket.lock();
             socket->send(oss.str());
             socket->shutdown();
         }
     }
 
-    void handleRobotsTxtRequest(const Poco::Net::HTTPRequest& request)
+    void handleRobotsTxtRequest(const Poco::Net::HTTPRequest& request,
+                                const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_DBG("HTTP request: " << request.getURI());
         const std::string mimeType = "text/plain";
         const std::string responseString = "User-agent: *\nDisallow: /\n";
@@ -2623,7 +2649,6 @@ private:
             oss << responseString;
         }
 
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
         socket->send(oss.str());
         socket->shutdown();
         LOG_INF("Sent robots.txt response successfully.");
@@ -2669,12 +2694,14 @@ private:
 
     void handlePostRequest(const Poco::Net::HTTPRequest& request,
                            Poco::MemoryInputStream& message,
-                           SocketDisposition &disposition)
+                           SocketDisposition& disposition,
+                           const std::shared_ptr<StreamSocket>& socket)
     {
+        assert(socket && "Must have a valid socket");
+
         LOG_INF("Post request: [" << LOOLWSD::anonymizeUrl(request.getURI()) << "]");
 
         Poco::Net::HTTPResponse response;
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
 
         StringTokenizer tokens(request.getURI(), "/?");
         if (tokens.count() > 2 && tokens[2] == "convert-to")
@@ -2968,14 +2995,10 @@ private:
     }
 
     void handleClientWsUpgrade(const Poco::Net::HTTPRequest& request, const std::string& url,
-                               SocketDisposition &disposition)
+                               SocketDisposition& disposition,
+                               const std::shared_ptr<StreamSocket>& socket)
     {
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
-        if (!socket)
-        {
-            LOG_WRN("No socket to handle client WS upgrade for request: " << LOOLWSD::anonymizeUrl(request.getURI()) << ", url: " << url);
-            return;
-        }
+        assert(socket && "Must have a valid socket");
 
         // must be trace for anonymization
         LOG_TRC("Client WS request: " << request.getURI() << ", url: " << url << ", socket #" << socket->getFD());
@@ -3197,9 +3220,10 @@ private:
     }
 
     /// Create the /hosting/capabilities JSON and return as string.
-    std::string getCapabilitiesJson(const Poco::Net::HTTPRequest& request)
+    std::string getCapabilitiesJson(const Poco::Net::HTTPRequest& request,
+                                    const std::shared_ptr<StreamSocket>& socket)
     {
-        std::shared_ptr<StreamSocket> socket = _socket.lock();
+        assert(socket && "Must have a valid socket");
 
         // Can the convert-to be used?
         Poco::JSON::Object::Ptr convert_to = new Poco::JSON::Object;
diff --git a/wsd/TileCache.cpp b/wsd/TileCache.cpp
index 5ef10804f..15f24b92f 100644
--- a/wsd/TileCache.cpp
+++ b/wsd/TileCache.cpp
@@ -656,7 +656,9 @@ void TileCache::TileBeingRendered::dumpState(std::ostream& os)
     for (const auto& it : _subscribers)
     {
         std::shared_ptr<ClientSession> session = it.lock();
-        os << "      " << session->getId() << " " << session->getUserId() << " " << session->getName() << "\n";
+        if (session)
+            os << "      " << session->getId() << ' ' << session->getUserId() << ' '
+               << session->getName() << '\n';
     }
 }
 


More information about the Libreoffice-commits mailing list