LibreOffice Module desktop (master) 1
lokinteractionhandler.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
21
24
25#include <com/sun/star/task/XInteractionAbort.hpp>
26#include <com/sun/star/task/XInteractionApprove.hpp>
27#include <com/sun/star/task/XInteractionPassword2.hpp>
28#include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
29#include <com/sun/star/task/InteractionHandler.hpp>
30#include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
31#include <com/sun/star/ucb/InteractiveNetworkOffLineException.hpp>
32
33#include <com/sun/star/ucb/InteractiveIOException.hpp>
34#include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
35#include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
36#include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
37
38#include <com/sun/star/task/DocumentPasswordRequest2.hpp>
39#include <com/sun/star/task/DocumentMSPasswordRequest2.hpp>
40
41#include <com/sun/star/document/FilterOptionsRequest.hpp>
42
43#include "../../inc/lib/init.hxx"
44
45#include <LibreOfficeKit/LibreOfficeKitEnums.h>
46#include <sfx2/lokhelper.hxx>
47#include <sfx2/viewsh.hxx>
48#include <utility>
49#include <vcl/svapp.hxx>
50
51#include <tools/json_writer.hxx>
52
53using namespace com::sun::star;
54
56 OString command,
57 desktop::LibLibreOffice_Impl *const pLOKit,
58 desktop::LibLODocument_Impl *const pLOKDocument)
59 : m_pLOKit(pLOKit)
60 , m_pLOKDocument(pLOKDocument)
61 , m_command(std::move(command))
62 , m_usePassword(false)
63{
64 assert(m_pLOKit);
65}
66
68{
69}
70
72{
73 return "com.sun.star.comp.uui.LOKInteractionHandler";
74}
75
76sal_Bool SAL_CALL LOKInteractionHandler::supportsService(OUString const & rServiceName)
77{
78 return cppu::supportsService(this, rServiceName);
79}
80
82{
83 return { "com.sun.star.task.InteractionHandler",
84 // added to indicate support for configuration.backend.MergeRecoveryRequest
85 "com.sun.star.configuration.backend.InteractionHandler",
86 // for backwards compatibility
87 "com.sun.star.uui.InteractionHandler" };
88}
89
91{
92}
93
96{
97 // just do the same thing in both cases
99}
100
101void LOKInteractionHandler::postError(css::task::InteractionClassification classif, const char* kind, ErrCode code, const OUString &message)
102{
103 std::string classification = "error";
104 switch (classif)
105 {
106 case task::InteractionClassification_ERROR: break;
107 case task::InteractionClassification_WARNING: classification = "warning"; break;
108 case task::InteractionClassification_INFO: classification = "info"; break;
109 case task::InteractionClassification_QUERY: classification = "query"; break;
110 default: assert(false); break;
111 }
112
113 // create the JSON representation
114 tools::JsonWriter aJson;
115 aJson.put("classification", classification);
116 aJson.put("cmd", m_command.getStr());
117 aJson.put("kind", kind);
118 aJson.put("code", static_cast<sal_uInt32>(code));
119 aJson.put("message", message.toUtf8());
120
121 std::size_t nView = SfxViewShell::Current() ? SfxLokHelper::getView() : 0;
123 m_pLOKDocument->mpCallbackFlushHandlers[nView]->queue(LOK_CALLBACK_ERROR, aJson.finishAndGetAsOString());
124 else if (m_pLOKit->mpCallback)
125 m_pLOKit->mpCallback(LOK_CALLBACK_ERROR, aJson.finishAndGetAsOString().getStr(), m_pLOKit->mpCallbackData);
126}
127
128namespace {
129
131void selectApproved(uno::Sequence<uno::Reference<task::XInteractionContinuation>> const &rContinuations)
132{
133 for (auto const & c : rContinuations)
134 {
135 uno::Reference<task::XInteractionApprove> xApprove(c, uno::UNO_QUERY);
136 if (xApprove.is())
137 xApprove->select();
138 }
139}
140
141}
142
143bool LOKInteractionHandler::handleIOException(const css::uno::Sequence<css::uno::Reference<css::task::XInteractionContinuation>> &rContinuations, const css::uno::Any& rRequest)
144{
145 ucb::InteractiveIOException aIoException;
146 if (!(rRequest >>= aIoException))
147 return false;
148
149 static ErrCode const aErrorCode[int(ucb::IOErrorCode_WRONG_VERSION) + 1] =
150 {
187 };
188
189 postError(aIoException.Classification, "io", aErrorCode[static_cast<int>(aIoException.Code)], "");
190 selectApproved(rContinuations);
191
192 return true;
193}
194
196{
197 ucb::InteractiveNetworkException aNetworkException;
198 if (!(rRequest >>= aNetworkException))
199 return false;
200
201 ErrCode nErrorCode;
202 OUString aMessage;
203
204 ucb::InteractiveNetworkOffLineException aOffLineException;
205 ucb::InteractiveNetworkResolveNameException aResolveNameException;
206 ucb::InteractiveNetworkConnectException aConnectException;
207 ucb::InteractiveNetworkReadException aReadException;
208 ucb::InteractiveNetworkWriteException aWriteException;
209 if (rRequest >>= aOffLineException)
210 {
211 nErrorCode = ERRCODE_INET_OFFLINE;
212 }
213 else if (rRequest >>= aResolveNameException)
214 {
215 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
216 aMessage = aResolveNameException.Server;
217 }
218 else if (rRequest >>= aConnectException)
219 {
220 nErrorCode = ERRCODE_INET_CONNECT;
221 aMessage = aConnectException.Server;
222 }
223 else if (rRequest >>= aReadException)
224 {
225 nErrorCode = ERRCODE_INET_READ;
226 aMessage = aReadException.Diagnostic;
227 }
228 else if (rRequest >>= aWriteException)
229 {
230 nErrorCode = ERRCODE_INET_WRITE;
231 aMessage = aWriteException.Diagnostic;
232 }
233 else
234 {
235 nErrorCode = ERRCODE_INET_GENERAL;
236 }
237
238 postError(aNetworkException.Classification, "network", nErrorCode, aMessage);
239 selectApproved(rContinuations);
240
241 return true;
242}
243
245{
246 bool bPasswordRequestFound = false;
247 bool bIsRequestPasswordToModify = false;
248
249 OString sUrl;
250
251 task::DocumentPasswordRequest passwordRequest;
252 if (rRequest >>= passwordRequest)
253 {
254 bIsRequestPasswordToModify = false;
255 sUrl = passwordRequest.Name.toUtf8();
256 bPasswordRequestFound = true;
257 }
258
259 task::DocumentPasswordRequest2 passwordRequest2;
260 if (rRequest >>= passwordRequest2)
261 {
262 bIsRequestPasswordToModify = passwordRequest2.IsRequestPasswordToModify;
263 sUrl = passwordRequest2.Name.toUtf8();
264 bPasswordRequestFound = true;
265 }
266
267 task::DocumentMSPasswordRequest2 passwordMSRequest;
268 if (rRequest >>= passwordMSRequest)
269 {
270 bIsRequestPasswordToModify = passwordMSRequest.IsRequestPasswordToModify;
271 sUrl = passwordMSRequest.Name.toUtf8();
272 bPasswordRequestFound = true;
273 }
274
275 if (!bPasswordRequestFound)
276 return false;
277
278 if (m_pLOKit->mpCallback &&
279 m_pLOKit->hasOptionalFeature(bIsRequestPasswordToModify ? LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY
280 : LOK_FEATURE_DOCUMENT_PASSWORD))
281 {
282 // release SolarMutex, so the callback handler, which may run in another thread,
283 // can acquire it in 'lo_setDocumentPassword'
284 SolarMutexReleaser aReleaser;
285 m_pLOKit->mpCallback(bIsRequestPasswordToModify ? LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY
286 : LOK_CALLBACK_DOCUMENT_PASSWORD,
287 sUrl.getStr(),
289
290 // block until SetPassword is called
291 m_havePassword.wait();
292 m_havePassword.reset();
293 }
294
295 for (auto const & cont : rContinuations)
296 {
297 if (m_usePassword)
298 {
299 if (bIsRequestPasswordToModify)
300 {
301 uno::Reference<task::XInteractionPassword2> const xIPW2(cont, uno::UNO_QUERY);
302 xIPW2->setPasswordToModify(m_Password);
303 xIPW2->select();
304 }
305 else
306 {
307 uno::Reference<task::XInteractionPassword> const xIPW(cont, uno::UNO_QUERY);
308 if (xIPW.is())
309 {
310 xIPW->setPassword(m_Password);
311 xIPW->select();
312 }
313 }
314 }
315 else
316 {
317 if (bIsRequestPasswordToModify)
318 {
319 uno::Reference<task::XInteractionPassword2> const xIPW2(cont, uno::UNO_QUERY);
320 xIPW2->setRecommendReadOnly(true);
321 xIPW2->select();
322 }
323 else
324 {
325 uno::Reference<task::XInteractionAbort> const xAbort(cont, uno::UNO_QUERY);
326 if (xAbort.is())
327 {
328 xAbort->select();
329 }
330 }
331 }
332 }
333 return true;
334}
335
337{
338 uno::Any const request(xRequest->getRequest());
339
340 task::DocumentMacroConfirmationRequest aConfirmRequest;
341 if (request >>= aConfirmRequest)
342 {
343 auto xInteraction(task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr));
344
345 if (xInteraction.is())
346 xInteraction->handleInteractionRequest(xRequest);
347
348 return true;
349 }
350 return false;
351}
352
354{
355 document::FilterOptionsRequest aFilterOptionsRequest;
356 uno::Any const request(xRequest->getRequest());
357 if (request >>= aFilterOptionsRequest)
358 {
360 task::InteractionHandler::createWithParent(
361 ::comphelper::getProcessComponentContext(), nullptr));
362
363 if (xInteraction.is())
364 xInteraction->handleInteractionRequest(xRequest);
365
366 return true;
367 }
368 return false;
369}
370
373{
374 uno::Sequence<uno::Reference<task::XInteractionContinuation>> const &rContinuations = xRequest->getContinuations();
375 uno::Any const request(xRequest->getRequest());
376
377 if (handleIOException(rContinuations, request))
378 return true;
379
380 if (handleNetworkException(rContinuations, request))
381 return true;
382
383 if (handlePasswordRequest(rContinuations, request))
384 return true;
385
386 if (handleFilterOptionsRequest(xRequest))
387 return true;
388
389 if (handleMacroConfirmationRequest(xRequest))
390 return true;
391
392 // TODO: perform more interactions 'for real' like the above
393 selectApproved(rContinuations);
394
395 return true;
396}
397
398void LOKInteractionHandler::SetPassword(char const*const pPassword)
399{
400 if (pPassword)
401 {
402 m_Password = OUString(pPassword, strlen(pPassword), RTL_TEXTENCODING_UTF8);
403 m_usePassword = true;
404 }
405 else
406 {
407 m_usePassword = false;
408 }
409 m_havePassword.set();
410}
411
412/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool handleIOException(const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > &rContinuations, const css::uno::Any &rRequest)
desktop::LibLODocument_Impl * m_pLOKDocument
desktop::LibLibreOffice_Impl * m_pLOKit
void postError(css::task::InteractionClassification classif, const char *kind, ErrCode code, const OUString &message)
Call the LOK_CALLBACK_ERROR on the LOK document (if available) or LOK lib.
virtual ~LOKInteractionHandler() override
LOKInteractionHandler(const LOKInteractionHandler &)=delete
virtual OUString SAL_CALL getImplementationName() override
virtual com::sun::star::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void SetPassword(char const *pPassword)
bool handleNetworkException(const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > &rContinuations, const css::uno::Any &rRequest)
virtual sal_Bool SAL_CALL supportsService(OUString const &rServiceName) override
bool handlePasswordRequest(const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > &rContinuations, const css::uno::Any &rRequest)
static bool handleFilterOptionsRequest(const ::com::sun::star::uno::Reference<::com::sun::star::task::XInteractionRequest > &Request)
virtual sal_Bool SAL_CALL handleInteractionRequest(const ::com::sun::star::uno::Reference<::com::sun::star::task::XInteractionRequest > &Request) override
OString m_command
Command for which we use this interaction handler (like "load", "save", "saveas", ....
virtual void SAL_CALL initialize(com::sun::star::uno::Sequence< com::sun::star::uno::Any > const &rArguments) override
static bool handleMacroConfirmationRequest(const css::uno::Reference< css::task::XInteractionRequest > &xRequest)
virtual void SAL_CALL handle(com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest > const &rRequest) override
static int getView(const SfxViewShell *pViewShell=nullptr)
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
void put(std::u16string_view pPropName, const OUString &rPropValue)
OString finishAndGetAsOString()
#define ERRCODE_IO_INVALIDLENGTH
#define ERRCODE_IO_BADCRC
#define ERRCODE_IO_ACCESSDENIED
#define ERRCODE_INET_WRITE
#define ERRCODE_IO_MISPLACEDCHAR
#define ERRCODE_IO_CANTTELL
#define ERRCODE_IO_OUTOFSPACE
#define ERRCODE_INET_GENERAL
#define ERRCODE_IO_INVALIDDEVICE
#define ERRCODE_IO_CURRENTDIR
#define ERRCODE_IO_NOTADIRECTORY
#define ERRCODE_IO_ABORT
#define ERRCODE_IO_CANTREAD
#define ERRCODE_IO_CANTCREATE
#define ERRCODE_IO_LOCKVIOLATION
#define ERRCODE_IO_GENERAL
#define ERRCODE_IO_NOTSAMEDEVICE
#define ERRCODE_IO_PENDING
#define ERRCODE_INET_OFFLINE
#define ERRCODE_IO_WRONGVERSION
#define ERRCODE_IO_CANTSEEK
#define ERRCODE_IO_DEVICENOTREADY
#define ERRCODE_IO_NOTEXISTSPATH
#define ERRCODE_IO_CANTWRITE
#define ERRCODE_IO_WRONGFORMAT
#define ERRCODE_INET_READ
#define ERRCODE_IO_NOTEXISTS
#define ERRCODE_IO_RECURSIVE
#define ERRCODE_IO_ALREADYEXISTS
#define ERRCODE_IO_INVALIDCHAR
#define ERRCODE_IO_NOTSUPPORTED
#define ERRCODE_IO_UNKNOWN
#define ERRCODE_IO_WRITEPROTECTED
#define ERRCODE_INET_CONNECT
#define ERRCODE_IO_INVALIDACCESS
#define ERRCODE_INET_NAME_RESOLVE
#define ERRCODE_IO_OUTOFMEMORY
#define ERRCODE_IO_NAMETOOLONG
#define ERRCODE_IO_TOOMANYOPENFILES
#define ERRCODE_IO_NOTAFILE
#define ERRCODE_IO_ISWILDCARD
#define ERRCODE_IO_INVALIDPARAMETER
Reference< XComponentContext > getProcessComponentContext()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
sal_Unicode code
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
std::map< size_t, std::shared_ptr< CallbackFlushHandler > > mpCallbackFlushHandlers
Definition: init.hxx:251
LibreOfficeKitCallback mpCallback
Definition: init.hxx:265
bool hasOptionalFeature(LibreOfficeKitOptionalFeatures const feature)
Definition: init.hxx:273
unsigned char sal_Bool