1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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/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/FutureDocumentVersionProductUpdateRequest.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/XInteractionAskLater.hpp"
41 #include "com/sun/star/task/XInteractionDisapprove.hpp"
42 #include "com/sun/star/task/XInteractionHandler2.hpp"
43 #include "com/sun/star/task/XInteractionRequest.hpp"
44 #include "com/sun/star/task/XInteractionRetry.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 "tools/rcid.h"
66 #include "tools/errinf.hxx"
67 #include "osl/mutex.hxx"
68 #include "osl/thread.hxx"
69 #include "tools/diagnose_ex.h"
70 #include "comphelper/documentconstants.hxx"
71 #include "svtools/sfxecode.hxx"
72 #include "vcl/msgbox.hxx"
73 #include "vcl/svapp.hxx"
74 #include "unotools/configmgr.hxx"
75 #include "toolkit/helper/vclunohelper.hxx"
76 #include "comphelper/processfactory.hxx"
77 #include "comphelper/namedvaluecollection.hxx"
78 #include "typelib/typedescription.hxx"
79 #include "unotools/confignode.hxx"
83 #include "getcontinuations.hxx"
84 #include "secmacrowarnings.hxx"
85 #include "newerverwarn.hxx"
88 #include "nameclashdlg.hxx"
90 #include <boost/scoped_ptr.hpp>
92 using ::com::sun::star::uno::Sequence
;
93 using ::com::sun::star::uno::UNO_QUERY
;
94 using ::com::sun::star::uno::Reference
;
95 using ::com::sun::star::task::XInteractionContinuation
;
96 using ::com::sun::star::task::XInteractionAbort
;
97 using ::com::sun::star::task::XInteractionApprove
;
98 using ::com::sun::star::task::XInteractionAskLater
;
99 using ::com::sun::star::task::FutureDocumentVersionProductUpdateRequest
;
100 using ::com::sun::star::uno::XInterface
;
101 using ::com::sun::star::lang::XInitialization
;
102 using ::com::sun::star::uno::UNO_QUERY_THROW
;
103 using ::com::sun::star::task::InteractionHandler
;
104 using ::com::sun::star::task::XInteractionHandler2
;
105 using ::com::sun::star::uno::Exception
;
106 using ::com::sun::star::uno::Any
;
107 using ::com::sun::star::task::XInteractionRequest
;
108 using ::com::sun::star::lang::XMultiServiceFactory
;
110 using namespace ::com::sun::star
;
114 class HandleData
: public osl::Condition
118 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
120 m_rRequest(rRequest
),
124 uno::Reference
< task::XInteractionRequest
> m_rRequest
;
126 beans::Optional
< OUString
> m_aResult
;
131 UUIInteractionHelper::UUIInteractionHelper(
132 uno::Reference
< uno::XComponentContext
> const & rxContext
,
133 uno::Reference
< awt::XWindow
> const & rxWindowParam
,
134 const OUString
& rContextParam
)
136 m_xContext(rxContext
),
137 m_xWindowParam(rxWindowParam
),
138 m_aContextParam(rContextParam
)
142 UUIInteractionHelper::UUIInteractionHelper(
143 uno::Reference
< uno::XComponentContext
> const & rxContext
)
145 m_xContext(rxContext
)
149 UUIInteractionHelper::~UUIInteractionHelper()
154 UUIInteractionHelper::handlerequest(
155 void* pHandleData
, void* pInteractionHelper
)
158 = static_cast< HandleData
* >(pHandleData
);
159 UUIInteractionHelper
* pUUI
160 = static_cast< UUIInteractionHelper
* >(pInteractionHelper
);
164 = pUUI
->handleRequest_impl(pHND
->m_rRequest
, false, bDummy
, aDummy
);
170 UUIInteractionHelper::handleRequest(
171 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
172 SAL_THROW((uno::RuntimeException
))
174 Application
* pApp
= 0;
176 // be aware,it is the same type
177 static_cast< oslThreadIdentifier
>(
178 Application::GetMainThreadIdentifier())
179 != osl::Thread::getCurrentIdentifier()
184 // we are not in the main thread, let it handle that stuff
185 HandleData
aHD(rRequest
);
186 Link
aLink(&aHD
,handlerequest
);
187 pApp
->PostUserEvent(aLink
,this);
188 sal_uLong locks
= Application::ReleaseSolarMutex();
190 Application::AcquireSolarMutex(locks
);
197 return handleRequest_impl(rRequest
, false, bDummy
, aDummy
);
202 UUIInteractionHelper::getstringfromrequest(
203 void* pHandleData
,void* pInteractionHelper
)
205 HandleData
* pHND
= (HandleData
*) pHandleData
;
206 UUIInteractionHelper
* pUUI
= (UUIInteractionHelper
*) pInteractionHelper
;
207 pHND
->m_aResult
= pUUI
->getStringFromRequest_impl(pHND
->m_rRequest
);
212 beans::Optional
< OUString
>
213 UUIInteractionHelper::getStringFromRequest_impl(
214 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
215 SAL_THROW((uno::RuntimeException
))
217 bool bSuccess
= false;
219 handleRequest_impl(rRequest
, true, bSuccess
, aMessage
);
221 OSL_ENSURE(bSuccess
||
222 !isInformationalErrorMessageRequest(
223 rRequest
->getContinuations()),
224 "Interaction request is a candidate for a string representation."
225 "Please implement!");
227 return beans::Optional
< OUString
>(bSuccess
, aMessage
);
230 beans::Optional
< OUString
>
231 UUIInteractionHelper::getStringFromRequest(
232 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
233 SAL_THROW((uno::RuntimeException
))
235 Application
* pApp
= 0;
237 // be aware,it is the same type
238 static_cast< oslThreadIdentifier
>(
239 Application::GetMainThreadIdentifier())
240 != osl::Thread::getCurrentIdentifier()
245 // we are not in the main thread, let it handle that stuff
246 HandleData
aHD(rRequest
);
247 Link
aLink(&aHD
,getstringfromrequest
);
248 pApp
->PostUserEvent(aLink
,this);
249 sal_uLong locks
= Application::ReleaseSolarMutex();
251 Application::AcquireSolarMutex(locks
);
252 return aHD
.m_aResult
;
255 return getStringFromRequest_impl(rRequest
);
259 UUIInteractionHelper::replaceMessageWithArguments(
261 std::vector
< OUString
> const & rArguments
)
263 for (sal_Int32 i
= 0;;)
265 i
= aMessage
.indexOf("$(ARG", i
);
268 if (aMessage
.getLength() - i
>= RTL_CONSTASCII_LENGTH("$(ARGx)")
269 && aMessage
[i
+ RTL_CONSTASCII_LENGTH("$(ARGx")] == ')')
271 sal_Unicode c
= aMessage
[i
+ RTL_CONSTASCII_LENGTH("$(ARG")];
272 if (c
>= '1' && c
<= '2')
274 std::vector
< OUString
>::size_type nIndex
275 = static_cast< std::vector
< OUString
>::size_type
>(
277 if (nIndex
< rArguments
.size())
280 = aMessage
.replaceAt(i
,
281 RTL_CONSTASCII_LENGTH("$(ARGx)"),
283 i
+= rArguments
[nIndex
].getLength();
295 UUIInteractionHelper::isInformationalErrorMessageRequest(
296 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const &
299 // Only requests with a single continuation (user has no choice, request
300 // is just informational)
301 if (rContinuations
.getLength() != 1 )
304 // user can only abort or approve, all other continuations are not
305 // considered to be informational.
306 uno::Reference
< task::XInteractionApprove
> xApprove(
307 rContinuations
[0], uno::UNO_QUERY
);
311 uno::Reference
< task::XInteractionAbort
> xAbort(
312 rContinuations
[0], uno::UNO_QUERY
);
320 UUIInteractionHelper::tryOtherInteractionHandler(
321 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
322 SAL_THROW((uno::RuntimeException
))
324 InteractionHandlerDataList dataList
;
325 getInteractionHandlerList(dataList
);
327 InteractionHandlerDataList::const_iterator
aEnd(dataList
.end());
328 for (InteractionHandlerDataList::const_iterator
aIt(dataList
.begin());
332 if ( handleCustomRequest( rRequest
, aIt
->ServiceName
) )
340 // .................................................................................................................
341 static bool lcl_matchesRequest( const Any
& i_rRequest
, const OUString
& i_rTypeName
, const OUString
& i_rPropagation
)
343 const ::com::sun::star::uno::TypeDescription
aTypeDesc( i_rTypeName
);
344 const typelib_TypeDescription
* pTypeDesc
= aTypeDesc
.get();
345 if ( !pTypeDesc
|| !pTypeDesc
->pWeakRef
)
347 #if OSL_DEBUG_LEVEL > 0
348 OStringBuffer aMessage
;
349 aMessage
.append( "no type found for '" );
350 aMessage
.append( OUStringToOString( i_rTypeName
, RTL_TEXTENCODING_UTF8
) );
351 aMessage
.append( "'" );
352 OSL_FAIL( aMessage
.makeStringAndClear().getStr() );
356 const ::com::sun::star::uno::Type
aType( pTypeDesc
->pWeakRef
);
358 const bool bExactMatch
= i_rPropagation
.equalsAscii( "named-only" );
360 return i_rRequest
.getValueType().equals( aType
);
362 return i_rRequest
.isExtractableTo( aType
);
366 // ---------------------------------------------------------------------------------------------------------------------
367 bool UUIInteractionHelper::handleCustomRequest( const Reference
< XInteractionRequest
>& i_rRequest
, const OUString
& i_rServiceName
) const
371 Reference
< XInteractionHandler2
> xHandler( m_xContext
->getServiceManager()->createInstanceWithContext( i_rServiceName
, m_xContext
), UNO_QUERY_THROW
);
373 Reference
< XInitialization
> xHandlerInit( xHandler
, UNO_QUERY
);
374 if ( xHandlerInit
.is() )
376 ::comphelper::NamedValueCollection aInitArgs
;
377 aInitArgs
.put( "Parent", getParentXWindow() );
378 xHandlerInit
->initialize( aInitArgs
.getWrappedPropertyValues() );
381 if ( xHandler
->handleInteractionRequest( i_rRequest
) )
384 catch( const Exception
& )
386 DBG_UNHANDLED_EXCEPTION();
391 // ---------------------------------------------------------------------------------------------------------------------
392 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference
< XInteractionRequest
> const & rRequest
)
395 const Any
aRequest( rRequest
->getRequest() );
397 const StringHashMap::const_iterator aCacheHitTest
= m_aTypedCustomHandlers
.find( aRequest
.getValueTypeName() );
398 if ( aCacheHitTest
!= m_aTypedCustomHandlers
.end() )
399 return handleCustomRequest( rRequest
, aCacheHitTest
->second
);
401 // the base registration node for "typed" interaction handlers
402 const ::utl::OConfigurationTreeRoot
aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext(
404 OUString( "/org.openoffice.Interaction/InteractionHandlers" ),
406 ::utl::OConfigurationTreeRoot::CM_READONLY
409 // loop through all registered implementations
410 const Sequence
< OUString
> aRegisteredHandlers( aConfigRoot
.getNodeNames() );
411 const OUString
* pHandlerName
= aRegisteredHandlers
.getConstArray();
412 const OUString
* pHandlersEnd
= aRegisteredHandlers
.getConstArray() + aRegisteredHandlers
.getLength();
413 for ( ; pHandlerName
!= pHandlersEnd
; ++pHandlerName
)
415 const ::utl::OConfigurationNode
aHandlerNode( aConfigRoot
.openNode( *pHandlerName
) );
416 const ::utl::OConfigurationNode
aTypesNode( aHandlerNode
.openNode( "HandledRequestTypes" ) );
418 // loop through all the types which the current handler is registered for
419 const Sequence
< OUString
> aHandledTypes( aTypesNode
.getNodeNames() );
420 const OUString
* pType
= aHandledTypes
.getConstArray();
421 const OUString
* pTypesEnd
= aHandledTypes
.getConstArray() + aHandledTypes
.getLength();
422 for ( ; pType
!= pTypesEnd
; ++pType
)
424 // the UNO type is the node name
425 ::utl::OConfigurationNode
aType( aTypesNode
.openNode( *pType
) );
426 // and there's a child denoting how the responsibility propagates
427 OUString sPropagation
;
428 OSL_VERIFY( aType
.getNodeValue( "Propagation" ) >>= sPropagation
);
429 if ( lcl_matchesRequest( aRequest
, *pType
, sPropagation
) )
431 // retrieve the service/implementation name of the handler
432 OUString sServiceName
;
433 OSL_VERIFY( aHandlerNode
.getNodeValue( "ServiceName" ) >>= sServiceName
);
434 // cache the information who feels responsible for requests of this type
435 m_aTypedCustomHandlers
[ aRequest
.getValueTypeName() ] = sServiceName
;
436 // actually handle the request
437 return handleCustomRequest( rRequest
, sServiceName
);
446 UUIInteractionHelper::handleRequest_impl(
447 uno::Reference
< task::XInteractionRequest
> const & rRequest
,
448 bool bObtainErrorStringOnly
,
449 bool & bHasErrorString
,
450 OUString
& rErrorString
)
451 SAL_THROW((uno::RuntimeException
))
458 uno::Any
aAnyRequest(rRequest
->getRequest());
460 script::ModuleSizeExceededRequest aModSizeException
;
461 if (aAnyRequest
>>= aModSizeException
)
463 ErrCode nErrorCode
= ERRCODE_UUI_IO_MODULESIZEEXCEEDED
;
464 std::vector
< OUString
> aArguments
;
465 uno::Sequence
< OUString
> sModules
466 = aModSizeException
.Names
;
467 if ( sModules
.getLength() )
470 for ( sal_Int32 index
=0; index
< sModules
.getLength(); ++index
)
473 aName
= aName
+ OUString( ',' ) + sModules
[index
];
475 aName
= sModules
[index
]; // 1st name
477 aArguments
.push_back( aName
);
479 handleErrorHandlerRequest( task::InteractionClassification_WARNING
,
482 rRequest
->getContinuations(),
483 bObtainErrorStringOnly
,
489 ucb::NameClashException aNCException
;
490 if (aAnyRequest
>>= aNCException
)
492 ErrCode nErrorCode
= ERRCODE_UUI_IO_TARGETALREADYEXISTS
;
493 std::vector
< OUString
> aArguments
;
495 if( !aNCException
.Name
.isEmpty() )
497 nErrorCode
= ERRCODE_UUI_IO_ALREADYEXISTS
;
498 aArguments
.push_back( aNCException
.Name
);
501 handleErrorHandlerRequest( aNCException
.Classification
,
504 rRequest
->getContinuations(),
505 bObtainErrorStringOnly
,
511 ucb::UnsupportedNameClashException aUORequest
;
512 if (aAnyRequest
>>= aUORequest
)
514 ErrCode nErrorCode
= ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE
;
515 std::vector
< OUString
> aArguments
;
517 uno::Reference
< task::XInteractionApprove
> xApprove
;
518 uno::Reference
< task::XInteractionDisapprove
> xDisapprove
;
520 rRequest
->getContinuations(), &xApprove
, &xDisapprove
);
522 if ( xApprove
.is() && xDisapprove
.is() )
524 handleErrorHandlerRequest( task::InteractionClassification_QUERY
,
527 rRequest
->getContinuations(),
528 bObtainErrorStringOnly
,
535 if ( handleInteractiveIOException( rRequest
,
536 bObtainErrorStringOnly
,
541 ucb::InteractiveAppException aAppException
;
542 if (aAnyRequest
>>= aAppException
)
544 std::vector
< OUString
> aArguments
;
545 handleErrorHandlerRequest( aAppException
.Classification
,
548 rRequest
->getContinuations(),
549 bObtainErrorStringOnly
,
555 ucb::InteractiveNetworkException aNetworkException
;
556 if (aAnyRequest
>>= aNetworkException
)
559 std::vector
< OUString
> aArguments
;
560 ucb::InteractiveNetworkOffLineException aOffLineException
;
561 ucb::InteractiveNetworkResolveNameException aResolveNameException
;
562 ucb::InteractiveNetworkConnectException aConnectException
;
563 ucb::InteractiveNetworkReadException aReadException
;
564 ucb::InteractiveNetworkWriteException aWriteException
;
565 if (aAnyRequest
>>= aOffLineException
)
566 nErrorCode
= ERRCODE_INET_OFFLINE
;
567 else if (aAnyRequest
>>= aResolveNameException
)
569 nErrorCode
= ERRCODE_INET_NAME_RESOLVE
;
570 aArguments
.push_back(aResolveNameException
.Server
);
572 else if (aAnyRequest
>>= aConnectException
)
574 nErrorCode
= ERRCODE_INET_CONNECT
;
575 aArguments
.push_back(aConnectException
.Server
);
577 else if (aAnyRequest
>>= aReadException
)
579 nErrorCode
= ERRCODE_INET_READ
;
580 aArguments
.push_back(aReadException
.Diagnostic
);
582 else if (aAnyRequest
>>= aWriteException
)
584 nErrorCode
= ERRCODE_INET_WRITE
;
585 aArguments
.push_back(aWriteException
.Diagnostic
);
588 nErrorCode
= ERRCODE_INET_GENERAL
;
590 handleErrorHandlerRequest(aNetworkException
.Classification
,
593 rRequest
->getContinuations(),
594 bObtainErrorStringOnly
,
600 ucb::InteractiveWrongMediumException aWrongMediumException
;
601 if (aAnyRequest
>>= aWrongMediumException
)
603 sal_Int32 nMedium
= 0;
604 aWrongMediumException
.Medium
>>= nMedium
;
605 std::vector
< OUString
> aArguments
;
606 aArguments
.push_back(OUString::number(nMedium
+ 1));
607 handleErrorHandlerRequest(aWrongMediumException
.Classification
,
608 ERRCODE_UUI_WRONGMEDIUM
,
610 rRequest
->getContinuations(),
611 bObtainErrorStringOnly
,
617 java::WrongJavaVersionException aWrongJavaVersionException
;
618 if (aAnyRequest
>>= aWrongJavaVersionException
)
621 std::vector
< OUString
> aArguments
;
622 if (aWrongJavaVersionException
.DetectedVersion
.isEmpty())
623 if (aWrongJavaVersionException
.LowestSupportedVersion
.isEmpty())
624 nErrorCode
= ERRCODE_UUI_WRONGJAVA
;
627 nErrorCode
= ERRCODE_UUI_WRONGJAVA_MIN
;
628 aArguments
.push_back(aWrongJavaVersionException
.LowestSupportedVersion
);
630 else if (aWrongJavaVersionException
.LowestSupportedVersion
.isEmpty())
632 nErrorCode
= ERRCODE_UUI_WRONGJAVA_VERSION
;
633 aArguments
.push_back(aWrongJavaVersionException
.DetectedVersion
);
637 nErrorCode
= ERRCODE_UUI_WRONGJAVA_VERSION_MIN
;
638 aArguments
.reserve(2);
639 aArguments
.push_back(aWrongJavaVersionException
.DetectedVersion
);
640 aArguments
.push_back(aWrongJavaVersionException
.LowestSupportedVersion
);
642 handleErrorHandlerRequest(task::InteractionClassification_ERROR
,
645 rRequest
->getContinuations(),
646 bObtainErrorStringOnly
,
652 configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest
;
653 if (aAnyRequest
>>= aMergeRecoveryRequest
)
655 ErrCode nErrorCode
= aMergeRecoveryRequest
.IsRemovalRequest
656 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
657 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE
;
659 std::vector
< OUString
> aArguments
;
660 aArguments
.push_back(aMergeRecoveryRequest
.ErrorLayerId
);
662 handleErrorHandlerRequest(task::InteractionClassification_ERROR
,
665 rRequest
->getContinuations(),
666 bObtainErrorStringOnly
,
672 configuration::backend::StratumCreationException
673 aStratumCreationException
;
675 if (aAnyRequest
>>= aStratumCreationException
)
677 const ErrCode nErrorCode
= ERRCODE_UUI_CONFIGURATION_BACKENDMISSING
;
679 OUString aStratum
= aStratumCreationException
.StratumData
;
680 if (aStratum
.isEmpty())
681 aStratum
= aStratumCreationException
.StratumService
;
683 std::vector
< OUString
> aArguments
;
684 aArguments
.push_back(aStratum
);
686 handleErrorHandlerRequest(task::InteractionClassification_ERROR
,
689 rRequest
->getContinuations(),
690 bObtainErrorStringOnly
,
696 xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException
;
697 if (aAnyRequest
>>= aInvalidDataOnSubmitException
)
699 const ErrCode nErrorCode
=
700 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA
;
702 std::vector
< OUString
> aArguments
;
704 handleErrorHandlerRequest(task::InteractionClassification_QUERY
,
707 rRequest
->getContinuations(),
708 bObtainErrorStringOnly
,
714 ucb::InteractiveLockingLockedException aLLException
;
715 if (aAnyRequest
>>= aLLException
)
717 ErrCode nErrorCode
= aLLException
.SelfOwned
718 ? ERRCODE_UUI_LOCKING_LOCKED_SELF
: ERRCODE_UUI_LOCKING_LOCKED
;
719 std::vector
< OUString
> aArguments
;
720 aArguments
.push_back( aLLException
.Url
);
722 handleErrorHandlerRequest( aLLException
.Classification
,
725 rRequest
->getContinuations(),
726 bObtainErrorStringOnly
,
732 ucb::InteractiveLockingNotLockedException aLNLException
;
733 if (aAnyRequest
>>= aLNLException
)
735 ErrCode nErrorCode
= ERRCODE_UUI_LOCKING_NOT_LOCKED
;
736 std::vector
< OUString
> aArguments
;
737 aArguments
.push_back( aLNLException
.Url
);
739 handleErrorHandlerRequest( aLNLException
.Classification
,
742 rRequest
->getContinuations(),
743 bObtainErrorStringOnly
,
749 ucb::InteractiveLockingLockExpiredException aLLEException
;
750 if (aAnyRequest
>>= aLLEException
)
752 ErrCode nErrorCode
= ERRCODE_UUI_LOCKING_LOCK_EXPIRED
;
753 std::vector
< OUString
> aArguments
;
754 aArguments
.push_back( aLLEException
.Url
);
756 handleErrorHandlerRequest( aLLEException
.Classification
,
759 rRequest
->getContinuations(),
760 bObtainErrorStringOnly
,
766 document::BrokenPackageRequest aBrokenPackageRequest
;
767 if (aAnyRequest
>>= aBrokenPackageRequest
)
769 std::vector
< OUString
> aArguments
;
771 if( !aBrokenPackageRequest
.aName
.isEmpty() )
772 aArguments
.push_back( aBrokenPackageRequest
.aName
);
774 handleBrokenPackageRequest( aArguments
,
775 rRequest
->getContinuations(),
776 bObtainErrorStringOnly
,
782 task::ErrorCodeRequest aErrorCodeRequest
;
783 if (aAnyRequest
>>= aErrorCodeRequest
)
785 // Sucky special handling for xlsx macro filter warning
786 if ( (sal_uInt32
)ERRCODE_SFX_VBASIC_CANTSAVE_STORAGE
== (sal_uInt32
)aErrorCodeRequest
.ErrCode
)
788 std::vector
< OUString
> aArguments
;
789 handleErrorHandlerRequest( task::InteractionClassification_WARNING
,
790 ERRCODE_UUI_IO_WARN_CANTSAVE_MACROS
,
792 rRequest
->getContinuations(),
793 bObtainErrorStringOnly
,
799 handleGenericErrorRequest( aErrorCodeRequest
.ErrCode
,
800 rRequest
->getContinuations(),
801 bObtainErrorStringOnly
,
808 task::ErrorCodeIOException aErrorCodeIOException
;
809 if (aAnyRequest
>>= aErrorCodeIOException
)
811 handleGenericErrorRequest( aErrorCodeIOException
.ErrCode
,
812 rRequest
->getContinuations(),
813 bObtainErrorStringOnly
,
819 loader::CannotActivateFactoryException aCannotActivateFactoryException
;
820 if (aAnyRequest
>>= aCannotActivateFactoryException
)
822 ErrCode nErrorCode
= ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY
;
823 std::vector
< OUString
> aArguments
;
824 aArguments
.push_back( aCannotActivateFactoryException
.Message
);
826 handleErrorHandlerRequest( task::InteractionClassification_ERROR
,
829 rRequest
->getContinuations(),
830 bObtainErrorStringOnly
,
837 ///////////////////////////////////////////////////////////////////
838 // Handle requests which do not have a plain string representation.
839 ///////////////////////////////////////////////////////////////////
840 if (!bObtainErrorStringOnly
)
842 if ( handleAuthenticationRequest( rRequest
) )
845 if ( handleCertificateValidationRequest( rRequest
) )
848 ucb::NameClashResolveRequest aNameClashResolveRequest
;
849 if (aAnyRequest
>>= aNameClashResolveRequest
)
851 handleNameClashResolveRequest(aNameClashResolveRequest
,
852 rRequest
->getContinuations());
856 if ( handleMasterPasswordRequest( rRequest
) )
859 if ( handlePasswordRequest( rRequest
) )
862 if ( handleNoSuchFilterRequest( rRequest
) )
865 if ( handleAmbigousFilterRequest( rRequest
) )
868 if ( handleFilterOptionsRequest( rRequest
) )
871 if ( handleLockedDocumentRequest( rRequest
) )
874 if ( handleChangedByOthersRequest( rRequest
) )
877 if ( handleLockFileIgnoreRequest( rRequest
) )
880 task::DocumentMacroConfirmationRequest aMacroConfirmRequest
;
881 if (aAnyRequest
>>= aMacroConfirmRequest
)
883 handleMacroConfirmRequest(
884 aMacroConfirmRequest
.DocumentURL
,
885 aMacroConfirmRequest
.DocumentStorage
,
886 !aMacroConfirmRequest
.DocumentVersion
.isEmpty() ? aMacroConfirmRequest
.DocumentVersion
: ODFVER_012_TEXT
,
887 aMacroConfirmRequest
.DocumentSignatureInformation
,
888 rRequest
->getContinuations());
892 task::FutureDocumentVersionProductUpdateRequest
893 aProductUpdateRequest
;
894 if (aAnyRequest
>>= aProductUpdateRequest
)
896 handleFutureDocumentVersionUpdateRequest(
897 aProductUpdateRequest
,
898 rRequest
->getContinuations());
902 ///////////////////////////////////////////////////////////////
903 // Last chance: interaction handlers registered in the configuration
904 ///////////////////////////////////////////////////////////////
906 // typed InteractionHandlers (ooo.Interactions)
907 if ( handleTypedHandlerImplementations( rRequest
) )
910 // legacy configuration (ooo.ucb.InteractionHandlers)
911 if (tryOtherInteractionHandler( rRequest
))
918 catch (std::bad_alloc
const &)
920 throw uno::RuntimeException("out of memory",
921 uno::Reference
< uno::XInterface
>());
923 catch( const uno::RuntimeException
& )
925 throw; // allowed to leave here
927 catch( const uno::Exception
& )
929 DBG_UNHANDLED_EXCEPTION();
935 UUIInteractionHelper::getInteractionHandlerList(
936 InteractionHandlerDataList
&rdataList
)
937 SAL_THROW((uno::RuntimeException
))
941 uno::Reference
< lang::XMultiServiceFactory
> xConfigProv
=
942 configuration::theDefaultProvider::get( m_xContext
);
944 OUStringBuffer aFullPath
;
945 aFullPath
.appendAscii(
946 "/org.openoffice.ucb.InteractionHandler/InteractionHandlers" );
948 uno::Sequence
< uno::Any
> aArguments( 1 );
949 beans::PropertyValue aProperty
;
950 aProperty
.Name
= "nodepath";
951 aProperty
.Value
<<= aFullPath
.makeStringAndClear();
952 aArguments
[ 0 ] <<= aProperty
;
954 uno::Reference
< uno::XInterface
> xInterface(
955 xConfigProv
->createInstanceWithArguments(
956 "com.sun.star.configuration.ConfigurationAccess" , aArguments
) );
958 if ( !xInterface
.is() )
959 throw uno::RuntimeException("unable to instanciate config access",
960 uno::Reference
< uno::XInterface
>());
962 uno::Reference
< container::XNameAccess
> xNameAccess(
963 xInterface
, uno::UNO_QUERY
);
964 if ( !xNameAccess
.is() )
965 throw uno::RuntimeException(OUString(
966 "config access does not implement XNameAccess"),
967 uno::Reference
< uno::XInterface
>());
969 uno::Sequence
< OUString
> aElems
= xNameAccess
->getElementNames();
970 const OUString
* pElems
= aElems
.getConstArray();
971 sal_Int32 nCount
= aElems
.getLength();
975 uno::Reference
< container::XHierarchicalNameAccess
>
976 xHierNameAccess( xInterface
, uno::UNO_QUERY
);
978 if ( !xHierNameAccess
.is() )
979 throw uno::RuntimeException(OUString(
980 "config access does not implement XHierarchicalNameAccess"),
981 uno::Reference
< uno::XInterface
>());
983 // Iterate over children.
984 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
986 OUStringBuffer aElemBuffer
;
987 aElemBuffer
.appendAscii( "['" );
988 aElemBuffer
.append( pElems
[ n
] );
992 InteractionHandlerData aInfo
;
994 // Obtain service name.
995 OUStringBuffer aKeyBuffer
= aElemBuffer
;
996 aKeyBuffer
.appendAscii( "']/ServiceName" );
999 if ( !( xHierNameAccess
->getByHierarchicalName(
1000 aKeyBuffer
.makeStringAndClear() ) >>= aValue
) )
1002 OSL_FAIL( "GetInteractionHandlerList - "
1003 "Error getting item value!" );
1007 aInfo
.ServiceName
= aValue
;
1009 // Append info to list.
1010 rdataList
.push_back( aInfo
);
1012 catch ( container::NoSuchElementException
& )
1014 // getByHierarchicalName
1016 OSL_FAIL( "GetInteractionHandlerList - "
1017 "caught NoSuchElementException!" );
1022 catch ( uno::RuntimeException
const & )
1026 catch ( uno::Exception
const & )
1028 OSL_FAIL( "GetInteractionHandlerList - Caught Exception!" );
1033 UUIInteractionHelper::getParentProperty()
1036 uno::Reference
< awt::XWindow
> xWindow
= getParentXWindow();
1038 return VCLUnoHelper::GetWindow(xWindow
);
1043 uno::Reference
< awt::XWindow
>
1044 UUIInteractionHelper::getParentXWindow() const
1047 return m_xWindowParam
;
1051 UUIInteractionHelper::getContextProperty()
1054 return m_aContextParam
;
1057 uno::Reference
< task::XInteractionHandler2
>
1058 UUIInteractionHelper::getInteractionHandler()
1059 SAL_THROW((uno::RuntimeException
))
1061 return InteractionHandler::createWithParentAndContext(
1062 m_xContext
, m_xWindowParam
,
1071 OUString
const & rTitle
,
1072 OUString
const & rMessage
,
1073 WinBits nButtonMask
)
1074 SAL_THROW((uno::RuntimeException
))
1076 SolarMutexGuard aGuard
;
1078 MessBox
xBox( pParent
, nButtonMask
, rTitle
, rMessage
);
1080 sal_uInt16 aResult
= xBox
.Execute();
1084 aResult
= ERRCODE_BUTTON_OK
;
1087 aResult
= ERRCODE_BUTTON_CANCEL
;
1090 aResult
= ERRCODE_BUTTON_YES
;
1093 aResult
= ERRCODE_BUTTON_NO
;
1096 aResult
= ERRCODE_BUTTON_RETRY
;
1103 NameClashResolveDialogResult
executeSimpleNameClashResolveDialog( Window
*pParent
,
1104 OUString
const & rTargetFolderURL
,
1105 OUString
const & rClashingName
,
1106 OUString
& rProposedNewName
,
1107 bool bAllowOverwrite
)
1109 boost::scoped_ptr
< ResMgr
> xManager( ResMgr::CreateResMgr( "uui" ) );
1110 if ( !xManager
.get() )
1113 NameClashDialog
aDialog( pParent
, xManager
.get(), rTargetFolderURL
,
1114 rClashingName
, rProposedNewName
, bAllowOverwrite
);
1116 NameClashResolveDialogResult eResult
= (NameClashResolveDialogResult
) aDialog
.Execute();
1117 rProposedNewName
= aDialog
.getNewName();
1124 UUIInteractionHelper::handleNameClashResolveRequest(
1125 ucb::NameClashResolveRequest
const & rRequest
,
1126 uno::Sequence
< uno::Reference
<
1127 task::XInteractionContinuation
> > const & rContinuations
)
1128 SAL_THROW((uno::RuntimeException
))
1130 OSL_ENSURE(!rRequest
.TargetFolderURL
.isEmpty(),
1131 "NameClashResolveRequest must not contain empty TargetFolderURL" );
1133 OSL_ENSURE(!rRequest
.ClashingName
.isEmpty(),
1134 "NameClashResolveRequest must not contain empty ClashingName" );
1136 uno::Reference
< task::XInteractionAbort
> xAbort
;
1137 uno::Reference
< ucb::XInteractionSupplyName
> xSupplyName
;
1138 uno::Reference
< ucb::XInteractionReplaceExistingData
> xReplaceExistingData
;
1140 rContinuations
, &xAbort
, &xSupplyName
, &xReplaceExistingData
);
1142 OSL_ENSURE( xAbort
.is(),
1143 "NameClashResolveRequest must contain Abort continuation" );
1145 OSL_ENSURE( xSupplyName
.is(),
1146 "NameClashResolveRequest must contain SupplyName continuation" );
1148 NameClashResolveDialogResult eResult
= ABORT
;
1149 OUString
aProposedNewName( rRequest
.ProposedNewName
);
1151 eResult
= executeSimpleNameClashResolveDialog( getParentProperty(),
1152 rRequest
.TargetFolderURL
,
1153 rRequest
.ClashingName
,
1155 xReplaceExistingData
.is() );
1164 xSupplyName
->setName( aProposedNewName
);
1165 xSupplyName
->select();
1170 xReplaceExistingData
.is(),
1171 "Invalid NameClashResolveDialogResult: OVERWRITE - "
1172 "No ReplaceExistingData continuation available!" );
1173 xReplaceExistingData
->select();
1179 UUIInteractionHelper::handleGenericErrorRequest(
1180 sal_Int32 nErrorCode
,
1181 uno::Sequence
< uno::Reference
<
1182 task::XInteractionContinuation
> > const & rContinuations
,
1183 bool bObtainErrorStringOnly
,
1184 bool & bHasErrorString
,
1185 OUString
& rErrorString
)
1186 SAL_THROW((uno::RuntimeException
))
1188 if (bObtainErrorStringOnly
)
1190 bHasErrorString
= isInformationalErrorMessageRequest(rContinuations
);
1191 if (bHasErrorString
)
1193 OUString aErrorString
;
1194 ErrorHandler::GetErrorString(nErrorCode
, aErrorString
);
1195 rErrorString
= aErrorString
;
1200 uno::Reference
< task::XInteractionAbort
> xAbort
;
1201 uno::Reference
< task::XInteractionApprove
> xApprove
;
1202 getContinuations(rContinuations
, &xApprove
, &xAbort
);
1204 // Note: It's important to convert the transported long to the
1205 // required unsigned long value. Otherwhise using as flag field
1207 ErrCode nError
= static_cast< ErrCode
>(nErrorCode
);
1208 sal_Bool bWarning
= !ERRCODE_TOERROR(nError
);
1210 if ( nError
== ERRCODE_SFX_BROKENSIGNATURE
1211 || nError
== ERRCODE_SFX_INCOMPLETE_ENCRYPTION
)
1213 // the security warning box needs a special title
1214 OUString aErrorString
;
1215 ErrorHandler::GetErrorString( nErrorCode
, aErrorString
);
1217 boost::scoped_ptr
< ResMgr
> xManager(
1218 ResMgr::CreateResMgr( "uui" ) );
1219 OUString
aTitle( utl::ConfigManager::getProductName() );
1222 = ResId( nError
== ERRCODE_SFX_BROKENSIGNATURE
1223 ? STR_WARNING_BROKENSIGNATURE_TITLE
1224 : STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE
,
1225 *xManager
.get() ).toString();
1227 if ( !aTitle
.isEmpty() && !aErrTitle
.isEmpty() )
1229 aTitle
+= aErrTitle
;
1232 getParentProperty(), aTitle
, aErrorString
, WB_OK
);
1235 ErrorHandler::HandleError(nErrorCode
);
1237 if (xApprove
.is() && bWarning
)
1239 else if (xAbort
.is())
1245 UUIInteractionHelper::handleMacroConfirmRequest(
1246 const OUString
& aDocumentURL
,
1247 const uno::Reference
< embed::XStorage
>& xZipStorage
,
1248 const OUString
& aDocumentVersion
,
1249 const uno::Sequence
< security::DocumentSignatureInformation
> aSignInfo
,
1250 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const &
1252 SAL_THROW((uno::RuntimeException
))
1254 uno::Reference
< task::XInteractionAbort
> xAbort
;
1255 uno::Reference
< task::XInteractionApprove
> xApprove
;
1256 getContinuations( rContinuations
, &xApprove
, &xAbort
);
1258 bool bApprove
= false;
1260 boost::scoped_ptr
< ResMgr
> pResMgr( ResMgr::CreateResMgr( "uui" ) );
1261 if ( pResMgr
.get() )
1263 bool bShowSignatures
= aSignInfo
.getLength() > 0;
1264 MacroWarning
aWarning(
1265 getParentProperty(), bShowSignatures
, *pResMgr
.get() );
1267 aWarning
.SetDocumentURL( aDocumentURL
);
1268 if ( aSignInfo
.getLength() > 1 )
1270 aWarning
.SetStorage( xZipStorage
, aDocumentVersion
, aSignInfo
);
1272 else if ( aSignInfo
.getLength() == 1 )
1274 aWarning
.SetCertificate( aSignInfo
[ 0 ].Signer
);
1277 bApprove
= aWarning
.Execute() == RET_OK
;
1280 if ( bApprove
&& xApprove
.is() )
1282 else if ( xAbort
.is() )
1287 UUIInteractionHelper::handleFutureDocumentVersionUpdateRequest(
1288 const task::FutureDocumentVersionProductUpdateRequest
& _rRequest
,
1289 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const &
1291 SAL_THROW((uno::RuntimeException
))
1293 uno::Reference
< task::XInteractionAbort
> xAbort
;
1294 uno::Reference
< task::XInteractionApprove
> xApprove
;
1295 uno::Reference
< task::XInteractionAskLater
> xAskLater
;
1296 getContinuations( rContinuations
, &xApprove
, &xAbort
, &xAskLater
);
1298 short nResult
= RET_CANCEL
;
1300 static bool s_bDeferredToNextSession
= false;
1301 // TODO: this static variable is somewhat hacky. Formerly (before the dialog was moved from SFX2 to the
1302 // interaction handler implementation), this was stored in SFX_APP()'s impl structure, in member
1303 // bODFVersionWarningLater. Of course, we do not have access to it here.
1305 // A proper solution which I would envision would be:
1306 // - There's a central implementation (this one here) of css.task.InteractionHandler
1307 // - There's a configuration which maps UNO names to service names
1308 // - If the handler is confronted with a request, it tries to find the name of the UNO structure describing
1309 // the request in the said configuration.
1310 // - If an entry is found, then
1311 // - the respective service is instantiated
1312 // - the component is queried for css.task.XInteractionHandler, and the request is delegated
1313 // - if no entry is found, then the request is silenced (with calling the AbortContinuation, if possible)
1314 // This way, the FutureDocumentVersionProductUpdateRequest could be handled in SFX (or any other
1315 // suitable place), again, and we would only have one place where we remember the s_bDeferredToNextSession
1318 // Note: The above pattern has been implemented in CWS autorecovery. Now the remaining task is to move the
1319 // handling of this interaction to SFX, again.
1321 if ( !s_bDeferredToNextSession
)
1323 boost::scoped_ptr
< ResMgr
> pResMgr( ResMgr::CreateResMgr( "uui" ) );
1324 if ( pResMgr
.get() )
1326 ::uui::NewerVersionWarningDialog
aDialog(
1327 getParentProperty(),
1328 _rRequest
.DocumentODFVersion
,
1330 nResult
= aDialog
.Execute();
1337 if ( xApprove
.is() )
1345 if ( xAskLater
.is() )
1346 xAskLater
->select();
1347 s_bDeferredToNextSession
= true;
1350 OSL_FAIL( "UUIInteractionHelper::handleFutureDocumentVersionUpdateRequest: "
1351 "unexpected dialog return value!" );
1357 UUIInteractionHelper::handleBrokenPackageRequest(
1358 std::vector
< OUString
> const & rArguments
,
1359 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const &
1361 bool bObtainErrorStringOnly
,
1362 bool & bHasErrorString
,
1363 OUString
& rErrorString
)
1364 SAL_THROW((uno::RuntimeException
))
1366 if (bObtainErrorStringOnly
)
1368 bHasErrorString
= isInformationalErrorMessageRequest(rContinuations
);
1369 if (!bHasErrorString
)
1373 uno::Reference
< task::XInteractionApprove
> xApprove
;
1374 uno::Reference
< task::XInteractionDisapprove
> xDisapprove
;
1375 uno::Reference
< task::XInteractionAbort
> xAbort
;
1376 getContinuations(rContinuations
, &xApprove
, &xDisapprove
, &xAbort
);
1379 if( xApprove
.is() && xDisapprove
.is() )
1381 nErrorCode
= ERRCODE_UUI_IO_BROKENPACKAGE
;
1383 else if ( xAbort
.is() )
1385 nErrorCode
= ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR
;
1392 SolarMutexGuard aGuard
;
1393 boost::scoped_ptr
< ResMgr
> xManager(ResMgr::CreateResMgr("uui"));
1394 if (!xManager
.get())
1397 ResId
aResId( RID_UUI_ERRHDL
, *xManager
.get() );
1398 if ( !ErrorResource(aResId
).getString(nErrorCode
, aMessage
) )
1402 aMessage
= replaceMessageWithArguments( aMessage
, rArguments
);
1404 if (bObtainErrorStringOnly
)
1406 rErrorString
= aMessage
;
1410 WinBits nButtonMask
;
1411 if( xApprove
.is() && xDisapprove
.is() )
1413 nButtonMask
= WB_YES_NO
| WB_DEF_YES
;
1415 else if ( xAbort
.is() )
1417 nButtonMask
= WB_OK
;
1423 utl::ConfigManager::getProductName() +
1425 utl::ConfigManager::getProductVersion() );
1428 executeMessageBox( getParentProperty(), title
, aMessage
, nButtonMask
) )
1430 case ERRCODE_BUTTON_OK
:
1431 OSL_ENSURE( xAbort
.is(), "unexpected situation" );
1436 case ERRCODE_BUTTON_NO
:
1437 OSL_ENSURE(xDisapprove
.is(), "unexpected situation");
1438 if (xDisapprove
.is())
1439 xDisapprove
->select();
1442 case ERRCODE_BUTTON_YES
:
1443 OSL_ENSURE(xApprove
.is(), "unexpected situation");
1450 //=========================================================================
1451 // ErrorResource Implementation
1452 //=========================================================================
1455 ErrorResource::getString(ErrCode nErrorCode
, OUString
&rString
)
1458 ResId
aResId(static_cast< sal_uInt16
>(nErrorCode
& ERRCODE_RES_MASK
),
1460 aResId
.SetRT(RSC_STRING
);
1461 if (!IsAvailableRes(aResId
))
1463 aResId
.SetAutoRelease(false);
1464 rString
= aResId
.toString();
1465 m_pResMgr
->PopContext();
1469 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */