summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/inc/lib/init.hxx5
-rw-r--r--desktop/source/lib/init.cxx29
-rw-r--r--desktop/source/lib/lokinteractionhandler.cxx89
-rw-r--r--desktop/source/lib/lokinteractionhandler.hxx15
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.h5
-rw-r--r--include/LibreOfficeKit/LibreOfficeKit.hxx24
-rw-r--r--include/LibreOfficeKit/LibreOfficeKitEnums.h19
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx8
8 files changed, 190 insertions, 4 deletions
diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx
index 9003859e5eba..ee598a0c07b0 100644
--- a/desktop/inc/lib/init.hxx
+++ b/desktop/inc/lib/init.hxx
@@ -14,9 +14,12 @@
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <memory>
+#include <map>
#include "../../source/inc/desktopdllapi.h"
#include <osl/thread.h>
+class LOKInteractionHandler;
+
namespace desktop {
struct DESKTOP_DLLPUBLIC LibLODocument_Impl : public _LibreOfficeKitDocument
{
@@ -36,8 +39,10 @@ namespace desktop {
oslThread maThread;
LibreOfficeKitCallback mpCallback;
void *mpCallbackData;
+ std::map<OString, rtl::Reference<LOKInteractionHandler>> mInteractionMap;
LibLibreOffice_Impl();
+ ~LibLibreOffice_Impl();
};
}
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index f2f90346a737..d022f6f69ba3 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -438,6 +438,9 @@ static void lo_registerCallback (LibreOfficeKit* pThis,
LibreOfficeKitCallback pCallback,
void* pData);
static char* lo_getFilterTypes(LibreOfficeKit* pThis);
+static void lo_setDocumentPassword(LibreOfficeKit* pThis,
+ const char* pURL,
+ const char* pPassword);
LibLibreOffice_Impl::LibLibreOffice_Impl()
: m_pOfficeClass( gOfficeClass.lock() )
@@ -456,6 +459,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl()
m_pOfficeClass->documentLoadWithOptions = lo_documentLoadWithOptions;
m_pOfficeClass->registerCallback = lo_registerCallback;
m_pOfficeClass->getFilterTypes = lo_getFilterTypes;
+ m_pOfficeClass->setDocumentPassword = lo_setDocumentPassword;
gOfficeClass = m_pOfficeClass;
}
@@ -463,6 +467,10 @@ LibLibreOffice_Impl::LibLibreOffice_Impl()
pClass = m_pOfficeClass.get();
}
+LibLibreOffice_Impl::~LibLibreOffice_Impl()
+{
+}
+
namespace
{
@@ -524,7 +532,10 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis,
uno::makeAny(OUString::createFromAscii(pOptions)),
beans::PropertyState_DIRECT_VALUE);
- uno::Reference<task::XInteractionHandler2> xInteraction(new LOKInteractionHandler(::comphelper::getProcessComponentContext()));
+ rtl::Reference<LOKInteractionHandler> const pInteraction(
+ new LOKInteractionHandler(::comphelper::getProcessComponentContext(), pLib));
+ auto const pair(pLib->mInteractionMap.insert(std::make_pair(aURL.toUtf8(), pInteraction)));
+ uno::Reference<task::XInteractionHandler2> const xInteraction(pInteraction.get());
aFilterOptions[1].Name = "InteractionHandler";
aFilterOptions[1].Value <<= xInteraction;
@@ -543,6 +554,12 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis,
aURL, "_blank", 0,
aFilterOptions);
+ assert(!xComponent.is() || pair.second); // concurrent loading of same URL ought to fail
+ if (!pair.second)
+ {
+ pLib->mInteractionMap.erase(aURL.toUtf8());
+ }
+
if (!xComponent.is())
{
pLib->maLastExceptionMsg = "loadComponentFromURL returned an empty reference";
@@ -1616,6 +1633,16 @@ static char* lo_getFilterTypes(LibreOfficeKit* pThis)
return strdup(aStream.str().c_str());
}
+static void lo_setDocumentPassword(LibreOfficeKit* pThis,
+ const char* pURL, const char* pPassword)
+{
+ assert(pThis);
+ assert(pURL);
+ LibLibreOffice_Impl *const pLib = static_cast<LibLibreOffice_Impl*>(pThis);
+ assert(pLib->mInteractionMap.find(OString(pURL)) != pLib->mInteractionMap.end());
+ pLib->mInteractionMap.find(OString(pURL))->second->SetPassword(pPassword);
+}
+
static void force_c_locale()
{
// force locale (and resource files loaded) to en-US
diff --git a/desktop/source/lib/lokinteractionhandler.cxx b/desktop/source/lib/lokinteractionhandler.cxx
index 713709459243..6b2f21922099 100644
--- a/desktop/source/lib/lokinteractionhandler.cxx
+++ b/desktop/source/lib/lokinteractionhandler.cxx
@@ -19,14 +19,27 @@
#include "lokinteractionhandler.hxx"
+#include <rtl/ref.hxx>
#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/task/XInteractionAbort.hpp>
#include <com/sun/star/task/XInteractionApprove.hpp>
+#include <com/sun/star/task/XInteractionPassword2.hpp>
+#include <com/sun/star/task/DocumentPasswordRequest2.hpp>
+
+#include <../../inc/lib/init.hxx>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
using namespace com::sun::star;
-LOKInteractionHandler::LOKInteractionHandler(uno::Reference<uno::XComponentContext> const & /*rxContext*/)
+LOKInteractionHandler::LOKInteractionHandler(
+ uno::Reference<uno::XComponentContext> const & /*rxContext*/,
+ desktop::LibLibreOffice_Impl *const pLOKit)
+ : m_pLOKit(pLOKit)
+ , m_usePassword(false)
{
+ assert(m_pLOKit);
}
LOKInteractionHandler::~LOKInteractionHandler()
@@ -72,6 +85,66 @@ throw (uno::RuntimeException, std::exception)
{
uno::Sequence<uno::Reference<task::XInteractionContinuation>> const &rContinuations = xRequest->getContinuations();
+ uno::Any const request(xRequest->getRequest());
+ task::DocumentPasswordRequest2 passwordRequest;
+ if (request >>= passwordRequest)
+ {
+ OString const url(passwordRequest.Name.toUtf8());
+ m_pLOKit->mpCallback(passwordRequest.IsRequestPasswordToModify
+ ? LOK_CALLBACK_DOCUMENT_PASSWORD
+ : LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY,
+ url.getStr(),
+ m_pLOKit->mpCallbackData);
+
+ // block until SetPassword is called
+ m_havePassword.wait(nullptr);
+ m_havePassword.reset();
+
+ for (sal_Int32 i = 0; i < rContinuations.getLength(); ++i)
+ {
+ if (m_usePassword)
+ {
+ if (passwordRequest.IsRequestPasswordToModify)
+ {
+ uno::Reference<task::XInteractionPassword2> const xIPW2(
+ rContinuations[i], uno::UNO_QUERY);
+ xIPW2->setPasswordToModify(m_Password);
+ xIPW2->select();
+ }
+ else
+ {
+ uno::Reference<task::XInteractionPassword> const xIPW(
+ rContinuations[i], uno::UNO_QUERY);
+ if (xIPW.is())
+ {
+ xIPW->setPassword(m_Password);
+ xIPW->select();
+ }
+ }
+ }
+ else
+ {
+ if (passwordRequest.IsRequestPasswordToModify)
+ {
+ uno::Reference<task::XInteractionPassword2> const xIPW2(
+ rContinuations[i], uno::UNO_QUERY);
+ xIPW2->setRecommendReadOnly(true);
+ xIPW2->select();
+ }
+ else
+ {
+ uno::Reference<task::XInteractionAbort> const xAbort(
+ rContinuations[i], uno::UNO_QUERY);
+ if (xAbort.is())
+ {
+ xAbort->select();
+ }
+ }
+ }
+ }
+ return sal_True;
+ }
+
// TODO: add LOK api that allows handling this for real, for the moment we
// just set the interaction as 'Approved'
for (sal_Int32 i = 0; i < rContinuations.getLength(); ++i)
@@ -84,4 +157,18 @@ throw (uno::RuntimeException, std::exception)
return sal_True;
}
+void LOKInteractionHandler::SetPassword(char const*const pPassword)
+{
+ if (pPassword)
+ {
+ m_Password = OUString(pPassword, strlen(pPassword), RTL_TEXTENCODING_UTF8);
+ m_usePassword = true;
+ }
+ else
+ {
+ m_usePassword = false;
+ }
+ m_havePassword.set();
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/lib/lokinteractionhandler.hxx b/desktop/source/lib/lokinteractionhandler.hxx
index 5b14154a6e61..85a71da7efae 100644
--- a/desktop/source/lib/lokinteractionhandler.hxx
+++ b/desktop/source/lib/lokinteractionhandler.hxx
@@ -20,12 +20,15 @@
#ifndef INCLUDED_DESKTOP_SOURCE_LIB_LOKINTERACTIONHANDLER_HXX
#define INCLUDED_DESKTOP_SOURCE_LIB_LOKINTERACTIONHANDLER_HXX
+#include <osl/conditn.hxx>
#include <cppuhelper/implbase.hxx>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/task/InteractionHandler.hpp>
+namespace desktop { struct LibLibreOffice_Impl; }
+
/** InteractionHandler is an interface that provides the user with various dialogs / error messages.
We need an own implementation for the LibreOfficeKit so that we can route the
@@ -38,11 +41,21 @@ class LOKInteractionHandler: public cppu::WeakImplHelper<com::sun::star::lang::X
com::sun::star::lang::XInitialization,
com::sun::star::task::XInteractionHandler2>
{
+private:
+ desktop::LibLibreOffice_Impl * m_pLOKit;
+ OUString m_Password;
+ bool m_usePassword;
+ osl::Condition m_havePassword;
+
LOKInteractionHandler(const LOKInteractionHandler&) = delete;
LOKInteractionHandler& operator=(const LOKInteractionHandler&) = delete;
public:
- explicit LOKInteractionHandler(com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const & rxContext);
+ void SetPassword(char const* pPassword);
+
+ explicit LOKInteractionHandler(
+ com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> const & rxContext,
+ desktop::LibLibreOffice_Impl *);
virtual ~LOKInteractionHandler();
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h
index 663f62034945..5a20ec5e47a1 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -64,6 +64,11 @@ struct _LibreOfficeKitClass
/// @see lok::Office::getFilterTypes().
char* (*getFilterTypes) (LibreOfficeKit* pThis);
+
+ /// @see lok::Office::setDocumentPassword().
+ void (*setDocumentPassword) (LibreOfficeKit* pThis,
+ char const* pURL,
+ char const* pPassword);
#endif
};
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx
index ee2b27e92aff..57066c69c18c 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -460,6 +460,30 @@ public:
{
return mpThis->pClass->getFilterTypes(mpThis);
}
+
+ /**
+ * Set password required for loading or editing a document.
+ *
+ * Loading the document is blocked until the password is provided.
+ *
+ * @param pURL the URL of the document, as sent to the callback
+ * @param pPassword the password, nullptr indicates no password
+ *
+ * In response to LOK_CALLBACK_DOCUMENT_PASSWORD, a vaild password
+ * will continue loading the document, an invalid password will
+ * result in another LOK_CALLBACK_DOCUMENT_PASSWORD request,
+ * and a NULL password will abort loading the document.
+ *
+ * In response to LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY, a vaild
+ * password will continue loading the document, an invalid password will
+ * result in another LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY request,
+ * and a NULL password will continue loading the document in read-only
+ * mode.
+ */
+ inline void setDocumentPassword(char const* pURL, char const* pPassword)
+ {
+ mpThis->pClass->setDocumentPassword(mpThis, pURL, pPassword);
+ }
#endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY
};
diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index 5509166c14e3..395b2b761891 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -221,7 +221,24 @@ typedef enum
/**
* The text content of the formula bar in Calc.
*/
- LOK_CALLBACK_CELL_FORMULA
+ LOK_CALLBACK_CELL_FORMULA,
+
+ /**
+ * Loading a document requires a password.
+ *
+ * Loading the document is blocked until the password is provided via
+ * lok::Office::setDocumentPassword(). The document cannot be loaded
+ * without the password.
+ */
+ LOK_CALLBACK_DOCUMENT_PASSWORD,
+
+ /**
+ * Editing a document requires a password.
+ *
+ * Loading the document is blocked until the password is provided via
+ * lok::Office::setDocumentPassword().
+ */
+ LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY,
}
LibreOfficeKitCallbackType;
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 73f27bc9fe0d..2b61e76d6136 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -809,6 +809,14 @@ globalCallback (gpointer pData)
g_signal_emit (pCallback->m_pDocView, doc_view_signals[LOAD_CHANGED], 0, 1.0);
}
break;
+ case LOK_CALLBACK_DOCUMENT_PASSWORD:
+ case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
+ {
+ char const*const pURL(pCallback->m_aPayload.c_str());
+ // TODO maybe allow more passwords
+ priv->m_pOffice->pClass->setDocumentPassword(priv->m_pOffice, pURL, "1");
+ }
+ break;
default:
g_assert(false);
break;