[Libreoffice-commits] online.git: loolwsd/ChildProcessSession.cpp loolwsd/ChildProcessSession.hpp loolwsd/LOOLKit.cpp loolwsd/LOOLSession.cpp loolwsd/LOOLSession.hpp loolwsd/MasterProcessSession.cpp
Pranav Kant
pranavk at collabora.co.uk
Fri Feb 19 21:50:05 UTC 2016
loolwsd/ChildProcessSession.cpp | 63 +++++++++++++++++++++++++++++++++++----
loolwsd/ChildProcessSession.hpp | 4 ++
loolwsd/LOOLKit.cpp | 5 +++
loolwsd/LOOLSession.cpp | 10 ++++++
loolwsd/LOOLSession.hpp | 20 ++++++++++++
loolwsd/MasterProcessSession.cpp | 30 +++++++++++++++++-
6 files changed, 126 insertions(+), 6 deletions(-)
New commits:
commit 3667bef9a6759181ac90b31e63633c75bf5bed72
Author: Pranav Kant <pranavk at collabora.co.uk>
Date: Thu Feb 4 23:05:26 2016 +0530
loolwsd: Handle password protected documents
Change-Id: Iceb5bb598ef1517bf640994c27bad4ca36bd72c1
Reviewed-on: https://gerrit.libreoffice.org/21894
Reviewed-by: Ashod Nakashian <ashnakash at gmail.com>
Tested-by: Ashod Nakashian <ashnakash at gmail.com>
diff --git a/loolwsd/ChildProcessSession.cpp b/loolwsd/ChildProcessSession.cpp
index dfef7b7..5fd53ee 100644
--- a/loolwsd/ChildProcessSession.cpp
+++ b/loolwsd/ChildProcessSession.cpp
@@ -118,6 +118,10 @@ public:
return std::string("LOK_CALLBACK_SET_PART");
case LOK_CALLBACK_PARTS_COUNT_CHANGED:
return std::string("LOK_CALLBACK_PARTS_COUNT_CHANGED");
+ case LOK_CALLBACK_DOCUMENT_PASSWORD:
+ return std::string("LOK_CALLBACK_DOCUMENT_PASSWORD");
+ case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
+ return std::string("LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY");
}
return std::to_string(nType);
}
@@ -245,8 +249,8 @@ public:
_session.sendTextFrame("unocommandresult: " + rPayload);
break;
case LOK_CALLBACK_DOCUMENT_PASSWORD:
- break;
case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
+ _session.setDocumentPassword(nType);
break;
case LOK_CALLBACK_ERROR:
{
@@ -321,12 +325,13 @@ std::recursive_mutex ChildProcessSession::Mutex;
ChildProcessSession::ChildProcessSession(const std::string& id,
std::shared_ptr<Poco::Net::WebSocket> ws,
- LibreOfficeKit* /*loKit*/,
+ LibreOfficeKit* loKit,
LibreOfficeKitDocument * loKitDocument,
const std::string& jailId,
std::function<LibreOfficeKitDocument*(const std::string&, const std::string&)> onLoad,
std::function<void(const std::string&)> onUnload) :
LOOLSession(id, Kind::ToMaster, ws),
+ _loKit(loKit),
_loKitDocument(loKitDocument),
_multiView(getenv("LOK_VIEW_CALLBACK")),
_jailId(jailId),
@@ -422,15 +427,31 @@ bool ChildProcessSession::_handleInput(const char *buffer, int length)
}
else if (tokens[0] == "load")
{
- if (_docURL != "")
+ if (_isDocLoaded)
{
sendTextFrame("error: cmd=load kind=docalreadyloaded");
return false;
}
- return loadDocument(buffer, length, tokens);
+ _isDocLoaded = loadDocument(buffer, length, tokens);
+ if (!_isDocLoaded && _isDocPasswordProtected)
+ {
+ if (!_isDocPasswordProvided)
+ {
+ std::string passwordFrame = "passwordrequired:";
+ if (_docPasswordType == PasswordType::ToView)
+ passwordFrame += "to-view";
+ else if (_docPasswordType == PasswordType::ToModify)
+ passwordFrame += "to-modify";
+ sendTextFrame("error: cmd=load kind=" + passwordFrame);
+ }
+ else
+ sendTextFrame("error: cmd=load kind=wrongpassword");
+ }
+
+ return _isDocLoaded;
}
- else if (_docURL == "")
+ else if (!_isDocLoaded)
{
sendTextFrame("error: cmd=" + tokens[0] + " kind=nodocloaded");
return false;
@@ -584,6 +605,9 @@ bool ChildProcessSession::loadDocument(const char * /*buffer*/, int /*length*/,
_loKitDocument = _onLoad(getId(), _jailedFilePath);
+ if (!_loKitDocument)
+ return false;
+
std::unique_lock<std::recursive_mutex> lock(Mutex);
if (_multiView)
@@ -606,6 +630,11 @@ bool ChildProcessSession::loadDocument(const char * /*buffer*/, int /*length*/,
_loKitDocument->pClass->setPart(_loKitDocument, part);
}
+ // 'statusindicatorfinish:' is used to let clients, and parent process know of successfull document load
+ // Usually, 'statusindicatorfinish:' is already sent when the load document operation finishes,
+ // but in case of multiple sessions accessing the same document, it won't be sent.
+ sendTextFrame("statusindicatorfinish:");
+
// Respond by the document status, which has no arguments.
if (!getStatus(nullptr, 0))
return false;
@@ -1320,6 +1349,30 @@ bool ChildProcessSession::setPage(const char* /*buffer*/, int /*length*/, String
return true;
}
+void ChildProcessSession::setDocumentPassword(const int nPasswordType)
+{
+
+ if (_isDocPasswordProtected && _isDocPasswordProvided)
+ {
+ // it means this is the second attempt with the wrong password; abort load operation
+ _loKit->pClass->setDocumentPassword(_loKit, _jailedFilePath.c_str(), nullptr);
+ return;
+ }
+
+ // One thing for sure, this is a password protected document
+ _isDocPasswordProtected = true;
+
+ if (nPasswordType == LOK_CALLBACK_DOCUMENT_PASSWORD)
+ _docPasswordType = PasswordType::ToView;
+ else if (nPasswordType == LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY)
+ _docPasswordType = PasswordType::ToModify;
+
+ if (_isDocPasswordProvided)
+ _loKit->pClass->setDocumentPassword(_loKit, _jailedFilePath.c_str(), _docPassword.c_str());
+ else
+ _loKit->pClass->setDocumentPassword(_loKit, _jailedFilePath.c_str(), nullptr);
+}
+
void ChildProcessSession::loKitCallback(const int nType, const char *pPayload)
{
auto pNotif = new CallbackNotification(nType, pPayload ? pPayload : "(nil)");
diff --git a/loolwsd/ChildProcessSession.hpp b/loolwsd/ChildProcessSession.hpp
index 3e7c957..259dccb 100644
--- a/loolwsd/ChildProcessSession.hpp
+++ b/loolwsd/ChildProcessSession.hpp
@@ -14,6 +14,7 @@
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKit.h>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <Poco/Thread.h>
#include <Poco/NotificationQueue.h>
@@ -89,6 +90,8 @@ public:
const Statistics& getStatistics() const { return _stats; }
bool isInactive() const { return _stats.getInactivityMS() >= InactivityThresholdMS; }
+ void setDocumentPassword(const int nPasswordType);
+
protected:
virtual bool loadDocument(const char *buffer, int length, Poco::StringTokenizer& tokens) override;
@@ -120,6 +123,7 @@ private:
virtual bool _handleInput(const char *buffer, int length) override;
private:
+ LibreOfficeKit *_loKit;
LibreOfficeKitDocument *_loKitDocument;
std::string _docType;
const bool _multiView;
diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp
index 3895609..9c55ff3 100644
--- a/loolwsd/LOOLKit.cpp
+++ b/loolwsd/LOOLKit.cpp
@@ -44,6 +44,7 @@
#define LOK_USE_UNSTABLE_API
#include <LibreOfficeKit/LibreOfficeKitInit.h>
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include "Common.hpp"
#include "QueueHandler.hpp"
@@ -518,7 +519,11 @@ private:
Log::info("Loading new document from URI: [" + uri + "] for session [" + sessionId + "].");
if ( LIBREOFFICEKIT_HAS(_loKit, registerCallback))
+ {
_loKit->pClass->registerCallback(_loKit, DocumentCallback, this);
+ _loKit->pClass->setOptionalFeatures(_loKit, LOK_FEATURE_DOCUMENT_PASSWORD |
+ LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY);
+ }
// documentLoad will trigger callback, which needs to take the lock.
lock.unlock();
diff --git a/loolwsd/LOOLSession.cpp b/loolwsd/LOOLSession.cpp
index 9a59292..65eb0ea 100644
--- a/loolwsd/LOOLSession.cpp
+++ b/loolwsd/LOOLSession.cpp
@@ -87,6 +87,10 @@ LOOLSession::LOOLSession(const std::string& id, const Kind kind,
_kindString(kind == Kind::ToClient ? "ToClient" :
kind == Kind::ToMaster ? "ToMaster" : "ToPrisoner"),
_ws(ws),
+ _docPassword(""),
+ _isDocPasswordProvided(false),
+ _isDocLoaded(false),
+ _isDocPasswordProtected(false),
_bShutdown(false),
_disconnected(false)
{
@@ -171,6 +175,12 @@ void LOOLSession::parseDocOptions(const StringTokenizer& tokens, int& part, std:
timestamp = tokens[i].substr(strlen("timestamp="));
++offset;
}
+ else if (tokens[i].find("password=") == 0)
+ {
+ _docPassword = tokens[i].substr(strlen("password="));
+ _isDocPasswordProvided = true;
+ ++offset;
+ }
}
if (tokens.count() > offset)
diff --git a/loolwsd/LOOLSession.hpp b/loolwsd/LOOLSession.hpp
index 62769e2..9bc7f85 100644
--- a/loolwsd/LOOLSession.hpp
+++ b/loolwsd/LOOLSession.hpp
@@ -41,6 +41,11 @@ public:
/// 3) Ditto, in the jailed loolwsd process
enum class Kind { ToClient, ToPrisoner, ToMaster };
+ /// We have two types of password protected documents
+ /// 1) Documents which require password to view
+ /// 2) Document which require password to modify
+ enum class PasswordType { ToView, ToModify };
+
const std::string& getId() const { return _id; }
const std::string& getName() const { return _name; }
bool isDisconnected() const { return _disconnected; }
@@ -103,6 +108,21 @@ protected:
// The Jailed document path.
std::string _jailedFilePath;
+ // Password provided, if any, to open the document
+ std::string _docPassword;
+
+ // If password is provided or not
+ bool _isDocPasswordProvided;
+
+ // Whether document has been opened succesfuly
+ bool _isDocLoaded;
+
+ // Whether document is password protected
+ bool _isDocPasswordProtected;
+
+ // Whether password is required to view the document, or modify it
+ PasswordType _docPasswordType;
+
/// Document options: a JSON string, containing options (rendering, also possibly load in the future).
std::string _docOptions;
diff --git a/loolwsd/MasterProcessSession.cpp b/loolwsd/MasterProcessSession.cpp
index de04450..d9b4f33 100644
--- a/loolwsd/MasterProcessSession.cpp
+++ b/loolwsd/MasterProcessSession.cpp
@@ -125,6 +125,31 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
if (_kind == Kind::ToPrisoner)
{
+ if (tokens[0] == "error:")
+ {
+ std::string errorCommand;
+ std::string errorKind;
+ if (getTokenString(tokens[1], "cmd", errorCommand) &&
+ getTokenString(tokens[2], "kind", errorKind) )
+ {
+ if (errorCommand == "load")
+ {
+ if (errorKind == "passwordrequired:to-view" ||
+ errorKind == "passwordrequired:to-modify" ||
+ errorKind == "wrongpassword")
+ {
+ _isDocPasswordProtected = true;
+ // Reset docURL so that client can send another load request with password
+ peer->_docURL = "";
+ // disconnect 'ToPrisoner' after letting client know that password is required
+ forwardToPeer(buffer, length);
+ LOOLSession::disconnect();
+ return false;
+ }
+ }
+ }
+ }
+
if (tokens[0] == "curpart:" &&
tokens.count() == 2 &&
getTokenInteger(tokens[1], "part", _curPart))
@@ -157,7 +182,7 @@ bool MasterProcessSession::_handleInput(const char *buffer, int length)
}
}
- if (_kind == Kind::ToPrisoner && peer && peer->_tileCache)
+ if (_kind == Kind::ToPrisoner && peer && peer->_tileCache && !_isDocPasswordProtected)
{
if (tokens[0] == "tile:")
{
@@ -789,6 +814,9 @@ void MasterProcessSession::dispatchChild()
if (_loadPart >= 0)
oss << " part=" + std::to_string(_loadPart);
+ if (_isDocPasswordProvided)
+ oss << " password=" << _docPassword;
+
if (!_docOptions.empty())
oss << " options=" << _docOptions;
More information about the Libreoffice-commits
mailing list