xref: /trunk/main/uui/source/iahndl.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <memory>
25 
26 #include "com/sun/star/awt/XWindow.hpp"
27 #include "com/sun/star/beans/PropertyValue.hpp"
28 #include "com/sun/star/configuration/backend/MergeRecoveryRequest.hpp"
29 #include "com/sun/star/configuration/backend/StratumCreationException.hpp"
30 #include "com/sun/star/container/XHierarchicalNameAccess.hpp"
31 #include "com/sun/star/document/BrokenPackageRequest.hpp"
32 #include "com/sun/star/task/DocumentMacroConfirmationRequest.hpp"
33 #include "com/sun/star/java/WrongJavaVersionException.hpp"
34 #include "com/sun/star/lang/XInitialization.hpp"
35 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
36 #include "com/sun/star/script/ModuleSizeExceededRequest.hpp"
37 #include "com/sun/star/sync2/BadPartnershipException.hpp"
38 #include "com/sun/star/task/ErrorCodeIOException.hpp"
39 #include "com/sun/star/task/ErrorCodeRequest.hpp"
40 #include "com/sun/star/task/FutureDocumentVersionProductUpdateRequest.hpp"
41 #include "com/sun/star/task/XInteractionAbort.hpp"
42 #include "com/sun/star/task/XInteractionApprove.hpp"
43 #include "com/sun/star/task/XInteractionAskLater.hpp"
44 #include "com/sun/star/task/XInteractionDisapprove.hpp"
45 #include "com/sun/star/task/XInteractionHandler2.hpp"
46 #include "com/sun/star/task/XInteractionRequest.hpp"
47 #include "com/sun/star/task/XInteractionRetry.hpp"
48 #include "com/sun/star/ucb/InteractiveAppException.hpp"
49 #include "com/sun/star/ucb/InteractiveCHAOSException.hpp"
50 #include "com/sun/star/ucb/InteractiveLockingLockedException.hpp"
51 #include "com/sun/star/ucb/InteractiveLockingNotLockedException.hpp"
52 #include "com/sun/star/ucb/InteractiveLockingLockExpiredException.hpp"
53 #include "com/sun/star/ucb/InteractiveNetworkConnectException.hpp"
54 #include "com/sun/star/ucb/InteractiveNetworkOffLineException.hpp"
55 #include "com/sun/star/ucb/InteractiveNetworkReadException.hpp"
56 #include "com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp"
57 #include "com/sun/star/ucb/InteractiveNetworkWriteException.hpp"
58 #include "com/sun/star/ucb/InteractiveWrongMediumException.hpp"
59 #include "com/sun/star/ucb/NameClashException.hpp"
60 #include "com/sun/star/ucb/NameClashResolveRequest.hpp"
61 #include "com/sun/star/ucb/UnsupportedNameClashException.hpp"
62 #include "com/sun/star/ucb/XInteractionReplaceExistingData.hpp"
63 #include "com/sun/star/ucb/XInteractionSupplyName.hpp"
64 #include "com/sun/star/xforms/InvalidDataOnSubmitException.hpp"
65 
66 #include "osl/conditn.hxx"
67 #include "tools/rcid.h" // RSC_STRING
68 #include "tools/errinf.hxx" // ErrorHandler, ErrorContext, ...
69 #include "vos/mutex.hxx"
70 #include "tools/diagnose_ex.h"
71 #include "comphelper/documentconstants.hxx" // ODFVER_012_TEXT
72 #include "svtools/sfxecode.hxx" // ERRCODE_SFX_*
73 #include "vcl/msgbox.hxx"
74 #include "vcl/svapp.hxx"
75 #include "unotools/configmgr.hxx"
76 #include "toolkit/helper/vclunohelper.hxx"
77 #include "comphelper/namedvaluecollection.hxx"
78 #include "typelib/typedescription.hxx"
79 #include "unotools/confignode.hxx"
80 
81 #include "ids.hrc"
82 
83 #include "getcontinuations.hxx"
84 #include "secmacrowarnings.hxx"
85 #include "newerverwarn.hxx"
86 
87 #include "iahndl.hxx"
88 #include "nameclashdlg.hxx"
89 
90 /** === begin UNO using === **/
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::task::FutureDocumentVersionProductUpdateRequest;
99 using ::com::sun::star::uno::XInterface;
100 using ::com::sun::star::lang::XInitialization;
101 using ::com::sun::star::uno::UNO_QUERY_THROW;
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;
107 /** === end UNO using === **/
108 
109 using namespace ::com::sun::star;
110 
111 namespace {
112 
113 class HandleData : public osl::Condition
114 {
115 public:
HandleData(uno::Reference<task::XInteractionRequest> const & rRequest)116     HandleData(
117         uno::Reference< task::XInteractionRequest > const & rRequest)
118         : osl::Condition(),
119           m_rRequest(rRequest),
120           bHandled( false )
121     {
122     }
123     uno::Reference< task::XInteractionRequest > m_rRequest;
124     bool                                        bHandled;
125     beans::Optional< rtl::OUString >            m_aResult;
126 };
127 
128 } /* namespace */
129 
UUIInteractionHelper(uno::Reference<lang::XMultiServiceFactory> const & rServiceFactory,uno::Sequence<uno::Any> const & rArguments)130 UUIInteractionHelper::UUIInteractionHelper(
131     uno::Reference< lang::XMultiServiceFactory > const & rServiceFactory,
132     uno::Sequence< uno::Any > const & rArguments)
133     SAL_THROW(()):
134         m_xServiceFactory(rServiceFactory),
135         m_aProperties(rArguments)
136 {
137 }
138 
UUIInteractionHelper(uno::Reference<lang::XMultiServiceFactory> const & rServiceFactory)139 UUIInteractionHelper::UUIInteractionHelper(
140     uno::Reference< lang::XMultiServiceFactory > const & rServiceFactory)
141     SAL_THROW(()):
142         m_xServiceFactory(rServiceFactory)
143 {
144 }
145 
~UUIInteractionHelper()146 UUIInteractionHelper::~UUIInteractionHelper()
147 {
148 }
149 
150 long
handlerequest(void * pHandleData,void * pInteractionHelper)151 UUIInteractionHelper::handlerequest(
152     void* pHandleData, void* pInteractionHelper)
153 {
154     HandleData* pHND
155         = static_cast< HandleData * >(pHandleData);
156     UUIInteractionHelper* pUUI
157         = static_cast< UUIInteractionHelper * >(pInteractionHelper);
158     bool bDummy = false;
159     rtl::OUString aDummy;
160     pHND->bHandled
161         = pUUI->handleRequest_impl(pHND->m_rRequest, false, bDummy, aDummy);
162     pHND->set();
163     return 0;
164 }
165 
166 bool
handleRequest(uno::Reference<task::XInteractionRequest> const & rRequest)167 UUIInteractionHelper::handleRequest(
168     uno::Reference< task::XInteractionRequest > const & rRequest)
169 {
170     Application* pApp = 0;
171     if(
172         // be aware,it is the same type
173         static_cast< oslThreadIdentifier >(
174             Application::GetMainThreadIdentifier())
175         != osl_getThreadIdentifier(NULL)
176         &&
177         (pApp = GetpApp())
178         != 0
179     ) {
180         // we are not in the main thread, let it handle that stuff
181         HandleData aHD(rRequest);
182         Link aLink(&aHD,handlerequest);
183         pApp->PostUserEvent(aLink,this);
184         sal_uLong locks = Application::ReleaseSolarMutex();
185         aHD.wait();
186         Application::AcquireSolarMutex(locks);
187         return aHD.bHandled;
188     }
189     else
190     {
191         bool bDummy = false;
192         rtl::OUString aDummy;
193         return handleRequest_impl(rRequest, false, bDummy, aDummy);
194     }
195 }
196 
197 long
getstringfromrequest(void * pHandleData,void * pInteractionHelper)198 UUIInteractionHelper::getstringfromrequest(
199     void* pHandleData,void* pInteractionHelper)
200 {
201     HandleData* pHND = (HandleData*) pHandleData;
202     UUIInteractionHelper* pUUI = (UUIInteractionHelper*) pInteractionHelper;
203     pHND->m_aResult = pUUI->getStringFromRequest_impl(pHND->m_rRequest);
204     pHND->set();
205     return 0;
206 }
207 
208 beans::Optional< rtl::OUString >
getStringFromRequest_impl(uno::Reference<task::XInteractionRequest> const & rRequest)209 UUIInteractionHelper::getStringFromRequest_impl(
210     uno::Reference< task::XInteractionRequest > const & rRequest)
211 {
212     bool bSuccess = false;
213     rtl::OUString aMessage;
214     handleRequest_impl(rRequest, true, bSuccess, aMessage);
215 
216     OSL_ENSURE(bSuccess ||
217                !isInformationalErrorMessageRequest(
218                    rRequest->getContinuations()),
219                "Interaction request is a candidate for a string representation."
220                "Please implement!");
221 
222     return beans::Optional< rtl::OUString >(bSuccess, aMessage);
223 }
224 
225 beans::Optional< rtl::OUString >
getStringFromRequest(uno::Reference<task::XInteractionRequest> const & rRequest)226 UUIInteractionHelper::getStringFromRequest(
227     uno::Reference< task::XInteractionRequest > const & rRequest)
228 {
229     Application* pApp = 0;
230     if(
231         // be aware,it is the same type
232         static_cast< oslThreadIdentifier >(
233             Application::GetMainThreadIdentifier())
234         != osl_getThreadIdentifier(NULL)
235         &&
236         (pApp = GetpApp())
237         != 0
238     ) {
239         // we are not in the main thread, let it handle that stuff
240         HandleData aHD(rRequest);
241         Link aLink(&aHD,getstringfromrequest);
242         pApp->PostUserEvent(aLink,this);
243         sal_uLong locks = Application::ReleaseSolarMutex();
244         aHD.wait();
245         Application::AcquireSolarMutex(locks);
246         return aHD.m_aResult;
247     }
248     else
249         return getStringFromRequest_impl(rRequest);
250 }
251 
252 ::rtl::OUString
replaceMessageWithArguments(::rtl::OUString aMessage,std::vector<rtl::OUString> const & rArguments)253 UUIInteractionHelper::replaceMessageWithArguments(
254     ::rtl::OUString aMessage,
255     std::vector< rtl::OUString > const & rArguments )
256 {
257     for (sal_Int32 i = 0;;)
258     {
259         i = aMessage.
260         indexOf(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("$(ARG")), i);
261         if (i == -1)
262             break;
263         if (aMessage.getLength() - i >= RTL_CONSTASCII_LENGTH("$(ARGx)")
264             && aMessage.getStr()[i + RTL_CONSTASCII_LENGTH("$(ARGx")] == ')')
265         {
266             sal_Unicode c
267                 = aMessage.getStr()[i + RTL_CONSTASCII_LENGTH("$(ARG")];
268             if (c >= '1' && c <= '2')
269             {
270                 std::vector< rtl::OUString >::size_type nIndex
271                     = static_cast< std::vector< rtl::OUString >::size_type >(
272                         c - '1');
273                 if (nIndex < rArguments.size())
274                 {
275                     aMessage
276                         = aMessage.replaceAt(i,
277                                              RTL_CONSTASCII_LENGTH("$(ARGx)"),
278                                              rArguments[nIndex]);
279                     i += rArguments[nIndex].getLength();
280                     continue;
281                 }
282             }
283         }
284         ++i;
285     }
286 
287     return aMessage;
288 }
289 
290 bool
isInformationalErrorMessageRequest(uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)291 UUIInteractionHelper::isInformationalErrorMessageRequest(
292     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
293         rContinuations)
294 {
295     // Only requests with a single continuation (user has no choice, request
296     // is just informational)
297     if (rContinuations.getLength() != 1 )
298         return false;
299 
300     // user can only abort or approve, all other continuations are not
301     // considered to be informational.
302     uno::Reference< task::XInteractionApprove > xApprove(
303         rContinuations[0], uno::UNO_QUERY);
304     if (xApprove.is())
305         return true;
306 
307     uno::Reference< task::XInteractionAbort > xAbort(
308         rContinuations[0], uno::UNO_QUERY);
309     if (xAbort.is())
310         return true;
311 
312     return false;
313 }
314 
315 bool
tryOtherInteractionHandler(uno::Reference<task::XInteractionRequest> const & rRequest)316 UUIInteractionHelper::tryOtherInteractionHandler(
317     uno::Reference< task::XInteractionRequest > const & rRequest)
318 {
319     InteractionHandlerDataList dataList;
320     getInteractionHandlerList(dataList);
321 
322     InteractionHandlerDataList::const_iterator aEnd(dataList.end());
323     for (InteractionHandlerDataList::const_iterator aIt(dataList.begin());
324          aIt != aEnd;
325          ++aIt)
326     {
327         if ( handleCustomRequest( rRequest, aIt->ServiceName ) )
328             return true;
329     }
330     return false;
331 }
332 
333 namespace
334 {
335     // .................................................................................................................
lcl_matchesRequest(const Any & i_rRequest,const::rtl::OUString & i_rTypeName,const::rtl::OUString & i_rPropagation)336     static bool lcl_matchesRequest( const Any& i_rRequest, const ::rtl::OUString& i_rTypeName, const ::rtl::OUString& i_rPropagation )
337     {
338         const ::com::sun::star::uno::TypeDescription aTypeDesc( i_rTypeName );
339         const typelib_TypeDescription* pTypeDesc = aTypeDesc.get();
340         if ( !pTypeDesc || !pTypeDesc->pWeakRef )
341         {
342 #if OSL_DEBUG_LEVEL > 0
343             ::rtl::OStringBuffer aMessage;
344             aMessage.append( "no type found for '" );
345             aMessage.append( ::rtl::OUStringToOString( i_rTypeName, RTL_TEXTENCODING_UTF8 ) );
346             aMessage.append( "'" );
347             OSL_ENSURE( false, aMessage.makeStringAndClear().getStr() );
348 #endif
349             return false;
350         }
351         const ::com::sun::star::uno::Type aType( pTypeDesc->pWeakRef );
352 
353         const bool bExactMatch = ( i_rPropagation.compareToAscii( "named-only" ) == 0 );
354         if ( bExactMatch )
355             return i_rRequest.getValueType().equals( aType );
356 
357         return i_rRequest.isExtractableTo( aType );
358     }
359 }
360 
361 // ---------------------------------------------------------------------------------------------------------------------
handleCustomRequest(const Reference<XInteractionRequest> & i_rRequest,const::rtl::OUString & i_rServiceName) const362 bool UUIInteractionHelper::handleCustomRequest( const Reference< XInteractionRequest >& i_rRequest, const ::rtl::OUString& i_rServiceName ) const
363 {
364     try
365     {
366         Reference< XInteractionHandler2 > xHandler( m_xServiceFactory->createInstance( i_rServiceName ), UNO_QUERY_THROW );
367 
368         Reference< XInitialization > xHandlerInit( xHandler, UNO_QUERY );
369         if ( xHandlerInit.is() )
370         {
371             ::comphelper::NamedValueCollection aInitArgs;
372             aInitArgs.put( "Parent", getParentXWindow() );
373             xHandlerInit->initialize( aInitArgs.getWrappedPropertyValues() );
374         }
375 
376         if ( xHandler->handleInteractionRequest( i_rRequest ) )
377             return true;
378     }
379     catch( const Exception& )
380     {
381         DBG_UNHANDLED_EXCEPTION();
382     }
383     return false;
384 }
385 
386 // ---------------------------------------------------------------------------------------------------------------------
handleTypedHandlerImplementations(Reference<XInteractionRequest> const & rRequest)387 bool UUIInteractionHelper::handleTypedHandlerImplementations( Reference< XInteractionRequest > const & rRequest )
388 {
389     // the request
390     const Any aRequest( rRequest->getRequest() );
391 
392     const StringHashMap::const_iterator aCacheHitTest = m_aTypedCustomHandlers.find( aRequest.getValueTypeName() );
393     if ( aCacheHitTest != m_aTypedCustomHandlers.end() )
394         return handleCustomRequest( rRequest, aCacheHitTest->second );
395 
396     // the base registration node for "typed" interaction handlers
397     const ::utl::OConfigurationTreeRoot aConfigRoot( ::utl::OConfigurationTreeRoot::createWithServiceFactory(
398         m_xServiceFactory,
399         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Interaction/InteractionHandlers" ) ),
400         -1,
401         ::utl::OConfigurationTreeRoot::CM_READONLY
402     ) );
403 
404     // loop through all registered implementations
405     const Sequence< ::rtl::OUString > aRegisteredHandlers( aConfigRoot.getNodeNames() );
406     const ::rtl::OUString* pHandlerName = aRegisteredHandlers.getConstArray();
407     const ::rtl::OUString* pHandlersEnd = aRegisteredHandlers.getConstArray() + aRegisteredHandlers.getLength();
408     for ( ; pHandlerName != pHandlersEnd; ++pHandlerName )
409     {
410         const ::utl::OConfigurationNode aHandlerNode( aConfigRoot.openNode( *pHandlerName ) );
411         const ::utl::OConfigurationNode aTypesNode( aHandlerNode.openNode( "HandledRequestTypes" ) );
412 
413         // loop through all the types which the current handler is registered for
414         const Sequence< ::rtl::OUString > aHandledTypes( aTypesNode.getNodeNames() );
415         const ::rtl::OUString* pType = aHandledTypes.getConstArray();
416         const ::rtl::OUString* pTypesEnd = aHandledTypes.getConstArray() + aHandledTypes.getLength();
417         for ( ; pType != pTypesEnd; ++pType )
418         {
419             // the UNO type is the node name
420             ::utl::OConfigurationNode aType( aTypesNode.openNode( *pType ) );
421             // and there's a child denoting how the responsibility propagates
422             ::rtl::OUString sPropagation;
423             OSL_VERIFY( aType.getNodeValue( "Propagation" ) >>= sPropagation );
424             if ( lcl_matchesRequest( aRequest, *pType, sPropagation ) )
425             {
426                 // retrieve the service/implementation name of the handler
427                 ::rtl::OUString sServiceName;
428                 OSL_VERIFY( aHandlerNode.getNodeValue( "ServiceName" ) >>= sServiceName );
429                 // cache the information who feels responsible for requests of this type
430                 m_aTypedCustomHandlers[ aRequest.getValueTypeName() ] = sServiceName;
431                 // actually handle the request
432                 return handleCustomRequest( rRequest, sServiceName );
433             }
434         }
435     }
436 
437     return false;
438 }
439 
440 bool
handleRequest_impl(uno::Reference<task::XInteractionRequest> const & rRequest,bool bObtainErrorStringOnly,bool & bHasErrorString,rtl::OUString & rErrorString)441 UUIInteractionHelper::handleRequest_impl(
442     uno::Reference< task::XInteractionRequest > const & rRequest,
443     bool bObtainErrorStringOnly,
444     bool & bHasErrorString,
445     rtl::OUString & rErrorString)
446 {
447     try
448     {
449         if (!rRequest.is())
450             return false;
451 
452         uno::Any aAnyRequest(rRequest->getRequest());
453 
454         script::ModuleSizeExceededRequest aModSizeException;
455         if (aAnyRequest >>= aModSizeException )
456         {
457             ErrCode nErrorCode = ERRCODE_UUI_IO_MODULESIZEEXCEEDED;
458             std::vector< rtl::OUString > aArguments;
459             uno::Sequence< rtl::OUString > sModules
460                 = aModSizeException.Names;
461             if ( sModules.getLength() )
462             {
463                 rtl::OUString aName;
464                 for ( sal_Int32 index=0; index< sModules.getLength(); ++index )
465                 {
466                     if ( index )
467                         aName = aName + rtl::OUString( ',' ) + sModules[index];
468                     else
469                         aName = sModules[index]; // 1st name
470                 }
471                 aArguments.push_back( aName );
472             }
473             handleErrorHandlerRequest( task::InteractionClassification_WARNING,
474                                        nErrorCode,
475                                        aArguments,
476                                        rRequest->getContinuations(),
477                                        bObtainErrorStringOnly,
478                                        bHasErrorString,
479                                        rErrorString);
480             return true;
481         }
482 
483         ucb::NameClashException aNCException;
484         if (aAnyRequest >>= aNCException)
485         {
486             ErrCode nErrorCode = ERRCODE_UUI_IO_TARGETALREADYEXISTS;
487             std::vector< rtl::OUString > aArguments;
488 
489             if( aNCException.Name.getLength() )
490             {
491                 nErrorCode = ERRCODE_UUI_IO_ALREADYEXISTS;
492                 aArguments.push_back( aNCException.Name );
493             }
494 
495             handleErrorHandlerRequest( aNCException.Classification,
496                                        nErrorCode,
497                                        aArguments,
498                                        rRequest->getContinuations(),
499                                        bObtainErrorStringOnly,
500                                        bHasErrorString,
501                                        rErrorString);
502             return true;
503         }
504 
505         ucb::UnsupportedNameClashException aUORequest;
506         if (aAnyRequest >>= aUORequest)
507         {
508             ErrCode nErrorCode = ERRCODE_UUI_IO_UNSUPPORTEDOVERWRITE;
509             std::vector< rtl::OUString > aArguments;
510 
511             uno::Reference< task::XInteractionApprove > xApprove;
512             uno::Reference< task::XInteractionDisapprove > xDisapprove;
513             getContinuations(
514                 rRequest->getContinuations(), &xApprove, &xDisapprove);
515 
516             if ( xApprove.is() && xDisapprove.is() )
517             {
518                 handleErrorHandlerRequest( task::InteractionClassification_QUERY,
519                                            nErrorCode,
520                                            aArguments,
521                                            rRequest->getContinuations(),
522                                            bObtainErrorStringOnly,
523                                            bHasErrorString,
524                                            rErrorString);
525             }
526             return true;
527         }
528 
529         if ( handleInteractiveIOException( rRequest,
530                                            bObtainErrorStringOnly,
531                                            bHasErrorString,
532                                            rErrorString ) )
533             return true;
534 
535         ucb::InteractiveAppException aAppException;
536         if (aAnyRequest >>= aAppException)
537         {
538             std::vector< rtl::OUString > aArguments;
539             handleErrorHandlerRequest( aAppException.Classification,
540                                        aAppException.Code,
541                                        aArguments,
542                                        rRequest->getContinuations(),
543                                        bObtainErrorStringOnly,
544                                        bHasErrorString,
545                                        rErrorString);
546             return true;
547         }
548 
549         ucb::InteractiveNetworkException aNetworkException;
550         if (aAnyRequest >>= aNetworkException)
551         {
552             ErrCode nErrorCode;
553             std::vector< rtl::OUString > aArguments;
554             ucb::InteractiveNetworkOffLineException aOffLineException;
555             ucb::InteractiveNetworkResolveNameException aResolveNameException;
556             ucb::InteractiveNetworkConnectException aConnectException;
557             ucb::InteractiveNetworkReadException aReadException;
558             ucb::InteractiveNetworkWriteException aWriteException;
559             if (aAnyRequest >>= aOffLineException)
560                 nErrorCode = ERRCODE_INET_OFFLINE;
561             else if (aAnyRequest >>= aResolveNameException)
562             {
563                 nErrorCode = ERRCODE_INET_NAME_RESOLVE;
564                 aArguments.push_back(aResolveNameException.Server);
565             }
566             else if (aAnyRequest >>= aConnectException)
567             {
568                 nErrorCode = ERRCODE_INET_CONNECT;
569                 aArguments.push_back(aConnectException.Server);
570             }
571             else if (aAnyRequest >>= aReadException)
572             {
573                 nErrorCode = ERRCODE_INET_READ;
574                 aArguments.push_back(aReadException.Diagnostic);
575             }
576             else if (aAnyRequest >>= aWriteException)
577             {
578                 nErrorCode = ERRCODE_INET_WRITE;
579                 aArguments.push_back(aWriteException.Diagnostic);
580             }
581             else
582                 nErrorCode = ERRCODE_INET_GENERAL;
583 
584             handleErrorHandlerRequest(aNetworkException.Classification,
585                                       nErrorCode,
586                                       aArguments,
587                                       rRequest->getContinuations(),
588                                       bObtainErrorStringOnly,
589                                       bHasErrorString,
590                                       rErrorString);
591             return true;
592         }
593 
594         ucb::InteractiveCHAOSException aChaosException;
595         if (aAnyRequest >>= aChaosException)
596         {
597             std::vector< rtl::OUString > aArguments;
598             sal_Int32 nCount
599                 = std::min< sal_Int32 >(aChaosException.Arguments.getLength(),
600                                         2);
601             aArguments.
602                 reserve(static_cast< std::vector< rtl::OUString >::size_type >(
603                     nCount));
604             for (sal_Int32 i = 0; i < nCount; ++i)
605                 aArguments.push_back(aChaosException.Arguments[i]);
606             handleErrorHandlerRequest(aChaosException.Classification,
607                                       aChaosException.ID,
608                                       aArguments,
609                                       rRequest->getContinuations(),
610                                       bObtainErrorStringOnly,
611                                       bHasErrorString,
612                                       rErrorString);
613             return true;
614         }
615 
616         ucb::InteractiveWrongMediumException aWrongMediumException;
617         if (aAnyRequest >>= aWrongMediumException)
618         {
619             sal_Int32 nMedium = 0;
620             aWrongMediumException.Medium >>= nMedium;
621             std::vector< rtl::OUString > aArguments;
622             aArguments.push_back(UniString::CreateFromInt32(nMedium + 1));
623             handleErrorHandlerRequest(aWrongMediumException.Classification,
624                                       ERRCODE_UUI_WRONGMEDIUM,
625                                       aArguments,
626                                       rRequest->getContinuations(),
627                                       bObtainErrorStringOnly,
628                                       bHasErrorString,
629                                       rErrorString);
630             return true;
631         }
632 
633         java::WrongJavaVersionException aWrongJavaVersionException;
634         if (aAnyRequest >>= aWrongJavaVersionException)
635         {
636             ErrCode nErrorCode;
637             std::vector< rtl::OUString > aArguments;
638             if (aWrongJavaVersionException.DetectedVersion.getLength() == 0)
639                 if (aWrongJavaVersionException.LowestSupportedVersion.
640                     getLength()
641                     == 0)
642                     nErrorCode = ERRCODE_UUI_WRONGJAVA;
643                 else
644                 {
645                     nErrorCode = ERRCODE_UUI_WRONGJAVA_MIN;
646                     aArguments.push_back(aWrongJavaVersionException.
647                                          LowestSupportedVersion);
648                 }
649             else if (aWrongJavaVersionException.LowestSupportedVersion.
650                      getLength()
651                      == 0)
652             {
653                 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION;
654                 aArguments.push_back(aWrongJavaVersionException.
655                                      DetectedVersion);
656             }
657             else
658             {
659                 nErrorCode = ERRCODE_UUI_WRONGJAVA_VERSION_MIN;
660                 aArguments.reserve(2);
661                 aArguments.push_back(aWrongJavaVersionException.
662                                      DetectedVersion);
663                 aArguments.push_back(aWrongJavaVersionException.
664                                      LowestSupportedVersion);
665             }
666             handleErrorHandlerRequest(task::InteractionClassification_ERROR,
667                                       nErrorCode,
668                                       aArguments,
669                                       rRequest->getContinuations(),
670                                       bObtainErrorStringOnly,
671                                       bHasErrorString,
672                                       rErrorString);
673             return true;
674         }
675 
676         sync2::BadPartnershipException aBadPartnershipException;
677         if (aAnyRequest >>= aBadPartnershipException)
678         {
679             ErrCode nErrorCode;
680             std::vector< rtl::OUString > aArguments;
681             if (aBadPartnershipException.Partnership.getLength() == 0)
682                 nErrorCode = ERRCODE_UUI_BADPARTNERSHIP;
683             else
684             {
685                 nErrorCode = ERRCODE_UUI_BADPARTNERSHIP_NAME;
686                 aArguments.push_back(aBadPartnershipException.Partnership);
687             }
688             handleErrorHandlerRequest(task::InteractionClassification_ERROR,
689                                       nErrorCode,
690                                       aArguments,
691                                       rRequest->getContinuations(),
692                                       bObtainErrorStringOnly,
693                                       bHasErrorString,
694                                       rErrorString);
695             return true;
696         }
697 
698         configuration::backend::MergeRecoveryRequest aMergeRecoveryRequest;
699         if (aAnyRequest >>= aMergeRecoveryRequest)
700         {
701             ErrCode nErrorCode = aMergeRecoveryRequest.IsRemovalRequest
702                 ? ERRCODE_UUI_CONFIGURATION_BROKENDATA_WITHREMOVE
703                 : ERRCODE_UUI_CONFIGURATION_BROKENDATA_NOREMOVE;
704 
705             std::vector< rtl::OUString > aArguments;
706             aArguments.push_back(aMergeRecoveryRequest.ErrorLayerId);
707 
708             handleErrorHandlerRequest(task::InteractionClassification_ERROR,
709                                       nErrorCode,
710                                       aArguments,
711                                       rRequest->getContinuations(),
712                                       bObtainErrorStringOnly,
713                                       bHasErrorString,
714                                       rErrorString);
715             return true;
716         }
717 
718         configuration::backend::StratumCreationException
719             aStratumCreationException;
720 
721         if (aAnyRequest >>= aStratumCreationException)
722         {
723             const ErrCode nErrorCode = ERRCODE_UUI_CONFIGURATION_BACKENDMISSING;
724 
725             rtl::OUString aStratum = aStratumCreationException.StratumData;
726             if (aStratum.getLength() == 0)
727                 aStratum = aStratumCreationException.StratumService;
728 
729             std::vector< rtl::OUString > aArguments;
730             aArguments.push_back(aStratum);
731 
732             handleErrorHandlerRequest(task::InteractionClassification_ERROR,
733                                       nErrorCode,
734                                       aArguments,
735                                       rRequest->getContinuations(),
736                                       bObtainErrorStringOnly,
737                                       bHasErrorString,
738                                       rErrorString);
739             return true;
740         }
741 
742         xforms::InvalidDataOnSubmitException aInvalidDataOnSubmitException;
743         if (aAnyRequest >>= aInvalidDataOnSubmitException)
744         {
745             const ErrCode nErrorCode =
746                 ERRCODE_UUI_INVALID_XFORMS_SUBMISSION_DATA;
747 
748             std::vector< rtl::OUString > aArguments;
749 
750             handleErrorHandlerRequest(task::InteractionClassification_QUERY,
751                                       nErrorCode,
752                                       aArguments,
753                                       rRequest->getContinuations(),
754                                       bObtainErrorStringOnly,
755                                       bHasErrorString,
756                                       rErrorString);
757             return true;
758         }
759 
760         ucb::InteractiveLockingLockedException aLLException;
761         if (aAnyRequest >>= aLLException)
762         {
763             ErrCode nErrorCode = aLLException.SelfOwned
764                 ? ERRCODE_UUI_LOCKING_LOCKED_SELF : ERRCODE_UUI_LOCKING_LOCKED;
765             std::vector< rtl::OUString > aArguments;
766             aArguments.push_back( aLLException.Url );
767 
768             handleErrorHandlerRequest( aLLException.Classification,
769                                        nErrorCode,
770                                        aArguments,
771                                        rRequest->getContinuations(),
772                                        bObtainErrorStringOnly,
773                                        bHasErrorString,
774                                        rErrorString );
775             return true;
776         }
777 
778         ucb::InteractiveLockingNotLockedException aLNLException;
779         if (aAnyRequest >>= aLNLException)
780         {
781             ErrCode nErrorCode = ERRCODE_UUI_LOCKING_NOT_LOCKED;
782             std::vector< rtl::OUString > aArguments;
783             aArguments.push_back( aLNLException.Url );
784 
785             handleErrorHandlerRequest( aLNLException.Classification,
786                                        nErrorCode,
787                                        aArguments,
788                                        rRequest->getContinuations(),
789                                        bObtainErrorStringOnly,
790                                        bHasErrorString,
791                                        rErrorString );
792             return true;
793         }
794 
795         ucb::InteractiveLockingLockExpiredException aLLEException;
796         if (aAnyRequest >>= aLLEException)
797         {
798             ErrCode nErrorCode = ERRCODE_UUI_LOCKING_LOCK_EXPIRED;
799             std::vector< rtl::OUString > aArguments;
800             aArguments.push_back( aLLEException.Url );
801 
802             handleErrorHandlerRequest( aLLEException.Classification,
803                                        nErrorCode,
804                                        aArguments,
805                                        rRequest->getContinuations(),
806                                        bObtainErrorStringOnly,
807                                        bHasErrorString,
808                                        rErrorString );
809             return true;
810         }
811 
812         document::BrokenPackageRequest aBrokenPackageRequest;
813         if (aAnyRequest >>= aBrokenPackageRequest)
814         {
815             std::vector< rtl::OUString > aArguments;
816 
817             if( aBrokenPackageRequest.aName.getLength() )
818                 aArguments.push_back( aBrokenPackageRequest.aName );
819 
820             handleBrokenPackageRequest( aArguments,
821                                         rRequest->getContinuations(),
822                                         bObtainErrorStringOnly,
823                                         bHasErrorString,
824                                         rErrorString );
825             return true;
826         }
827 
828         task::ErrorCodeRequest aErrorCodeRequest;
829         if (aAnyRequest >>= aErrorCodeRequest)
830         {
831             handleGenericErrorRequest( aErrorCodeRequest.ErrCode,
832                                        rRequest->getContinuations(),
833                                        bObtainErrorStringOnly,
834                                        bHasErrorString,
835                                        rErrorString);
836             return true;
837         }
838 
839         task::ErrorCodeIOException aErrorCodeIOException;
840         if (aAnyRequest >>= aErrorCodeIOException)
841         {
842             handleGenericErrorRequest( aErrorCodeIOException.ErrCode,
843                                        rRequest->getContinuations(),
844                                        bObtainErrorStringOnly,
845                                        bHasErrorString,
846                                        rErrorString);
847             return true;
848         }
849 
850 
851         ///////////////////////////////////////////////////////////////////
852         // Handle requests which do not have a plain string representation.
853         ///////////////////////////////////////////////////////////////////
854         if (!bObtainErrorStringOnly)
855         {
856             if ( handleAuthenticationRequest( rRequest ) )
857                 return true;
858 
859             if ( handleCertificateValidationRequest( rRequest ) )
860                 return true;
861 
862             ucb::NameClashResolveRequest aNameClashResolveRequest;
863             if (aAnyRequest >>= aNameClashResolveRequest)
864             {
865                 handleNameClashResolveRequest(aNameClashResolveRequest,
866                                               rRequest->getContinuations());
867                 return true;
868             }
869 
870             if ( handleMasterPasswordRequest( rRequest ) )
871                 return true;
872 
873             if ( handlePasswordRequest( rRequest ) )
874                 return true;
875 
876             if ( handleCookiesRequest( rRequest ) )
877                 return true;
878 
879             if ( handleNoSuchFilterRequest( rRequest ) )
880                 return true;
881 
882             if ( handleAmbigousFilterRequest( rRequest ) )
883                 return true;
884 
885             if ( handleFilterOptionsRequest( rRequest ) )
886                 return true;
887 
888             if ( handleLockedDocumentRequest( rRequest ) )
889                 return true;
890 
891             if ( handleChangedByOthersRequest( rRequest ) )
892                 return true;
893 
894             if ( handleLockFileIgnoreRequest( rRequest ) )
895                 return true;
896 
897             task::DocumentMacroConfirmationRequest aMacroConfirmRequest;
898             if (aAnyRequest >>= aMacroConfirmRequest)
899             {
900                 handleMacroConfirmRequest(
901                     aMacroConfirmRequest.DocumentURL,
902                     aMacroConfirmRequest.DocumentStorage,
903                     aMacroConfirmRequest.DocumentVersion.getLength() ? aMacroConfirmRequest.DocumentVersion : ODFVER_012_TEXT,
904                     aMacroConfirmRequest.DocumentSignatureInformation,
905                     rRequest->getContinuations());
906                 return true;
907             }
908 
909             task::FutureDocumentVersionProductUpdateRequest
910                 aProductUpdateRequest;
911             if (aAnyRequest >>= aProductUpdateRequest)
912             {
913                 handleFutureDocumentVersionUpdateRequest(
914                     aProductUpdateRequest,
915                     rRequest->getContinuations());
916                 return true;
917             }
918 
919             ///////////////////////////////////////////////////////////////
920             // Last chance: interaction handlers registered in the configuration
921             ///////////////////////////////////////////////////////////////
922 
923             // typed InteractionHandlers (ooo.Interactions)
924             if ( handleTypedHandlerImplementations( rRequest ) )
925                 return true;
926 
927             // legacy configuration (ooo.ucb.InteractionHandlers)
928             if (tryOtherInteractionHandler( rRequest ))
929                 return true;
930         }
931 
932         // Not handled.
933         return false;
934     }
935     catch (std::bad_alloc const &)
936     {
937         throw uno::RuntimeException(
938             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")),
939             uno::Reference< uno::XInterface >());
940     }
941     catch( const uno::RuntimeException& )
942     {
943         throw;  // allowed to leave here
944     }
945     catch( const uno::Exception& )
946     {
947         DBG_UNHANDLED_EXCEPTION();
948     }
949     return false;
950 }
951 
952 void
getInteractionHandlerList(InteractionHandlerDataList & rdataList)953 UUIInteractionHelper::getInteractionHandlerList(
954     InteractionHandlerDataList &rdataList)
955 {
956     try
957     {
958         uno::Reference< lang::XMultiServiceFactory > xConfigProv(
959             m_xServiceFactory->createInstance(
960                 rtl::OUString::createFromAscii(
961                     "com.sun.star.configuration.ConfigurationProvider" ) ),
962             uno::UNO_QUERY );
963 
964         if ( !xConfigProv.is() )
965             throw uno::RuntimeException(
966                 rtl::OUString(
967                     RTL_CONSTASCII_USTRINGPARAM(
968                         "unable to instantiate config provider service")),
969                 uno::Reference< uno::XInterface >());
970 
971         rtl::OUStringBuffer aFullPath;
972         aFullPath.appendAscii(
973             "/org.openoffice.ucb.InteractionHandler/InteractionHandlers" );
974 
975         uno::Sequence< uno::Any > aArguments( 1 );
976         beans::PropertyValue      aProperty;
977         aProperty.Name
978             = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) );
979         aProperty.Value <<= aFullPath.makeStringAndClear();
980         aArguments[ 0 ] <<= aProperty;
981 
982         uno::Reference< uno::XInterface > xInterface(
983                 xConfigProv->createInstanceWithArguments(
984                     rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
985                         "com.sun.star.configuration.ConfigurationAccess" ) ),
986                     aArguments ) );
987 
988         if ( !xInterface.is() )
989             throw uno::RuntimeException(
990                 rtl::OUString(
991                     RTL_CONSTASCII_USTRINGPARAM(
992                         "unable to instantiate config access")),
993                 uno::Reference< uno::XInterface >());
994 
995         uno::Reference< container::XNameAccess > xNameAccess(
996             xInterface, uno::UNO_QUERY );
997         if ( !xNameAccess.is() )
998             throw uno::RuntimeException(
999                 rtl::OUString(
1000                     RTL_CONSTASCII_USTRINGPARAM(
1001                         "config access does not implement XNameAccess")),
1002                 uno::Reference< uno::XInterface >());
1003 
1004         uno::Sequence< rtl::OUString > aElems = xNameAccess->getElementNames();
1005         const rtl::OUString* pElems = aElems.getConstArray();
1006         sal_Int32 nCount = aElems.getLength();
1007 
1008         if ( nCount > 0 )
1009         {
1010             uno::Reference< container::XHierarchicalNameAccess >
1011                                 xHierNameAccess( xInterface, uno::UNO_QUERY );
1012 
1013             if ( !xHierNameAccess.is() )
1014             throw uno::RuntimeException(
1015                 rtl::OUString(
1016                     RTL_CONSTASCII_USTRINGPARAM(
1017                         "config access does not implement XHierarchicalNameAccess")),
1018                 uno::Reference< uno::XInterface >());
1019 
1020             // Iterate over children.
1021             for ( sal_Int32 n = 0; n < nCount; ++n )
1022             {
1023                 rtl::OUStringBuffer aElemBuffer;
1024                 aElemBuffer.appendAscii( "['" );
1025                 aElemBuffer.append( pElems[ n ] );
1026 
1027                 try
1028                 {
1029                     InteractionHandlerData aInfo;
1030 
1031                     // Obtain service name.
1032                     rtl::OUStringBuffer aKeyBuffer = aElemBuffer;
1033                     aKeyBuffer.appendAscii( "']/ServiceName" );
1034 
1035                     rtl::OUString aValue;
1036                     if ( !( xHierNameAccess->getByHierarchicalName(
1037                                 aKeyBuffer.makeStringAndClear() ) >>= aValue ) )
1038                     {
1039                         OSL_ENSURE( false,
1040                                     "GetInteractionHandlerList - "
1041                                     "Error getting item value!" );
1042                         continue;
1043                     }
1044 
1045                     aInfo.ServiceName = aValue;
1046 
1047                     // Append info to list.
1048                     rdataList.push_back( aInfo );
1049                 }
1050                 catch ( container::NoSuchElementException& )
1051                 {
1052                     // getByHierarchicalName
1053 
1054                     OSL_ENSURE( false,
1055                                 "GetInteractionHandlerList - "
1056                                 "caught NoSuchElementException!" );
1057                 }
1058             }
1059         }
1060     }
1061     catch ( uno::RuntimeException const & )
1062     {
1063         throw;
1064     }
1065     catch ( uno::Exception const & )
1066     {
1067         OSL_ENSURE( false, "GetInteractionHandlerList - Caught Exception!" );
1068     }
1069 }
1070 
1071 Window *
getParentProperty()1072 UUIInteractionHelper::getParentProperty()
1073     SAL_THROW(())
1074 {
1075     uno::Reference< awt::XWindow > xWindow = getParentXWindow();
1076     if ( xWindow.is() )
1077         return VCLUnoHelper::GetWindow(xWindow);
1078 
1079     return 0;
1080 }
1081 
1082 uno::Reference< awt::XWindow>
getParentXWindow() const1083 UUIInteractionHelper::getParentXWindow() const
1084     SAL_THROW(())
1085 {
1086     osl::MutexGuard aGuard(m_aPropertyMutex);
1087     ::comphelper::NamedValueCollection aProperties( m_aProperties );
1088     if ( aProperties.has( "Parent" ) )
1089     {
1090         uno::Reference< awt::XWindow > xWindow;
1091         OSL_VERIFY( aProperties.get( "Parent" ) >>= xWindow );
1092         return xWindow;
1093     }
1094     return 0;
1095 }
1096 
1097 rtl::OUString
getContextProperty()1098 UUIInteractionHelper::getContextProperty()
1099     SAL_THROW(())
1100 {
1101     osl::MutexGuard aGuard(m_aPropertyMutex);
1102     for (sal_Int32 i = 0; i < m_aProperties.getLength(); ++i)
1103     {
1104         beans::PropertyValue aProperty;
1105         if ((m_aProperties[i] >>= aProperty)
1106             && aProperty.
1107                    Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Context")))
1108         {
1109             rtl::OUString aContext;
1110             aProperty.Value >>= aContext;
1111             return aContext;
1112         }
1113     }
1114     return rtl::OUString();
1115 }
1116 
1117 uno::Reference< task::XInteractionHandler >
getInteractionHandler()1118 UUIInteractionHelper::getInteractionHandler()
1119 {
1120     uno::Reference< task::XInteractionHandler > xIH;
1121     try
1122     {
1123         xIH.set(m_xServiceFactory->createInstanceWithArguments(
1124                     rtl::OUString(
1125                         RTL_CONSTASCII_USTRINGPARAM(
1126                             "com.sun.star.task.InteractionHandler")),
1127                     m_aProperties),
1128                 uno::UNO_QUERY);
1129     }
1130     catch (uno::Exception const &)
1131     {}
1132 
1133     if (!xIH.is())
1134         throw uno::RuntimeException(
1135             rtl::OUString(
1136                 RTL_CONSTASCII_USTRINGPARAM(
1137                     "unable to instantiate Interaction Handler service")),
1138             uno::Reference< uno::XInterface >());
1139     return xIH;
1140 }
1141 
1142 namespace {
1143 
1144 sal_uInt16
executeMessageBox(Window * pParent,rtl::OUString const & rTitle,rtl::OUString const & rMessage,WinBits nButtonMask)1145 executeMessageBox(
1146     Window * pParent,
1147     rtl::OUString const & rTitle,
1148     rtl::OUString const & rMessage,
1149     WinBits nButtonMask )
1150 {
1151     vos::OGuard aGuard(Application::GetSolarMutex());
1152 
1153     MessBox xBox( pParent, nButtonMask, rTitle, rMessage );
1154 
1155     sal_uInt16 aResult = xBox.Execute();
1156     switch( aResult )
1157     {
1158     case BUTTONID_OK:
1159         aResult = ERRCODE_BUTTON_OK;
1160         break;
1161     case BUTTONID_CANCEL:
1162         aResult = ERRCODE_BUTTON_CANCEL;
1163         break;
1164     case BUTTONID_YES:
1165         aResult = ERRCODE_BUTTON_YES;
1166         break;
1167     case BUTTONID_NO:
1168         aResult = ERRCODE_BUTTON_NO;
1169         break;
1170     case BUTTONID_RETRY:
1171         aResult = ERRCODE_BUTTON_RETRY;
1172         break;
1173     }
1174 
1175     return aResult;
1176 }
1177 
executeSimpleNameClashResolveDialog(Window * pParent,rtl::OUString const & rTargetFolderURL,rtl::OUString const & rClashingName,rtl::OUString & rProposedNewName,bool bAllowOverwrite)1178 NameClashResolveDialogResult executeSimpleNameClashResolveDialog( Window *pParent,
1179                                                                   rtl::OUString const & rTargetFolderURL,
1180                                                                   rtl::OUString const & rClashingName,
1181                                                                   rtl::OUString & rProposedNewName,
1182                                                                   bool bAllowOverwrite )
1183 {
1184     std::auto_ptr< ResMgr > xManager( ResMgr::CreateResMgr( CREATEVERSIONRESMGR_NAME( uui ) ) );
1185     if ( !xManager.get() )
1186         return ABORT;
1187 
1188     NameClashDialog aDialog( pParent, xManager.get(), rTargetFolderURL,
1189                              rClashingName, rProposedNewName, bAllowOverwrite );
1190 
1191     NameClashResolveDialogResult eResult = (NameClashResolveDialogResult) aDialog.Execute();
1192     rProposedNewName = aDialog.getNewName();
1193     return eResult;
1194 }
1195 
1196 } // namespace
1197 
1198 void
handleNameClashResolveRequest(ucb::NameClashResolveRequest const & rRequest,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)1199 UUIInteractionHelper::handleNameClashResolveRequest(
1200     ucb::NameClashResolveRequest const & rRequest,
1201     uno::Sequence< uno::Reference<
1202         task::XInteractionContinuation > > const & rContinuations)
1203 {
1204     OSL_ENSURE(
1205         rRequest.TargetFolderURL.getLength() > 0,
1206         "NameClashResolveRequest must not contain empty TargetFolderURL" );
1207 
1208     OSL_ENSURE(
1209         rRequest.ClashingName.getLength() > 0,
1210         "NameClashResolveRequest must not contain empty ClashingName" );
1211 
1212     uno::Reference< task::XInteractionAbort > xAbort;
1213     uno::Reference< ucb::XInteractionSupplyName > xSupplyName;
1214     uno::Reference< ucb::XInteractionReplaceExistingData > xReplaceExistingData;
1215     getContinuations(
1216         rContinuations, &xAbort, &xSupplyName, &xReplaceExistingData);
1217 
1218     OSL_ENSURE( xAbort.is(),
1219         "NameClashResolveRequest must contain Abort continuation" );
1220 
1221     OSL_ENSURE( xSupplyName.is(),
1222         "NameClashResolveRequest must contain SupplyName continuation" );
1223 
1224     NameClashResolveDialogResult eResult = ABORT;
1225     rtl::OUString aProposedNewName( rRequest.ProposedNewName );
1226 
1227     eResult = executeSimpleNameClashResolveDialog( getParentProperty(),
1228                     rRequest.TargetFolderURL,
1229                     rRequest.ClashingName,
1230                     aProposedNewName,
1231                     xReplaceExistingData.is() );
1232 
1233     switch ( eResult )
1234     {
1235     case ABORT:
1236         xAbort->select();
1237         break;
1238 
1239     case RENAME:
1240         xSupplyName->setName( aProposedNewName );
1241         xSupplyName->select();
1242         break;
1243 
1244     case OVERWRITE:
1245         OSL_ENSURE(
1246             xReplaceExistingData.is(),
1247             "Invalid NameClashResolveDialogResult: OVERWRITE - "
1248             "No ReplaceExistingData continuation available!" );
1249         xReplaceExistingData->select();
1250         break;
1251     }
1252 }
1253 
1254 void
handleGenericErrorRequest(sal_Int32 nErrorCode,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations,bool bObtainErrorStringOnly,bool & bHasErrorString,rtl::OUString & rErrorString)1255 UUIInteractionHelper::handleGenericErrorRequest(
1256     sal_Int32 nErrorCode,
1257     uno::Sequence< uno::Reference<
1258         task::XInteractionContinuation > > const & rContinuations,
1259     bool bObtainErrorStringOnly,
1260     bool & bHasErrorString,
1261     rtl::OUString & rErrorString)
1262 {
1263     if (bObtainErrorStringOnly)
1264     {
1265         bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1266         if (bHasErrorString)
1267         {
1268             String aErrorString;
1269             ErrorHandler::GetErrorString(nErrorCode, aErrorString);
1270             rErrorString = aErrorString;
1271         }
1272     }
1273     else
1274     {
1275         uno::Reference< task::XInteractionAbort > xAbort;
1276         uno::Reference< task::XInteractionApprove > xApprove;
1277         getContinuations(rContinuations, &xApprove, &xAbort);
1278 
1279         // Note: It's important to convert the transported long to the
1280         // required unsigned long value. Otherwise using as flag field
1281         // can fail ...
1282         ErrCode  nError   = static_cast< ErrCode >(nErrorCode);
1283         sal_Bool bWarning = !ERRCODE_TOERROR(nError);
1284 
1285         if ( nError == ERRCODE_SFX_BROKENSIGNATURE
1286              || nError == ERRCODE_SFX_INCOMPLETE_ENCRYPTION )
1287         {
1288             // the security warning box needs a special title
1289             String aErrorString;
1290             ErrorHandler::GetErrorString( nErrorCode, aErrorString );
1291 
1292             std::auto_ptr< ResMgr > xManager(
1293                 ResMgr::CreateResMgr( CREATEVERSIONRESMGR_NAME( uui ) ) );
1294             ::rtl::OUString aTitle;
1295 
1296             try
1297             {
1298                 uno::Any aProductNameAny =
1299                     ::utl::ConfigManager::GetConfigManager()
1300                         ->GetDirectConfigProperty(
1301                            ::utl::ConfigManager::PRODUCTNAME );
1302                 aProductNameAny >>= aTitle;
1303             }
1304             catch( uno::Exception& )
1305             {
1306             }
1307 
1308             ::rtl::OUString aErrTitle
1309                   = String( ResId( nError == ERRCODE_SFX_BROKENSIGNATURE
1310                                        ? STR_WARNING_BROKENSIGNATURE_TITLE
1311                                        : STR_WARNING_INCOMPLETE_ENCRYPTION_TITLE,
1312                                    *xManager.get() ) );
1313 
1314             if ( aTitle.getLength() && aErrTitle.getLength() )
1315                 aTitle += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " - " ) );
1316             aTitle += aErrTitle;
1317 
1318             executeMessageBox(
1319                 getParentProperty(), aTitle, aErrorString, WB_OK );
1320         }
1321         else
1322             ErrorHandler::HandleError(nErrorCode);
1323 
1324         if (xApprove.is() && bWarning)
1325             xApprove->select();
1326         else if (xAbort.is())
1327             xAbort->select();
1328     }
1329 }
1330 
1331 void
handleMacroConfirmRequest(const::rtl::OUString & aDocumentURL,const uno::Reference<embed::XStorage> & xZipStorage,const::rtl::OUString & aDocumentVersion,const uno::Sequence<security::DocumentSignatureInformation> aSignInfo,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)1332 UUIInteractionHelper::handleMacroConfirmRequest(
1333     const ::rtl::OUString& aDocumentURL,
1334     const uno::Reference< embed::XStorage >& xZipStorage,
1335     const ::rtl::OUString& aDocumentVersion,
1336     const uno::Sequence< security::DocumentSignatureInformation > aSignInfo,
1337     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1338         rContinuations )
1339 {
1340     uno::Reference< task::XInteractionAbort > xAbort;
1341     uno::Reference< task::XInteractionApprove > xApprove;
1342     getContinuations( rContinuations, &xApprove, &xAbort );
1343 
1344     bool bApprove = false;
1345 
1346     std::auto_ptr< ResMgr > pResMgr(
1347         ResMgr::CreateResMgr( CREATEVERSIONRESMGR_NAME( uui ) ) );
1348     if ( pResMgr.get() )
1349     {
1350         bool bShowSignatures = aSignInfo.getLength() > 0;
1351         MacroWarning aWarning(
1352             getParentProperty(), bShowSignatures, *pResMgr.get() );
1353 
1354         aWarning.SetDocumentURL( aDocumentURL );
1355         if ( aSignInfo.getLength() > 1 )
1356         {
1357             aWarning.SetStorage( xZipStorage, aDocumentVersion, aSignInfo );
1358         }
1359         else if ( aSignInfo.getLength() == 1 )
1360         {
1361             aWarning.SetCertificate( aSignInfo[ 0 ].Signer );
1362         }
1363 
1364         bApprove = aWarning.Execute() == RET_OK;
1365     }
1366 
1367     if ( bApprove && xApprove.is() )
1368         xApprove->select();
1369     else if ( xAbort.is() )
1370         xAbort->select();
1371 }
1372 
1373 void
handleFutureDocumentVersionUpdateRequest(const task::FutureDocumentVersionProductUpdateRequest & _rRequest,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations)1374 UUIInteractionHelper::handleFutureDocumentVersionUpdateRequest(
1375     const task::FutureDocumentVersionProductUpdateRequest& _rRequest,
1376     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1377         rContinuations )
1378 {
1379     uno::Reference< task::XInteractionAbort > xAbort;
1380     uno::Reference< task::XInteractionApprove > xApprove;
1381     uno::Reference< task::XInteractionAskLater > xAskLater;
1382     getContinuations( rContinuations, &xApprove, &xAbort, &xAskLater );
1383 
1384     short nResult = RET_CANCEL;
1385 
1386     static bool s_bDeferredToNextSession = false;
1387     // TODO: this static variable is somewhat hacky. Formerly (before the dialog was moved from SFX2 to the
1388     // interaction handler implementation), this was stored in SFX_APP()'s impl structure, in member
1389     // bODFVersionWarningLater. Of course, we do not have access to it here.
1390     //
1391     // A proper solution which I would envision would be:
1392     // - There's a central implementation (this one here) of css.task.InteractionHandler
1393     // - There's a configuration which maps UNO names to service names
1394     // - If the handler is confronted with a request, it tries to find the name of the UNO structure describing
1395     //   the request in the said configuration.
1396     //   - If an entry is found, then
1397     //     - the respective service is instantiated
1398     //     - the component is queried for css.task.XInteractionHandler, and the request is delegated
1399     //   - if no entry is found, then the request is silenced (with calling the AbortContinuation, if possible)
1400     // This way, the FutureDocumentVersionProductUpdateRequest could be handled in SFX (or any other
1401     // suitable place), again, and we would only have one place where we remember the s_bDeferredToNextSession
1402     // flag.
1403     //
1404     // Note: The above pattern has been implemented in CWS autorecovery. Now the remaining task is to move the
1405     // handling of this interaction to SFX, again.
1406 
1407     if ( !s_bDeferredToNextSession )
1408     {
1409         std::auto_ptr< ResMgr > pResMgr(
1410             ResMgr::CreateResMgr( CREATEVERSIONRESMGR_NAME( uui ) ) );
1411         if ( pResMgr.get() )
1412         {
1413             ::uui::NewerVersionWarningDialog aDialog(
1414                 getParentProperty(),
1415                 _rRequest.DocumentODFVersion,
1416                 *pResMgr.get() );
1417             nResult = aDialog.Execute();
1418         }
1419     }
1420 
1421     switch ( nResult )
1422     {
1423     case RET_OK:
1424         if ( xApprove.is() )
1425             xApprove->select();
1426         break;
1427     case RET_CANCEL:
1428         if ( xAbort.is() )
1429             xAbort->select();
1430         break;
1431     case RET_ASK_LATER:
1432         if ( xAskLater.is() )
1433             xAskLater->select();
1434         s_bDeferredToNextSession = true;
1435         break;
1436     default:
1437         OSL_ENSURE( false,
1438             "UUIInteractionHelper::handleFutureDocumentVersionUpdateRequest: "
1439                     "unexpected dialog return value!" );
1440         break;
1441     }
1442 }
1443 
1444 void
handleBrokenPackageRequest(std::vector<rtl::OUString> const & rArguments,uno::Sequence<uno::Reference<task::XInteractionContinuation>> const & rContinuations,bool bObtainErrorStringOnly,bool & bHasErrorString,rtl::OUString & rErrorString)1445 UUIInteractionHelper::handleBrokenPackageRequest(
1446     std::vector< rtl::OUString > const & rArguments,
1447     uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
1448         rContinuations,
1449     bool bObtainErrorStringOnly,
1450     bool & bHasErrorString,
1451     rtl::OUString & rErrorString)
1452 {
1453     if (bObtainErrorStringOnly)
1454     {
1455         bHasErrorString = isInformationalErrorMessageRequest(rContinuations);
1456         if (!bHasErrorString)
1457             return;
1458     }
1459 
1460     uno::Reference< task::XInteractionApprove > xApprove;
1461     uno::Reference< task::XInteractionDisapprove > xDisapprove;
1462     uno::Reference< task::XInteractionAbort > xAbort;
1463     getContinuations(rContinuations, &xApprove, &xDisapprove, &xAbort);
1464 
1465     ErrCode nErrorCode;
1466     if( xApprove.is() && xDisapprove.is() )
1467     {
1468         nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE;
1469     }
1470     else if ( xAbort.is() )
1471     {
1472         nErrorCode = ERRCODE_UUI_IO_BROKENPACKAGE_CANTREPAIR;
1473     }
1474     else
1475         return;
1476 
1477     ::rtl::OUString aMessage;
1478     {
1479         vos::OGuard aGuard(Application::GetSolarMutex());
1480         std::auto_ptr< ResMgr > xManager(
1481             ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(uui)));
1482         if (!xManager.get())
1483             return;
1484 
1485         ResId aResId( RID_UUI_ERRHDL, *xManager.get() );
1486         if ( !ErrorResource(aResId).getString(nErrorCode, &aMessage) )
1487             return;
1488     }
1489 
1490     aMessage = replaceMessageWithArguments( aMessage, rArguments );
1491 
1492     if (bObtainErrorStringOnly)
1493     {
1494         rErrorString = aMessage;
1495         return;
1496     }
1497 
1498     WinBits nButtonMask;
1499     if( xApprove.is() && xDisapprove.is() )
1500     {
1501         nButtonMask = WB_YES_NO | WB_DEF_YES;
1502     }
1503     else if ( xAbort.is() )
1504     {
1505         nButtonMask = WB_OK;
1506     }
1507     else
1508         return;
1509 
1510     uno::Any aProductNameAny =
1511         ::utl::ConfigManager::GetConfigManager()->GetDirectConfigProperty(
1512             ::utl::ConfigManager::PRODUCTNAME );
1513     uno::Any aProductVersionAny =
1514         ::utl::ConfigManager::GetConfigManager()->GetDirectConfigProperty(
1515             ::utl::ConfigManager::PRODUCTVERSION );
1516     ::rtl::OUString aProductName, aProductVersion;
1517     if ( !( aProductNameAny >>= aProductName ) )
1518         aProductName
1519             = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("StarOffice") );
1520 
1521     ::rtl::OUString aTitle( aProductName );
1522     if( aProductVersionAny >>= aProductVersion )
1523     {
1524         aTitle += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(" ") );
1525         aTitle += aProductVersion;
1526     }
1527 
1528     switch ( executeMessageBox( getParentProperty(),
1529                                 aTitle,
1530                                 aMessage,
1531                                 nButtonMask ))
1532     {
1533     case ERRCODE_BUTTON_OK:
1534         OSL_ENSURE( xAbort.is(), "unexpected situation" );
1535         if (xAbort.is())
1536             xAbort->select();
1537         break;
1538 
1539     case ERRCODE_BUTTON_NO:
1540         OSL_ENSURE(xDisapprove.is(), "unexpected situation");
1541         if (xDisapprove.is())
1542             xDisapprove->select();
1543         break;
1544 
1545     case ERRCODE_BUTTON_YES:
1546         OSL_ENSURE(xApprove.is(), "unexpected situation");
1547         if (xApprove.is())
1548             xApprove->select();
1549         break;
1550     }
1551 }
1552 
1553 //=========================================================================
1554 // ErrorResource Implementation
1555 //=========================================================================
1556 
1557 bool
getString(ErrCode nErrorCode,rtl::OUString * pString) const1558 ErrorResource::getString(ErrCode nErrorCode, rtl::OUString * pString)
1559     const SAL_THROW(())
1560 {
1561     OSL_ENSURE(pString, "specification violation");
1562     ResId aResId(static_cast< sal_uInt16 >(nErrorCode & ERRCODE_RES_MASK),
1563                  *m_pResMgr);
1564     aResId.SetRT(RSC_STRING);
1565     if (!IsAvailableRes(aResId))
1566         return false;
1567     aResId.SetAutoRelease(false);
1568     *pString = UniString(aResId);
1569     m_pResMgr->PopContext();
1570     return true;
1571 }
1572