diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2023-02-22 11:11:35 +0100 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2023-03-15 15:14:15 +0100 |
commit | 8111f01c5f92cd350b30405da33607a65d657019 (patch) | |
tree | 2da22d92fc74750eff54f33e7c241222bd0dca69 | |
parent | Bump version to 22.05.11.1 (diff) | |
download | online-8111f01c5f92cd350b30405da33607a65d657019.tar.gz online-8111f01c5f92cd350b30405da33607a65d657019.zip |
Add extract-link-targets endpoint
Original author was Mert Tümer.
Example output for: POST http://localhost:9980/cool/extract-link-targets/
{
"Targets": {
"Tables": {
"Table1": "Table1|table"
},
"Frames": {},
"Images": {
"image7.png": "image7.png|graphic"
},
"OLE objects": {},
"Sections": {
"Table of Contents1": "Table of Contents1|region"
},
"Headings": {},
"Bookmarks": {
"_lh2zfxamp5al": "_lh2zfxamp5al"
},
"Drawing objects": {}
}
}
Signed-off-by: Szymon Kłos <szymon.klos@collabora.com>
Change-Id: Iab55ec631d78dbe25b2800ed9296bc0cb8997e97
-rw-r--r-- | kit/ChildSession.cpp | 31 | ||||
-rw-r--r-- | wsd/COOLWSD.cpp | 48 | ||||
-rw-r--r-- | wsd/ClientSession.cpp | 24 | ||||
-rw-r--r-- | wsd/DocumentBroker.cpp | 26 | ||||
-rw-r--r-- | wsd/DocumentBroker.hpp | 23 |
5 files changed, 144 insertions, 8 deletions
diff --git a/kit/ChildSession.cpp b/kit/ChildSession.cpp index aaebb25227..488ba6cf77 100644 --- a/kit/ChildSession.cpp +++ b/kit/ChildSession.cpp @@ -249,6 +249,37 @@ bool ChildSession::_handleInput(const char *buffer, int length) LOG_TRC("isDocLoaded state after loadDocument: " << _isDocLoaded); return _isDocLoaded; } + else if (tokens.equals(0, "extractlinktargets")) + { + if (tokens.size() < 2) + { + sendTextFrameAndLogError("error: cmd=extractlinktargets kind=syntax"); + return false; + } + + if (!_isDocLoaded) + { + sendTextFrameAndLogError("error: cmd=extractlinktargets kind=docnotloaded"); + return false; + } + + assert(!getDocURL().empty()); + assert(!getJailedFilePath().empty()); + + char* data = _docManager->getLOKit()->extractRequest(getJailedFilePath().c_str()); + if (!data) + { + LOG_TRC("extractRequest returned no data."); + sendTextFrame("extractedlinktargets: { }"); + return false; + } + + LOG_TRC("Extracted link targets: " << data); + bool success = sendTextFrame("extractedlinktargets: " + std::string(data)); + free(data); + + return success; + } else if (!_isDocLoaded) { sendTextFrameAndLogError("error: cmd=" + tokens[0] + " kind=nodocloaded"); diff --git a/wsd/COOLWSD.cpp b/wsd/COOLWSD.cpp index c200150b5b..0858d2b917 100644 --- a/wsd/COOLWSD.cpp +++ b/wsd/COOLWSD.cpp @@ -4543,6 +4543,54 @@ private: } return; } + else if (requestDetails.equals(1, "extract-link-targets")) + { + // just like convert-to but this will not do save-as at the end and send the output back + // instead it will generate a list of the target links of the document + + // Validate sender - FIXME: should do this even earlier. + if (!allowConvertTo(socket->clientAddress(), request)) + { + LOG_WRN("Conversion requests not allowed from this address: " << socket->clientAddress()); + http::Response httpResponse(http::StatusCode::Forbidden); + httpResponse.set("Content-Length", "0"); + socket->sendAndShutdown(httpResponse); + socket->ignoreInput(); + return; + } + + ConvertToPartHandler handler; + HTMLForm form(request, message, handler); + + const std::string fromPath = handler.getFilename(); + LOG_INF("Extract request for URI [" << fromPath << "]."); + + if (!fromPath.empty()) + { + Poco::URI uriPublic = RequestDetails::sanitizeURI(fromPath); + const std::string docKey = RequestDetails::getDocKey(uriPublic); + + std::string lang = (form.has("lang") ? form.get("lang") : ""); + + std::unique_lock<std::mutex> docBrokersLock(DocBrokersMutex); + + LOG_DBG("New DocumentBroker for docKey [" << docKey << "]."); + auto docBroker = std::make_shared<ExtractLinkTargetsBroker>(fromPath, uriPublic, docKey, "", "", lang); + handler.takeFile(); + + cleanupDocBrokers(); + + DocBrokers.emplace(docKey, docBroker); + LOG_TRC("Have " << DocBrokers.size() << " DocBrokers after inserting [" << docKey << "]."); + + if (!docBroker->startConversion(disposition, _id)) + { + LOG_WRN("Failed to create Client Session with id [" << _id << "] on docKey [" << docKey << "]."); + cleanupDocBrokers(); + } + } + return; + } else if (requestDetails.equals(2, "insertfile")) { LOG_INF("Insert file request."); diff --git a/wsd/ClientSession.cpp b/wsd/ClientSession.cpp index 8e5af4a9d2..997a941453 100644 --- a/wsd/ClientSession.cpp +++ b/wsd/ClientSession.cpp @@ -2050,6 +2050,30 @@ bool ClientSession::handleKitToClientMessage(const std::shared_ptr<Message>& pay payload->data().size() - firstLine.size() - 1); return forwardToClient(payload); } + else if (tokens.equals(0, "extractedlinktargets:")) + { + LOG_TRC("Sending extracted link targets response."); + + const std::string stringJSON = payload->jsonString(); + + Poco::Net::HTTPResponse response; + response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_OK); + std::ostringstream oss; + oss << "HTTP/1.1 200 OK\r\n" + "Last-Modified: " << Util::getHttpTimeNow() << "\r\n" + "User-Agent: " WOPI_AGENT_STRING "\r\n" + "Content-Type: application/json\r\n" + "X-Content-Type-Options: nosniff\r\n" + "\r\n" + << stringJSON; + + _saveAsSocket->send(oss.str()); + _saveAsSocket->shutdown(); + + // Now terminate. + docBroker->closeDocument("extractedlinktargets"); + return true; + } } else { diff --git a/wsd/DocumentBroker.cpp b/wsd/DocumentBroker.cpp index 4d8ee626db..dd325e7c0a 100644 --- a/wsd/DocumentBroker.cpp +++ b/wsd/DocumentBroker.cpp @@ -3694,18 +3694,32 @@ bool ConvertToBroker::startConversion(SocketDisposition &disposition, const std: // Load the document manually and request saving in the target format. std::string encodedFrom; Poco::URI::encode(docBroker->getPublicUri().getPath(), "", encodedFrom); - // add batch mode, no interactive dialogs - std::string _load = "load url=" + encodedFrom + " batch=true"; - if (!docBroker->getLang().empty()) - _load += " lang=" + docBroker->getLang(); - std::vector<char> loadRequest(_load.begin(), _load.end()); - docBroker->_clientSession->handleMessage(loadRequest); + + docBroker->sendStartMessage(docBroker->_clientSession, encodedFrom); // Save is done in the setLoaded }); return true; } +void ConvertToBroker::sendStartMessage(std::shared_ptr<ClientSession> clientSession, const std::string& encodedFrom) +{ + // add batch mode, no interactive dialogs + std::string _load = "load url=" + encodedFrom + " batch=true"; + if (!getLang().empty()) + _load += " lang=" + getLang(); + std::vector<char> loadRequest(_load.begin(), _load.end()); + clientSession->handleMessage(loadRequest); +} + +void ExtractLinkTargetsBroker::sendStartMessage(std::shared_ptr<ClientSession> clientSession, const std::string& encodedFrom) +{ + ConvertToBroker::sendStartMessage(clientSession, encodedFrom); + + const auto command = "extractlinktargets url=" + encodedFrom; + forwardToChild(clientSession, command); +} + void ConvertToBroker::dispose() { if (!_uriOrig.empty()) diff --git a/wsd/DocumentBroker.hpp b/wsd/DocumentBroker.hpp index dcb0c160fc..26e7e2c421 100644 --- a/wsd/DocumentBroker.hpp +++ b/wsd/DocumentBroker.hpp @@ -1483,7 +1483,7 @@ public: static void removeFile(const std::string &uri); }; -class ConvertToBroker final : public StatelessBatchBroker +class ConvertToBroker : public StatelessBatchBroker { const std::string _format; const std::string _sOptions; @@ -1514,8 +1514,27 @@ public: /// How many live conversions are running. static std::size_t getInstanceCount(); -private: +protected: bool isConvertTo() const override { return true; } + + virtual void sendStartMessage(std::shared_ptr<ClientSession> clientSession, const std::string& encodedFrom); +}; + +class ExtractLinkTargetsBroker final : public ConvertToBroker +{ +public: + /// Construct DocumentBroker with URI and docKey + ExtractLinkTargetsBroker(const std::string& uri, + const Poco::URI& uriPublic, + const std::string& docKey, + const std::string& format, + const std::string& sOptions, + const std::string& lang) + : ConvertToBroker(uri, uriPublic, docKey, format, sOptions, lang) + {} + +private: + void sendStartMessage(std::shared_ptr<ClientSession> clientSession, const std::string& encodedFrom) override; }; class RenderSearchResultBroker final : public StatelessBatchBroker |