summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzymon Kłos <szymon.klos@collabora.com>2023-02-22 11:11:35 +0100
committerAndras Timar <andras.timar@collabora.com>2023-03-15 15:14:15 +0100
commit8111f01c5f92cd350b30405da33607a65d657019 (patch)
tree2da22d92fc74750eff54f33e7c241222bd0dca69
parentBump version to 22.05.11.1 (diff)
downloadonline-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.cpp31
-rw-r--r--wsd/COOLWSD.cpp48
-rw-r--r--wsd/ClientSession.cpp24
-rw-r--r--wsd/DocumentBroker.cpp26
-rw-r--r--wsd/DocumentBroker.hpp23
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