/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "getcontinuations.hxx" #include "secmacrowarnings.hxx" #include "iahndl.hxx" #include "nameclashdlg.hxx" #include using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::Reference; using ::com::sun::star::task::XInteractionContinuation; using ::com::sun::star::task::XInteractionAbort; using ::com::sun::star::task::XInteractionApprove; using ::com::sun::star::uno::XInterface; using ::com::sun::star::lang::XInitialization; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::task::InteractionHandler; using ::com::sun::star::task::XInteractionHandler2; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::Any; using ::com::sun::star::task::XInteractionRequest; using ::com::sun::star::lang::XMultiServiceFactory; using namespace ::com::sun::star; namespace { class HandleData : public osl::Condition { public: explicit HandleData( uno::Reference< task::XInteractionRequest > xRequest) : m_rRequest(std::move(xRequest)), bHandled( false ) { } uno::Reference< task::XInteractionRequest > m_rRequest; bool bHandled; beans::Optional< OUString > m_aResult; }; } /* namespace */ UUIInteractionHelper::UUIInteractionHelper( uno::Reference< uno::XComponentContext > xContext) : m_xContext(std::move(xContext)) { } UUIInteractionHelper::~UUIInteractionHelper() { } void UUIInteractionHelper::handlerequest( void* pHandleData, void* pInteractionHelper) { HandleData* pHND = static_cast< HandleData * >(pHandleData); UUIInteractionHelper* pUUI = static_cast< UUIInteractionHelper * >(pInteractionHelper); bool bDummy = false; OUString aDummy; try { pHND->bHandled = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy); pHND->set(); } catch (css::uno::Exception&) { TOOLS_WARN_EXCEPTION("uui", ""); } } bool UUIInteractionHelper::handleRequest( uno::Reference< task::XInteractionRequest > const & rRequest) { if(!Application::IsMainThread() && GetpApp()) { // we are not in the main thread, let it handle that stuff HandleData aHD(rRequest); Link aLink(&aHD,handlerequest); Application::PostUserEvent(aLink,this); comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex(); sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0; aHD.wait(); if (nLockCount) rSolarMutex.acquire(nLockCount); return aHD.bHandled; } else { bool bDummy = false; OUString aDummy; return handleRequest_impl(rRequest, false, bDummy, aDummy); } } void UUIInteractionHelper::getstringfromrequest( void* pHandleData,void* pInteractionHelper) { HandleData* pHND = static_cast(pHandleData); UUIInteractionHelper* pUUI = static_cast(pInteractionHelper); pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest); pHND->set(); } beans::Optional< OUString > UUIInteractionHelper::getStringFromRequest_impl( uno::Reference< task::XInteractionRequest > const & rRequest) { bool bSuccess = false; OUString aMessage; handleRequest_impl(rRequest, true, bSuccess, aMessage); OSL_ENSURE(bSuccess || !isInformationalErrorMessageRequest( rRequest->getContinuations()), "Interaction request is a candidate for a string representation." "Please implement!"); return beans::Optional< OUString >(bSuccess, aMessage); } beans::Optional< OUString > UUIInteractionHelper::getStringFromRequest( uno::Reference< task::XInteractionRequest > const & rRequest) { if(!Application::IsMainThread() && GetpApp()) { // we are not in the main thread, let it handle that stuff HandleData aHD(rRequest); Link aLink(&aHD,getstringfromrequest); Application::PostUserEvent(aLink,this); comphelper::SolarMutex& rSolarMutex = Application::GetSolarMutex(); sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0; aHD.wait(); if (nLockCount) rSolarMutex.acquire(nLockCount); return aHD.m_aResult; } else return getStringFromRequest_impl(rRequest); } OUString UUIInteractionHelper::replaceMessageWithArguments( const OUString& _aMessage, std::vector< OUString > const & rArguments ) { OUString aMessage = _aMessage; SAL_WARN_IF(rArguments.empty(), "uui", "replaceMessageWithArguments: No arguments passed!"); for (size_t i = 0; i < rArguments.size(); ++i) { const OUString sReplaceTemplate = "$(ARG" + OUString::number(i+1) + ")"; aMessage = aMessage.replaceAll(sReplaceTemplate, rArguments[i]); } return aMessage; } bool UUIInteractionHelper::isInformationalErrorMessageRequest( uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations) { // Only requests with a single continuation (user has no choice, request // is just informational) if (rContinuations.getLength() != 1 ) return false; // user can only abort or approve, all other continuations are not // considered to be informational. uno::Reference< task::XInteractionApprove > xApprove( rContinuations[0], uno::UNO_QUERY); if (xApprove.is()) return true; uno::Reference< task::XInteractionAbort > xAbort( rContinuations[0], uno::UNO_QUERY); return xAbort.is(); } bool UUIInteractionHelper::tryOtherInteractionHandler( uno::Reference< task::XInteractionRequest > const & rRequest) { InteractionHandlerDataList dataList; getInteractionHandlerList(dataList); return std::any_of(dataList.cbegin(), dataList.cend(), [&](const InteractionHandlerData& rData) { return handleCustomRequest( rRequest, rData.ServiceName ); }); } namespace { bool lcl_matchesRequest( const Any& i_rRequest, const OUString& i_rTypeName, std::u16string_view i_rPropagation ) { const css::uno::TypeDescription aTypeDesc( i_rTypeName ); const typelib_TypeDescription* pTypeDesc = aTypeDesc.get(); if ( !pTypeDesc || !pTypeDesc->pWeakRef ) { SAL_WARN( "uui","no type found for '" << i_rTypeName << "'" ); return false; } const css::uno::Type aType( pTypeDesc->pWeakRef ); const bool bExactMatch = i_rPropagation == u"named-only"; if ( bExactMatch ) return i_rRequest.getValueType().equals( aType ); return i_rRequest.isExtractableTo( aType ); } } bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const OUString& i_rServiceName ) const { try { Reference< XInteractionHandler2 > xHandler( m_xContext->getServiceManager()->createInstanceWithContext( i_rServiceName, m_xContext ), UNO_QUERY_THROW ); Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY ); if ( xHandlerInit.is() ) { ::comphelper::NamedValueCollection aInitArgs; aInitArgs.put( "Parent", getParentXWindow() ); xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() ); } if ( xHandler->handleInteractionRequest( i_rRequest ) ) return true; } catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("uui"); } return false; } bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest ) { // the request const Any aRequest( rRequest->getRequest() ); const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() ); if ( aCacheHitTest != m_aTypedCustomHandlers.end() ) return handleCustomRequest( rRequest, aCacheHitTest->second ); // the base registration node for "typed" interaction handlers const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithComponentContext( m_xContext, "/org.openoffice.Interaction/InteractionHandlers", -1, ::utl::OConfigurationTreeRoot::CM_READONLY ) ); // loop through all registered implementations const Sequence< OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() ); for ( auto const & handlerName : aRegisteredHandlers ) { const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( handlerName ) ); const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) ); // loop through all the types which the current handler is registered for const Sequence< OUString > aHandledTypes( aTypesNode.getNodeNames() ); for ( auto const & type : aHandledTypes ) { // the UNO type is the node name ::utl::OConfigurationNode aType( aTypesNode.openNode( type ) ); // and there's a child denoting how the responsibility propagates OUString sPropagation; OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation ); if ( lcl_matchesRequest( aRequest, type, sPropagation ) ) { // retrieve the service/implementation name of the handler OUString sServiceName; OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName ); // cache the information who feels responsible for requests of this type m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName; // actually handle the request return handleCustomRequest( rRequest, sServiceName ); } } } return false; } bool UUIInteractionHelper::handleRequest_impl( uno::Reference< task::XInteractionRequest > const & rRequest, bool bObtainErrorStringOnly, bool & bHasErrorString, OUString & rErrorString) { try { if (!rRequest.is()) return false; uno::Any aAnyRequest(rRequest->getRequest()); script::ModuleSizeExceededRequest aModSizeException; if (aAnyRequest >>= aModSizeException ) { std::vector< OUString > aArguments; aArguments.push_back( comphelper::string::convertCommaSeparated(aModSizeException.Names)); handleErrorHandlerRequest( task::InteractionClassification_WARNING, ERRCODE_UUI_IO_MODULESIZEEXCEEDED, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } document::ExoticFileLoadException aExoticFileLoadException; if (aAnyRequest >>= aExoticFileLoadException) { std::vector< OUString > aArguments; if( !aExoticFileLoadException.URL.isEmpty() ) { aArguments.push_back( aExoticFileLoadException.URL ); } if( !aExoticFileLoadException.FilterUIName.isEmpty() ) { aArguments.push_back( aExoticFileLoadException.FilterUIName ); } handleErrorHandlerRequest( task::InteractionClassification_WARNING, ERRCODE_UUI_IO_EXOTICFILEFORMAT, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } ucb::NameClashException aNCException; if (aAnyRequest >>= aNCException) { ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS; std::vector< OUString > aArguments; if( !aNCException.Name.isEmpty() ) { nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS; aArguments.push_back( aNCException.Name ); } handleErrorHandlerRequest( aNCException.Classification, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } ucb::UnsupportedNameClashException aUORequest; if (aAnyRequest >>= aUORequest) { uno::Reference< task::XInteractionApprove > xApprove; uno::Reference< task::XInteractionDisapprove > xDisapprove; getContinuations( rRequest->getContinuations(), &xApprove, &xDisapprove); if ( xApprove.is() && xDisapprove.is() ) { std::vector< OUString > aArguments; handleErrorHandlerRequest( task::InteractionClassification_QUERY, ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); } return true; } if ( handleInteractiveIOException( rRequest, bObtainErrorStringOnly, bHasErrorString, rErrorString ) ) return true; ucb::InteractiveAppException aAppException; if (aAnyRequest >>= aAppException) { std::vector< OUString > aArguments; handleErrorHandlerRequest( aAppException.Classification, ErrCode(aAppException.Code), aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } ucb::InteractiveNetworkException aNetworkException; if (aAnyRequest >>= aNetworkException) { ErrCode nErrorCode; std::vector< OUString > aArguments; ucb::InteractiveNetworkOffLineException aOffLineException; ucb::InteractiveNetworkResolveNameException aResolveNameException; ucb::InteractiveNetworkConnectException aConnectException; ucb::InteractiveNetworkReadException aReadException; ucb::InteractiveNetworkWriteException aWriteException; if (aAnyRequest >>= aOffLineException) nErrorCode = ERRCODE_INET_OFFLINE; else if (aAnyRequest >>= aResolveNameException) { nErrorCode = ERRCODE_INET_NAME_RESOLVE; aArguments.push_back(aResolveNameException.Server); } else if (aAnyRequest >>= aConnectException) { nErrorCode = ERRCODE_INET_CONNECT; aArguments.push_back(aConnectException.Server); } else if (aAnyRequest >>= aReadException) { nErrorCode = ERRCODE_INET_READ; aArguments.push_back(aReadException.Diagnostic); } else if (aAnyRequest >>= aWriteException) { nErrorCode = ERRCODE_INET_WRITE; aArguments.push_back(aWriteException.Diagnostic); } else nErrorCode = ERRCODE_INET_GENERAL; handleErrorHandlerRequest(aNetworkException.Classification, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } ucb::InteractiveWrongMediumException aWrongMediumException; if (aAnyRequest >>= aWrongMediumException) { sal_Int32 nMedium = 0; aWrongMediumException.Medium >>= nMedium; std::vector< OUString > aArguments { OUString::number(nMedium + 1) }; handleErrorHandlerRequest(aWrongMediumException.Classification, ERRCODE_UUI_WRONGMEDIUM, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } java::WrongJavaVersionException aWrongJavaVersionException; if (aAnyRequest >>= aWrongJavaVersionException) { ErrCode nErrorCode; std::vector< OUString > aArguments; if (aWrongJavaVersionException.DetectedVersion.isEmpty()) if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty()) nErrorCode = ERRCODE_UUI_WRONGJAVA; else { nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN; aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion); } else if (aWrongJavaVersionException.LowestSupportedVersion.isEmpty()) { nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION; aArguments.push_back(aWrongJavaVersionException.DetectedVersion); } else { nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN; aArguments.reserve(2); aArguments.push_back(aWrongJavaVersionException.DetectedVersion); aArguments.push_back(aWrongJavaVersionException.LowestSupportedVersion); } handleErrorHandlerRequest(task::InteractionClassification_ERROR, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest; if (aAnyRequest >>= aMergeRecoveryRequest) { ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE; std::vector< OUString > aArguments { aMergeRecoveryRequest.ErrorLayerId }; handleErrorHandlerRequest(task::InteractionClassification_ERROR, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } configuration::backend::StratumCreationException aStratumCreationException; if (aAnyRequest >>= aStratumCreationException) { const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING; OUString aStratum = aStratumCreationException.StratumData; if (aStratum.isEmpty()) aStratum = aStratumCreationException.StratumService; std::vector< OUString > aArguments { aStratum }; handleErrorHandlerRequest(task::InteractionClassification_ERROR, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException; if (aAnyRequest >>= aInvalidDataOnSubmitException) { const ErrCode nErrorCode = ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA; std::vector< OUString > aArguments; handleErrorHandlerRequest(task::InteractionClassification_QUERY, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } ucb::InteractiveLockingLockedException aLLException; if (aAnyRequest >>= aLLException) { ErrCode nErrorCode = aLLException.SelfOwned ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED; std::vector< OUString > aArguments { aLLException.Url }; handleErrorHandlerRequest( aLLException.Classification, nErrorCode, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString ); return true; } ucb::InteractiveLockingNotLockedException aLNLException; if (aAnyRequest >>= aLNLException) { std::vector< OUString > aArguments { aLNLException.Url }; handleErrorHandlerRequest( aLNLException.Classification, ERRCODE_UUI_LOCKING_NOT_LOCKED, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString ); return true; } ucb::InteractiveLockingLockExpiredException aLLEException; if (aAnyRequest >>= aLLEException) { std::vector< OUString > aArguments { aLLEException.Url }; handleErrorHandlerRequest( aLLEException.Classification, ERRCODE_UUI_LOCKING_LOCK_EXPIRED, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString ); return true; } document::BrokenPackageRequest aBrokenPackageRequest; if (aAnyRequest >>= aBrokenPackageRequest) { std::vector< OUString > aArguments; if( !aBrokenPackageRequest.aName.isEmpty() ) aArguments.push_back( aBrokenPackageRequest.aName ); handleBrokenPackageRequest( aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString ); return true; } task::ErrorCodeRequest2 aErrorCodeRequest2; if (aAnyRequest >>= aErrorCodeRequest2) { handleGenericErrorRequest( ErrCodeMsg(ErrCode(aErrorCodeRequest2.ErrCode), aErrorCodeRequest2.Arg1, aErrorCodeRequest2.Arg2, static_cast(aErrorCodeRequest2.DialogMask)), rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } task::ErrorCodeRequest aErrorCodeRequest; if (aAnyRequest >>= aErrorCodeRequest) { handleGenericErrorRequest( ErrCode(aErrorCodeRequest.ErrCode), rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } task::ErrorCodeIOException aErrorCodeIOException; if (aAnyRequest >>= aErrorCodeIOException) { handleGenericErrorRequest( ErrCode(aErrorCodeIOException.ErrCode), rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString); return true; } loader::CannotActivateFactoryException aCannotActivateFactoryException; if (aAnyRequest >>= aCannotActivateFactoryException) { std::vector< OUString > aArguments { aCannotActivateFactoryException.Message }; handleErrorHandlerRequest( task::InteractionClassification_ERROR, ERRCODE_UUI_CANNOT_ACTIVATE_FACTORY, aArguments, rRequest->getContinuations(), bObtainErrorStringOnly, bHasErrorString, rErrorString ); return true; } // Handle requests which do not have a plain string representation. if (!bObtainErrorStringOnly) { ucb::AuthenticationFallbackRequest anAuthFallbackRequest; if ( aAnyRequest >>= anAuthFallbackRequest ) { handleAuthFallbackRequest( anAuthFallbackRequest.instructions, anAuthFallbackRequest.url, rRequest->getContinuations() ); return true; } if ( handleAuthenticationRequest( rRequest ) ) return true; if ( handleCertificateValidationRequest( rRequest ) ) return true; ucb::NameClashResolveRequest aNameClashResolveRequest; if (aAnyRequest >>= aNameClashResolveRequest) { handleNameClashResolveRequest(aNameClashResolveRequest, rRequest->getContinuations()); return true; } if ( handleMasterPasswordRequest( rRequest ) ) return true; if ( handlePasswordRequest( rRequest ) ) return true; if ( handleNoSuchFilterRequest( rRequest ) ) return true; if ( handleFilterOptionsRequest( rRequest ) ) return true; if ( handleLockedDocumentRequest( rRequest ) ) return true; if ( handleChangedByOthersRequest( rRequest ) ) return true; if ( handleLockFileProblemRequest( rRequest ) ) return true; if ( handleReloadEditableRequest( rRequest ) ) return true; task::DocumentMacroConfirmationRequest aMacroConfirmRequest; if (aAnyRequest >>= aMacroConfirmRequest) { handleMacroConfirmRequest( aMacroConfirmRequest.DocumentURL, aMacroConfirmRequest.DocumentStorage, !aMacroConfirmRequest.DocumentVersion.isEmpty() ? aMacroConfirmRequest.DocumentVersion : ODFVER_013_TEXT, aMacroConfirmRequest.DocumentSignatureInformation, rRequest->getContinuations()); return true; } OUString aFileName; beans::NamedValue aLoadReadOnlyRequest; if ((aAnyRequest >>= aLoadReadOnlyRequest) && aLoadReadOnlyRequest.Name == "LoadReadOnlyRequest" && (aLoadReadOnlyRequest.Value >>= aFileName)) { handleLoadReadOnlyRequest(aFileName, rRequest->getContinuations()); return true; } // Last chance: interaction handlers registered in the configuration // typed InteractionHandlers (ooo.Interactions) if ( handleTypedHandlerImplementations( rRequest ) ) return true; // legacy configuration (ooo.ucb.InteractionHandlers) if (tryOtherInteractionHandler( rRequest )) return true; } // Not handled. return false; } catch( const uno::RuntimeException& ) { throw; // allowed to leave here } catch( const uno::Exception& ) { DBG_UNHANDLED_EXCEPTION("uui"); } return false; } void UUIInteractionHelper::getInteractionHandlerList( InteractionHandlerDataList &rdataList) { try { uno::Reference< lang::XMultiServiceFactory > xConfigProv = configuration::theDefaultProvider::get( m_xContext ); uno::Sequence aArguments(comphelper::InitAnyPropertySequence( { {"nodepath", uno::Any(OUString("/org.openoffice.ucb.InteractionHandler/InteractionHandlers"))} })); uno::Reference< uno::XInterface > xInterface( xConfigProv->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess" , aArguments ) ); if ( !xInterface.is() ) throw uno::RuntimeException("unable to instantiate config access"); uno::Reference< container::XNameAccess > xNameAccess( xInterface, uno::UNO_QUERY_THROW ); const uno::Sequence< OUString > aElems = xNameAccess->getElementNames(); if ( aElems.hasElements() ) { uno::Reference< container::XHierarchicalNameAccess > xHierNameAccess( xInterface, uno::UNO_QUERY_THROW ); // Iterate over children. for ( const auto& rElem : aElems ) { try { InteractionHandlerData aInfo; // Obtain service name. OUString aKeyBuffer = "['" + rElem + "']/ServiceName"; OUString aValue; if ( !( xHierNameAccess->getByHierarchicalName( aKeyBuffer ) >>= aValue ) ) { OSL_FAIL( "GetInteractionHandlerList - " "Error getting item value!" ); continue; } aInfo.ServiceName = aValue; // Append info to list. rdataList.push_back( aInfo ); } catch ( container::NoSuchElementException& ) { // getByHierarchicalName OSL_FAIL( "GetInteractionHandlerList - " "caught NoSuchElementException!" ); } } } } catch ( uno::RuntimeException const & ) { throw; } catch ( uno::Exception const & ) { TOOLS_WARN_EXCEPTION( "uui", "GetInteractionHandlerList" ); } } const uno::Reference< awt::XWindow>& UUIInteractionHelper::getParentXWindow() const { return m_xWindowParam; } uno::Reference< task::XInteractionHandler2 > UUIInteractionHelper::getInteractionHandler() const { return InteractionHandler::createWithParentAndContext( m_xContext, m_xWindowParam, m_aContextParam); } namespace { DialogMask executeMessageBox( weld::Window * pParent, OUString const & rTitle, OUString const & rMessage, VclMessageType eMessageType) { SolarMutexGuard aGuard; std::unique_ptr xBox(Application::CreateMessageDialog(pParent, eMessageType, eMessageType == VclMessageType::Question ? VclButtonsType::YesNo : VclButtonsType::Ok, rMessage, GetpApp())); xBox->set_title(rTitle); short nMessResult = xBox->run(); DialogMask aResult = DialogMask::NONE; switch (nMessResult) { case RET_OK: aResult = DialogMask::ButtonsOk; break; case RET_CANCEL: aResult = DialogMask::ButtonsCancel; break; case RET_YES: aResult = DialogMask::ButtonsYes; break; case RET_NO: aResult = DialogMask::ButtonsNo; break; default: assert(false); } return aResult; } NameClashResolveDialogResult executeSimpleNameClashResolveDialog(weld::Window *pParent, OUString const & rTargetFolderURL, OUString const & rClashingName, OUString & rProposedNewName, bool bAllowOverwrite) { std::locale aResLocale = Translate::Create("uui"); NameClashDialog aDialog(pParent, aResLocale, rTargetFolderURL, rClashingName, rProposedNewName, bAllowOverwrite); NameClashResolveDialogResult eResult = static_cast(aDialog.run()); rProposedNewName = aDialog.getNewName(); return eResult; } } // namespace void UUIInteractionHelper::handleNameClashResolveRequest( ucb::NameClashResolveRequest const & rRequest, uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations) { OSL_ENSURE(!rRequest.TargetFolderURL.isEmpty(), "NameClashResolveRequest must not contain empty TargetFolderURL" ); OSL_ENSURE(!rRequest.ClashingName.isEmpty(), "NameClashResolveRequest must not contain empty ClashingName" ); uno::Reference< task::XInteractionAbort > xAbort; uno::Reference< ucb::XInteractionSupplyName > xSupplyName; uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData; getContinuations( rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData); OSL_ENSURE( xAbort.is(), "NameClashResolveRequest must contain Abort continuation" ); OSL_ENSURE( xSupplyName.is(), "NameClashResolveRequest must contain SupplyName continuation" ); NameClashResolveDialogResult eResult = ABORT; OUString aProposedNewName( rRequest.ProposedNewName ); uno::Reference xParent = getParentXWindow(); eResult = executeSimpleNameClashResolveDialog(Application::GetFrameWeld(xParent), rRequest.TargetFolderURL, rRequest.ClashingName, aProposedNewName, xReplaceExistingData.is()); switch ( eResult ) { case ABORT: xAbort->select(); break; case RENAME: xSupplyName->setName( aProposedNewName ); xSupplyName->select(); break; case OVERWRITE: OSL_ENSURE( xReplaceExistingData.is(), "Invalid NameClashResolveDialogResult: OVERWRITE - " "No ReplaceExistingData continuation available!" ); xReplaceExistingData->select(); break; } } void UUIInteractionHelper::handleGenericErrorRequest( ErrCodeMsg nErrorCode, uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations, bool bObtainErrorStringOnly, bool & bHasErrorString, OUString & rErrorString) { if (bObtainErrorStringOnly) { bHasErrorString = isInformationalErrorMessageRequest(rContinuations); if (bHasErrorString) { OUString aErrorString; ErrorHandler::GetErrorString(nErrorCode, aErrorString); rErrorString = aErrorString; } } else { uno::Reference< task::XInteractionAbort > xAbort; uno::Reference< task::XInteractionApprove > xApprove; getContinuations(rContinuations, &xApprove, &xAbort); // Note: It's important to convert the transported long to the // required unsigned long value. Otherwise using as flag field // can fail ... bool bWarning = !nErrorCode.IgnoreWarning(); if ( nErrorCode == ERRCODE_SFX_INCOMPLETE_ENCRYPTION ) { // the security warning box needs a special title OUString aErrorString; ErrorHandler::GetErrorString( nErrorCode, aErrorString ); std::locale aResLocale = Translate::Create("uui"); OUString aTitle( utl::ConfigManager::getProductName() ); OUString aErrTitle = Translate::get(STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE, aResLocale); if ( !aTitle.isEmpty() && !aErrTitle.isEmpty() ) aTitle += " - " ; aTitle += aErrTitle; uno::Reference xParent = getParentXWindow(); executeMessageBox(Application::GetFrameWeld(xParent), aTitle, aErrorString, VclMessageType::Error); } else { uno::Reference xParent = getParentXWindow(); ErrorHandler::HandleError(nErrorCode, Application::GetFrameWeld(xParent)); } if (xApprove.is() && bWarning) xApprove->select(); else if (xAbort.is()) xAbort->select(); } } void UUIInteractionHelper::handleMacroConfirmRequest( const OUString& aDocumentURL, const uno::Reference< embed::XStorage >& xZipStorage, const OUString& aDocumentVersion, const uno::Sequence< security::DocumentSignatureInformation >& aSignInfo, uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations ) { uno::Reference< task::XInteractionAbort > xAbort; uno::Reference< task::XInteractionApprove > xApprove; getContinuations( rContinuations, &xApprove, &xAbort ); bool bApprove = false; bool bShowSignatures = aSignInfo.hasElements(); uno::Reference xParent = getParentXWindow(); MacroWarning aWarning(Application::GetFrameWeld(xParent), bShowSignatures); aWarning.SetDocumentURL(aDocumentURL); if ( aSignInfo.getLength() > 1 ) { aWarning.SetStorage(xZipStorage, aDocumentVersion, aSignInfo); } else if ( aSignInfo.getLength() == 1 ) { aWarning.SetCertificate(aSignInfo[0].Signer); } bApprove = aWarning.run() == RET_OK; if ( bApprove && xApprove.is() ) xApprove->select(); else if ( xAbort.is() ) xAbort->select(); } void UUIInteractionHelper::handleBrokenPackageRequest( std::vector< OUString > const & rArguments, uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & rContinuations, bool bObtainErrorStringOnly, bool & bHasErrorString, OUString & rErrorString) { if (bObtainErrorStringOnly) { bHasErrorString = isInformationalErrorMessageRequest(rContinuations); if (!bHasErrorString) return; } uno::Reference< task::XInteractionApprove > xApprove; uno::Reference< task::XInteractionDisapprove > xDisapprove; uno::Reference< task::XInteractionAbort > xAbort; getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort); ErrCode nErrorCode; if( xApprove.is() && xDisapprove.is() ) { nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE; } else if ( xAbort.is() ) { nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR; } else return; OUString aMessage; { std::locale aResLocale = Translate::Create("uui"); ErrorResource aErrorResource(RID_UUI_ERRHDL, aResLocale); if (!aErrorResource.getString(nErrorCode, aMessage)) return; } aMessage = replaceMessageWithArguments( aMessage, rArguments ); if (bObtainErrorStringOnly) { rErrorString = aMessage; return; } VclMessageType eMessageType; if( xApprove.is() && xDisapprove.is() ) eMessageType = VclMessageType::Question; else if ( xAbort.is() ) eMessageType = VclMessageType::Warning; else return; OUString title( utl::ConfigManager::getProductName() + " " + utl::ConfigManager::getProductVersion() ); uno::Reference xParent = getParentXWindow(); switch (executeMessageBox(Application::GetFrameWeld(xParent), title, aMessage, eMessageType)) { case DialogMask::ButtonsOk: OSL_ENSURE( xAbort.is(), "unexpected situation" ); if (xAbort.is()) xAbort->select(); break; case DialogMask::ButtonsNo: OSL_ENSURE(xDisapprove.is(), "unexpected situation"); if (xDisapprove.is()) xDisapprove->select(); break; case DialogMask::ButtonsYes: OSL_ENSURE(xApprove.is(), "unexpected situation"); if (xApprove.is()) xApprove->select(); break; default: break; } } // ErrorResource Implementation bool ErrorResource::getString(ErrCode nErrorCode, OUString &rString) const { for (const std::pair* pStringArray = m_pStringArray; pStringArray->first; ++pStringArray) { if (nErrorCode.StripWarning() == pStringArray->second.StripWarning()) { rString = Translate::get(pStringArray->first, m_rResLocale); return true; } } return false; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */