Update git submodules
[LibreOffice.git] / uui / source / iahndl.cxx
blobec8cb02258dbe8cfdeddb868981c0aafdf4fe8b7
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 <vcl/errinf.hxx>
66 #include <vcl/svapp.hxx>
67 #include <vcl/weld.hxx>
68 #include <tools/diagnose_ex.h>
69 #include <comphelper/documentconstants.hxx>
70 #include <comphelper/propertysequence.hxx>
71 #include <svtools/sfxecode.hxx>
72 #include <unotools/configmgr.hxx>
73 #include <comphelper/namedvaluecollection.hxx>
74 #include <typelib/typedescription.hxx>
75 #include <unotools/confignode.hxx>
77 #include <ids.hxx>
78 #include <ids.hrc>
79 #include <strings.hrc>
81 #include "getcontinuations.hxx"
82 #include "secmacrowarnings.hxx"
84 #include "iahndl.hxx"
85 #include "nameclashdlg.hxx"
87 using ::com::sun::star::uno::Sequence;
88 using ::com::sun::star::uno::UNO_QUERY;
89 using ::com::sun::star::uno::Reference;
90 using ::com::sun::star::task::XInteractionContinuation;
91 using ::com::sun::star::task::XInteractionAbort;
92 using ::com::sun::star::task::XInteractionApprove;
93 using ::com::sun::star::uno::XInterface;
94 using ::com::sun::star::lang::XInitialization;
95 using ::com::sun::star::uno::UNO_QUERY_THROW;
96 using ::com::sun::star::task::InteractionHandler;
97 using ::com::sun::star::task::XInteractionHandler2;
98 using ::com::sun::star::uno::Exception;
99 using ::com::sun::star::uno::Any;
100 using ::com::sun::star::task::XInteractionRequest;
101 using ::com::sun::star::lang::XMultiServiceFactory;
103 using namespace ::com::sun::star;
105 namespace {
107 class HandleData : public osl::Condition
109 public:
110 explicit HandleData(
111 uno::Reference< task::XInteractionRequest > const & rRequest)
112 : osl::Condition(),
113 m_rRequest(rRequest),
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 > const & rxContext,
126 uno::Reference< awt::XWindow > const & rxWindowParam,
127 const OUString & rContextParam)
128 : m_xContext(rxContext),
129 m_xWindowParam(rxWindowParam),
130 m_aContextParam(rContextParam)
134 UUIInteractionHelper::UUIInteractionHelper(
135 uno::Reference< uno::XComponentContext > const & rxContext)
136 : m_xContext(rxContext)
140 UUIInteractionHelper::~UUIInteractionHelper()
144 void UUIInteractionHelper::handlerequest(
145 void* pHandleData, void* pInteractionHelper)
147 HandleData* pHND
148 = static_cast< HandleData * >(pHandleData);
149 UUIInteractionHelper* pUUI
150 = static_cast< UUIInteractionHelper * >(pInteractionHelper);
151 bool bDummy = false;
152 OUString aDummy;
153 pHND->bHandled
154 = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy);
155 pHND->set();
158 bool
159 UUIInteractionHelper::handleRequest(
160 uno::Reference< task::XInteractionRequest > const & rRequest)
162 if(!Application::IsMainThread() && GetpApp())
164 // we are not in the main thread, let it handle that stuff
165 HandleData aHD(rRequest);
166 Link<void*,void> aLink(&aHD,handlerequest);
167 Application::PostUserEvent(aLink,this);
168 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
169 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
170 aHD.wait();
171 if (nLockCount)
172 rSolarMutex.acquire(nLockCount);
173 return aHD.bHandled;
175 else
177 bool bDummy = false;
178 OUString aDummy;
179 return handleRequest_impl(rRequest, false, bDummy, aDummy);
183 void UUIInteractionHelper::getstringfromrequest(
184 void* pHandleData,void* pInteractionHelper)
186 HandleData* pHND = static_cast<HandleData*>(pHandleData);
187 UUIInteractionHelper* pUUI = static_cast<UUIInteractionHelper*>(pInteractionHelper);
188 pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest);
189 pHND->set();
192 beans::Optional< OUString >
193 UUIInteractionHelper::getStringFromRequest_impl(
194 uno::Reference< task::XInteractionRequest > const & rRequest)
196 bool bSuccess = false;
197 OUString aMessage;
198 handleRequest_impl(rRequest, true, bSuccess, aMessage);
200 OSL_ENSURE(bSuccess ||
201 !isInformationalErrorMessageRequest(
202 rRequest->getContinuations()),
203 "Interaction request is a candidate for a string representation."
204 "Please implement!");
206 return beans::Optional< OUString >(bSuccess, aMessage);
209 beans::Optional< OUString >
210 UUIInteractionHelper::getStringFromRequest(
211 uno::Reference< task::XInteractionRequest > const & rRequest)
213 if(!Application::IsMainThread() && GetpApp())
215 // we are not in the main thread, let it handle that stuff
216 HandleData aHD(rRequest);
217 Link<void*,void> aLink(&aHD,getstringfromrequest);
218 Application::PostUserEvent(aLink,this);
219 comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex();
220 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
221 aHD.wait();
222 if (nLockCount)
223 rSolarMutex.acquire(nLockCount);
224 return aHD.m_aResult;
226 else
227 return getStringFromRequest_impl(rRequest);
230 OUString
231 UUIInteractionHelper::replaceMessageWithArguments(
232 const OUString& _aMessage,
233 std::vector< OUString > const & rArguments )
235 OUString aMessage = _aMessage;
237 SAL_WARN_IF(rArguments.empty(), "uui", "replaceMessageWithArguments: No arguments passed!");
238 for (size_t i = 0; i < rArguments.size(); ++i)
240 const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")";
241 aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]);
244 return aMessage;
247 bool
248 UUIInteractionHelper::isInformationalErrorMessageRequest(
249 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
250 rContinuations)
252 // Only requests with a single continuation (user has no choice, request
253 // is just informational)
254 if (rContinuations.getLength() != 1 )
255 return false;
257 // user can only abort or approve, all other continuations are not
258 // considered to be informational.
259 uno::Reference< task::XInteractionApprove > xApprove(
260 rContinuations[0], uno::UNO_QUERY);
261 if (xApprove.is())
262 return true;
264 uno::Reference< task::XInteractionAbort > xAbort(
265 rContinuations[0], uno::UNO_QUERY);
266 return xAbort.is();
269 bool
270 UUIInteractionHelper::tryOtherInteractionHandler(
271 uno::Reference< task::XInteractionRequest > const & rRequest)
273 InteractionHandlerDataList dataList;
274 getInteractionHandlerList(dataList);
276 return std::any_of(dataList.cbegin(), dataList.cend(),
277 [&](const InteractionHandlerData& rData) { return handleCustomRequest( rRequest, rData.ServiceName ); });
280 namespace
283 bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, std::u16string_view i_rPropagation )
285 const css::uno::TypeDescription aTypeDesc( i_rTypeName );
286 const typelib_TypeDescription* pTypeDesc = aTypeDesc.get();
287 if ( !pTypeDesc || !pTypeDesc->pWeakRef )
289 SAL_WARN( "uui","no type found for '" << i_rTypeName << "'" );
290 return false;
292 const css::uno::Type aType( pTypeDesc->pWeakRef );
294 const bool bExactMatch = i_rPropagation == u"named-only";
295 if ( bExactMatch )
296 return i_rRequest.getValueType().equals( aType );
298 return i_rRequest.isExtractableTo( aType );
303 bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const
307 Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW );
309 Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY );
310 if ( xHandlerInit.is() )
312 ::comphelper::NamedValueCollection aInitArgs;
313 aInitArgs.put( "Parent", getParentXWindow() );
314 xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() );
317 if ( xHandler->handleInteractionRequest( i_rRequest ) )
318 return true;
320 catch( const Exception& )
322 DBG_UNHANDLED_EXCEPTION("uui");
324 return false;
328 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest )
330 // the request
331 const Any aRequest( rRequest->getRequest() );
333 const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() );
334 if ( aCacheHitTest != m_aTypedCustomHandlers.end() )
335 return handleCustomRequest( rRequest, aCacheHitTest->second );
337 // the base registration node for "typed" interaction handlers
338 const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext(
339 m_xContext,
340 "/org.openoffice.Interaction/InteractionHandlers",
342 ::utl::OConfigurationTreeRoot::CM_READONLY
343 ) );
345 // loop through all registered implementations
346 const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() );
347 for ( auto const & handlerName : aRegisteredHandlers )
349 const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( handlerName ) );
350 const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) );
352 // loop through all the types which the current handler is registered for
353 const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() );
354 for ( auto const & type : aHandledTypes )
356 // the UNO type is the node name
357 ::utl::OConfigurationNode aType( aTypesNode.openNode( type ) );
358 // and there's a child denoting how the responsibility propagates
359 OUString sPropagation;
360 OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation );
361 if ( lcl_matchesRequest( aRequest, type, sPropagation ) )
363 // retrieve the service/implementation name of the handler
364 OUString sServiceName;
365 OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName );
366 // cache the information who feels responsible for requests of this type
367 m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName;
368 // actually handle the request
369 return handleCustomRequest( rRequest, sServiceName );
374 return false;
377 bool
378 UUIInteractionHelper::handleRequest_impl(
379 uno::Reference< task::XInteractionRequest > const & rRequest,
380 bool bObtainErrorStringOnly,
381 bool & bHasErrorString,
382 OUString & rErrorString)
386 if (!rRequest.is())
387 return false;
389 uno::Any aAnyRequest(rRequest->getRequest());
391 script::ModuleSizeExceededRequest aModSizeException;
392 if (aAnyRequest >>= aModSizeException )
394 std::vector< OUString > aArguments;
395 uno::Sequence< OUString > sModules
396 = aModSizeException.Names;
397 if ( sModules.hasElements() )
399 OUStringBuffer aName;
400 for ( sal_Int32 index=0; index< sModules.getLength(); ++index )
402 if ( index )
403 aName.append(",");
404 aName.append(sModules[index]);
406 aArguments.push_back( aName.makeStringAndClear() );
408 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
409 ERRCODE_UUI_IO_MODULESIZEEXCEEDED,
410 aArguments,
411 rRequest->getContinuations(),
412 bObtainErrorStringOnly,
413 bHasErrorString,
414 rErrorString);
415 return true;
418 document::ExoticFileLoadException aExoticFileLoadException;
419 if (aAnyRequest >>= aExoticFileLoadException)
421 std::vector< OUString > aArguments;
423 if( !aExoticFileLoadException.URL.isEmpty() )
425 aArguments.push_back( aExoticFileLoadException.URL );
427 if( !aExoticFileLoadException.FilterUIName.isEmpty() )
429 aArguments.push_back( aExoticFileLoadException.FilterUIName );
432 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
433 ERRCODE_UUI_IO_EXOTICFILEFORMAT,
434 aArguments,
435 rRequest->getContinuations(),
436 bObtainErrorStringOnly,
437 bHasErrorString,
438 rErrorString);
439 return true;
442 ucb::NameClashException aNCException;
443 if (aAnyRequest >>= aNCException)
445 ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS;
446 std::vector< OUString > aArguments;
448 if( !aNCException.Name.isEmpty() )
450 nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS;
451 aArguments.push_back( aNCException.Name );
454 handleErrorHandlerRequest( aNCException.Classification,
455 nErrorCode,
456 aArguments,
457 rRequest->getContinuations(),
458 bObtainErrorStringOnly,
459 bHasErrorString,
460 rErrorString);
461 return true;
464 ucb::UnsupportedNameClashException aUORequest;
465 if (aAnyRequest >>= aUORequest)
467 std::vector< OUString > aArguments;
469 uno::Reference< task::XInteractionApprove > xApprove;
470 uno::Reference< task::XInteractionDisapprove > xDisapprove;
471 getContinuations(
472 rRequest->getContinuations(), &xApprove, &xDisapprove);
474 if ( xApprove.is() && xDisapprove.is() )
476 handleErrorHandlerRequest( task::InteractionClassification_QUERY,
477 ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE,
478 aArguments,
479 rRequest->getContinuations(),
480 bObtainErrorStringOnly,
481 bHasErrorString,
482 rErrorString);
484 return true;
487 if ( handleInteractiveIOException( rRequest,
488 bObtainErrorStringOnly,
489 bHasErrorString,
490 rErrorString ) )
491 return true;
493 ucb::InteractiveAppException aAppException;
494 if (aAnyRequest >>= aAppException)
496 std::vector< OUString > aArguments;
497 handleErrorHandlerRequest( aAppException.Classification,
498 ErrCode(aAppException.Code),
499 aArguments,
500 rRequest->getContinuations(),
501 bObtainErrorStringOnly,
502 bHasErrorString,
503 rErrorString);
504 return true;
507 ucb::InteractiveNetworkException aNetworkException;
508 if (aAnyRequest >>= aNetworkException)
510 ErrCode nErrorCode;
511 std::vector< OUString > aArguments;
512 ucb::InteractiveNetworkOffLineException aOffLineException;
513 ucb::InteractiveNetworkResolveNameException aResolveNameException;
514 ucb::InteractiveNetworkConnectException aConnectException;
515 ucb::InteractiveNetworkReadException aReadException;
516 ucb::InteractiveNetworkWriteException aWriteException;
517 if (aAnyRequest >>= aOffLineException)
518 nErrorCode = ERRCODE_INET_OFFLINE;
519 else if (aAnyRequest >>= aResolveNameException)
521 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
522 aArguments.push_back(aResolveNameException.Server);
524 else if (aAnyRequest >>= aConnectException)
526 nErrorCode = ERRCODE_INET_CONNECT;
527 aArguments.push_back(aConnectException.Server);
529 else if (aAnyRequest >>= aReadException)
531 nErrorCode = ERRCODE_INET_READ;
532 aArguments.push_back(aReadException.Diagnostic);
534 else if (aAnyRequest >>= aWriteException)
536 nErrorCode = ERRCODE_INET_WRITE;
537 aArguments.push_back(aWriteException.Diagnostic);
539 else
540 nErrorCode = ERRCODE_INET_GENERAL;
542 handleErrorHandlerRequest(aNetworkException.Classification,
543 nErrorCode,
544 aArguments,
545 rRequest->getContinuations(),
546 bObtainErrorStringOnly,
547 bHasErrorString,
548 rErrorString);
549 return true;
552 ucb::InteractiveWrongMediumException aWrongMediumException;
553 if (aAnyRequest >>= aWrongMediumException)
555 sal_Int32 nMedium = 0;
556 aWrongMediumException.Medium >>= nMedium;
557 std::vector< OUString > aArguments;
558 aArguments.push_back(OUString::number(nMedium + 1));
559 handleErrorHandlerRequest(aWrongMediumException.Classification,
560 ERRCODE_UUI_WRONGMEDIUM,
561 aArguments,
562 rRequest->getContinuations(),
563 bObtainErrorStringOnly,
564 bHasErrorString,
565 rErrorString);
566 return true;
569 java::WrongJavaVersionException aWrongJavaVersionException;
570 if (aAnyRequest >>= aWrongJavaVersionException)
572 ErrCode nErrorCode;
573 std::vector< OUString > aArguments;
574 if (aWrongJavaVersionException.DetectedVersion.isEmpty())
575 if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
576 nErrorCode = ERRCODE_UUI_WRONGJAVA;
577 else
579 nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN;
580 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
582 else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
584 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION;
585 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
587 else
589 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN;
590 aArguments.reserve(2);
591 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
592 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
594 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
595 nErrorCode,
596 aArguments,
597 rRequest->getContinuations(),
598 bObtainErrorStringOnly,
599 bHasErrorString,
600 rErrorString);
601 return true;
604 configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest;
605 if (aAnyRequest >>= aMergeRecoveryRequest)
607 ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest
608 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
609 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE;
611 std::vector< OUString > aArguments;
612 aArguments.push_back(aMergeRecoveryRequest.ErrorLayerId);
614 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
615 nErrorCode,
616 aArguments,
617 rRequest->getContinuations(),
618 bObtainErrorStringOnly,
619 bHasErrorString,
620 rErrorString);
621 return true;
624 configuration::backend::StratumCreationException
625 aStratumCreationException;
627 if (aAnyRequest >>= aStratumCreationException)
629 const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING;
631 OUString aStratum = aStratumCreationException.StratumData;
632 if (aStratum.isEmpty())
633 aStratum = aStratumCreationException.StratumService;
635 std::vector< OUString > aArguments;
636 aArguments.push_back(aStratum);
638 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
639 nErrorCode,
640 aArguments,
641 rRequest->getContinuations(),
642 bObtainErrorStringOnly,
643 bHasErrorString,
644 rErrorString);
645 return true;
648 xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException;
649 if (aAnyRequest >>= aInvalidDataOnSubmitException)
651 const ErrCode nErrorCode =
652 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA;
654 std::vector< OUString > aArguments;
656 handleErrorHandlerRequest(task::InteractionClassification_QUERY,
657 nErrorCode,
658 aArguments,
659 rRequest->getContinuations(),
660 bObtainErrorStringOnly,
661 bHasErrorString,
662 rErrorString);
663 return true;
666 ucb::InteractiveLockingLockedException aLLException;
667 if (aAnyRequest >>= aLLException)
669 ErrCode nErrorCode = aLLException.SelfOwned
670 ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED;
671 std::vector< OUString > aArguments;
672 aArguments.push_back( aLLException.Url );
674 handleErrorHandlerRequest( aLLException.Classification,
675 nErrorCode,
676 aArguments,
677 rRequest->getContinuations(),
678 bObtainErrorStringOnly,
679 bHasErrorString,
680 rErrorString );
681 return true;
684 ucb::InteractiveLockingNotLockedException aLNLException;
685 if (aAnyRequest >>= aLNLException)
687 std::vector< OUString > aArguments;
688 aArguments.push_back( aLNLException.Url );
690 handleErrorHandlerRequest( aLNLException.Classification,
691 ERRCODE_UUI_LOCKING_NOT_LOCKED,
692 aArguments,
693 rRequest->getContinuations(),
694 bObtainErrorStringOnly,
695 bHasErrorString,
696 rErrorString );
697 return true;
700 ucb::InteractiveLockingLockExpiredException aLLEException;
701 if (aAnyRequest >>= aLLEException)
703 std::vector< OUString > aArguments;
704 aArguments.push_back( aLLEException.Url );
706 handleErrorHandlerRequest( aLLEException.Classification,
707 ERRCODE_UUI_LOCKING_LOCK_EXPIRED,
708 aArguments,
709 rRequest->getContinuations(),
710 bObtainErrorStringOnly,
711 bHasErrorString,
712 rErrorString );
713 return true;
716 document::BrokenPackageRequest aBrokenPackageRequest;
717 if (aAnyRequest >>= aBrokenPackageRequest)
719 std::vector< OUString > aArguments;
721 if( !aBrokenPackageRequest.aName.isEmpty() )
722 aArguments.push_back( aBrokenPackageRequest.aName );
724 handleBrokenPackageRequest( aArguments,
725 rRequest->getContinuations(),
726 bObtainErrorStringOnly,
727 bHasErrorString,
728 rErrorString );
729 return true;
732 task::ErrorCodeRequest aErrorCodeRequest;
733 if (aAnyRequest >>= aErrorCodeRequest)
735 handleGenericErrorRequest( ErrCode(aErrorCodeRequest.ErrCode),
736 rRequest->getContinuations(),
737 bObtainErrorStringOnly,
738 bHasErrorString,
739 rErrorString);
740 return true;
743 task::ErrorCodeIOException aErrorCodeIOException;
744 if (aAnyRequest >>= aErrorCodeIOException)
746 handleGenericErrorRequest( ErrCode(aErrorCodeIOException.ErrCode),
747 rRequest->getContinuations(),
748 bObtainErrorStringOnly,
749 bHasErrorString,
750 rErrorString);
751 return true;
754 loader::CannotActivateFactoryException aCannotActivateFactoryException;
755 if (aAnyRequest >>= aCannotActivateFactoryException)
757 std::vector< OUString > aArguments;
758 aArguments.push_back( aCannotActivateFactoryException.Message );
760 handleErrorHandlerRequest( task::InteractionClassification_ERROR,
761 ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY,
762 aArguments,
763 rRequest->getContinuations(),
764 bObtainErrorStringOnly,
765 bHasErrorString,
766 rErrorString );
767 return true;
771 // Handle requests which do not have a plain string representation.
773 if (!bObtainErrorStringOnly)
775 ucb::AuthenticationFallbackRequest anAuthFallbackRequest;
776 if ( aAnyRequest >>= anAuthFallbackRequest )
778 handleAuthFallbackRequest( anAuthFallbackRequest.instructions,
779 anAuthFallbackRequest.url, rRequest->getContinuations() );
780 return true;
783 if ( handleAuthenticationRequest( rRequest ) )
784 return true;
786 if ( handleCertificateValidationRequest( rRequest ) )
787 return true;
789 ucb::NameClashResolveRequest aNameClashResolveRequest;
790 if (aAnyRequest >>= aNameClashResolveRequest)
792 handleNameClashResolveRequest(aNameClashResolveRequest,
793 rRequest->getContinuations());
794 return true;
797 if ( handleMasterPasswordRequest( rRequest ) )
798 return true;
800 if ( handlePasswordRequest( rRequest ) )
801 return true;
803 if ( handleNoSuchFilterRequest( rRequest ) )
804 return true;
806 if ( handleFilterOptionsRequest( rRequest ) )
807 return true;
809 if ( handleLockedDocumentRequest( rRequest ) )
810 return true;
812 if ( handleChangedByOthersRequest( rRequest ) )
813 return true;
815 if ( handleLockFileProblemRequest( rRequest ) )
816 return true;
818 task::DocumentMacroConfirmationRequest aMacroConfirmRequest;
819 if (aAnyRequest >>= aMacroConfirmRequest)
821 handleMacroConfirmRequest(
822 aMacroConfirmRequest.DocumentURL,
823 aMacroConfirmRequest.DocumentStorage,
824 !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_013_TEXT,
825 aMacroConfirmRequest.DocumentSignatureInformation,
826 rRequest->getContinuations());
827 return true;
830 // Last chance: interaction handlers registered in the configuration
833 // typed InteractionHandlers (ooo.Interactions)
834 if ( handleTypedHandlerImplementations( rRequest ) )
835 return true;
837 // legacy configuration (ooo.ucb.InteractionHandlers)
838 if (tryOtherInteractionHandler( rRequest ))
839 return true;
842 // Not handled.
843 return false;
845 catch( const uno::RuntimeException& )
847 throw; // allowed to leave here
849 catch( const uno::Exception& )
851 DBG_UNHANDLED_EXCEPTION("uui");
853 return false;
856 void
857 UUIInteractionHelper::getInteractionHandlerList(
858 InteractionHandlerDataList &rdataList)
862 uno::Reference< lang::XMultiServiceFactory > xConfigProv =
863 configuration::theDefaultProvider::get( m_xContext );
865 uno::Sequence<uno::Any> aArguments(comphelper::InitAnyPropertySequence(
867 {"nodepath", uno::Any(OUString("/org.openoffice.ucb.InteractionHandler/InteractionHandlers"))}
868 }));
870 uno::Reference< uno::XInterface > xInterface(
871 xConfigProv->createInstanceWithArguments(
872 "com.sun.star.configuration.ConfigurationAccess" , aArguments ) );
874 if ( !xInterface.is() )
875 throw uno::RuntimeException("unable to instantiate config access");
877 uno::Reference< container::XNameAccess > xNameAccess(
878 xInterface, uno::UNO_QUERY_THROW );
879 const uno::Sequence< OUString > aElems = xNameAccess->getElementNames();
881 if ( aElems.hasElements() )
883 uno::Reference< container::XHierarchicalNameAccess >
884 xHierNameAccess( xInterface, uno::UNO_QUERY_THROW );
886 // Iterate over children.
887 for ( const auto& rElem : aElems )
891 InteractionHandlerData aInfo;
893 // Obtain service name.
894 OUString aKeyBuffer = "['" + rElem + "']/ServiceName";
896 OUString aValue;
897 if ( !( xHierNameAccess->getByHierarchicalName(
898 aKeyBuffer ) >>= aValue ) )
900 OSL_FAIL( "GetInteractionHandlerList - "
901 "Error getting item value!" );
902 continue;
905 aInfo.ServiceName = aValue;
907 // Append info to list.
908 rdataList.push_back( aInfo );
910 catch ( container::NoSuchElementException& )
912 // getByHierarchicalName
914 OSL_FAIL( "GetInteractionHandlerList - "
915 "caught NoSuchElementException!" );
920 catch ( uno::RuntimeException const & )
922 throw;
924 catch ( uno::Exception const & )
926 TOOLS_WARN_EXCEPTION( "uui", "GetInteractionHandlerList" );
930 const uno::Reference< awt::XWindow>&
931 UUIInteractionHelper::getParentXWindow() const
933 return m_xWindowParam;
936 uno::Reference< task::XInteractionHandler2 >
937 UUIInteractionHelper::getInteractionHandler() const
939 return InteractionHandler::createWithParentAndContext(
940 m_xContext, m_xWindowParam,
941 m_aContextParam);
944 namespace {
946 DialogMask
947 executeMessageBox(
948 weld::Window * pParent,
949 OUString const & rTitle,
950 OUString const & rMessage,
951 VclMessageType eMessageType)
953 SolarMutexGuard aGuard;
955 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent, eMessageType,
956 eMessageType == VclMessageType::Question ? VclButtonsType::YesNo : VclButtonsType::Ok, rMessage));
957 xBox->set_title(rTitle);
959 short nMessResult = xBox->run();
960 DialogMask aResult = DialogMask::NONE;
961 switch (nMessResult)
963 case RET_OK:
964 aResult = DialogMask::ButtonsOk;
965 break;
966 case RET_CANCEL:
967 aResult = DialogMask::ButtonsCancel;
968 break;
969 case RET_YES:
970 aResult = DialogMask::ButtonsYes;
971 break;
972 case RET_NO:
973 aResult = DialogMask::ButtonsNo;
974 break;
975 default:
976 assert(false);
979 return aResult;
982 NameClashResolveDialogResult executeSimpleNameClashResolveDialog(weld::Window *pParent,
983 OUString const & rTargetFolderURL,
984 OUString const & rClashingName,
985 OUString & rProposedNewName,
986 bool bAllowOverwrite)
988 std::locale aResLocale = Translate::Create("uui");
989 NameClashDialog aDialog(pParent, aResLocale, rTargetFolderURL,
990 rClashingName, rProposedNewName, bAllowOverwrite);
992 NameClashResolveDialogResult eResult = static_cast<NameClashResolveDialogResult>(aDialog.run());
993 rProposedNewName = aDialog.getNewName();
994 return eResult;
997 } // namespace
999 void
1000 UUIInteractionHelper::handleNameClashResolveRequest(
1001 ucb::NameClashResolveRequest const & rRequest,
1002 uno::Sequence< uno::Reference<
1003 task::XInteractionContinuation > > const & rContinuations)
1005 OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(),
1006 "NameClashResolveRequest must not contain empty TargetFolderURL" );
1008 OSL_ENSURE(!rRequest.ClashingName.isEmpty(),
1009 "NameClashResolveRequest must not contain empty ClashingName" );
1011 uno::Reference< task::XInteractionAbort > xAbort;
1012 uno::Reference< ucb::XInteractionSupplyName > xSupplyName;
1013 uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData;
1014 getContinuations(
1015 rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData);
1017 OSL_ENSURE( xAbort.is(),
1018 "NameClashResolveRequest must contain Abort continuation" );
1020 OSL_ENSURE( xSupplyName.is(),
1021 "NameClashResolveRequest must contain SupplyName continuation" );
1023 NameClashResolveDialogResult eResult = ABORT;
1024 OUString aProposedNewName( rRequest.ProposedNewName );
1026 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1027 eResult = executeSimpleNameClashResolveDialog(Application::GetFrameWeld(xParent),
1028 rRequest.TargetFolderURL,
1029 rRequest.ClashingName,
1030 aProposedNewName,
1031 xReplaceExistingData.is());
1033 switch ( eResult )
1035 case ABORT:
1036 xAbort->select();
1037 break;
1039 case RENAME:
1040 xSupplyName->setName( aProposedNewName );
1041 xSupplyName->select();
1042 break;
1044 case OVERWRITE:
1045 OSL_ENSURE(
1046 xReplaceExistingData.is(),
1047 "Invalid NameClashResolveDialogResult: OVERWRITE - "
1048 "No ReplaceExistingData continuation available!" );
1049 xReplaceExistingData->select();
1050 break;
1054 void
1055 UUIInteractionHelper::handleGenericErrorRequest(
1056 ErrCode nErrorCode,
1057 uno::Sequence< uno::Reference<
1058 task::XInteractionContinuation > > const & rContinuations,
1059 bool bObtainErrorStringOnly,
1060 bool & bHasErrorString,
1061 OUString & rErrorString)
1063 if (bObtainErrorStringOnly)
1065 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1066 if (bHasErrorString)
1068 OUString aErrorString;
1069 ErrorHandler::GetErrorString(nErrorCode, aErrorString);
1070 rErrorString = aErrorString;
1073 else
1075 uno::Reference< task::XInteractionAbort > xAbort;
1076 uno::Reference< task::XInteractionApprove > xApprove;
1077 getContinuations(rContinuations, &xApprove, &xAbort);
1079 // Note: It's important to convert the transported long to the
1080 // required unsigned long value. Otherwise using as flag field
1081 // can fail ...
1082 ErrCode nError(nErrorCode);
1083 bool bWarning = !nError.IgnoreWarning();
1085 if ( nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION )
1087 // the security warning box needs a special title
1088 OUString aErrorString;
1089 ErrorHandler::GetErrorString( nErrorCode, aErrorString );
1091 std::locale aResLocale = Translate::Create("uui");
1092 OUString aTitle( utl::ConfigManager::getProductName() );
1094 OUString aErrTitle = Translate::get(STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE, aResLocale);
1096 if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() )
1097 aTitle += " - " ;
1098 aTitle += aErrTitle;
1100 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1101 executeMessageBox(Application::GetFrameWeld(xParent), aTitle, aErrorString, VclMessageType::Error);
1103 else
1105 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1106 ErrorHandler::HandleError(nErrorCode, Application::GetFrameWeld(xParent));
1109 if (xApprove.is() && bWarning)
1110 xApprove->select();
1111 else if (xAbort.is())
1112 xAbort->select();
1116 void
1117 UUIInteractionHelper::handleMacroConfirmRequest(
1118 const OUString& aDocumentURL,
1119 const uno::Reference< embed::XStorage >& xZipStorage,
1120 const OUString& aDocumentVersion,
1121 const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo,
1122 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1123 rContinuations )
1125 uno::Reference< task::XInteractionAbort > xAbort;
1126 uno::Reference< task::XInteractionApprove > xApprove;
1127 getContinuations( rContinuations, &xApprove, &xAbort );
1129 bool bApprove = false;
1131 bool bShowSignatures = aSignInfo.hasElements();
1132 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1133 MacroWarning aWarning(Application::GetFrameWeld(xParent), bShowSignatures);
1135 aWarning.SetDocumentURL(aDocumentURL);
1136 if ( aSignInfo.getLength() > 1 )
1138 aWarning.SetStorage(xZipStorage, aDocumentVersion, aSignInfo);
1140 else if ( aSignInfo.getLength() == 1 )
1142 aWarning.SetCertificate(aSignInfo[0].Signer);
1145 bApprove = aWarning.run() == RET_OK;
1147 if ( bApprove && xApprove.is() )
1148 xApprove->select();
1149 else if ( xAbort.is() )
1150 xAbort->select();
1153 void
1154 UUIInteractionHelper::handleBrokenPackageRequest(
1155 std::vector< OUString > const & rArguments,
1156 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1157 rContinuations,
1158 bool bObtainErrorStringOnly,
1159 bool & bHasErrorString,
1160 OUString & rErrorString)
1162 if (bObtainErrorStringOnly)
1164 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1165 if (!bHasErrorString)
1166 return;
1169 uno::Reference< task::XInteractionApprove > xApprove;
1170 uno::Reference< task::XInteractionDisapprove > xDisapprove;
1171 uno::Reference< task::XInteractionAbort > xAbort;
1172 getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort);
1174 ErrCode nErrorCode;
1175 if( xApprove.is() && xDisapprove.is() )
1177 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE;
1179 else if ( xAbort.is() )
1181 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR;
1183 else
1184 return;
1186 OUString aMessage;
1188 std::locale aResLocale = Translate::Create("uui");
1189 ErrorResource aErrorResource(RID_UUI_ERRHDL, aResLocale);
1190 if (!aErrorResource.getString(nErrorCode, aMessage))
1191 return;
1194 aMessage = replaceMessageWithArguments( aMessage, rArguments );
1196 if (bObtainErrorStringOnly)
1198 rErrorString = aMessage;
1199 return;
1202 VclMessageType eMessageType;
1203 if( xApprove.is() && xDisapprove.is() )
1204 eMessageType = VclMessageType::Question;
1205 else if ( xAbort.is() )
1206 eMessageType = VclMessageType::Warning;
1207 else
1208 return;
1210 OUString title(
1211 utl::ConfigManager::getProductName() +
1212 " " +
1213 utl::ConfigManager::getProductVersion() );
1215 uno::Reference<awt::XWindow> xParent = getParentXWindow();
1216 switch (executeMessageBox(Application::GetFrameWeld(xParent), title, aMessage, eMessageType))
1218 case DialogMask::ButtonsOk:
1219 OSL_ENSURE( xAbort.is(), "unexpected situation" );
1220 if (xAbort.is())
1221 xAbort->select();
1222 break;
1224 case DialogMask::ButtonsNo:
1225 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
1226 if (xDisapprove.is())
1227 xDisapprove->select();
1228 break;
1230 case DialogMask::ButtonsYes:
1231 OSL_ENSURE(xApprove.is(), "unexpected situation");
1232 if (xApprove.is())
1233 xApprove->select();
1234 break;
1236 default: break;
1240 // ErrorResource Implementation
1241 bool ErrorResource::getString(ErrCode nErrorCode, OUString &rString) const
1243 for (const std::pair<const char*, ErrCode>* pStringArray = m_pStringArray; pStringArray->first != nullptr; ++pStringArray)
1245 if (nErrorCode.StripWarningAndDynamic() == pStringArray->second.StripWarningAndDynamic())
1247 rString = Translate::get(pStringArray->first, m_rResLocale);
1248 return true;
1251 return false;
1254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */