loplugin:sequenceloop in unoxml..vcl
[LibreOffice.git] / uui / source / iahndl.cxx
blob7f31daafd5c223526ebec838c473e099345eee6b
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/beans/PropertyValue.hpp>
24 #include <com/sun/star/configuration/theDefaultProvider.hpp>
25 #include <com/sun/star/configuration/backend/MergeRecoveryRequest.hpp>
26 #include <com/sun/star/configuration/backend/StratumCreationException.hpp>
27 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
28 #include <com/sun/star/document/BrokenPackageRequest.hpp>
29 #include <com/sun/star/document/ExoticFileLoadException.hpp>
30 #include <com/sun/star/task/DocumentMacroConfirmationRequest.hpp>
31 #include <com/sun/star/java/WrongJavaVersionException.hpp>
32 #include <com/sun/star/lang/XInitialization.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/script/ModuleSizeExceededRequest.hpp>
35 #include <com/sun/star/task/ErrorCodeIOException.hpp>
36 #include <com/sun/star/task/ErrorCodeRequest.hpp>
37 #include <com/sun/star/task/InteractionHandler.hpp>
38 #include <com/sun/star/task/XInteractionAbort.hpp>
39 #include <com/sun/star/task/XInteractionApprove.hpp>
40 #include <com/sun/star/task/XInteractionDisapprove.hpp>
41 #include <com/sun/star/task/XInteractionHandler2.hpp>
42 #include <com/sun/star/task/XInteractionRequest.hpp>
43 #include <com/sun/star/task/XInteractionRetry.hpp>
44 #include <com/sun/star/ucb/AuthenticationFallbackRequest.hpp>
45 #include <com/sun/star/ucb/InteractiveAppException.hpp>
46 #include <com/sun/star/ucb/InteractiveLockingLockedException.hpp>
47 #include <com/sun/star/ucb/InteractiveLockingNotLockedException.hpp>
48 #include <com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp>
49 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
50 #include <com/sun/star/ucb/InteractiveNetworkOffLineException.hpp>
51 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
52 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
53 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
54 #include <com/sun/star/ucb/InteractiveWrongMediumException.hpp>
55 #include <com/sun/star/ucb/NameClashException.hpp>
56 #include <com/sun/star/ucb/NameClashResolveRequest.hpp>
57 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
58 #include <com/sun/star/ucb/XInteractionReplaceExistingData.hpp>
59 #include <com/sun/star/ucb/XInteractionSupplyName.hpp>
60 #include <com/sun/star/xforms/InvalidDataOnSubmitException.hpp>
61 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
63 #include <rtl/strbuf.hxx>
64 #include <sal/log.hxx>
65 #include <osl/conditn.hxx>
66 #include <unotools/resmgr.hxx>
67 #include <vcl/errinf.hxx>
68 #include <vcl/svapp.hxx>
69 #include <vcl/weld.hxx>
70 #include <osl/thread.hxx>
71 #include <tools/diagnose_ex.h>
72 #include <comphelper/documentconstants.hxx>
73 #include <comphelper/propertysequence.hxx>
74 #include <svtools/sfxecode.hxx>
75 #include <unotools/configmgr.hxx>
76 #include <comphelper/namedvaluecollection.hxx>
77 #include <typelib/typedescription.hxx>
78 #include <unotools/confignode.hxx>
80 #include <ids.hxx>
81 #include <ids.hrc>
82 #include <strings.hrc>
84 #include "getcontinuations.hxx"
85 #include "secmacrowarnings.hxx"
87 #include "iahndl.hxx"
88 #include "nameclashdlg.hxx"
90 using ::com::sun::star::uno::Sequence;
91 using ::com::sun::star::uno::UNO_QUERY;
92 using ::com::sun::star::uno::Reference;
93 using ::com::sun::star::task::XInteractionContinuation;
94 using ::com::sun::star::task::XInteractionAbort;
95 using ::com::sun::star::task::XInteractionApprove;
96 using ::com::sun::star::uno::XInterface;
97 using ::com::sun::star::lang::XInitialization;
98 using ::com::sun::star::uno::UNO_QUERY_THROW;
99 using ::com::sun::star::task::InteractionHandler;
100 using ::com::sun::star::task::XInteractionHandler2;
101 using ::com::sun::star::uno::Exception;
102 using ::com::sun::star::uno::Any;
103 using ::com::sun::star::task::XInteractionRequest;
104 using ::com::sun::star::lang::XMultiServiceFactory;
106 using namespace ::com::sun::star;
108 namespace {
110 class HandleData : public osl::Condition
112 public:
113 explicit HandleData(
114 uno::Reference< task::XInteractionRequest > const & rRequest)
115 : osl::Condition(),
116 m_rRequest(rRequest),
117 bHandled( false )
120 uno::Reference< task::XInteractionRequest > m_rRequest;
121 bool bHandled;
122 beans::Optional< OUString > m_aResult;
125 } /* namespace */
127 UUIInteractionHelper::UUIInteractionHelper(
128 uno::Reference< uno::XComponentContext > const & rxContext,
129 uno::Reference< awt::XWindow > const & rxWindowParam,
130 const OUString & rContextParam)
131 : m_xContext(rxContext),
132 m_xWindowParam(rxWindowParam),
133 m_aContextParam(rContextParam)
137 UUIInteractionHelper::UUIInteractionHelper(
138 uno::Reference< uno::XComponentContext > const & rxContext)
139 : m_xContext(rxContext)
143 UUIInteractionHelper::~UUIInteractionHelper()
147 void UUIInteractionHelper::handlerequest(
148 void* pHandleData, void* pInteractionHelper)
150 HandleData* pHND
151 = static_cast< HandleData * >(pHandleData);
152 UUIInteractionHelper* pUUI
153 = static_cast< UUIInteractionHelper * >(pInteractionHelper);
154 bool bDummy = false;
155 OUString aDummy;
156 pHND->bHandled
157 = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy);
158 pHND->set();
161 bool
162 UUIInteractionHelper::handleRequest(
163 uno::Reference< task::XInteractionRequest > const & rRequest)
165 if(!Application::IsMainThread() && GetpApp())
167 // we are not in the main thread, let it handle that stuff
168 HandleData aHD(rRequest);
169 Link<void*,void> aLink(&aHD,handlerequest);
170 Application::PostUserEvent(aLink,this);
171 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
172 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
173 aHD.wait();
174 if (nLockCount)
175 rSolarMutex.acquire(nLockCount);
176 return aHD.bHandled;
178 else
180 bool bDummy = false;
181 OUString aDummy;
182 return handleRequest_impl(rRequest, false, bDummy, aDummy);
186 void UUIInteractionHelper::getstringfromrequest(
187 void* pHandleData,void* pInteractionHelper)
189 HandleData* pHND = static_cast<HandleData*>(pHandleData);
190 UUIInteractionHelper* pUUI = static_cast<UUIInteractionHelper*>(pInteractionHelper);
191 pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest);
192 pHND->set();
195 beans::Optional< OUString >
196 UUIInteractionHelper::getStringFromRequest_impl(
197 uno::Reference< task::XInteractionRequest > const & rRequest)
199 bool bSuccess = false;
200 OUString aMessage;
201 handleRequest_impl(rRequest, true, bSuccess, aMessage);
203 OSL_ENSURE(bSuccess ||
204 !isInformationalErrorMessageRequest(
205 rRequest->getContinuations()),
206 "Interaction request is a candidate for a string representation."
207 "Please implement!");
209 return beans::Optional< OUString >(bSuccess, aMessage);
212 beans::Optional< OUString >
213 UUIInteractionHelper::getStringFromRequest(
214 uno::Reference< task::XInteractionRequest > const & rRequest)
216 if(!Application::IsMainThread() && GetpApp())
218 // we are not in the main thread, let it handle that stuff
219 HandleData aHD(rRequest);
220 Link<void*,void> aLink(&aHD,getstringfromrequest);
221 Application::PostUserEvent(aLink,this);
222 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
223 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
224 aHD.wait();
225 if (nLockCount)
226 rSolarMutex.acquire(nLockCount);
227 return aHD.m_aResult;
229 else
230 return getStringFromRequest_impl(rRequest);
233 OUString
234 UUIInteractionHelper::replaceMessageWithArguments(
235 const OUString& _aMessage,
236 std::vector< OUString > const & rArguments )
238 OUString aMessage = _aMessage;
240 SAL_WARN_IF(rArguments.empty(), "uui", "replaceMessageWithArguments: No arguments passed!");
241 for (size_t i = 0; i < rArguments.size(); ++i)
243 const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")";
244 aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]);
247 return aMessage;
250 bool
251 UUIInteractionHelper::isInformationalErrorMessageRequest(
252 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
253 rContinuations)
255 // Only requests with a single continuation (user has no choice, request
256 // is just informational)
257 if (rContinuations.getLength() != 1 )
258 return false;
260 // user can only abort or approve, all other continuations are not
261 // considered to be informational.
262 uno::Reference< task::XInteractionApprove > xApprove(
263 rContinuations[0], uno::UNO_QUERY);
264 if (xApprove.is())
265 return true;
267 uno::Reference< task::XInteractionAbort > xAbort(
268 rContinuations[0], uno::UNO_QUERY);
269 return xAbort.is();
272 bool
273 UUIInteractionHelper::tryOtherInteractionHandler(
274 uno::Reference< task::XInteractionRequest > const & rRequest)
276 InteractionHandlerDataList dataList;
277 getInteractionHandlerList(dataList);
279 return std::any_of(dataList.cbegin(), dataList.cend(),
280 [&](const InteractionHandlerData& rData) { return handleCustomRequest( rRequest, rData.ServiceName ); });
283 namespace
286 bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, const OUString& i_rPropagation )
288 const css::uno::TypeDescription aTypeDesc( i_rTypeName );
289 const typelib_TypeDescription* pTypeDesc = aTypeDesc.get();
290 if ( !pTypeDesc || !pTypeDesc->pWeakRef )
292 SAL_WARN( "uui","no type found for '" << i_rTypeName << "'" );
293 return false;
295 const css::uno::Type aType( pTypeDesc->pWeakRef );
297 const bool bExactMatch = i_rPropagation == "named-only";
298 if ( bExactMatch )
299 return i_rRequest.getValueType().equals( aType );
301 return i_rRequest.isExtractableTo( aType );
306 bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const
310 Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW );
312 Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY );
313 if ( xHandlerInit.is() )
315 ::comphelper::NamedValueCollection aInitArgs;
316 aInitArgs.put( "Parent", getParentXWindow() );
317 xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() );
320 if ( xHandler->handleInteractionRequest( i_rRequest ) )
321 return true;
323 catch( const Exception& )
325 DBG_UNHANDLED_EXCEPTION("uui");
327 return false;
331 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest )
333 // the request
334 const Any aRequest( rRequest->getRequest() );
336 const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() );
337 if ( aCacheHitTest != m_aTypedCustomHandlers.end() )
338 return handleCustomRequest( rRequest, aCacheHitTest->second );
340 // the base registration node for "typed" interaction handlers
341 const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext(
342 m_xContext,
343 "/org.openoffice.Interaction/InteractionHandlers",
345 ::utl::OConfigurationTreeRoot::CM_READONLY
346 ) );
348 // loop through all registered implementations
349 const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() );
350 for ( auto const & handlerName : aRegisteredHandlers )
352 const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( handlerName ) );
353 const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) );
355 // loop through all the types which the current handler is registered for
356 const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() );
357 for ( auto const & type : aHandledTypes )
359 // the UNO type is the node name
360 ::utl::OConfigurationNode aType( aTypesNode.openNode( type ) );
361 // and there's a child denoting how the responsibility propagates
362 OUString sPropagation;
363 OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation );
364 if ( lcl_matchesRequest( aRequest, type, sPropagation ) )
366 // retrieve the service/implementation name of the handler
367 OUString sServiceName;
368 OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName );
369 // cache the information who feels responsible for requests of this type
370 m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName;
371 // actually handle the request
372 return handleCustomRequest( rRequest, sServiceName );
377 return false;
380 bool
381 UUIInteractionHelper::handleRequest_impl(
382 uno::Reference< task::XInteractionRequest > const & rRequest,
383 bool bObtainErrorStringOnly,
384 bool & bHasErrorString,
385 OUString & rErrorString)
389 if (!rRequest.is())
390 return false;
392 uno::Any aAnyRequest(rRequest->getRequest());
394 script::ModuleSizeExceededRequest aModSizeException;
395 if (aAnyRequest >>= aModSizeException )
397 std::vector< OUString > aArguments;
398 uno::Sequence< OUString > sModules
399 = aModSizeException.Names;
400 if ( sModules.hasElements() )
402 OUStringBuffer aName;
403 for ( sal_Int32 index=0; index< sModules.getLength(); ++index )
405 if ( index )
406 aName.append(",");
407 aName.append(sModules[index]);
409 aArguments.push_back( aName.makeStringAndClear() );
411 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
412 ERRCODE_UUI_IO_MODULESIZEEXCEEDED,
413 aArguments,
414 rRequest->getContinuations(),
415 bObtainErrorStringOnly,
416 bHasErrorString,
417 rErrorString);
418 return true;
421 document::ExoticFileLoadException aExoticFileLoadException;
422 if (aAnyRequest >>= aExoticFileLoadException)
424 std::vector< OUString > aArguments;
426 if( !aExoticFileLoadException.URL.isEmpty() )
428 aArguments.push_back( aExoticFileLoadException.URL );
430 if( !aExoticFileLoadException.FilterUIName.isEmpty() )
432 aArguments.push_back( aExoticFileLoadException.FilterUIName );
435 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
436 ERRCODE_UUI_IO_EXOTICFILEFORMAT,
437 aArguments,
438 rRequest->getContinuations(),
439 bObtainErrorStringOnly,
440 bHasErrorString,
441 rErrorString);
442 return true;
445 ucb::NameClashException aNCException;
446 if (aAnyRequest >>= aNCException)
448 ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS;
449 std::vector< OUString > aArguments;
451 if( !aNCException.Name.isEmpty() )
453 nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS;
454 aArguments.push_back( aNCException.Name );
457 handleErrorHandlerRequest( aNCException.Classification,
458 nErrorCode,
459 aArguments,
460 rRequest->getContinuations(),
461 bObtainErrorStringOnly,
462 bHasErrorString,
463 rErrorString);
464 return true;
467 ucb::UnsupportedNameClashException aUORequest;
468 if (aAnyRequest >>= aUORequest)
470 std::vector< OUString > aArguments;
472 uno::Reference< task::XInteractionApprove > xApprove;
473 uno::Reference< task::XInteractionDisapprove > xDisapprove;
474 getContinuations(
475 rRequest->getContinuations(), &xApprove, &xDisapprove);
477 if ( xApprove.is() && xDisapprove.is() )
479 handleErrorHandlerRequest( task::InteractionClassification_QUERY,
480 ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE,
481 aArguments,
482 rRequest->getContinuations(),
483 bObtainErrorStringOnly,
484 bHasErrorString,
485 rErrorString);
487 return true;
490 if ( handleInteractiveIOException( rRequest,
491 bObtainErrorStringOnly,
492 bHasErrorString,
493 rErrorString ) )
494 return true;
496 ucb::InteractiveAppException aAppException;
497 if (aAnyRequest >>= aAppException)
499 std::vector< OUString > aArguments;
500 handleErrorHandlerRequest( aAppException.Classification,
501 ErrCode(aAppException.Code),
502 aArguments,
503 rRequest->getContinuations(),
504 bObtainErrorStringOnly,
505 bHasErrorString,
506 rErrorString);
507 return true;
510 ucb::InteractiveNetworkException aNetworkException;
511 if (aAnyRequest >>= aNetworkException)
513 ErrCode nErrorCode;
514 std::vector< OUString > aArguments;
515 ucb::InteractiveNetworkOffLineException aOffLineException;
516 ucb::InteractiveNetworkResolveNameException aResolveNameException;
517 ucb::InteractiveNetworkConnectException aConnectException;
518 ucb::InteractiveNetworkReadException aReadException;
519 ucb::InteractiveNetworkWriteException aWriteException;
520 if (aAnyRequest >>= aOffLineException)
521 nErrorCode = ERRCODE_INET_OFFLINE;
522 else if (aAnyRequest >>= aResolveNameException)
524 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
525 aArguments.push_back(aResolveNameException.Server);
527 else if (aAnyRequest >>= aConnectException)
529 nErrorCode = ERRCODE_INET_CONNECT;
530 aArguments.push_back(aConnectException.Server);
532 else if (aAnyRequest >>= aReadException)
534 nErrorCode = ERRCODE_INET_READ;
535 aArguments.push_back(aReadException.Diagnostic);
537 else if (aAnyRequest >>= aWriteException)
539 nErrorCode = ERRCODE_INET_WRITE;
540 aArguments.push_back(aWriteException.Diagnostic);
542 else
543 nErrorCode = ERRCODE_INET_GENERAL;
545 handleErrorHandlerRequest(aNetworkException.Classification,
546 nErrorCode,
547 aArguments,
548 rRequest->getContinuations(),
549 bObtainErrorStringOnly,
550 bHasErrorString,
551 rErrorString);
552 return true;
555 ucb::InteractiveWrongMediumException aWrongMediumException;
556 if (aAnyRequest >>= aWrongMediumException)
558 sal_Int32 nMedium = 0;
559 aWrongMediumException.Medium >>= nMedium;
560 std::vector< OUString > aArguments;
561 aArguments.push_back(OUString::number(nMedium + 1));
562 handleErrorHandlerRequest(aWrongMediumException.Classification,
563 ERRCODE_UUI_WRONGMEDIUM,
564 aArguments,
565 rRequest->getContinuations(),
566 bObtainErrorStringOnly,
567 bHasErrorString,
568 rErrorString);
569 return true;
572 java::WrongJavaVersionException aWrongJavaVersionException;
573 if (aAnyRequest >>= aWrongJavaVersionException)
575 ErrCode nErrorCode;
576 std::vector< OUString > aArguments;
577 if (aWrongJavaVersionException.DetectedVersion.isEmpty())
578 if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
579 nErrorCode = ERRCODE_UUI_WRONGJAVA;
580 else
582 nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN;
583 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
585 else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
587 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION;
588 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
590 else
592 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN;
593 aArguments.reserve(2);
594 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
595 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
597 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
598 nErrorCode,
599 aArguments,
600 rRequest->getContinuations(),
601 bObtainErrorStringOnly,
602 bHasErrorString,
603 rErrorString);
604 return true;
607 configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest;
608 if (aAnyRequest >>= aMergeRecoveryRequest)
610 ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest
611 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
612 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE;
614 std::vector< OUString > aArguments;
615 aArguments.push_back(aMergeRecoveryRequest.ErrorLayerId);
617 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
618 nErrorCode,
619 aArguments,
620 rRequest->getContinuations(),
621 bObtainErrorStringOnly,
622 bHasErrorString,
623 rErrorString);
624 return true;
627 configuration::backend::StratumCreationException
628 aStratumCreationException;
630 if (aAnyRequest >>= aStratumCreationException)
632 const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING;
634 OUString aStratum = aStratumCreationException.StratumData;
635 if (aStratum.isEmpty())
636 aStratum = aStratumCreationException.StratumService;
638 std::vector< OUString > aArguments;
639 aArguments.push_back(aStratum);
641 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
642 nErrorCode,
643 aArguments,
644 rRequest->getContinuations(),
645 bObtainErrorStringOnly,
646 bHasErrorString,
647 rErrorString);
648 return true;
651 xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException;
652 if (aAnyRequest >>= aInvalidDataOnSubmitException)
654 const ErrCode nErrorCode =
655 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA;
657 std::vector< OUString > aArguments;
659 handleErrorHandlerRequest(task::InteractionClassification_QUERY,
660 nErrorCode,
661 aArguments,
662 rRequest->getContinuations(),
663 bObtainErrorStringOnly,
664 bHasErrorString,
665 rErrorString);
666 return true;
669 ucb::InteractiveLockingLockedException aLLException;
670 if (aAnyRequest >>= aLLException)
672 ErrCode nErrorCode = aLLException.SelfOwned
673 ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED;
674 std::vector< OUString > aArguments;
675 aArguments.push_back( aLLException.Url );
677 handleErrorHandlerRequest( aLLException.Classification,
678 nErrorCode,
679 aArguments,
680 rRequest->getContinuations(),
681 bObtainErrorStringOnly,
682 bHasErrorString,
683 rErrorString );
684 return true;
687 ucb::InteractiveLockingNotLockedException aLNLException;
688 if (aAnyRequest >>= aLNLException)
690 std::vector< OUString > aArguments;
691 aArguments.push_back( aLNLException.Url );
693 handleErrorHandlerRequest( aLNLException.Classification,
694 ERRCODE_UUI_LOCKING_NOT_LOCKED,
695 aArguments,
696 rRequest->getContinuations(),
697 bObtainErrorStringOnly,
698 bHasErrorString,
699 rErrorString );
700 return true;
703 ucb::InteractiveLockingLockExpiredException aLLEException;
704 if (aAnyRequest >>= aLLEException)
706 std::vector< OUString > aArguments;
707 aArguments.push_back( aLLEException.Url );
709 handleErrorHandlerRequest( aLLEException.Classification,
710 ERRCODE_UUI_LOCKING_LOCK_EXPIRED,
711 aArguments,
712 rRequest->getContinuations(),
713 bObtainErrorStringOnly,
714 bHasErrorString,
715 rErrorString );
716 return true;
719 document::BrokenPackageRequest aBrokenPackageRequest;
720 if (aAnyRequest >>= aBrokenPackageRequest)
722 std::vector< OUString > aArguments;
724 if( !aBrokenPackageRequest.aName.isEmpty() )
725 aArguments.push_back( aBrokenPackageRequest.aName );
727 handleBrokenPackageRequest( aArguments,
728 rRequest->getContinuations(),
729 bObtainErrorStringOnly,
730 bHasErrorString,
731 rErrorString );
732 return true;
735 task::ErrorCodeRequest aErrorCodeRequest;
736 if (aAnyRequest >>= aErrorCodeRequest)
738 handleGenericErrorRequest( ErrCode(aErrorCodeRequest.ErrCode),
739 rRequest->getContinuations(),
740 bObtainErrorStringOnly,
741 bHasErrorString,
742 rErrorString);
743 return true;
746 task::ErrorCodeIOException aErrorCodeIOException;
747 if (aAnyRequest >>= aErrorCodeIOException)
749 handleGenericErrorRequest( ErrCode(aErrorCodeIOException.ErrCode),
750 rRequest->getContinuations(),
751 bObtainErrorStringOnly,
752 bHasErrorString,
753 rErrorString);
754 return true;
757 loader::CannotActivateFactoryException aCannotActivateFactoryException;
758 if (aAnyRequest >>= aCannotActivateFactoryException)
760 std::vector< OUString > aArguments;
761 aArguments.push_back( aCannotActivateFactoryException.Message );
763 handleErrorHandlerRequest( task::InteractionClassification_ERROR,
764 ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY,
765 aArguments,
766 rRequest->getContinuations(),
767 bObtainErrorStringOnly,
768 bHasErrorString,
769 rErrorString );
770 return true;
774 // Handle requests which do not have a plain string representation.
776 if (!bObtainErrorStringOnly)
778 ucb::AuthenticationFallbackRequest anAuthFallbackRequest;
779 if ( aAnyRequest >>= anAuthFallbackRequest )
781 handleAuthFallbackRequest( anAuthFallbackRequest.instructions,
782 anAuthFallbackRequest.url, rRequest->getContinuations() );
783 return true;
786 if ( handleAuthenticationRequest( rRequest ) )
787 return true;
789 if ( handleCertificateValidationRequest( rRequest ) )
790 return true;
792 ucb::NameClashResolveRequest aNameClashResolveRequest;
793 if (aAnyRequest >>= aNameClashResolveRequest)
795 handleNameClashResolveRequest(aNameClashResolveRequest,
796 rRequest->getContinuations());
797 return true;
800 if ( handleMasterPasswordRequest( rRequest ) )
801 return true;
803 if ( handlePasswordRequest( rRequest ) )
804 return true;
806 if ( handleNoSuchFilterRequest( rRequest ) )
807 return true;
809 if ( handleFilterOptionsRequest( rRequest ) )
810 return true;
812 if ( handleLockedDocumentRequest( rRequest ) )
813 return true;
815 if ( handleChangedByOthersRequest( rRequest ) )
816 return true;
818 if ( handleLockFileProblemRequest( rRequest ) )
819 return true;
821 task::DocumentMacroConfirmationRequest aMacroConfirmRequest;
822 if (aAnyRequest >>= aMacroConfirmRequest)
824 handleMacroConfirmRequest(
825 aMacroConfirmRequest.DocumentURL,
826 aMacroConfirmRequest.DocumentStorage,
827 !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_012_TEXT,
828 aMacroConfirmRequest.DocumentSignatureInformation,
829 rRequest->getContinuations());
830 return true;
833 // Last chance: interaction handlers registered in the configuration
836 // typed InteractionHandlers (ooo.Interactions)
837 if ( handleTypedHandlerImplementations( rRequest ) )
838 return true;
840 // legacy configuration (ooo.ucb.InteractionHandlers)
841 if (tryOtherInteractionHandler( rRequest ))
842 return true;
845 // Not handled.
846 return false;
848 catch( const uno::RuntimeException& )
850 throw; // allowed to leave here
852 catch( const uno::Exception& )
854 DBG_UNHANDLED_EXCEPTION("uui");
856 return false;
859 void
860 UUIInteractionHelper::getInteractionHandlerList(
861 InteractionHandlerDataList &rdataList)
865 uno::Reference< lang::XMultiServiceFactory > xConfigProv =
866 configuration::theDefaultProvider::get( m_xContext );
868 OUStringBuffer aFullPath;
869 aFullPath.append(
870 "/org.openoffice.ucb.InteractionHandler/InteractionHandlers" );
872 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
874 {"nodepath", uno::Any(aFullPath.makeStringAndClear())}
875 }));
877 uno::Reference< uno::XInterface > xInterface(
878 xConfigProv->createInstanceWithArguments(
879 "com.sun.star.configuration.ConfigurationAccess" , aArguments ) );
881 if ( !xInterface.is() )
882 throw uno::RuntimeException("unable to instantiate config access");
884 uno::Reference< container::XNameAccess > xNameAccess(
885 xInterface, uno::UNO_QUERY_THROW );
886 const uno::Sequence< OUString > aElems = xNameAccess->getElementNames();
888 if ( aElems.hasElements() )
890 uno::Reference< container::XHierarchicalNameAccess >
891 xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
893 // Iterate over children.
894 for ( const auto& rElem : aElems )
896 OUStringBuffer aElemBuffer;
897 aElemBuffer.append( "['" );
898 aElemBuffer.append( rElem );
902 InteractionHandlerData aInfo;
904 // Obtain service name.
905 OUStringBuffer aKeyBuffer = aElemBuffer;
906 aKeyBuffer.append( "']/ServiceName" );
908 OUString aValue;
909 if ( !( xHierNameAccess->getByHierarchicalName(
910 aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
912 OSL_FAIL( "GetInteractionHandlerList - "
913 "Error getting item value!" );
914 continue;
917 aInfo.ServiceName = aValue;
919 // Append info to list.
920 rdataList.push_back( aInfo );
922 catch ( container::NoSuchElementException& )
924 // getByHierarchicalName
926 OSL_FAIL( "GetInteractionHandlerList - "
927 "caught NoSuchElementException!" );
932 catch ( uno::RuntimeException const & )
934 throw;
936 catch ( uno::Exception const & )
938 OSL_FAIL( "GetInteractionHandlerList - Caught Exception!" );
942 const uno::Reference< awt::XWindow>&
943 UUIInteractionHelper::getParentXWindow() const
945 return m_xWindowParam;
948 uno::Reference< task::XInteractionHandler2 >
949 UUIInteractionHelper::getInteractionHandler()
951 return InteractionHandler::createWithParentAndContext(
952 m_xContext, m_xWindowParam,
953 m_aContextParam);
956 namespace {
958 DialogMask
959 executeMessageBox(
960 weld::Window * pParent,
961 OUString const & rTitle,
962 OUString const & rMessage,
963 VclMessageType eMessageType)
965 SolarMutexGuard aGuard;
967 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, eMessageType,
968 eMessageType == VclMessageType::Question ? VclButtonsType::YesNo : VclButtonsType::Ok, rMessage));
969 xBox->set_title(rTitle);
971 short nMessResult = xBox->run();
972 DialogMask aResult = DialogMask::NONE;
973 switch (nMessResult)
975 case RET_OK:
976 aResult = DialogMask::ButtonsOk;
977 break;
978 case RET_CANCEL:
979 aResult = DialogMask::ButtonsCancel;
980 break;
981 case RET_YES:
982 aResult = DialogMask::ButtonsYes;
983 break;
984 case RET_NO:
985 aResult = DialogMask::ButtonsNo;
986 break;
987 default:
988 assert(false);
991 return aResult;
994 NameClashResolveDialogResult executeSimpleNameClashResolveDialog(weld::Window *pParent,
995 OUString const & rTargetFolderURL,
996 OUString const & rClashingName,
997 OUString & rProposedNewName,
998 bool bAllowOverwrite)
1000 std::locale aResLocale = Translate::Create("uui");
1001 NameClashDialog aDialog(pParent, aResLocale, rTargetFolderURL,
1002 rClashingName, rProposedNewName, bAllowOverwrite);
1004 NameClashResolveDialogResult eResult = static_cast<NameClashResolveDialogResult>(aDialog.run());
1005 rProposedNewName = aDialog.getNewName();
1006 return eResult;
1009 } // namespace
1011 void
1012 UUIInteractionHelper::handleNameClashResolveRequest(
1013 ucb::NameClashResolveRequest const & rRequest,
1014 uno::Sequence< uno::Reference<
1015 task::XInteractionContinuation > > const & rContinuations)
1017 OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(),
1018 "NameClashResolveRequest must not contain empty TargetFolderURL" );
1020 OSL_ENSURE(!rRequest.ClashingName.isEmpty(),
1021 "NameClashResolveRequest must not contain empty ClashingName" );
1023 uno::Reference< task::XInteractionAbort > xAbort;
1024 uno::Reference< ucb::XInteractionSupplyName > xSupplyName;
1025 uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData;
1026 getContinuations(
1027 rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData);
1029 OSL_ENSURE( xAbort.is(),
1030 "NameClashResolveRequest must contain Abort continuation" );
1032 OSL_ENSURE( xSupplyName.is(),
1033 "NameClashResolveRequest must contain SupplyName continuation" );
1035 NameClashResolveDialogResult eResult = ABORT;
1036 OUString aProposedNewName( rRequest.ProposedNewName );
1038 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1039 eResult = executeSimpleNameClashResolveDialog(Application::GetFrameWeld(xParent),
1040 rRequest.TargetFolderURL,
1041 rRequest.ClashingName,
1042 aProposedNewName,
1043 xReplaceExistingData.is());
1045 switch ( eResult )
1047 case ABORT:
1048 xAbort->select();
1049 break;
1051 case RENAME:
1052 xSupplyName->setName( aProposedNewName );
1053 xSupplyName->select();
1054 break;
1056 case OVERWRITE:
1057 OSL_ENSURE(
1058 xReplaceExistingData.is(),
1059 "Invalid NameClashResolveDialogResult: OVERWRITE - "
1060 "No ReplaceExistingData continuation available!" );
1061 xReplaceExistingData->select();
1062 break;
1066 void
1067 UUIInteractionHelper::handleGenericErrorRequest(
1068 ErrCode nErrorCode,
1069 uno::Sequence< uno::Reference<
1070 task::XInteractionContinuation > > const & rContinuations,
1071 bool bObtainErrorStringOnly,
1072 bool & bHasErrorString,
1073 OUString & rErrorString)
1075 if (bObtainErrorStringOnly)
1077 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1078 if (bHasErrorString)
1080 OUString aErrorString;
1081 ErrorHandler::GetErrorString(nErrorCode, aErrorString);
1082 rErrorString = aErrorString;
1085 else
1087 uno::Reference< task::XInteractionAbort > xAbort;
1088 uno::Reference< task::XInteractionApprove > xApprove;
1089 getContinuations(rContinuations, &xApprove, &xAbort);
1091 // Note: It's important to convert the transported long to the
1092 // required unsigned long value. Otherwise using as flag field
1093 // can fail ...
1094 ErrCode nError(nErrorCode);
1095 bool bWarning = !nError.IgnoreWarning();
1097 if ( nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION )
1099 // the security warning box needs a special title
1100 OUString aErrorString;
1101 ErrorHandler::GetErrorString( nErrorCode, aErrorString );
1103 std::locale aResLocale = Translate::Create("uui");
1104 OUString aTitle( utl::ConfigManager::getProductName() );
1106 OUString aErrTitle = Translate::get(STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE, aResLocale);
1108 if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() )
1109 aTitle += " - " ;
1110 aTitle += aErrTitle;
1112 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1113 executeMessageBox(Application::GetFrameWeld(xParent), aTitle, aErrorString, VclMessageType::Error);
1115 else
1117 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1118 ErrorHandler::HandleError(nErrorCode, Application::GetFrameWeld(xParent));
1121 if (xApprove.is() && bWarning)
1122 xApprove->select();
1123 else if (xAbort.is())
1124 xAbort->select();
1128 void
1129 UUIInteractionHelper::handleMacroConfirmRequest(
1130 const OUString& aDocumentURL,
1131 const uno::Reference< embed::XStorage >& xZipStorage,
1132 const OUString& aDocumentVersion,
1133 const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo,
1134 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1135 rContinuations )
1137 uno::Reference< task::XInteractionAbort > xAbort;
1138 uno::Reference< task::XInteractionApprove > xApprove;
1139 getContinuations( rContinuations, &xApprove, &xAbort );
1141 bool bApprove = false;
1143 bool bShowSignatures = aSignInfo.hasElements();
1144 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1145 MacroWarning aWarning(Application::GetFrameWeld(xParent), bShowSignatures);
1147 aWarning.SetDocumentURL(aDocumentURL);
1148 if ( aSignInfo.getLength() > 1 )
1150 aWarning.SetStorage(xZipStorage, aDocumentVersion, aSignInfo);
1152 else if ( aSignInfo.getLength() == 1 )
1154 aWarning.SetCertificate(aSignInfo[0].Signer);
1157 bApprove = aWarning.run() == RET_OK;
1159 if ( bApprove && xApprove.is() )
1160 xApprove->select();
1161 else if ( xAbort.is() )
1162 xAbort->select();
1165 void
1166 UUIInteractionHelper::handleBrokenPackageRequest(
1167 std::vector< OUString > const & rArguments,
1168 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1169 rContinuations,
1170 bool bObtainErrorStringOnly,
1171 bool & bHasErrorString,
1172 OUString & rErrorString)
1174 if (bObtainErrorStringOnly)
1176 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1177 if (!bHasErrorString)
1178 return;
1181 uno::Reference< task::XInteractionApprove > xApprove;
1182 uno::Reference< task::XInteractionDisapprove > xDisapprove;
1183 uno::Reference< task::XInteractionAbort > xAbort;
1184 getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort);
1186 ErrCode nErrorCode;
1187 if( xApprove.is() && xDisapprove.is() )
1189 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE;
1191 else if ( xAbort.is() )
1193 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR;
1195 else
1196 return;
1198 OUString aMessage;
1200 std::locale aResLocale = Translate::Create("uui");
1201 ErrorResource aErrorResource(RID_UUI_ERRHDL, aResLocale);
1202 if (!aErrorResource.getString(nErrorCode, aMessage))
1203 return;
1206 aMessage = replaceMessageWithArguments( aMessage, rArguments );
1208 if (bObtainErrorStringOnly)
1210 rErrorString = aMessage;
1211 return;
1214 VclMessageType eMessageType;
1215 if( xApprove.is() && xDisapprove.is() )
1216 eMessageType = VclMessageType::Question;
1217 else if ( xAbort.is() )
1218 eMessageType = VclMessageType::Warning;
1219 else
1220 return;
1222 OUString title(
1223 utl::ConfigManager::getProductName() +
1224 " " +
1225 utl::ConfigManager::getProductVersion() );
1227 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1228 switch (executeMessageBox(Application::GetFrameWeld(xParent), title, aMessage, eMessageType))
1230 case DialogMask::ButtonsOk:
1231 OSL_ENSURE( xAbort.is(), "unexpected situation" );
1232 if (xAbort.is())
1233 xAbort->select();
1234 break;
1236 case DialogMask::ButtonsNo:
1237 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
1238 if (xDisapprove.is())
1239 xDisapprove->select();
1240 break;
1242 case DialogMask::ButtonsYes:
1243 OSL_ENSURE(xApprove.is(), "unexpected situation");
1244 if (xApprove.is())
1245 xApprove->select();
1246 break;
1248 default: break;
1252 // ErrorResource Implementation
1253 bool ErrorResource::getString(ErrCode nErrorCode, OUString &rString) const
1255 for (const std::pair<const char*, ErrCode>* pStringArray = m_pStringArray; pStringArray->first != nullptr; ++pStringArray)
1257 if (nErrorCode.StripWarningAndDynamic() == pStringArray->second.StripWarningAndDynamic())
1259 rString = Translate::get(pStringArray->first, m_rResLocale);
1260 return true;
1263 return false;
1266 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */