diff options
-rw-r--r-- | desktop/inc/lib/init.hxx | 5 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 29 | ||||
-rw-r--r-- | desktop/source/lib/lokinteractionhandler.cxx | 89 | ||||
-rw-r--r-- | desktop/source/lib/lokinteractionhandler.hxx | 15 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.h | 5 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.hxx | 24 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKitEnums.h | 19 | ||||
-rw-r--r-- | libreofficekit/source/gtk/lokdocview.cxx | 8 |
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; |