Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / uui / source / iahndl.cxx
blobce5dfffa88dba9cce36f32a0a5bdbeb459de01d7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <memory>
22 #include <com/sun/star/awt/XWindow.hpp>
23 #include <com/sun/star/configuration/theDefaultProvider.hpp>
24 #include <com/sun/star/configuration/backend/MergeRecoveryRequest.hpp>
25 #include <com/sun/star/configuration/backend/StratumCreationException.hpp>
26 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
27 #include <com/sun/star/document/BrokenPackageRequest.hpp>
28 #include <com/sun/star/document/ExoticFileLoadException.hpp>
29 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
30 #include <com/sun/star/java/WrongJavaVersionException.hpp>
31 #include <com/sun/star/lang/XInitialization.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/script/ModuleSizeExceededRequest.hpp>
34 #include <com/sun/star/task/ErrorCodeIOException.hpp>
35 #include <com/sun/star/task/ErrorCodeRequest.hpp>
36 #include <com/sun/star/task/InteractionHandler.hpp>
37 #include <com/sun/star/task/XInteractionAbort.hpp>
38 #include <com/sun/star/task/XInteractionApprove.hpp>
39 #include <com/sun/star/task/XInteractionDisapprove.hpp>
40 #include <com/sun/star/task/XInteractionHandler2.hpp>
41 #include <com/sun/star/task/XInteractionRequest.hpp>
42 #include <com/sun/star/ucb/AuthenticationFallbackRequest.hpp>
43 #include <com/sun/star/ucb/InteractiveAppException.hpp>
44 #include <com/sun/star/ucb/InteractiveLockingLockedException.hpp>
45 #include <com/sun/star/ucb/InteractiveLockingNotLockedException.hpp>
46 #include <com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp>
47 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
48 #include <com/sun/star/ucb/InteractiveNetworkOffLineException.hpp>
49 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
50 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
51 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
52 #include <com/sun/star/ucb/InteractiveWrongMediumException.hpp>
53 #include <com/sun/star/ucb/NameClashException.hpp>
54 #include <com/sun/star/ucb/NameClashResolveRequest.hpp>
55 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
56 #include <com/sun/star/ucb/XInteractionReplaceExistingData.hpp>
57 #include <com/sun/star/ucb/XInteractionSupplyName.hpp>
58 #include <com/sun/star/xforms/InvalidDataOnSubmitException.hpp>
59 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
61 #include <sal/log.hxx>
62 #include <rtl/ustrbuf.hxx>
63 #include <osl/conditn.hxx>
64 #include <unotools/resmgr.hxx>
65 #include <utility>
66 #include <vcl/errinf.hxx>
67 #include <vcl/svapp.hxx>
68 #include <vcl/weld.hxx>
69 #include <comphelper/diagnose_ex.hxx>
70 #include <comphelper/documentconstants.hxx>
71 #include <comphelper/propertysequence.hxx>
72 #include <svtools/sfxecode.hxx>
73 #include <unotools/configmgr.hxx>
74 #include <comphelper/namedvaluecollection.hxx>
75 #include <typelib/typedescription.hxx>
76 #include <unotools/confignode.hxx>
78 #include <ids.hxx>
79 #include <ids.hrc>
80 #include <strings.hrc>
82 #include "getcontinuations.hxx"
83 #include "secmacrowarnings.hxx"
85 #include "iahndl.hxx"
86 #include "nameclashdlg.hxx"
88 using ::com::sun::star::uno::Sequence;
89 using ::com::sun::star::uno::UNO_QUERY;
90 using ::com::sun::star::uno::Reference;
91 using ::com::sun::star::task::XInteractionContinuation;
92 using ::com::sun::star::task::XInteractionAbort;
93 using ::com::sun::star::task::XInteractionApprove;
94 using ::com::sun::star::uno::XInterface;
95 using ::com::sun::star::lang::XInitialization;
96 using ::com::sun::star::uno::UNO_QUERY_THROW;
97 using ::com::sun::star::task::InteractionHandler;
98 using ::com::sun::star::task::XInteractionHandler2;
99 using ::com::sun::star::uno::Exception;
100 using ::com::sun::star::uno::Any;
101 using ::com::sun::star::task::XInteractionRequest;
102 using ::com::sun::star::lang::XMultiServiceFactory;
104 using namespace ::com::sun::star;
106 namespace {
108 class HandleData : public osl::Condition
110 public:
111 explicit HandleData(
112 uno::Reference< task::XInteractionRequest > xRequest)
113 : m_rRequest(std::move(xRequest)),
114 bHandled( false )
117 uno::Reference< task::XInteractionRequest > m_rRequest;
118 bool bHandled;
119 beans::Optional< OUString > m_aResult;
122 } /* namespace */
124 UUIInteractionHelper::UUIInteractionHelper(
125 uno::Reference< uno::XComponentContext > xContext)
126 : m_xContext(std::move(xContext))
130 UUIInteractionHelper::~UUIInteractionHelper()
134 void UUIInteractionHelper::handlerequest(
135 void* pHandleData, void* pInteractionHelper)
137 HandleData* pHND
138 = static_cast< HandleData * >(pHandleData);
139 UUIInteractionHelper* pUUI
140 = static_cast< UUIInteractionHelper * >(pInteractionHelper);
141 bool bDummy = false;
142 OUString aDummy;
143 pHND->bHandled
144 = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy);
145 pHND->set();
148 bool
149 UUIInteractionHelper::handleRequest(
150 uno::Reference< task::XInteractionRequest > const & rRequest)
152 if(!Application::IsMainThread() && GetpApp())
154 // we are not in the main thread, let it handle that stuff
155 HandleData aHD(rRequest);
156 Link<void*,void> aLink(&aHD,handlerequest);
157 Application::PostUserEvent(aLink,this);
158 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
159 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
160 aHD.wait();
161 if (nLockCount)
162 rSolarMutex.acquire(nLockCount);
163 return aHD.bHandled;
165 else
167 bool bDummy = false;
168 OUString aDummy;
169 return handleRequest_impl(rRequest, false, bDummy, aDummy);
173 void UUIInteractionHelper::getstringfromrequest(
174 void* pHandleData,void* pInteractionHelper)
176 HandleData* pHND = static_cast<HandleData*>(pHandleData);
177 UUIInteractionHelper* pUUI = static_cast<UUIInteractionHelper*>(pInteractionHelper);
178 pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest);
179 pHND->set();
182 beans::Optional< OUString >
183 UUIInteractionHelper::getStringFromRequest_impl(
184 uno::Reference< task::XInteractionRequest > const & rRequest)
186 bool bSuccess = false;
187 OUString aMessage;
188 handleRequest_impl(rRequest, true, bSuccess, aMessage);
190 OSL_ENSURE(bSuccess ||
191 !isInformationalErrorMessageRequest(
192 rRequest->getContinuations()),
193 "Interaction request is a candidate for a string representation."
194 "Please implement!");
196 return beans::Optional< OUString >(bSuccess, aMessage);
199 beans::Optional< OUString >
200 UUIInteractionHelper::getStringFromRequest(
201 uno::Reference< task::XInteractionRequest > const & rRequest)
203 if(!Application::IsMainThread() && GetpApp())
205 // we are not in the main thread, let it handle that stuff
206 HandleData aHD(rRequest);
207 Link<void*,void> aLink(&aHD,getstringfromrequest);
208 Application::PostUserEvent(aLink,this);
209 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
210 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
211 aHD.wait();
212 if (nLockCount)
213 rSolarMutex.acquire(nLockCount);
214 return aHD.m_aResult;
216 else
217 return getStringFromRequest_impl(rRequest);
220 OUString
221 UUIInteractionHelper::replaceMessageWithArguments(
222 const OUString& _aMessage,
223 std::vector< OUString > const & rArguments )
225 OUString aMessage = _aMessage;
227 SAL_WARN_IF(rArguments.empty(), "uui", "replaceMessageWithArguments: No arguments passed!");
228 for (size_t i = 0; i < rArguments.size(); ++i)
230 const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")";
231 aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]);
234 return aMessage;
237 bool
238 UUIInteractionHelper::isInformationalErrorMessageRequest(
239 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
240 rContinuations)
242 // Only requests with a single continuation (user has no choice, request
243 // is just informational)
244 if (rContinuations.getLength() != 1 )
245 return false;
247 // user can only abort or approve, all other continuations are not
248 // considered to be informational.
249 uno::Reference< task::XInteractionApprove > xApprove(
250 rContinuations[0], uno::UNO_QUERY);
251 if (xApprove.is())
252 return true;
254 uno::Reference< task::XInteractionAbort > xAbort(
255 rContinuations[0], uno::UNO_QUERY);
256 return xAbort.is();
259 bool
260 UUIInteractionHelper::tryOtherInteractionHandler(
261 uno::Reference< task::XInteractionRequest > const & rRequest)
263 InteractionHandlerDataList dataList;
264 getInteractionHandlerList(dataList);
266 return std::any_of(dataList.cbegin(), dataList.cend(),
267 [&](const InteractionHandlerData& rData) { return handleCustomRequest( rRequest, rData.ServiceName ); });
270 namespace
273 bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, std::u16string_view i_rPropagation )
275 const css::uno::TypeDescription aTypeDesc( i_rTypeName );
276 const typelib_TypeDescription* pTypeDesc = aTypeDesc.get();
277 if ( !pTypeDesc || !pTypeDesc->pWeakRef )
279 SAL_WARN( "uui","no type found for '" << i_rTypeName << "'" );
280 return false;
282 const css::uno::Type aType( pTypeDesc->pWeakRef );
284 const bool bExactMatch = i_rPropagation == u"named-only";
285 if ( bExactMatch )
286 return i_rRequest.getValueType().equals( aType );
288 return i_rRequest.isExtractableTo( aType );
293 bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const
297 Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW );
299 Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY );
300 if ( xHandlerInit.is() )
302 ::comphelper::NamedValueCollection aInitArgs;
303 aInitArgs.put( "Parent", getParentXWindow() );
304 xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() );
307 if ( xHandler->handleInteractionRequest( i_rRequest ) )
308 return true;
310 catch( const Exception& )
312 DBG_UNHANDLED_EXCEPTION("uui");
314 return false;
318 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest )
320 // the request
321 const Any aRequest( rRequest->getRequest() );
323 const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() );
324 if ( aCacheHitTest != m_aTypedCustomHandlers.end() )
325 return handleCustomRequest( rRequest, aCacheHitTest->second );
327 // the base registration node for "typed" interaction handlers
328 const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext(
329 m_xContext,
330 "/org.openoffice.Interaction/InteractionHandlers",
332 ::utl::OConfigurationTreeRoot::CM_READONLY
333 ) );
335 // loop through all registered implementations
336 const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() );
337 for ( auto const & handlerName : aRegisteredHandlers )
339 const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( handlerName ) );
340 const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) );
342 // loop through all the types which the current handler is registered for
343 const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() );
344 for ( auto const & type : aHandledTypes )
346 // the UNO type is the node name
347 ::utl::OConfigurationNode aType( aTypesNode.openNode( type ) );
348 // and there's a child denoting how the responsibility propagates
349 OUString sPropagation;
350 OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation );
351 if ( lcl_matchesRequest( aRequest, type, sPropagation ) )
353 // retrieve the service/implementation name of the handler
354 OUString sServiceName;
355 OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName );
356 // cache the information who feels responsible for requests of this type
357 m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName;
358 // actually handle the request
359 return handleCustomRequest( rRequest, sServiceName );
364 return false;
367 bool
368 UUIInteractionHelper::handleRequest_impl(
369 uno::Reference< task::XInteractionRequest > const & rRequest,
370 bool bObtainErrorStringOnly,
371 bool & bHasErrorString,
372 OUString & rErrorString)
376 if (!rRequest.is())
377 return false;
379 uno::Any aAnyRequest(rRequest->getRequest());
381 script::ModuleSizeExceededRequest aModSizeException;
382 if (aAnyRequest >>= aModSizeException )
384 std::vector< OUString > aArguments;
385 uno::Sequence< OUString > sModules
386 = aModSizeException.Names;
387 if ( sModules.hasElements() )
389 OUStringBuffer aName;
390 for ( sal_Int32 index=0; index< sModules.getLength(); ++index )
392 if ( index )
393 aName.append(",");
394 aName.append(sModules[index]);
396 aArguments.push_back( aName.makeStringAndClear() );
398 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
399 ERRCODE_UUI_IO_MODULESIZEEXCEEDED,
400 aArguments,
401 rRequest->getContinuations(),
402 bObtainErrorStringOnly,
403 bHasErrorString,
404 rErrorString);
405 return true;
408 document::ExoticFileLoadException aExoticFileLoadException;
409 if (aAnyRequest >>= aExoticFileLoadException)
411 std::vector< OUString > aArguments;
413 if( !aExoticFileLoadException.URL.isEmpty() )
415 aArguments.push_back( aExoticFileLoadException.URL );
417 if( !aExoticFileLoadException.FilterUIName.isEmpty() )
419 aArguments.push_back( aExoticFileLoadException.FilterUIName );
422 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
423 ERRCODE_UUI_IO_EXOTICFILEFORMAT,
424 aArguments,
425 rRequest->getContinuations(),
426 bObtainErrorStringOnly,
427 bHasErrorString,
428 rErrorString);
429 return true;
432 ucb::NameClashException aNCException;
433 if (aAnyRequest >>= aNCException)
435 ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS;
436 std::vector< OUString > aArguments;
438 if( !aNCException.Name.isEmpty() )
440 nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS;
441 aArguments.push_back( aNCException.Name );
444 handleErrorHandlerRequest( aNCException.Classification,
445 nErrorCode,
446 aArguments,
447 rRequest->getContinuations(),
448 bObtainErrorStringOnly,
449 bHasErrorString,
450 rErrorString);
451 return true;
454 ucb::UnsupportedNameClashException aUORequest;
455 if (aAnyRequest >>= aUORequest)
458 uno::Reference< task::XInteractionApprove > xApprove;
459 uno::Reference< task::XInteractionDisapprove > xDisapprove;
460 getContinuations(
461 rRequest->getContinuations(), &xApprove, &xDisapprove);
463 if ( xApprove.is() && xDisapprove.is() )
465 std::vector< OUString > aArguments;
466 handleErrorHandlerRequest( task::InteractionClassification_QUERY,
467 ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE,
468 aArguments,
469 rRequest->getContinuations(),
470 bObtainErrorStringOnly,
471 bHasErrorString,
472 rErrorString);
474 return true;
477 if ( handleInteractiveIOException( rRequest,
478 bObtainErrorStringOnly,
479 bHasErrorString,
480 rErrorString ) )
481 return true;
483 ucb::InteractiveAppException aAppException;
484 if (aAnyRequest >>= aAppException)
486 std::vector< OUString > aArguments;
487 handleErrorHandlerRequest( aAppException.Classification,
488 ErrCode(aAppException.Code),
489 aArguments,
490 rRequest->getContinuations(),
491 bObtainErrorStringOnly,
492 bHasErrorString,
493 rErrorString);
494 return true;
497 ucb::InteractiveNetworkException aNetworkException;
498 if (aAnyRequest >>= aNetworkException)
500 ErrCode nErrorCode;
501 std::vector< OUString > aArguments;
502 ucb::InteractiveNetworkOffLineException aOffLineException;
503 ucb::InteractiveNetworkResolveNameException aResolveNameException;
504 ucb::InteractiveNetworkConnectException aConnectException;
505 ucb::InteractiveNetworkReadException aReadException;
506 ucb::InteractiveNetworkWriteException aWriteException;
507 if (aAnyRequest >>= aOffLineException)
508 nErrorCode = ERRCODE_INET_OFFLINE;
509 else if (aAnyRequest >>= aResolveNameException)
511 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
512 aArguments.push_back(aResolveNameException.Server);
514 else if (aAnyRequest >>= aConnectException)
516 nErrorCode = ERRCODE_INET_CONNECT;
517 aArguments.push_back(aConnectException.Server);
519 else if (aAnyRequest >>= aReadException)
521 nErrorCode = ERRCODE_INET_READ;
522 aArguments.push_back(aReadException.Diagnostic);
524 else if (aAnyRequest >>= aWriteException)
526 nErrorCode = ERRCODE_INET_WRITE;
527 aArguments.push_back(aWriteException.Diagnostic);
529 else
530 nErrorCode = ERRCODE_INET_GENERAL;
532 handleErrorHandlerRequest(aNetworkException.Classification,
533 nErrorCode,
534 aArguments,
535 rRequest->getContinuations(),
536 bObtainErrorStringOnly,
537 bHasErrorString,
538 rErrorString);
539 return true;
542 ucb::InteractiveWrongMediumException aWrongMediumException;
543 if (aAnyRequest >>= aWrongMediumException)
545 sal_Int32 nMedium = 0;
546 aWrongMediumException.Medium >>= nMedium;
547 std::vector< OUString > aArguments { OUString::number(nMedium + 1) };
548 handleErrorHandlerRequest(aWrongMediumException.Classification,
549 ERRCODE_UUI_WRONGMEDIUM,
550 aArguments,
551 rRequest->getContinuations(),
552 bObtainErrorStringOnly,
553 bHasErrorString,
554 rErrorString);
555 return true;
558 java::WrongJavaVersionException aWrongJavaVersionException;
559 if (aAnyRequest >>= aWrongJavaVersionException)
561 ErrCode nErrorCode;
562 std::vector< OUString > aArguments;
563 if (aWrongJavaVersionException.DetectedVersion.isEmpty())
564 if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
565 nErrorCode = ERRCODE_UUI_WRONGJAVA;
566 else
568 nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN;
569 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
571 else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
573 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION;
574 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
576 else
578 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN;
579 aArguments.reserve(2);
580 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
581 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
583 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
584 nErrorCode,
585 aArguments,
586 rRequest->getContinuations(),
587 bObtainErrorStringOnly,
588 bHasErrorString,
589 rErrorString);
590 return true;
593 configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest;
594 if (aAnyRequest >>= aMergeRecoveryRequest)
596 ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest
597 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
598 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE;
600 std::vector< OUString > aArguments { aMergeRecoveryRequest.ErrorLayerId };
602 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
603 nErrorCode,
604 aArguments,
605 rRequest->getContinuations(),
606 bObtainErrorStringOnly,
607 bHasErrorString,
608 rErrorString);
609 return true;
612 configuration::backend::StratumCreationException
613 aStratumCreationException;
615 if (aAnyRequest >>= aStratumCreationException)
617 const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING;
619 OUString aStratum = aStratumCreationException.StratumData;
620 if (aStratum.isEmpty())
621 aStratum = aStratumCreationException.StratumService;
623 std::vector< OUString > aArguments { aStratum };
625 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
626 nErrorCode,
627 aArguments,
628 rRequest->getContinuations(),
629 bObtainErrorStringOnly,
630 bHasErrorString,
631 rErrorString);
632 return true;
635 xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException;
636 if (aAnyRequest >>= aInvalidDataOnSubmitException)
638 const ErrCode nErrorCode =
639 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA;
641 std::vector< OUString > aArguments;
643 handleErrorHandlerRequest(task::InteractionClassification_QUERY,
644 nErrorCode,
645 aArguments,
646 rRequest->getContinuations(),
647 bObtainErrorStringOnly,
648 bHasErrorString,
649 rErrorString);
650 return true;
653 ucb::InteractiveLockingLockedException aLLException;
654 if (aAnyRequest >>= aLLException)
656 ErrCode nErrorCode = aLLException.SelfOwned
657 ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED;
658 std::vector< OUString > aArguments { aLLException.Url };
660 handleErrorHandlerRequest( aLLException.Classification,
661 nErrorCode,
662 aArguments,
663 rRequest->getContinuations(),
664 bObtainErrorStringOnly,
665 bHasErrorString,
666 rErrorString );
667 return true;
670 ucb::InteractiveLockingNotLockedException aLNLException;
671 if (aAnyRequest >>= aLNLException)
673 std::vector< OUString > aArguments { aLNLException.Url };
675 handleErrorHandlerRequest( aLNLException.Classification,
676 ERRCODE_UUI_LOCKING_NOT_LOCKED,
677 aArguments,
678 rRequest->getContinuations(),
679 bObtainErrorStringOnly,
680 bHasErrorString,
681 rErrorString );
682 return true;
685 ucb::InteractiveLockingLockExpiredException aLLEException;
686 if (aAnyRequest >>= aLLEException)
688 std::vector< OUString > aArguments { aLLEException.Url };
690 handleErrorHandlerRequest( aLLEException.Classification,
691 ERRCODE_UUI_LOCKING_LOCK_EXPIRED,
692 aArguments,
693 rRequest->getContinuations(),
694 bObtainErrorStringOnly,
695 bHasErrorString,
696 rErrorString );
697 return true;
700 document::BrokenPackageRequest aBrokenPackageRequest;
701 if (aAnyRequest >>= aBrokenPackageRequest)
703 std::vector< OUString > aArguments;
705 if( !aBrokenPackageRequest.aName.isEmpty() )
706 aArguments.push_back( aBrokenPackageRequest.aName );
708 handleBrokenPackageRequest( aArguments,
709 rRequest->getContinuations(),
710 bObtainErrorStringOnly,
711 bHasErrorString,
712 rErrorString );
713 return true;
716 task::ErrorCodeRequest aErrorCodeRequest;
717 if (aAnyRequest >>= aErrorCodeRequest)
719 handleGenericErrorRequest( ErrCode(aErrorCodeRequest.ErrCode),
720 rRequest->getContinuations(),
721 bObtainErrorStringOnly,
722 bHasErrorString,
723 rErrorString);
724 return true;
727 task::ErrorCodeIOException aErrorCodeIOException;
728 if (aAnyRequest >>= aErrorCodeIOException)
730 handleGenericErrorRequest( ErrCode(aErrorCodeIOException.ErrCode),
731 rRequest->getContinuations(),
732 bObtainErrorStringOnly,
733 bHasErrorString,
734 rErrorString);
735 return true;
738 loader::CannotActivateFactoryException aCannotActivateFactoryException;
739 if (aAnyRequest >>= aCannotActivateFactoryException)
741 std::vector< OUString > aArguments { aCannotActivateFactoryException.Message };
743 handleErrorHandlerRequest( task::InteractionClassification_ERROR,
744 ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY,
745 aArguments,
746 rRequest->getContinuations(),
747 bObtainErrorStringOnly,
748 bHasErrorString,
749 rErrorString );
750 return true;
754 // Handle requests which do not have a plain string representation.
756 if (!bObtainErrorStringOnly)
758 ucb::AuthenticationFallbackRequest anAuthFallbackRequest;
759 if ( aAnyRequest >>= anAuthFallbackRequest )
761 handleAuthFallbackRequest( anAuthFallbackRequest.instructions,
762 anAuthFallbackRequest.url, rRequest->getContinuations() );
763 return true;
766 if ( handleAuthenticationRequest( rRequest ) )
767 return true;
769 if ( handleCertificateValidationRequest( rRequest ) )
770 return true;
772 ucb::NameClashResolveRequest aNameClashResolveRequest;
773 if (aAnyRequest >>= aNameClashResolveRequest)
775 handleNameClashResolveRequest(aNameClashResolveRequest,
776 rRequest->getContinuations());
777 return true;
780 if ( handleMasterPasswordRequest( rRequest ) )
781 return true;
783 if ( handlePasswordRequest( rRequest ) )
784 return true;
786 if ( handleNoSuchFilterRequest( rRequest ) )
787 return true;
789 if ( handleFilterOptionsRequest( rRequest ) )
790 return true;
792 if ( handleLockedDocumentRequest( rRequest ) )
793 return true;
795 if ( handleChangedByOthersRequest( rRequest ) )
796 return true;
798 if ( handleLockFileProblemRequest( rRequest ) )
799 return true;
801 if ( handleReloadEditableRequest( rRequest ) )
802 return true;
804 task::DocumentMacroConfirmationRequest aMacroConfirmRequest;
805 if (aAnyRequest >>= aMacroConfirmRequest)
807 handleMacroConfirmRequest(
808 aMacroConfirmRequest.DocumentURL,
809 aMacroConfirmRequest.DocumentStorage,
810 !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_013_TEXT,
811 aMacroConfirmRequest.DocumentSignatureInformation,
812 rRequest->getContinuations());
813 return true;
816 // Last chance: interaction handlers registered in the configuration
819 // typed InteractionHandlers (ooo.Interactions)
820 if ( handleTypedHandlerImplementations( rRequest ) )
821 return true;
823 // legacy configuration (ooo.ucb.InteractionHandlers)
824 if (tryOtherInteractionHandler( rRequest ))
825 return true;
828 // Not handled.
829 return false;
831 catch( const uno::RuntimeException& )
833 throw; // allowed to leave here
835 catch( const uno::Exception& )
837 DBG_UNHANDLED_EXCEPTION("uui");
839 return false;
842 void
843 UUIInteractionHelper::getInteractionHandlerList(
844 InteractionHandlerDataList &rdataList)
848 uno::Reference< lang::XMultiServiceFactory > xConfigProv =
849 configuration::theDefaultProvider::get( m_xContext );
851 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
853 {"nodepath", uno::Any(OUString("/org.openoffice.ucb.InteractionHandler/InteractionHandlers"))}
854 }));
856 uno::Reference< uno::XInterface > xInterface(
857 xConfigProv->createInstanceWithArguments(
858 "com.sun.star.configuration.ConfigurationAccess" , aArguments ) );
860 if ( !xInterface.is() )
861 throw uno::RuntimeException("unable to instantiate config access");
863 uno::Reference< container::XNameAccess > xNameAccess(
864 xInterface, uno::UNO_QUERY_THROW );
865 const uno::Sequence< OUString > aElems = xNameAccess->getElementNames();
867 if ( aElems.hasElements() )
869 uno::Reference< container::XHierarchicalNameAccess >
870 xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
872 // Iterate over children.
873 for ( const auto& rElem : aElems )
877 InteractionHandlerData aInfo;
879 // Obtain service name.
880 OUString aKeyBuffer = "['" + rElem + "']/ServiceName";
882 OUString aValue;
883 if ( !( xHierNameAccess->getByHierarchicalName(
884 aKeyBuffer ) >>= aValue ) )
886 OSL_FAIL( "GetInteractionHandlerList - "
887 "Error getting item value!" );
888 continue;
891 aInfo.ServiceName = aValue;
893 // Append info to list.
894 rdataList.push_back( aInfo );
896 catch ( container::NoSuchElementException& )
898 // getByHierarchicalName
900 OSL_FAIL( "GetInteractionHandlerList - "
901 "caught NoSuchElementException!" );
906 catch ( uno::RuntimeException const & )
908 throw;
910 catch ( uno::Exception const & )
912 TOOLS_WARN_EXCEPTION( "uui", "GetInteractionHandlerList" );
916 const uno::Reference< awt::XWindow>&
917 UUIInteractionHelper::getParentXWindow() const
919 return m_xWindowParam;
922 uno::Reference< task::XInteractionHandler2 >
923 UUIInteractionHelper::getInteractionHandler() const
925 return InteractionHandler::createWithParentAndContext(
926 m_xContext, m_xWindowParam,
927 m_aContextParam);
930 namespace {
932 DialogMask
933 executeMessageBox(
934 weld::Window * pParent,
935 OUString const & rTitle,
936 OUString const & rMessage,
937 VclMessageType eMessageType)
939 SolarMutexGuard aGuard;
941 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, eMessageType,
942 eMessageType == VclMessageType::Question ? VclButtonsType::YesNo : VclButtonsType::Ok, rMessage));
943 xBox->set_title(rTitle);
945 short nMessResult = xBox->run();
946 DialogMask aResult = DialogMask::NONE;
947 switch (nMessResult)
949 case RET_OK:
950 aResult = DialogMask::ButtonsOk;
951 break;
952 case RET_CANCEL:
953 aResult = DialogMask::ButtonsCancel;
954 break;
955 case RET_YES:
956 aResult = DialogMask::ButtonsYes;
957 break;
958 case RET_NO:
959 aResult = DialogMask::ButtonsNo;
960 break;
961 default:
962 assert(false);
965 return aResult;
968 NameClashResolveDialogResult executeSimpleNameClashResolveDialog(weld::Window *pParent,
969 OUString const & rTargetFolderURL,
970 OUString const & rClashingName,
971 OUString & rProposedNewName,
972 bool bAllowOverwrite)
974 std::locale aResLocale = Translate::Create("uui");
975 NameClashDialog aDialog(pParent, aResLocale, rTargetFolderURL,
976 rClashingName, rProposedNewName, bAllowOverwrite);
978 NameClashResolveDialogResult eResult = static_cast<NameClashResolveDialogResult>(aDialog.run());
979 rProposedNewName = aDialog.getNewName();
980 return eResult;
983 } // namespace
985 void
986 UUIInteractionHelper::handleNameClashResolveRequest(
987 ucb::NameClashResolveRequest const & rRequest,
988 uno::Sequence< uno::Reference<
989 task::XInteractionContinuation > > const & rContinuations)
991 OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(),
992 "NameClashResolveRequest must not contain empty TargetFolderURL" );
994 OSL_ENSURE(!rRequest.ClashingName.isEmpty(),
995 "NameClashResolveRequest must not contain empty ClashingName" );
997 uno::Reference< task::XInteractionAbort > xAbort;
998 uno::Reference< ucb::XInteractionSupplyName > xSupplyName;
999 uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData;
1000 getContinuations(
1001 rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData);
1003 OSL_ENSURE( xAbort.is(),
1004 "NameClashResolveRequest must contain Abort continuation" );
1006 OSL_ENSURE( xSupplyName.is(),
1007 "NameClashResolveRequest must contain SupplyName continuation" );
1009 NameClashResolveDialogResult eResult = ABORT;
1010 OUString aProposedNewName( rRequest.ProposedNewName );
1012 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1013 eResult = executeSimpleNameClashResolveDialog(Application::GetFrameWeld(xParent),
1014 rRequest.TargetFolderURL,
1015 rRequest.ClashingName,
1016 aProposedNewName,
1017 xReplaceExistingData.is());
1019 switch ( eResult )
1021 case ABORT:
1022 xAbort->select();
1023 break;
1025 case RENAME:
1026 xSupplyName->setName( aProposedNewName );
1027 xSupplyName->select();
1028 break;
1030 case OVERWRITE:
1031 OSL_ENSURE(
1032 xReplaceExistingData.is(),
1033 "Invalid NameClashResolveDialogResult: OVERWRITE - "
1034 "No ReplaceExistingData continuation available!" );
1035 xReplaceExistingData->select();
1036 break;
1040 void
1041 UUIInteractionHelper::handleGenericErrorRequest(
1042 ErrCode nErrorCode,
1043 uno::Sequence< uno::Reference<
1044 task::XInteractionContinuation > > const & rContinuations,
1045 bool bObtainErrorStringOnly,
1046 bool & bHasErrorString,
1047 OUString & rErrorString)
1049 if (bObtainErrorStringOnly)
1051 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1052 if (bHasErrorString)
1054 OUString aErrorString;
1055 ErrorHandler::GetErrorString(nErrorCode, aErrorString);
1056 rErrorString = aErrorString;
1059 else
1061 uno::Reference< task::XInteractionAbort > xAbort;
1062 uno::Reference< task::XInteractionApprove > xApprove;
1063 getContinuations(rContinuations, &xApprove, &xAbort);
1065 // Note: It's important to convert the transported long to the
1066 // required unsigned long value. Otherwise using as flag field
1067 // can fail ...
1068 ErrCode nError(nErrorCode);
1069 bool bWarning = !nError.IgnoreWarning();
1071 if ( nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION )
1073 // the security warning box needs a special title
1074 OUString aErrorString;
1075 ErrorHandler::GetErrorString( nErrorCode, aErrorString );
1077 std::locale aResLocale = Translate::Create("uui");
1078 OUString aTitle( utl::ConfigManager::getProductName() );
1080 OUString aErrTitle = Translate::get(STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE, aResLocale);
1082 if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() )
1083 aTitle += " - " ;
1084 aTitle += aErrTitle;
1086 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1087 executeMessageBox(Application::GetFrameWeld(xParent), aTitle, aErrorString, VclMessageType::Error);
1089 else
1091 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1092 ErrorHandler::HandleError(nErrorCode, Application::GetFrameWeld(xParent));
1095 if (xApprove.is() && bWarning)
1096 xApprove->select();
1097 else if (xAbort.is())
1098 xAbort->select();
1102 void
1103 UUIInteractionHelper::handleMacroConfirmRequest(
1104 const OUString& aDocumentURL,
1105 const uno::Reference< embed::XStorage >& xZipStorage,
1106 const OUString& aDocumentVersion,
1107 const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo,
1108 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1109 rContinuations )
1111 uno::Reference< task::XInteractionAbort > xAbort;
1112 uno::Reference< task::XInteractionApprove > xApprove;
1113 getContinuations( rContinuations, &xApprove, &xAbort );
1115 bool bApprove = false;
1117 bool bShowSignatures = aSignInfo.hasElements();
1118 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1119 MacroWarning aWarning(Application::GetFrameWeld(xParent), bShowSignatures);
1121 aWarning.SetDocumentURL(aDocumentURL);
1122 if ( aSignInfo.getLength() > 1 )
1124 aWarning.SetStorage(xZipStorage, aDocumentVersion, aSignInfo);
1126 else if ( aSignInfo.getLength() == 1 )
1128 aWarning.SetCertificate(aSignInfo[0].Signer);
1131 bApprove = aWarning.run() == RET_OK;
1133 if ( bApprove && xApprove.is() )
1134 xApprove->select();
1135 else if ( xAbort.is() )
1136 xAbort->select();
1139 void
1140 UUIInteractionHelper::handleBrokenPackageRequest(
1141 std::vector< OUString > const & rArguments,
1142 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1143 rContinuations,
1144 bool bObtainErrorStringOnly,
1145 bool & bHasErrorString,
1146 OUString & rErrorString)
1148 if (bObtainErrorStringOnly)
1150 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1151 if (!bHasErrorString)
1152 return;
1155 uno::Reference< task::XInteractionApprove > xApprove;
1156 uno::Reference< task::XInteractionDisapprove > xDisapprove;
1157 uno::Reference< task::XInteractionAbort > xAbort;
1158 getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort);
1160 ErrCode nErrorCode;
1161 if( xApprove.is() && xDisapprove.is() )
1163 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE;
1165 else if ( xAbort.is() )
1167 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR;
1169 else
1170 return;
1172 OUString aMessage;
1174 std::locale aResLocale = Translate::Create("uui");
1175 ErrorResource aErrorResource(RID_UUI_ERRHDL, aResLocale);
1176 if (!aErrorResource.getString(nErrorCode, aMessage))
1177 return;
1180 aMessage = replaceMessageWithArguments( aMessage, rArguments );
1182 if (bObtainErrorStringOnly)
1184 rErrorString = aMessage;
1185 return;
1188 VclMessageType eMessageType;
1189 if( xApprove.is() && xDisapprove.is() )
1190 eMessageType = VclMessageType::Question;
1191 else if ( xAbort.is() )
1192 eMessageType = VclMessageType::Warning;
1193 else
1194 return;
1196 OUString title(
1197 utl::ConfigManager::getProductName() +
1198 " " +
1199 utl::ConfigManager::getProductVersion() );
1201 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1202 switch (executeMessageBox(Application::GetFrameWeld(xParent), title, aMessage, eMessageType))
1204 case DialogMask::ButtonsOk:
1205 OSL_ENSURE( xAbort.is(), "unexpected situation" );
1206 if (xAbort.is())
1207 xAbort->select();
1208 break;
1210 case DialogMask::ButtonsNo:
1211 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
1212 if (xDisapprove.is())
1213 xDisapprove->select();
1214 break;
1216 case DialogMask::ButtonsYes:
1217 OSL_ENSURE(xApprove.is(), "unexpected situation");
1218 if (xApprove.is())
1219 xApprove->select();
1220 break;
1222 default: break;
1226 // ErrorResource Implementation
1227 bool ErrorResource::getString(ErrCode nErrorCode, OUString &rString) const
1229 for (const std::pair<TranslateId, ErrCode>* pStringArray = m_pStringArray; pStringArray->first; ++pStringArray)
1231 if (nErrorCode.StripWarningAndDynamic() == pStringArray->second.StripWarningAndDynamic())
1233 rString = Translate::get(pStringArray->first, m_rResLocale);
1234 return true;
1237 return false;
1240 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */