Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / uui / source / iahndl.cxx
blob16fd450ce05c7d80056316a4a2fb94dc0e81cc67
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 <osl/conditn.hxx>
65 #include <unotools/resmgr.hxx>
66 #include <vcl/errinf.hxx>
67 #include <vcl/svapp.hxx>
68 #include <vcl/weld.hxx>
69 #include <osl/thread.hxx>
70 #include <tools/diagnose_ex.h>
71 #include <comphelper/documentconstants.hxx>
72 #include <comphelper/propertysequence.hxx>
73 #include <svtools/sfxecode.hxx>
74 #include <unotools/configmgr.hxx>
75 #include <comphelper/namedvaluecollection.hxx>
76 #include <typelib/typedescription.hxx>
77 #include <unotools/confignode.hxx>
79 #include <ids.hxx>
80 #include <ids.hrc>
81 #include <strings.hrc>
83 #include "getcontinuations.hxx"
84 #include "secmacrowarnings.hxx"
86 #include "iahndl.hxx"
87 #include "nameclashdlg.hxx"
89 using ::com::sun::star::uno::Sequence;
90 using ::com::sun::star::uno::UNO_QUERY;
91 using ::com::sun::star::uno::Reference;
92 using ::com::sun::star::task::XInteractionContinuation;
93 using ::com::sun::star::task::XInteractionAbort;
94 using ::com::sun::star::task::XInteractionApprove;
95 using ::com::sun::star::uno::XInterface;
96 using ::com::sun::star::lang::XInitialization;
97 using ::com::sun::star::uno::UNO_QUERY_THROW;
98 using ::com::sun::star::task::InteractionHandler;
99 using ::com::sun::star::task::XInteractionHandler2;
100 using ::com::sun::star::uno::Exception;
101 using ::com::sun::star::uno::Any;
102 using ::com::sun::star::task::XInteractionRequest;
103 using ::com::sun::star::lang::XMultiServiceFactory;
105 using namespace ::com::sun::star;
107 namespace {
109 class HandleData : public osl::Condition
111 public:
112 explicit HandleData(
113 uno::Reference< task::XInteractionRequest > const & rRequest)
114 : osl::Condition(),
115 m_rRequest(rRequest),
116 bHandled( false )
119 uno::Reference< task::XInteractionRequest > m_rRequest;
120 bool bHandled;
121 beans::Optional< OUString > m_aResult;
124 } /* namespace */
126 UUIInteractionHelper::UUIInteractionHelper(
127 uno::Reference< uno::XComponentContext > const & rxContext,
128 uno::Reference< awt::XWindow > const & rxWindowParam,
129 const OUString & rContextParam)
130 : m_xContext(rxContext),
131 m_xWindowParam(rxWindowParam),
132 m_aContextParam(rContextParam)
136 UUIInteractionHelper::UUIInteractionHelper(
137 uno::Reference< uno::XComponentContext > const & rxContext)
138 : m_xContext(rxContext)
142 UUIInteractionHelper::~UUIInteractionHelper()
146 void UUIInteractionHelper::handlerequest(
147 void* pHandleData, void* pInteractionHelper)
149 HandleData* pHND
150 = static_cast< HandleData * >(pHandleData);
151 UUIInteractionHelper* pUUI
152 = static_cast< UUIInteractionHelper * >(pInteractionHelper);
153 bool bDummy = false;
154 OUString aDummy;
155 pHND->bHandled
156 = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy);
157 pHND->set();
160 bool
161 UUIInteractionHelper::handleRequest(
162 uno::Reference< task::XInteractionRequest > const & rRequest)
165 Application::GetMainThreadIdentifier()
166 != osl::Thread::getCurrentIdentifier()
168 GetpApp()
170 // we are not in the main thread, let it handle that stuff
171 HandleData aHD(rRequest);
172 Link<void*,void> aLink(&aHD,handlerequest);
173 Application::PostUserEvent(aLink,this);
174 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
175 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
176 aHD.wait();
177 if (nLockCount)
178 rSolarMutex.acquire(nLockCount);
179 return aHD.bHandled;
181 else
183 bool bDummy = false;
184 OUString aDummy;
185 return handleRequest_impl(rRequest, false, bDummy, aDummy);
189 void UUIInteractionHelper::getstringfromrequest(
190 void* pHandleData,void* pInteractionHelper)
192 HandleData* pHND = static_cast<HandleData*>(pHandleData);
193 UUIInteractionHelper* pUUI = static_cast<UUIInteractionHelper*>(pInteractionHelper);
194 pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest);
195 pHND->set();
198 beans::Optional< OUString >
199 UUIInteractionHelper::getStringFromRequest_impl(
200 uno::Reference< task::XInteractionRequest > const & rRequest)
202 bool bSuccess = false;
203 OUString aMessage;
204 handleRequest_impl(rRequest, true, bSuccess, aMessage);
206 OSL_ENSURE(bSuccess ||
207 !isInformationalErrorMessageRequest(
208 rRequest->getContinuations()),
209 "Interaction request is a candidate for a string representation."
210 "Please implement!");
212 return beans::Optional< OUString >(bSuccess, aMessage);
215 beans::Optional< OUString >
216 UUIInteractionHelper::getStringFromRequest(
217 uno::Reference< task::XInteractionRequest > const & rRequest)
220 Application::GetMainThreadIdentifier()
221 != osl::Thread::getCurrentIdentifier()
223 GetpApp()
225 // we are not in the main thread, let it handle that stuff
226 HandleData aHD(rRequest);
227 Link<void*,void> aLink(&aHD,getstringfromrequest);
228 Application::PostUserEvent(aLink,this);
229 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
230 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
231 aHD.wait();
232 if (nLockCount)
233 rSolarMutex.acquire(nLockCount);
234 return aHD.m_aResult;
236 else
237 return getStringFromRequest_impl(rRequest);
240 OUString
241 UUIInteractionHelper::replaceMessageWithArguments(
242 const OUString& _aMessage,
243 std::vector< OUString > const & rArguments )
245 OUString aMessage = _aMessage;
247 SAL_WARN_IF(rArguments.size() == 0, "uui", "replaceMessageWithArguments: No arguments passed!");
248 for (size_t i = 0; i < rArguments.size(); ++i)
250 const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")";
251 aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]);
254 return aMessage;
257 bool
258 UUIInteractionHelper::isInformationalErrorMessageRequest(
259 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
260 rContinuations)
262 // Only requests with a single continuation (user has no choice, request
263 // is just informational)
264 if (rContinuations.getLength() != 1 )
265 return false;
267 // user can only abort or approve, all other continuations are not
268 // considered to be informational.
269 uno::Reference< task::XInteractionApprove > xApprove(
270 rContinuations[0], uno::UNO_QUERY);
271 if (xApprove.is())
272 return true;
274 uno::Reference< task::XInteractionAbort > xAbort(
275 rContinuations[0], uno::UNO_QUERY);
276 return xAbort.is();
279 bool
280 UUIInteractionHelper::tryOtherInteractionHandler(
281 uno::Reference< task::XInteractionRequest > const & rRequest)
283 InteractionHandlerDataList dataList;
284 getInteractionHandlerList(dataList);
286 InteractionHandlerDataList::const_iterator aEnd(dataList.end());
287 for (InteractionHandlerDataList::const_iterator aIt(dataList.begin());
288 aIt != aEnd;
289 ++aIt)
291 if ( handleCustomRequest( rRequest, aIt->ServiceName ) )
292 return true;
294 return false;
297 namespace
300 bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, const OUString& i_rPropagation )
302 const css::uno::TypeDescription aTypeDesc( i_rTypeName );
303 const typelib_TypeDescription* pTypeDesc = aTypeDesc.get();
304 if ( !pTypeDesc || !pTypeDesc->pWeakRef )
306 SAL_WARN( "uui","no type found for '" << i_rTypeName << "'" );
307 return false;
309 const css::uno::Type aType( pTypeDesc->pWeakRef );
311 const bool bExactMatch = i_rPropagation == "named-only";
312 if ( bExactMatch )
313 return i_rRequest.getValueType().equals( aType );
315 return i_rRequest.isExtractableTo( aType );
320 bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const
324 Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW );
326 Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY );
327 if ( xHandlerInit.is() )
329 ::comphelper::NamedValueCollection aInitArgs;
330 aInitArgs.put( "Parent", getParentXWindow() );
331 xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() );
334 if ( xHandler->handleInteractionRequest( i_rRequest ) )
335 return true;
337 catch( const Exception& )
339 DBG_UNHANDLED_EXCEPTION("uui");
341 return false;
345 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest )
347 // the request
348 const Any aRequest( rRequest->getRequest() );
350 const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() );
351 if ( aCacheHitTest != m_aTypedCustomHandlers.end() )
352 return handleCustomRequest( rRequest, aCacheHitTest->second );
354 // the base registration node for "typed" interaction handlers
355 const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext(
356 m_xContext,
357 "/org.openoffice.Interaction/InteractionHandlers",
359 ::utl::OConfigurationTreeRoot::CM_READONLY
360 ) );
362 // loop through all registered implementations
363 const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() );
364 for ( auto const & handlerName : aRegisteredHandlers )
366 const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( handlerName ) );
367 const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) );
369 // loop through all the types which the current handler is registered for
370 const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() );
371 for ( auto const & type : aHandledTypes )
373 // the UNO type is the node name
374 ::utl::OConfigurationNode aType( aTypesNode.openNode( type ) );
375 // and there's a child denoting how the responsibility propagates
376 OUString sPropagation;
377 OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation );
378 if ( lcl_matchesRequest( aRequest, type, sPropagation ) )
380 // retrieve the service/implementation name of the handler
381 OUString sServiceName;
382 OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName );
383 // cache the information who feels responsible for requests of this type
384 m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName;
385 // actually handle the request
386 return handleCustomRequest( rRequest, sServiceName );
391 return false;
394 bool
395 UUIInteractionHelper::handleRequest_impl(
396 uno::Reference< task::XInteractionRequest > const & rRequest,
397 bool bObtainErrorStringOnly,
398 bool & bHasErrorString,
399 OUString & rErrorString)
403 if (!rRequest.is())
404 return false;
406 uno::Any aAnyRequest(rRequest->getRequest());
408 script::ModuleSizeExceededRequest aModSizeException;
409 if (aAnyRequest >>= aModSizeException )
411 std::vector< OUString > aArguments;
412 uno::Sequence< OUString > sModules
413 = aModSizeException.Names;
414 if ( sModules.getLength() )
416 OUString aName;
417 for ( sal_Int32 index=0; index< sModules.getLength(); ++index )
419 if ( index )
420 aName += "," + sModules[index];
421 else
422 aName = sModules[index]; // 1st name
424 aArguments.push_back( aName );
426 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
427 ERRCODE_UUI_IO_MODULESIZEEXCEEDED,
428 aArguments,
429 rRequest->getContinuations(),
430 bObtainErrorStringOnly,
431 bHasErrorString,
432 rErrorString);
433 return true;
436 document::ExoticFileLoadException aExoticFileLoadException;
437 if (aAnyRequest >>= aExoticFileLoadException)
439 std::vector< OUString > aArguments;
441 if( !aExoticFileLoadException.URL.isEmpty() )
443 aArguments.push_back( aExoticFileLoadException.URL );
445 if( !aExoticFileLoadException.FilterUIName.isEmpty() )
447 aArguments.push_back( aExoticFileLoadException.FilterUIName );
450 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
451 ERRCODE_UUI_IO_EXOTICFILEFORMAT,
452 aArguments,
453 rRequest->getContinuations(),
454 bObtainErrorStringOnly,
455 bHasErrorString,
456 rErrorString);
457 return true;
460 ucb::NameClashException aNCException;
461 if (aAnyRequest >>= aNCException)
463 ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS;
464 std::vector< OUString > aArguments;
466 if( !aNCException.Name.isEmpty() )
468 nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS;
469 aArguments.push_back( aNCException.Name );
472 handleErrorHandlerRequest( aNCException.Classification,
473 nErrorCode,
474 aArguments,
475 rRequest->getContinuations(),
476 bObtainErrorStringOnly,
477 bHasErrorString,
478 rErrorString);
479 return true;
482 ucb::UnsupportedNameClashException aUORequest;
483 if (aAnyRequest >>= aUORequest)
485 std::vector< OUString > aArguments;
487 uno::Reference< task::XInteractionApprove > xApprove;
488 uno::Reference< task::XInteractionDisapprove > xDisapprove;
489 getContinuations(
490 rRequest->getContinuations(), &xApprove, &xDisapprove);
492 if ( xApprove.is() && xDisapprove.is() )
494 handleErrorHandlerRequest( task::InteractionClassification_QUERY,
495 ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE,
496 aArguments,
497 rRequest->getContinuations(),
498 bObtainErrorStringOnly,
499 bHasErrorString,
500 rErrorString);
502 return true;
505 if ( handleInteractiveIOException( rRequest,
506 bObtainErrorStringOnly,
507 bHasErrorString,
508 rErrorString ) )
509 return true;
511 ucb::InteractiveAppException aAppException;
512 if (aAnyRequest >>= aAppException)
514 std::vector< OUString > aArguments;
515 handleErrorHandlerRequest( aAppException.Classification,
516 ErrCode(aAppException.Code),
517 aArguments,
518 rRequest->getContinuations(),
519 bObtainErrorStringOnly,
520 bHasErrorString,
521 rErrorString);
522 return true;
525 ucb::InteractiveNetworkException aNetworkException;
526 if (aAnyRequest >>= aNetworkException)
528 ErrCode nErrorCode;
529 std::vector< OUString > aArguments;
530 ucb::InteractiveNetworkOffLineException aOffLineException;
531 ucb::InteractiveNetworkResolveNameException aResolveNameException;
532 ucb::InteractiveNetworkConnectException aConnectException;
533 ucb::InteractiveNetworkReadException aReadException;
534 ucb::InteractiveNetworkWriteException aWriteException;
535 if (aAnyRequest >>= aOffLineException)
536 nErrorCode = ERRCODE_INET_OFFLINE;
537 else if (aAnyRequest >>= aResolveNameException)
539 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
540 aArguments.push_back(aResolveNameException.Server);
542 else if (aAnyRequest >>= aConnectException)
544 nErrorCode = ERRCODE_INET_CONNECT;
545 aArguments.push_back(aConnectException.Server);
547 else if (aAnyRequest >>= aReadException)
549 nErrorCode = ERRCODE_INET_READ;
550 aArguments.push_back(aReadException.Diagnostic);
552 else if (aAnyRequest >>= aWriteException)
554 nErrorCode = ERRCODE_INET_WRITE;
555 aArguments.push_back(aWriteException.Diagnostic);
557 else
558 nErrorCode = ERRCODE_INET_GENERAL;
560 handleErrorHandlerRequest(aNetworkException.Classification,
561 nErrorCode,
562 aArguments,
563 rRequest->getContinuations(),
564 bObtainErrorStringOnly,
565 bHasErrorString,
566 rErrorString);
567 return true;
570 ucb::InteractiveWrongMediumException aWrongMediumException;
571 if (aAnyRequest >>= aWrongMediumException)
573 sal_Int32 nMedium = 0;
574 aWrongMediumException.Medium >>= nMedium;
575 std::vector< OUString > aArguments;
576 aArguments.push_back(OUString::number(nMedium + 1));
577 handleErrorHandlerRequest(aWrongMediumException.Classification,
578 ERRCODE_UUI_WRONGMEDIUM,
579 aArguments,
580 rRequest->getContinuations(),
581 bObtainErrorStringOnly,
582 bHasErrorString,
583 rErrorString);
584 return true;
587 java::WrongJavaVersionException aWrongJavaVersionException;
588 if (aAnyRequest >>= aWrongJavaVersionException)
590 ErrCode nErrorCode;
591 std::vector< OUString > aArguments;
592 if (aWrongJavaVersionException.DetectedVersion.isEmpty())
593 if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
594 nErrorCode = ERRCODE_UUI_WRONGJAVA;
595 else
597 nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN;
598 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
600 else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
602 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION;
603 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
605 else
607 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN;
608 aArguments.reserve(2);
609 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
610 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
612 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
613 nErrorCode,
614 aArguments,
615 rRequest->getContinuations(),
616 bObtainErrorStringOnly,
617 bHasErrorString,
618 rErrorString);
619 return true;
622 configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest;
623 if (aAnyRequest >>= aMergeRecoveryRequest)
625 ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest
626 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
627 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE;
629 std::vector< OUString > aArguments;
630 aArguments.push_back(aMergeRecoveryRequest.ErrorLayerId);
632 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
633 nErrorCode,
634 aArguments,
635 rRequest->getContinuations(),
636 bObtainErrorStringOnly,
637 bHasErrorString,
638 rErrorString);
639 return true;
642 configuration::backend::StratumCreationException
643 aStratumCreationException;
645 if (aAnyRequest >>= aStratumCreationException)
647 const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING;
649 OUString aStratum = aStratumCreationException.StratumData;
650 if (aStratum.isEmpty())
651 aStratum = aStratumCreationException.StratumService;
653 std::vector< OUString > aArguments;
654 aArguments.push_back(aStratum);
656 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
657 nErrorCode,
658 aArguments,
659 rRequest->getContinuations(),
660 bObtainErrorStringOnly,
661 bHasErrorString,
662 rErrorString);
663 return true;
666 xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException;
667 if (aAnyRequest >>= aInvalidDataOnSubmitException)
669 const ErrCode nErrorCode =
670 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA;
672 std::vector< OUString > aArguments;
674 handleErrorHandlerRequest(task::InteractionClassification_QUERY,
675 nErrorCode,
676 aArguments,
677 rRequest->getContinuations(),
678 bObtainErrorStringOnly,
679 bHasErrorString,
680 rErrorString);
681 return true;
684 ucb::InteractiveLockingLockedException aLLException;
685 if (aAnyRequest >>= aLLException)
687 ErrCode nErrorCode = aLLException.SelfOwned
688 ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED;
689 std::vector< OUString > aArguments;
690 aArguments.push_back( aLLException.Url );
692 handleErrorHandlerRequest( aLLException.Classification,
693 nErrorCode,
694 aArguments,
695 rRequest->getContinuations(),
696 bObtainErrorStringOnly,
697 bHasErrorString,
698 rErrorString );
699 return true;
702 ucb::InteractiveLockingNotLockedException aLNLException;
703 if (aAnyRequest >>= aLNLException)
705 std::vector< OUString > aArguments;
706 aArguments.push_back( aLNLException.Url );
708 handleErrorHandlerRequest( aLNLException.Classification,
709 ERRCODE_UUI_LOCKING_NOT_LOCKED,
710 aArguments,
711 rRequest->getContinuations(),
712 bObtainErrorStringOnly,
713 bHasErrorString,
714 rErrorString );
715 return true;
718 ucb::InteractiveLockingLockExpiredException aLLEException;
719 if (aAnyRequest >>= aLLEException)
721 std::vector< OUString > aArguments;
722 aArguments.push_back( aLLEException.Url );
724 handleErrorHandlerRequest( aLLEException.Classification,
725 ERRCODE_UUI_LOCKING_LOCK_EXPIRED,
726 aArguments,
727 rRequest->getContinuations(),
728 bObtainErrorStringOnly,
729 bHasErrorString,
730 rErrorString );
731 return true;
734 document::BrokenPackageRequest aBrokenPackageRequest;
735 if (aAnyRequest >>= aBrokenPackageRequest)
737 std::vector< OUString > aArguments;
739 if( !aBrokenPackageRequest.aName.isEmpty() )
740 aArguments.push_back( aBrokenPackageRequest.aName );
742 handleBrokenPackageRequest( aArguments,
743 rRequest->getContinuations(),
744 bObtainErrorStringOnly,
745 bHasErrorString,
746 rErrorString );
747 return true;
750 task::ErrorCodeRequest aErrorCodeRequest;
751 if (aAnyRequest >>= aErrorCodeRequest)
753 handleGenericErrorRequest( ErrCode(aErrorCodeRequest.ErrCode),
754 rRequest->getContinuations(),
755 bObtainErrorStringOnly,
756 bHasErrorString,
757 rErrorString);
758 return true;
761 task::ErrorCodeIOException aErrorCodeIOException;
762 if (aAnyRequest >>= aErrorCodeIOException)
764 handleGenericErrorRequest( ErrCode(aErrorCodeIOException.ErrCode),
765 rRequest->getContinuations(),
766 bObtainErrorStringOnly,
767 bHasErrorString,
768 rErrorString);
769 return true;
772 loader::CannotActivateFactoryException aCannotActivateFactoryException;
773 if (aAnyRequest >>= aCannotActivateFactoryException)
775 std::vector< OUString > aArguments;
776 aArguments.push_back( aCannotActivateFactoryException.Message );
778 handleErrorHandlerRequest( task::InteractionClassification_ERROR,
779 ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY,
780 aArguments,
781 rRequest->getContinuations(),
782 bObtainErrorStringOnly,
783 bHasErrorString,
784 rErrorString );
785 return true;
789 // Handle requests which do not have a plain string representation.
791 if (!bObtainErrorStringOnly)
793 ucb::AuthenticationFallbackRequest anAuthFallbackRequest;
794 if ( aAnyRequest >>= anAuthFallbackRequest )
796 handleAuthFallbackRequest( anAuthFallbackRequest.instructions,
797 anAuthFallbackRequest.url, rRequest->getContinuations() );
798 return true;
801 if ( handleAuthenticationRequest( rRequest ) )
802 return true;
804 if ( handleCertificateValidationRequest( rRequest ) )
805 return true;
807 ucb::NameClashResolveRequest aNameClashResolveRequest;
808 if (aAnyRequest >>= aNameClashResolveRequest)
810 handleNameClashResolveRequest(aNameClashResolveRequest,
811 rRequest->getContinuations());
812 return true;
815 if ( handleMasterPasswordRequest( rRequest ) )
816 return true;
818 if ( handlePasswordRequest( rRequest ) )
819 return true;
821 if ( handleNoSuchFilterRequest( rRequest ) )
822 return true;
824 if ( handleFilterOptionsRequest( rRequest ) )
825 return true;
827 if ( handleLockedDocumentRequest( rRequest ) )
828 return true;
830 if ( handleChangedByOthersRequest( rRequest ) )
831 return true;
833 if ( handleLockFileProblemRequest( rRequest ) )
834 return true;
836 task::DocumentMacroConfirmationRequest aMacroConfirmRequest;
837 if (aAnyRequest >>= aMacroConfirmRequest)
839 handleMacroConfirmRequest(
840 aMacroConfirmRequest.DocumentURL,
841 aMacroConfirmRequest.DocumentStorage,
842 !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_012_TEXT,
843 aMacroConfirmRequest.DocumentSignatureInformation,
844 rRequest->getContinuations());
845 return true;
848 // Last chance: interaction handlers registered in the configuration
851 // typed InteractionHandlers (ooo.Interactions)
852 if ( handleTypedHandlerImplementations( rRequest ) )
853 return true;
855 // legacy configuration (ooo.ucb.InteractionHandlers)
856 if (tryOtherInteractionHandler( rRequest ))
857 return true;
860 // Not handled.
861 return false;
863 catch( const uno::RuntimeException& )
865 throw; // allowed to leave here
867 catch( const uno::Exception& )
869 DBG_UNHANDLED_EXCEPTION("uui");
871 return false;
874 void
875 UUIInteractionHelper::getInteractionHandlerList(
876 InteractionHandlerDataList &rdataList)
880 uno::Reference< lang::XMultiServiceFactory > xConfigProv =
881 configuration::theDefaultProvider::get( m_xContext );
883 OUStringBuffer aFullPath;
884 aFullPath.append(
885 "/org.openoffice.ucb.InteractionHandler/InteractionHandlers" );
887 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
889 {"nodepath", uno::Any(aFullPath.makeStringAndClear())}
890 }));
892 uno::Reference< uno::XInterface > xInterface(
893 xConfigProv->createInstanceWithArguments(
894 "com.sun.star.configuration.ConfigurationAccess" , aArguments ) );
896 if ( !xInterface.is() )
897 throw uno::RuntimeException("unable to instantiate config access");
899 uno::Reference< container::XNameAccess > xNameAccess(
900 xInterface, uno::UNO_QUERY_THROW );
901 uno::Sequence< OUString > aElems = xNameAccess->getElementNames();
902 const OUString* pElems = aElems.getConstArray();
903 sal_Int32 nCount = aElems.getLength();
905 if ( nCount > 0 )
907 uno::Reference< container::XHierarchicalNameAccess >
908 xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
910 // Iterate over children.
911 for ( sal_Int32 n = 0; n < nCount; ++n )
913 OUStringBuffer aElemBuffer;
914 aElemBuffer.append( "['" );
915 aElemBuffer.append( pElems[ n ] );
919 InteractionHandlerData aInfo;
921 // Obtain service name.
922 OUStringBuffer aKeyBuffer = aElemBuffer;
923 aKeyBuffer.append( "']/ServiceName" );
925 OUString aValue;
926 if ( !( xHierNameAccess->getByHierarchicalName(
927 aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
929 OSL_FAIL( "GetInteractionHandlerList - "
930 "Error getting item value!" );
931 continue;
934 aInfo.ServiceName = aValue;
936 // Append info to list.
937 rdataList.push_back( aInfo );
939 catch ( container::NoSuchElementException& )
941 // getByHierarchicalName
943 OSL_FAIL( "GetInteractionHandlerList - "
944 "caught NoSuchElementException!" );
949 catch ( uno::RuntimeException const & )
951 throw;
953 catch ( uno::Exception const & )
955 OSL_FAIL( "GetInteractionHandlerList - Caught Exception!" );
959 const uno::Reference< awt::XWindow>&
960 UUIInteractionHelper::getParentXWindow() const
962 return m_xWindowParam;
965 uno::Reference< task::XInteractionHandler2 >
966 UUIInteractionHelper::getInteractionHandler()
968 return InteractionHandler::createWithParentAndContext(
969 m_xContext, m_xWindowParam,
970 m_aContextParam);
973 namespace {
975 DialogMask
976 executeMessageBox(
977 weld::Window * pParent,
978 OUString const & rTitle,
979 OUString const & rMessage,
980 VclMessageType eMessageType)
982 SolarMutexGuard aGuard;
984 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, eMessageType,
985 eMessageType == VclMessageType::Question ? VclButtonsType::YesNo : VclButtonsType::Ok, rMessage));
986 xBox->set_title(rTitle);
988 short nMessResult = xBox->run();
989 DialogMask aResult = DialogMask::NONE;
990 switch (nMessResult)
992 case RET_OK:
993 aResult = DialogMask::ButtonsOk;
994 break;
995 case RET_CANCEL:
996 aResult = DialogMask::ButtonsCancel;
997 break;
998 case RET_YES:
999 aResult = DialogMask::ButtonsYes;
1000 break;
1001 case RET_NO:
1002 aResult = DialogMask::ButtonsNo;
1003 break;
1004 default:
1005 assert(false);
1008 return aResult;
1011 NameClashResolveDialogResult executeSimpleNameClashResolveDialog(weld::Window *pParent,
1012 OUString const & rTargetFolderURL,
1013 OUString const & rClashingName,
1014 OUString & rProposedNewName,
1015 bool bAllowOverwrite)
1017 std::locale aResLocale = Translate::Create("uui");
1018 NameClashDialog aDialog(pParent, aResLocale, rTargetFolderURL,
1019 rClashingName, rProposedNewName, bAllowOverwrite);
1021 NameClashResolveDialogResult eResult = static_cast<NameClashResolveDialogResult>(aDialog.run());
1022 rProposedNewName = aDialog.getNewName();
1023 return eResult;
1026 } // namespace
1028 void
1029 UUIInteractionHelper::handleNameClashResolveRequest(
1030 ucb::NameClashResolveRequest const & rRequest,
1031 uno::Sequence< uno::Reference<
1032 task::XInteractionContinuation > > const & rContinuations)
1034 OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(),
1035 "NameClashResolveRequest must not contain empty TargetFolderURL" );
1037 OSL_ENSURE(!rRequest.ClashingName.isEmpty(),
1038 "NameClashResolveRequest must not contain empty ClashingName" );
1040 uno::Reference< task::XInteractionAbort > xAbort;
1041 uno::Reference< ucb::XInteractionSupplyName > xSupplyName;
1042 uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData;
1043 getContinuations(
1044 rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData);
1046 OSL_ENSURE( xAbort.is(),
1047 "NameClashResolveRequest must contain Abort continuation" );
1049 OSL_ENSURE( xSupplyName.is(),
1050 "NameClashResolveRequest must contain SupplyName continuation" );
1052 NameClashResolveDialogResult eResult = ABORT;
1053 OUString aProposedNewName( rRequest.ProposedNewName );
1055 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1056 eResult = executeSimpleNameClashResolveDialog(Application::GetFrameWeld(xParent),
1057 rRequest.TargetFolderURL,
1058 rRequest.ClashingName,
1059 aProposedNewName,
1060 xReplaceExistingData.is());
1062 switch ( eResult )
1064 case ABORT:
1065 xAbort->select();
1066 break;
1068 case RENAME:
1069 xSupplyName->setName( aProposedNewName );
1070 xSupplyName->select();
1071 break;
1073 case OVERWRITE:
1074 OSL_ENSURE(
1075 xReplaceExistingData.is(),
1076 "Invalid NameClashResolveDialogResult: OVERWRITE - "
1077 "No ReplaceExistingData continuation available!" );
1078 xReplaceExistingData->select();
1079 break;
1083 void
1084 UUIInteractionHelper::handleGenericErrorRequest(
1085 ErrCode nErrorCode,
1086 uno::Sequence< uno::Reference<
1087 task::XInteractionContinuation > > const & rContinuations,
1088 bool bObtainErrorStringOnly,
1089 bool & bHasErrorString,
1090 OUString & rErrorString)
1092 if (bObtainErrorStringOnly)
1094 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1095 if (bHasErrorString)
1097 OUString aErrorString;
1098 ErrorHandler::GetErrorString(nErrorCode, aErrorString);
1099 rErrorString = aErrorString;
1102 else
1104 uno::Reference< task::XInteractionAbort > xAbort;
1105 uno::Reference< task::XInteractionApprove > xApprove;
1106 getContinuations(rContinuations, &xApprove, &xAbort);
1108 // Note: It's important to convert the transported long to the
1109 // required unsigned long value. Otherwise using as flag field
1110 // can fail ...
1111 ErrCode nError(nErrorCode);
1112 bool bWarning = !nError.IgnoreWarning();
1114 if ( nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION )
1116 // the security warning box needs a special title
1117 OUString aErrorString;
1118 ErrorHandler::GetErrorString( nErrorCode, aErrorString );
1120 std::locale aResLocale = Translate::Create("uui");
1121 OUString aTitle( utl::ConfigManager::getProductName() );
1123 OUString aErrTitle = Translate::get(STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE, aResLocale);
1125 if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() )
1126 aTitle += " - " ;
1127 aTitle += aErrTitle;
1129 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1130 executeMessageBox(Application::GetFrameWeld(xParent), aTitle, aErrorString, VclMessageType::Error);
1132 else
1134 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1135 ErrorHandler::HandleError(nErrorCode, Application::GetFrameWeld(xParent));
1138 if (xApprove.is() && bWarning)
1139 xApprove->select();
1140 else if (xAbort.is())
1141 xAbort->select();
1145 void
1146 UUIInteractionHelper::handleMacroConfirmRequest(
1147 const OUString& aDocumentURL,
1148 const uno::Reference< embed::XStorage >& xZipStorage,
1149 const OUString& aDocumentVersion,
1150 const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo,
1151 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1152 rContinuations )
1154 uno::Reference< task::XInteractionAbort > xAbort;
1155 uno::Reference< task::XInteractionApprove > xApprove;
1156 getContinuations( rContinuations, &xApprove, &xAbort );
1158 bool bApprove = false;
1160 bool bShowSignatures = aSignInfo.getLength() > 0;
1161 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1162 MacroWarning aWarning(Application::GetFrameWeld(xParent), bShowSignatures);
1164 aWarning.SetDocumentURL(aDocumentURL);
1165 if ( aSignInfo.getLength() > 1 )
1167 aWarning.SetStorage(xZipStorage, aDocumentVersion, aSignInfo);
1169 else if ( aSignInfo.getLength() == 1 )
1171 aWarning.SetCertificate(aSignInfo[0].Signer);
1174 bApprove = aWarning.run() == RET_OK;
1176 if ( bApprove && xApprove.is() )
1177 xApprove->select();
1178 else if ( xAbort.is() )
1179 xAbort->select();
1182 void
1183 UUIInteractionHelper::handleBrokenPackageRequest(
1184 std::vector< OUString > const & rArguments,
1185 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1186 rContinuations,
1187 bool bObtainErrorStringOnly,
1188 bool & bHasErrorString,
1189 OUString & rErrorString)
1191 if (bObtainErrorStringOnly)
1193 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1194 if (!bHasErrorString)
1195 return;
1198 uno::Reference< task::XInteractionApprove > xApprove;
1199 uno::Reference< task::XInteractionDisapprove > xDisapprove;
1200 uno::Reference< task::XInteractionAbort > xAbort;
1201 getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort);
1203 ErrCode nErrorCode;
1204 if( xApprove.is() && xDisapprove.is() )
1206 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE;
1208 else if ( xAbort.is() )
1210 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR;
1212 else
1213 return;
1215 OUString aMessage;
1217 std::locale aResLocale = Translate::Create("uui");
1218 ErrorResource aErrorResource(RID_UUI_ERRHDL, aResLocale);
1219 if (!aErrorResource.getString(nErrorCode, aMessage))
1220 return;
1223 aMessage = replaceMessageWithArguments( aMessage, rArguments );
1225 if (bObtainErrorStringOnly)
1227 rErrorString = aMessage;
1228 return;
1231 VclMessageType eMessageType;
1232 if( xApprove.is() && xDisapprove.is() )
1233 eMessageType = VclMessageType::Question;
1234 else if ( xAbort.is() )
1235 eMessageType = VclMessageType::Warning;
1236 else
1237 return;
1239 OUString title(
1240 utl::ConfigManager::getProductName() +
1241 " " +
1242 utl::ConfigManager::getProductVersion() );
1244 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1245 switch (executeMessageBox(Application::GetFrameWeld(xParent), title, aMessage, eMessageType))
1247 case DialogMask::ButtonsOk:
1248 OSL_ENSURE( xAbort.is(), "unexpected situation" );
1249 if (xAbort.is())
1250 xAbort->select();
1251 break;
1253 case DialogMask::ButtonsNo:
1254 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
1255 if (xDisapprove.is())
1256 xDisapprove->select();
1257 break;
1259 case DialogMask::ButtonsYes:
1260 OSL_ENSURE(xApprove.is(), "unexpected situation");
1261 if (xApprove.is())
1262 xApprove->select();
1263 break;
1265 default: break;
1269 // ErrorResource Implementation
1270 bool ErrorResource::getString(ErrCode nErrorCode, OUString &rString) const
1272 for (const std::pair<const char*, ErrCode>* pStringArray = m_pStringArray; pStringArray->first != nullptr; ++pStringArray)
1274 if (nErrorCode.StripWarningAndDynamic() == pStringArray->second.StripWarningAndDynamic())
1276 rString = Translate::get(pStringArray->first, m_rResLocale);
1277 return true;
1280 return false;
1283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */