bump product version to 5.0.4.1
[LibreOffice.git] / uui / source / iahndl.cxx
blob1f20c31ccafc0f3b1e2d1479894fe124de0e3747
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/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/XInteractionAskLater.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 <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>
81 #include "ids.hrc"
83 #include "getcontinuations.hxx"
84 #include "secmacrowarnings.hxx"
86 #include "iahndl.hxx"
87 #include "nameclashdlg.hxx"
89 #include <boost/scoped_ptr.hpp>
91 using ::com::sun::star::uno::Sequence;
92 using ::com::sun::star::uno::UNO_QUERY;
93 using ::com::sun::star::uno::Reference;
94 using ::com::sun::star::task::XInteractionContinuation;
95 using ::com::sun::star::task::XInteractionAbort;
96 using ::com::sun::star::task::XInteractionApprove;
97 using ::com::sun::star::task::XInteractionAskLater;
98 using ::com::sun::star::uno::XInterface;
99 using ::com::sun::star::lang::XInitialization;
100 using ::com::sun::star::uno::UNO_QUERY_THROW;
101 using ::com::sun::star::task::InteractionHandler;
102 using ::com::sun::star::task::XInteractionHandler2;
103 using ::com::sun::star::uno::Exception;
104 using ::com::sun::star::uno::Any;
105 using ::com::sun::star::task::XInteractionRequest;
106 using ::com::sun::star::lang::XMultiServiceFactory;
108 using namespace ::com::sun::star;
110 namespace {
112 class HandleData : public osl::Condition
114 public:
115 HandleData(
116 uno::Reference< task::XInteractionRequest > const & rRequest)
117 : osl::Condition(),
118 m_rRequest(rRequest),
119 bHandled( false )
122 uno::Reference< task::XInteractionRequest > m_rRequest;
123 bool bHandled;
124 beans::Optional< OUString > m_aResult;
127 } /* namespace */
129 UUIInteractionHelper::UUIInteractionHelper(
130 uno::Reference< uno::XComponentContext > const & rxContext,
131 uno::Reference< awt::XWindow > const & rxWindowParam,
132 const OUString & rContextParam)
133 : m_xContext(rxContext),
134 m_xWindowParam(rxWindowParam),
135 m_aContextParam(rContextParam)
139 UUIInteractionHelper::UUIInteractionHelper(
140 uno::Reference< uno::XComponentContext > const & rxContext)
141 : m_xContext(rxContext)
145 UUIInteractionHelper::~UUIInteractionHelper()
149 sal_IntPtr
150 UUIInteractionHelper::handlerequest(
151 void* pHandleData, void* pInteractionHelper)
153 HandleData* pHND
154 = static_cast< HandleData * >(pHandleData);
155 UUIInteractionHelper* pUUI
156 = static_cast< UUIInteractionHelper * >(pInteractionHelper);
157 bool bDummy = false;
158 OUString aDummy;
159 pHND->bHandled
160 = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy);
161 pHND->set();
162 return 0;
165 bool
166 UUIInteractionHelper::handleRequest(
167 uno::Reference< task::XInteractionRequest > const & rRequest)
170 // be aware,it is the same type
171 static_cast< oslThreadIdentifier >(
172 Application::GetMainThreadIdentifier())
173 != osl::Thread::getCurrentIdentifier()
175 GetpApp()
177 // we are not in the main thread, let it handle that stuff
178 HandleData aHD(rRequest);
179 Link<> aLink(&aHD,handlerequest);
180 Application::PostUserEvent(aLink,this);
181 SolarMutexReleaser aReleaser;
182 aHD.wait();
183 return aHD.bHandled;
185 else
187 bool bDummy = false;
188 OUString aDummy;
189 return handleRequest_impl(rRequest, false, bDummy, aDummy);
193 sal_IntPtr
194 UUIInteractionHelper::getstringfromrequest(
195 void* pHandleData,void* pInteractionHelper)
197 HandleData* pHND = static_cast<HandleData*>(pHandleData);
198 UUIInteractionHelper* pUUI = static_cast<UUIInteractionHelper*>(pInteractionHelper);
199 pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest);
200 pHND->set();
201 return 0;
204 beans::Optional< OUString >
205 UUIInteractionHelper::getStringFromRequest_impl(
206 uno::Reference< task::XInteractionRequest > const & rRequest)
208 bool bSuccess = false;
209 OUString aMessage;
210 handleRequest_impl(rRequest, true, bSuccess, aMessage);
212 OSL_ENSURE(bSuccess ||
213 !isInformationalErrorMessageRequest(
214 rRequest->getContinuations()),
215 "Interaction request is a candidate for a string representation."
216 "Please implement!");
218 return beans::Optional< OUString >(bSuccess, aMessage);
221 beans::Optional< OUString >
222 UUIInteractionHelper::getStringFromRequest(
223 uno::Reference< task::XInteractionRequest > const & rRequest)
226 // be aware,it is the same type
227 static_cast< oslThreadIdentifier >(
228 Application::GetMainThreadIdentifier())
229 != osl::Thread::getCurrentIdentifier()
231 GetpApp()
233 // we are not in the main thread, let it handle that stuff
234 HandleData aHD(rRequest);
235 Link<> aLink(&aHD,getstringfromrequest);
236 Application::PostUserEvent(aLink,this);
237 SolarMutexReleaser aReleaser;
238 aHD.wait();
239 return aHD.m_aResult;
241 else
242 return getStringFromRequest_impl(rRequest);
245 OUString
246 UUIInteractionHelper::replaceMessageWithArguments(
247 const OUString& _aMessage,
248 std::vector< OUString > const & rArguments )
250 OUString aMessage = _aMessage;
252 SAL_WARN_IF(rArguments.size() == 0, "uui", "replaceMessageWithArguments: No arguments passed!");
253 if (rArguments.size() > 0)
254 aMessage = aMessage.replaceAll("$(ARG1)", rArguments[0]);
255 if (rArguments.size() > 1)
256 aMessage = aMessage.replaceAll("$(ARG2)", rArguments[1]);
258 return aMessage;
261 bool
262 UUIInteractionHelper::isInformationalErrorMessageRequest(
263 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
264 rContinuations)
266 // Only requests with a single continuation (user has no choice, request
267 // is just informational)
268 if (rContinuations.getLength() != 1 )
269 return false;
271 // user can only abort or approve, all other continuations are not
272 // considered to be informational.
273 uno::Reference< task::XInteractionApprove > xApprove(
274 rContinuations[0], uno::UNO_QUERY);
275 if (xApprove.is())
276 return true;
278 uno::Reference< task::XInteractionAbort > xAbort(
279 rContinuations[0], uno::UNO_QUERY);
280 if (xAbort.is())
281 return true;
283 return false;
286 bool
287 UUIInteractionHelper::tryOtherInteractionHandler(
288 uno::Reference< task::XInteractionRequest > const & rRequest)
290 InteractionHandlerDataList dataList;
291 getInteractionHandlerList(dataList);
293 InteractionHandlerDataList::const_iterator aEnd(dataList.end());
294 for (InteractionHandlerDataList::const_iterator aIt(dataList.begin());
295 aIt != aEnd;
296 ++aIt)
298 if ( handleCustomRequest( rRequest, aIt->ServiceName ) )
299 return true;
301 return false;
304 namespace
307 static bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, const OUString& i_rPropagation )
309 const ::com::sun::star::uno::TypeDescription aTypeDesc( i_rTypeName );
310 const typelib_TypeDescription* pTypeDesc = aTypeDesc.get();
311 if ( !pTypeDesc || !pTypeDesc->pWeakRef )
313 #if OSL_DEBUG_LEVEL > 0
314 OStringBuffer aMessage;
315 aMessage.append( "no type found for '" );
316 aMessage.append( OUStringToOString( i_rTypeName, RTL_TEXTENCODING_UTF8 ) );
317 aMessage.append( "'" );
318 OSL_FAIL( aMessage.makeStringAndClear().getStr() );
319 #endif
320 return false;
322 const ::com::sun::star::uno::Type aType( pTypeDesc->pWeakRef );
324 const bool bExactMatch = i_rPropagation == "named-only";
325 if ( bExactMatch )
326 return i_rRequest.getValueType().equals( aType );
328 return i_rRequest.isExtractableTo( aType );
333 bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const
337 Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW );
339 Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY );
340 if ( xHandlerInit.is() )
342 ::comphelper::NamedValueCollection aInitArgs;
343 aInitArgs.put( "Parent", getParentXWindow() );
344 xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() );
347 if ( xHandler->handleInteractionRequest( i_rRequest ) )
348 return true;
350 catch( const Exception& )
352 DBG_UNHANDLED_EXCEPTION();
354 return false;
358 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest )
360 // the request
361 const Any aRequest( rRequest->getRequest() );
363 const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() );
364 if ( aCacheHitTest != m_aTypedCustomHandlers.end() )
365 return handleCustomRequest( rRequest, aCacheHitTest->second );
367 // the base registration node for "typed" interaction handlers
368 const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext(
369 m_xContext,
370 OUString( "/org.openoffice.Interaction/InteractionHandlers" ),
372 ::utl::OConfigurationTreeRoot::CM_READONLY
373 ) );
375 // loop through all registered implementations
376 const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() );
377 const OUString* pHandlerName = aRegisteredHandlers.getConstArray();
378 const OUString* pHandlersEnd = aRegisteredHandlers.getConstArray() + aRegisteredHandlers.getLength();
379 for ( ; pHandlerName != pHandlersEnd; ++pHandlerName )
381 const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( *pHandlerName ) );
382 const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) );
384 // loop through all the types which the current handler is registered for
385 const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() );
386 const OUString* pType = aHandledTypes.getConstArray();
387 const OUString* pTypesEnd = aHandledTypes.getConstArray() + aHandledTypes.getLength();
388 for ( ; pType != pTypesEnd; ++pType )
390 // the UNO type is the node name
391 ::utl::OConfigurationNode aType( aTypesNode.openNode( *pType ) );
392 // and there's a child denoting how the responsibility propagates
393 OUString sPropagation;
394 OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation );
395 if ( lcl_matchesRequest( aRequest, *pType, sPropagation ) )
397 // retrieve the service/implementation name of the handler
398 OUString sServiceName;
399 OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName );
400 // cache the information who feels responsible for requests of this type
401 m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName;
402 // actually handle the request
403 return handleCustomRequest( rRequest, sServiceName );
408 return false;
411 bool
412 UUIInteractionHelper::handleRequest_impl(
413 uno::Reference< task::XInteractionRequest > const & rRequest,
414 bool bObtainErrorStringOnly,
415 bool & bHasErrorString,
416 OUString & rErrorString)
420 if (!rRequest.is())
421 return false;
423 uno::Any aAnyRequest(rRequest->getRequest());
425 script::ModuleSizeExceededRequest aModSizeException;
426 if (aAnyRequest >>= aModSizeException )
428 ErrCode nErrorCode = ERRCODE_UUI_IO_MODULESIZEEXCEEDED;
429 std::vector< OUString > aArguments;
430 uno::Sequence< OUString > sModules
431 = aModSizeException.Names;
432 if ( sModules.getLength() )
434 OUString aName;
435 for ( sal_Int32 index=0; index< sModules.getLength(); ++index )
437 if ( index )
438 aName += "," + sModules[index];
439 else
440 aName = sModules[index]; // 1st name
442 aArguments.push_back( aName );
444 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
445 nErrorCode,
446 aArguments,
447 rRequest->getContinuations(),
448 bObtainErrorStringOnly,
449 bHasErrorString,
450 rErrorString);
451 return true;
454 ucb::NameClashException aNCException;
455 if (aAnyRequest >>= aNCException)
457 ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS;
458 std::vector< OUString > aArguments;
460 if( !aNCException.Name.isEmpty() )
462 nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS;
463 aArguments.push_back( aNCException.Name );
466 handleErrorHandlerRequest( aNCException.Classification,
467 nErrorCode,
468 aArguments,
469 rRequest->getContinuations(),
470 bObtainErrorStringOnly,
471 bHasErrorString,
472 rErrorString);
473 return true;
476 ucb::UnsupportedNameClashException aUORequest;
477 if (aAnyRequest >>= aUORequest)
479 ErrCode nErrorCode = ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE;
480 std::vector< OUString > aArguments;
482 uno::Reference< task::XInteractionApprove > xApprove;
483 uno::Reference< task::XInteractionDisapprove > xDisapprove;
484 getContinuations(
485 rRequest->getContinuations(), &xApprove, &xDisapprove);
487 if ( xApprove.is() && xDisapprove.is() )
489 handleErrorHandlerRequest( task::InteractionClassification_QUERY,
490 nErrorCode,
491 aArguments,
492 rRequest->getContinuations(),
493 bObtainErrorStringOnly,
494 bHasErrorString,
495 rErrorString);
497 return true;
500 if ( handleInteractiveIOException( rRequest,
501 bObtainErrorStringOnly,
502 bHasErrorString,
503 rErrorString ) )
504 return true;
506 ucb::InteractiveAppException aAppException;
507 if (aAnyRequest >>= aAppException)
509 std::vector< OUString > aArguments;
510 handleErrorHandlerRequest( aAppException.Classification,
511 aAppException.Code,
512 aArguments,
513 rRequest->getContinuations(),
514 bObtainErrorStringOnly,
515 bHasErrorString,
516 rErrorString);
517 return true;
520 ucb::InteractiveNetworkException aNetworkException;
521 if (aAnyRequest >>= aNetworkException)
523 ErrCode nErrorCode;
524 std::vector< OUString > aArguments;
525 ucb::InteractiveNetworkOffLineException aOffLineException;
526 ucb::InteractiveNetworkResolveNameException aResolveNameException;
527 ucb::InteractiveNetworkConnectException aConnectException;
528 ucb::InteractiveNetworkReadException aReadException;
529 ucb::InteractiveNetworkWriteException aWriteException;
530 if (aAnyRequest >>= aOffLineException)
531 nErrorCode = ERRCODE_INET_OFFLINE;
532 else if (aAnyRequest >>= aResolveNameException)
534 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
535 aArguments.push_back(aResolveNameException.Server);
537 else if (aAnyRequest >>= aConnectException)
539 nErrorCode = ERRCODE_INET_CONNECT;
540 aArguments.push_back(aConnectException.Server);
542 else if (aAnyRequest >>= aReadException)
544 nErrorCode = ERRCODE_INET_READ;
545 aArguments.push_back(aReadException.Diagnostic);
547 else if (aAnyRequest >>= aWriteException)
549 nErrorCode = ERRCODE_INET_WRITE;
550 aArguments.push_back(aWriteException.Diagnostic);
552 else
553 nErrorCode = ERRCODE_INET_GENERAL;
555 handleErrorHandlerRequest(aNetworkException.Classification,
556 nErrorCode,
557 aArguments,
558 rRequest->getContinuations(),
559 bObtainErrorStringOnly,
560 bHasErrorString,
561 rErrorString);
562 return true;
565 ucb::InteractiveWrongMediumException aWrongMediumException;
566 if (aAnyRequest >>= aWrongMediumException)
568 sal_Int32 nMedium = 0;
569 aWrongMediumException.Medium >>= nMedium;
570 std::vector< OUString > aArguments;
571 aArguments.push_back(OUString::number(nMedium + 1));
572 handleErrorHandlerRequest(aWrongMediumException.Classification,
573 ERRCODE_UUI_WRONGMEDIUM,
574 aArguments,
575 rRequest->getContinuations(),
576 bObtainErrorStringOnly,
577 bHasErrorString,
578 rErrorString);
579 return true;
582 java::WrongJavaVersionException aWrongJavaVersionException;
583 if (aAnyRequest >>= aWrongJavaVersionException)
585 ErrCode nErrorCode;
586 std::vector< OUString > aArguments;
587 if (aWrongJavaVersionException.DetectedVersion.isEmpty())
588 if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
589 nErrorCode = ERRCODE_UUI_WRONGJAVA;
590 else
592 nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN;
593 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
595 else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty())
597 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION;
598 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
600 else
602 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN;
603 aArguments.reserve(2);
604 aArguments.push_back(aWrongJavaVersionException.DetectedVersion);
605 aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion);
607 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
608 nErrorCode,
609 aArguments,
610 rRequest->getContinuations(),
611 bObtainErrorStringOnly,
612 bHasErrorString,
613 rErrorString);
614 return true;
617 configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest;
618 if (aAnyRequest >>= aMergeRecoveryRequest)
620 ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest
621 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
622 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE;
624 std::vector< OUString > aArguments;
625 aArguments.push_back(aMergeRecoveryRequest.ErrorLayerId);
627 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
628 nErrorCode,
629 aArguments,
630 rRequest->getContinuations(),
631 bObtainErrorStringOnly,
632 bHasErrorString,
633 rErrorString);
634 return true;
637 configuration::backend::StratumCreationException
638 aStratumCreationException;
640 if (aAnyRequest >>= aStratumCreationException)
642 const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING;
644 OUString aStratum = aStratumCreationException.StratumData;
645 if (aStratum.isEmpty())
646 aStratum = aStratumCreationException.StratumService;
648 std::vector< OUString > aArguments;
649 aArguments.push_back(aStratum);
651 handleErrorHandlerRequest(task::InteractionClassification_ERROR,
652 nErrorCode,
653 aArguments,
654 rRequest->getContinuations(),
655 bObtainErrorStringOnly,
656 bHasErrorString,
657 rErrorString);
658 return true;
661 xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException;
662 if (aAnyRequest >>= aInvalidDataOnSubmitException)
664 const ErrCode nErrorCode =
665 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA;
667 std::vector< OUString > aArguments;
669 handleErrorHandlerRequest(task::InteractionClassification_QUERY,
670 nErrorCode,
671 aArguments,
672 rRequest->getContinuations(),
673 bObtainErrorStringOnly,
674 bHasErrorString,
675 rErrorString);
676 return true;
679 ucb::InteractiveLockingLockedException aLLException;
680 if (aAnyRequest >>= aLLException)
682 ErrCode nErrorCode = aLLException.SelfOwned
683 ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED;
684 std::vector< OUString > aArguments;
685 aArguments.push_back( aLLException.Url );
687 handleErrorHandlerRequest( aLLException.Classification,
688 nErrorCode,
689 aArguments,
690 rRequest->getContinuations(),
691 bObtainErrorStringOnly,
692 bHasErrorString,
693 rErrorString );
694 return true;
697 ucb::InteractiveLockingNotLockedException aLNLException;
698 if (aAnyRequest >>= aLNLException)
700 ErrCode nErrorCode = ERRCODE_UUI_LOCKING_NOT_LOCKED;
701 std::vector< OUString > aArguments;
702 aArguments.push_back( aLNLException.Url );
704 handleErrorHandlerRequest( aLNLException.Classification,
705 nErrorCode,
706 aArguments,
707 rRequest->getContinuations(),
708 bObtainErrorStringOnly,
709 bHasErrorString,
710 rErrorString );
711 return true;
714 ucb::InteractiveLockingLockExpiredException aLLEException;
715 if (aAnyRequest >>= aLLEException)
717 ErrCode nErrorCode = ERRCODE_UUI_LOCKING_LOCK_EXPIRED;
718 std::vector< OUString > aArguments;
719 aArguments.push_back( aLLEException.Url );
721 handleErrorHandlerRequest( aLLEException.Classification,
722 nErrorCode,
723 aArguments,
724 rRequest->getContinuations(),
725 bObtainErrorStringOnly,
726 bHasErrorString,
727 rErrorString );
728 return true;
731 document::BrokenPackageRequest aBrokenPackageRequest;
732 if (aAnyRequest >>= aBrokenPackageRequest)
734 std::vector< OUString > aArguments;
736 if( !aBrokenPackageRequest.aName.isEmpty() )
737 aArguments.push_back( aBrokenPackageRequest.aName );
739 handleBrokenPackageRequest( aArguments,
740 rRequest->getContinuations(),
741 bObtainErrorStringOnly,
742 bHasErrorString,
743 rErrorString );
744 return true;
747 task::ErrorCodeRequest aErrorCodeRequest;
748 if (aAnyRequest >>= aErrorCodeRequest)
750 // Sucky special handling for xlsx macro filter warning
751 if ( (sal_uInt32)ERRCODE_SFX_VBASIC_CANTSAVE_STORAGE == (sal_uInt32)aErrorCodeRequest.ErrCode)
753 std::vector< OUString > aArguments;
754 handleErrorHandlerRequest( task::InteractionClassification_WARNING,
755 ERRCODE_UUI_IO_WARN_CANTSAVE_MACROS,
756 aArguments,
757 rRequest->getContinuations(),
758 bObtainErrorStringOnly,
759 bHasErrorString,
760 rErrorString);
762 else
764 handleGenericErrorRequest( aErrorCodeRequest.ErrCode,
765 rRequest->getContinuations(),
766 bObtainErrorStringOnly,
767 bHasErrorString,
768 rErrorString);
770 return true;
773 task::ErrorCodeIOException aErrorCodeIOException;
774 if (aAnyRequest >>= aErrorCodeIOException)
776 handleGenericErrorRequest( aErrorCodeIOException.ErrCode,
777 rRequest->getContinuations(),
778 bObtainErrorStringOnly,
779 bHasErrorString,
780 rErrorString);
781 return true;
784 loader::CannotActivateFactoryException aCannotActivateFactoryException;
785 if (aAnyRequest >>= aCannotActivateFactoryException)
787 ErrCode nErrorCode = ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY;
788 std::vector< OUString > aArguments;
789 aArguments.push_back( aCannotActivateFactoryException.Message );
791 handleErrorHandlerRequest( task::InteractionClassification_ERROR,
792 nErrorCode,
793 aArguments,
794 rRequest->getContinuations(),
795 bObtainErrorStringOnly,
796 bHasErrorString,
797 rErrorString );
798 return true;
803 // Handle requests which do not have a plain string representation.
805 if (!bObtainErrorStringOnly)
807 ucb::AuthenticationFallbackRequest anAuthFallbackRequest;
808 if ( aAnyRequest >>= anAuthFallbackRequest )
810 handleAuthFallbackRequest( anAuthFallbackRequest.instructions,
811 anAuthFallbackRequest.url, rRequest->getContinuations() );
812 return true;
815 if ( handleAuthenticationRequest( rRequest ) )
816 return true;
818 if ( handleCertificateValidationRequest( rRequest ) )
819 return true;
821 ucb::NameClashResolveRequest aNameClashResolveRequest;
822 if (aAnyRequest >>= aNameClashResolveRequest)
824 handleNameClashResolveRequest(aNameClashResolveRequest,
825 rRequest->getContinuations());
826 return true;
829 if ( handleMasterPasswordRequest( rRequest ) )
830 return true;
832 if ( handlePasswordRequest( rRequest ) )
833 return true;
835 if ( handleNoSuchFilterRequest( rRequest ) )
836 return true;
838 if ( handleFilterOptionsRequest( rRequest ) )
839 return true;
841 if ( handleLockedDocumentRequest( rRequest ) )
842 return true;
844 if ( handleChangedByOthersRequest( rRequest ) )
845 return true;
847 if ( handleLockFileIgnoreRequest( rRequest ) )
848 return true;
850 task::DocumentMacroConfirmationRequest aMacroConfirmRequest;
851 if (aAnyRequest >>= aMacroConfirmRequest)
853 handleMacroConfirmRequest(
854 aMacroConfirmRequest.DocumentURL,
855 aMacroConfirmRequest.DocumentStorage,
856 !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_012_TEXT,
857 aMacroConfirmRequest.DocumentSignatureInformation,
858 rRequest->getContinuations());
859 return true;
862 // Last chance: interaction handlers registered in the configuration
865 // typed InteractionHandlers (ooo.Interactions)
866 if ( handleTypedHandlerImplementations( rRequest ) )
867 return true;
869 // legacy configuration (ooo.ucb.InteractionHandlers)
870 if (tryOtherInteractionHandler( rRequest ))
871 return true;
874 // Not handled.
875 return false;
877 catch (std::bad_alloc const &)
879 throw uno::RuntimeException("out of memory");
881 catch( const uno::RuntimeException& )
883 throw; // allowed to leave here
885 catch( const uno::Exception& )
887 DBG_UNHANDLED_EXCEPTION();
889 return false;
892 void
893 UUIInteractionHelper::getInteractionHandlerList(
894 InteractionHandlerDataList &rdataList)
898 uno::Reference< lang::XMultiServiceFactory > xConfigProv =
899 configuration::theDefaultProvider::get( m_xContext );
901 OUStringBuffer aFullPath;
902 aFullPath.appendAscii(
903 "/org.openoffice.ucb.InteractionHandler/InteractionHandlers" );
905 uno::Sequence< uno::Any > aArguments( 1 );
906 beans::PropertyValue aProperty;
907 aProperty.Name = "nodepath";
908 aProperty.Value <<= aFullPath.makeStringAndClear();
909 aArguments[ 0 ] <<= aProperty;
911 uno::Reference< uno::XInterface > xInterface(
912 xConfigProv->createInstanceWithArguments(
913 "com.sun.star.configuration.ConfigurationAccess" , aArguments ) );
915 if ( !xInterface.is() )
916 throw uno::RuntimeException("unable to instanciate config access");
918 uno::Reference< container::XNameAccess > xNameAccess(
919 xInterface, uno::UNO_QUERY );
920 if ( !xNameAccess.is() )
921 throw uno::RuntimeException(
922 "config access does not implement XNameAccess");
924 uno::Sequence< OUString > aElems = xNameAccess->getElementNames();
925 const OUString* pElems = aElems.getConstArray();
926 sal_Int32 nCount = aElems.getLength();
928 if ( nCount > 0 )
930 uno::Reference< container::XHierarchicalNameAccess >
931 xHierNameAccess( xInterface, uno::UNO_QUERY );
933 if ( !xHierNameAccess.is() )
934 throw uno::RuntimeException(
935 "config access does not implement XHierarchicalNameAccess");
937 // Iterate over children.
938 for ( sal_Int32 n = 0; n < nCount; ++n )
940 OUStringBuffer aElemBuffer;
941 aElemBuffer.appendAscii( "['" );
942 aElemBuffer.append( pElems[ n ] );
946 InteractionHandlerData aInfo;
948 // Obtain service name.
949 OUStringBuffer aKeyBuffer = aElemBuffer;
950 aKeyBuffer.appendAscii( "']/ServiceName" );
952 OUString aValue;
953 if ( !( xHierNameAccess->getByHierarchicalName(
954 aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
956 OSL_FAIL( "GetInteractionHandlerList - "
957 "Error getting item value!" );
958 continue;
961 aInfo.ServiceName = aValue;
963 // Append info to list.
964 rdataList.push_back( aInfo );
966 catch ( container::NoSuchElementException& )
968 // getByHierarchicalName
970 OSL_FAIL( "GetInteractionHandlerList - "
971 "caught NoSuchElementException!" );
976 catch ( uno::RuntimeException const & )
978 throw;
980 catch ( uno::Exception const & )
982 OSL_FAIL( "GetInteractionHandlerList - Caught Exception!" );
986 vcl::Window *
987 UUIInteractionHelper::getParentProperty()
989 uno::Reference< awt::XWindow > xWindow = getParentXWindow();
990 if ( xWindow.is() )
991 return VCLUnoHelper::GetWindow(xWindow);
993 return 0;
996 uno::Reference< awt::XWindow>
997 UUIInteractionHelper::getParentXWindow() const
999 return m_xWindowParam;
1002 OUString
1003 UUIInteractionHelper::getContextProperty()
1005 return m_aContextParam;
1008 uno::Reference< task::XInteractionHandler2 >
1009 UUIInteractionHelper::getInteractionHandler()
1011 return InteractionHandler::createWithParentAndContext(
1012 m_xContext, m_xWindowParam,
1013 m_aContextParam);
1016 namespace {
1018 sal_uInt16
1019 executeMessageBox(
1020 vcl::Window * pParent,
1021 OUString const & rTitle,
1022 OUString const & rMessage,
1023 WinBits nButtonMask )
1025 SolarMutexGuard aGuard;
1027 ScopedVclPtrInstance< MessBox > xBox(pParent, nButtonMask, rTitle, rMessage);
1029 sal_uInt16 aResult = xBox->Execute();
1030 switch( aResult )
1032 case RET_OK:
1033 aResult = ERRCODE_BUTTON_OK;
1034 break;
1035 case RET_CANCEL:
1036 aResult = ERRCODE_BUTTON_CANCEL;
1037 break;
1038 case RET_YES:
1039 aResult = ERRCODE_BUTTON_YES;
1040 break;
1041 case RET_NO:
1042 aResult = ERRCODE_BUTTON_NO;
1043 break;
1044 case RET_RETRY:
1045 aResult = ERRCODE_BUTTON_RETRY;
1046 break;
1049 return aResult;
1052 NameClashResolveDialogResult executeSimpleNameClashResolveDialog( vcl::Window *pParent,
1053 OUString const & rTargetFolderURL,
1054 OUString const & rClashingName,
1055 OUString & rProposedNewName,
1056 bool bAllowOverwrite )
1058 boost::scoped_ptr< ResMgr > xManager( ResMgr::CreateResMgr( "uui" ) );
1059 if ( !xManager.get() )
1060 return ABORT;
1062 ScopedVclPtrInstance<NameClashDialog> aDialog(pParent, xManager.get(), rTargetFolderURL,
1063 rClashingName, rProposedNewName, bAllowOverwrite);
1065 NameClashResolveDialogResult eResult = (NameClashResolveDialogResult) aDialog->Execute();
1066 rProposedNewName = aDialog->getNewName();
1067 return eResult;
1070 } // namespace
1072 void
1073 UUIInteractionHelper::handleNameClashResolveRequest(
1074 ucb::NameClashResolveRequest const & rRequest,
1075 uno::Sequence< uno::Reference<
1076 task::XInteractionContinuation > > const & rContinuations)
1078 OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(),
1079 "NameClashResolveRequest must not contain empty TargetFolderURL" );
1081 OSL_ENSURE(!rRequest.ClashingName.isEmpty(),
1082 "NameClashResolveRequest must not contain empty ClashingName" );
1084 uno::Reference< task::XInteractionAbort > xAbort;
1085 uno::Reference< ucb::XInteractionSupplyName > xSupplyName;
1086 uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData;
1087 getContinuations(
1088 rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData);
1090 OSL_ENSURE( xAbort.is(),
1091 "NameClashResolveRequest must contain Abort continuation" );
1093 OSL_ENSURE( xSupplyName.is(),
1094 "NameClashResolveRequest must contain SupplyName continuation" );
1096 NameClashResolveDialogResult eResult = ABORT;
1097 OUString aProposedNewName( rRequest.ProposedNewName );
1099 eResult = executeSimpleNameClashResolveDialog( getParentProperty(),
1100 rRequest.TargetFolderURL,
1101 rRequest.ClashingName,
1102 aProposedNewName,
1103 xReplaceExistingData.is() );
1105 switch ( eResult )
1107 case ABORT:
1108 xAbort->select();
1109 break;
1111 case RENAME:
1112 xSupplyName->setName( aProposedNewName );
1113 xSupplyName->select();
1114 break;
1116 case OVERWRITE:
1117 OSL_ENSURE(
1118 xReplaceExistingData.is(),
1119 "Invalid NameClashResolveDialogResult: OVERWRITE - "
1120 "No ReplaceExistingData continuation available!" );
1121 xReplaceExistingData->select();
1122 break;
1126 void
1127 UUIInteractionHelper::handleGenericErrorRequest(
1128 sal_Int32 nErrorCode,
1129 uno::Sequence< uno::Reference<
1130 task::XInteractionContinuation > > const & rContinuations,
1131 bool bObtainErrorStringOnly,
1132 bool & bHasErrorString,
1133 OUString & rErrorString)
1135 if (bObtainErrorStringOnly)
1137 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1138 if (bHasErrorString)
1140 OUString aErrorString;
1141 ErrorHandler::GetErrorString(nErrorCode, aErrorString);
1142 rErrorString = aErrorString;
1145 else
1147 uno::Reference< task::XInteractionAbort > xAbort;
1148 uno::Reference< task::XInteractionApprove > xApprove;
1149 getContinuations(rContinuations, &xApprove, &xAbort);
1151 // Note: It's important to convert the transported long to the
1152 // required unsigned long value. Otherwhise using as flag field
1153 // can fail ...
1154 ErrCode nError = static_cast< ErrCode >(nErrorCode);
1155 bool bWarning = !ERRCODE_TOERROR(nError);
1157 if ( nError == ERRCODE_SFX_BROKENSIGNATURE
1158 || nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION )
1160 // the security warning box needs a special title
1161 OUString aErrorString;
1162 ErrorHandler::GetErrorString( nErrorCode, aErrorString );
1164 boost::scoped_ptr< ResMgr > xManager(
1165 ResMgr::CreateResMgr( "uui" ) );
1166 OUString aTitle( utl::ConfigManager::getProductName() );
1168 OUString aErrTitle
1169 = ResId( nError == ERRCODE_SFX_BROKENSIGNATURE
1170 ? STR_WARNING_BROKENSIGNATURE_TITLE
1171 : STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE,
1172 *xManager.get() ).toString();
1174 if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() )
1175 aTitle += " - " ;
1176 aTitle += aErrTitle;
1178 executeMessageBox(
1179 getParentProperty(), aTitle, aErrorString, WB_OK );
1181 else
1182 ErrorHandler::HandleError(nErrorCode);
1184 if (xApprove.is() && bWarning)
1185 xApprove->select();
1186 else if (xAbort.is())
1187 xAbort->select();
1191 void
1192 UUIInteractionHelper::handleMacroConfirmRequest(
1193 const OUString& aDocumentURL,
1194 const uno::Reference< embed::XStorage >& xZipStorage,
1195 const OUString& aDocumentVersion,
1196 const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo,
1197 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1198 rContinuations )
1200 uno::Reference< task::XInteractionAbort > xAbort;
1201 uno::Reference< task::XInteractionApprove > xApprove;
1202 getContinuations( rContinuations, &xApprove, &xAbort );
1204 bool bApprove = false;
1206 boost::scoped_ptr< ResMgr > pResMgr( ResMgr::CreateResMgr( "uui" ) );
1207 if ( pResMgr.get() )
1209 bool bShowSignatures = aSignInfo.getLength() > 0;
1210 ScopedVclPtrInstance<MacroWarning> aWarning(
1211 getParentProperty(), bShowSignatures, *pResMgr.get() );
1213 aWarning->SetDocumentURL( aDocumentURL );
1214 if ( aSignInfo.getLength() > 1 )
1216 aWarning->SetStorage( xZipStorage, aDocumentVersion, aSignInfo );
1218 else if ( aSignInfo.getLength() == 1 )
1220 aWarning->SetCertificate( aSignInfo[ 0 ].Signer );
1223 bApprove = aWarning->Execute() == RET_OK;
1226 if ( bApprove && xApprove.is() )
1227 xApprove->select();
1228 else if ( xAbort.is() )
1229 xAbort->select();
1232 void
1233 UUIInteractionHelper::handleBrokenPackageRequest(
1234 std::vector< OUString > const & rArguments,
1235 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1236 rContinuations,
1237 bool bObtainErrorStringOnly,
1238 bool & bHasErrorString,
1239 OUString & rErrorString)
1241 if (bObtainErrorStringOnly)
1243 bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1244 if (!bHasErrorString)
1245 return;
1248 uno::Reference< task::XInteractionApprove > xApprove;
1249 uno::Reference< task::XInteractionDisapprove > xDisapprove;
1250 uno::Reference< task::XInteractionAbort > xAbort;
1251 getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort);
1253 ErrCode nErrorCode;
1254 if( xApprove.is() && xDisapprove.is() )
1256 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE;
1258 else if ( xAbort.is() )
1260 nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR;
1262 else
1263 return;
1265 OUString aMessage;
1267 SolarMutexGuard aGuard;
1268 boost::scoped_ptr< ResMgr > xManager(ResMgr::CreateResMgr("uui"));
1269 if (!xManager.get())
1270 return;
1272 ResId aResId( RID_UUI_ERRHDL, *xManager.get() );
1273 if ( !ErrorResource(aResId).getString(nErrorCode, aMessage) )
1274 return;
1277 aMessage = replaceMessageWithArguments( aMessage, rArguments );
1279 if (bObtainErrorStringOnly)
1281 rErrorString = aMessage;
1282 return;
1285 WinBits nButtonMask;
1286 if( xApprove.is() && xDisapprove.is() )
1288 nButtonMask = WB_YES_NO | WB_DEF_YES;
1290 else if ( xAbort.is() )
1292 nButtonMask = WB_OK;
1294 else
1295 return;
1297 OUString title(
1298 utl::ConfigManager::getProductName() +
1299 " " +
1300 utl::ConfigManager::getProductVersion() );
1302 switch (
1303 executeMessageBox( getParentProperty(), title, aMessage, nButtonMask ) )
1305 case ERRCODE_BUTTON_OK:
1306 OSL_ENSURE( xAbort.is(), "unexpected situation" );
1307 if (xAbort.is())
1308 xAbort->select();
1309 break;
1311 case ERRCODE_BUTTON_NO:
1312 OSL_ENSURE(xDisapprove.is(), "unexpected situation");
1313 if (xDisapprove.is())
1314 xDisapprove->select();
1315 break;
1317 case ERRCODE_BUTTON_YES:
1318 OSL_ENSURE(xApprove.is(), "unexpected situation");
1319 if (xApprove.is())
1320 xApprove->select();
1321 break;
1326 // ErrorResource Implementation
1329 bool
1330 ErrorResource::getString(ErrCode nErrorCode, OUString &rString)
1331 const
1333 ResId aResId(static_cast< sal_uInt16 >(nErrorCode & ERRCODE_RES_MASK),
1334 *m_pResMgr);
1335 aResId.SetRT(RSC_STRING);
1336 if (!IsAvailableRes(aResId))
1337 return false;
1338 aResId.SetAutoRelease(false);
1339 rString = aResId.toString();
1340 m_pResMgr->PopContext();
1341 return true;
1344 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */