Avoid potential negative array index access to cached text.
[LibreOffice.git] / embedserv / source / embed / intercept.cxx
blob0f1566fd780d867fdbef41b3d2e55be5c78e336f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <cppuhelper/weak.hxx>
21 #include <embeddoc.hxx>
22 #include <docholder.hxx>
23 #include <intercept.hxx>
25 using namespace ::com::sun::star;
28 #define IUL 6
30 constexpr OUString IU0 = u".uno:Save"_ustr;
31 constexpr OUString IU1 = u".uno:SaveAll"_ustr;
32 constexpr OUString IU2 = u".uno:CloseDoc"_ustr;
33 constexpr OUString IU3 = u".uno:CloseWin"_ustr;
34 constexpr OUString IU4 = u".uno:CloseFrame"_ustr;
35 constexpr OUString IU5 = u".uno:SaveAs"_ustr;
36 const uno::Sequence< OUString > Interceptor::m_aInterceptedURL{ IU0, IU1, IU2, IU3, IU4, IU5};
40 void
41 Interceptor::addEventListener(
42 const uno::Reference<lang::XEventListener >& Listener )
44 osl::MutexGuard aGuard( m_aMutex );
46 if ( ! m_pDisposeEventListeners )
47 m_pDisposeEventListeners =
48 new comphelper::OInterfaceContainerHelper2( m_aMutex );
50 m_pDisposeEventListeners->addInterface( Listener );
54 void
55 Interceptor::removeEventListener(
56 const uno::Reference< lang::XEventListener >& Listener )
58 osl::MutexGuard aGuard( m_aMutex );
60 if ( m_pDisposeEventListeners )
61 m_pDisposeEventListeners->removeInterface( Listener );
65 void Interceptor::dispose()
67 lang::EventObject aEvt;
68 aEvt.Source = static_cast< frame::XDispatch* >( this );
70 osl::MutexGuard aGuard(m_aMutex);
72 if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
73 m_pDisposeEventListeners->disposeAndClear( aEvt );
75 if(m_pStatCL)
76 m_pStatCL->disposeAndClear( aEvt );
78 m_xSlaveDispatchProvider = nullptr;
79 m_xMasterDispatchProvider = nullptr;
83 Interceptor::Interceptor(
84 const ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl >& xOleAccess,
85 DocumentHolder* pDocH,
86 bool bLink )
87 : m_xOleAccess( xOleAccess ),
88 m_xDocHLocker( cppu::getXWeak( pDocH ) ),
89 m_pDocH(pDocH),
90 m_pDisposeEventListeners(nullptr),
91 m_pStatCL(nullptr),
92 m_bLink( bLink )
97 Interceptor::~Interceptor()
99 delete m_pDisposeEventListeners;
100 delete m_pStatCL;
102 DocumentHolder* pTmpDocH = nullptr;
103 uno::Reference< uno::XInterface > xLock;
105 osl::MutexGuard aGuard(m_aMutex);
106 xLock = m_xDocHLocker.get();
107 if ( xLock.is() )
108 pTmpDocH = m_pDocH;
111 if ( pTmpDocH )
112 pTmpDocH->ClearInterceptor();
115 void Interceptor::DisconnectDocHolder()
117 osl::MutexGuard aGuard(m_aMutex);
118 m_xDocHLocker.clear();
119 m_pDocH = nullptr;
120 m_xOleAccess = nullptr;
123 //XDispatch
124 void SAL_CALL
125 Interceptor::dispatch(
126 const util::URL& URL,
127 const uno::Sequence<
128 beans::PropertyValue >& Arguments )
130 ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl > xOleAccess;
132 osl::MutexGuard aGuard(m_aMutex);
133 xOleAccess = m_xOleAccess;
136 if ( xOleAccess.is() )
138 LockedEmbedDocument_Impl aDocLock = xOleAccess->GetEmbedDocument();
139 if ( aDocLock.GetEmbedDocument() )
141 if( !m_bLink && URL.Complete == m_aInterceptedURL[0])
142 aDocLock.GetEmbedDocument()->SaveObject();
143 else if(!m_bLink
144 && ( URL.Complete == m_aInterceptedURL[2] ||
145 URL.Complete == m_aInterceptedURL[3] ||
146 URL.Complete == m_aInterceptedURL[4] ) )
147 aDocLock.GetEmbedDocument()->Close( 0 );
148 else if ( URL.Complete == m_aInterceptedURL[5] )
150 uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
151 sal_Int32 nInd = 0;
153 while( nInd < aNewArgs.getLength() )
155 if ( aNewArgs[nInd].Name == "SaveTo" )
157 aNewArgs.getArray()[nInd].Value <<= true;
158 break;
160 nInd++;
163 if ( nInd == aNewArgs.getLength() )
165 aNewArgs.realloc( nInd + 1 );
166 auto pNewArgs = aNewArgs.getArray();
167 pNewArgs[nInd].Name = "SaveTo";
168 pNewArgs[nInd].Value <<= true;
171 uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
172 URL, "_self", 0 );
173 if ( xDispatch.is() )
174 xDispatch->dispatch( URL, aNewArgs );
181 void Interceptor::generateFeatureStateEvent()
183 if( m_pStatCL )
185 DocumentHolder* pTmpDocH = nullptr;
186 uno::Reference< uno::XInterface > xLock;
188 osl::MutexGuard aGuard(m_aMutex);
189 xLock = m_xDocHLocker.get();
190 if ( xLock.is() )
191 pTmpDocH = m_pDocH;
194 OUString aTitle;
195 if ( pTmpDocH )
196 aTitle = pTmpDocH->getTitle();
198 for(int i = 0; i < IUL; ++i)
200 if( i == 1 || (m_bLink && i != 5) )
201 continue;
203 comphelper::OInterfaceContainerHelper3<css::frame::XStatusListener>* pICH =
204 m_pStatCL->getContainer(m_aInterceptedURL[i]);
205 if(!pICH)
206 continue;
207 std::vector<uno::Reference<css::frame::XStatusListener> > aSeq = pICH->getElements();
208 if(aSeq.empty())
209 continue;
211 frame::FeatureStateEvent aStateEvent;
212 aStateEvent.IsEnabled = true;
213 aStateEvent.Requery = false;
214 if(i == 0)
217 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
218 aStateEvent.FeatureDescriptor = "Update";
219 aStateEvent.State <<= "($1) " + aTitle;
222 else if ( i == 5 )
224 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
225 aStateEvent.FeatureDescriptor = "SaveCopyTo";
226 aStateEvent.State <<= OUString("($3)");
228 else
230 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
231 aStateEvent.FeatureDescriptor = "Close and Return";
232 aStateEvent.State <<= "($2) " + aTitle;
236 for(uno::Reference<css::frame::XStatusListener> const & control : std::as_const(aSeq))
237 control->statusChanged(aStateEvent);
243 void SAL_CALL
244 Interceptor::addStatusListener(
245 const uno::Reference<
246 frame::XStatusListener >& Control,
247 const util::URL& URL )
249 if(!Control.is())
250 return;
252 if( !m_bLink && URL.Complete == m_aInterceptedURL[0] )
253 { // Save
254 DocumentHolder* pTmpDocH = nullptr;
255 uno::Reference< uno::XInterface > xLock;
257 osl::MutexGuard aGuard(m_aMutex);
258 xLock = m_xDocHLocker.get();
259 if ( xLock.is() )
260 pTmpDocH = m_pDocH;
263 OUString aTitle;
264 if ( pTmpDocH )
265 aTitle = pTmpDocH->getTitle();
267 frame::FeatureStateEvent aStateEvent;
268 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
269 aStateEvent.FeatureDescriptor = "Update";
270 aStateEvent.IsEnabled = true;
271 aStateEvent.Requery = false;
272 aStateEvent.State <<= "($1) " + aTitle;
273 Control->statusChanged(aStateEvent);
276 osl::MutexGuard aGuard(m_aMutex);
277 if(!m_pStatCL)
278 m_pStatCL =
279 new StatusChangeListenerContainer(m_aMutex);
282 m_pStatCL->addInterface(URL.Complete,Control);
283 return;
286 sal_Int32 i = 2;
287 if ( !m_bLink
288 && ( URL.Complete == m_aInterceptedURL[i] ||
289 URL.Complete == m_aInterceptedURL[++i] ||
290 URL.Complete == m_aInterceptedURL[++i] ) )
291 { // Close and return
292 DocumentHolder* pTmpDocH = nullptr;
293 uno::Reference< uno::XInterface > xLock;
295 osl::MutexGuard aGuard(m_aMutex);
296 xLock = m_xDocHLocker.get();
297 if ( xLock.is() )
298 pTmpDocH = m_pDocH;
301 OUString aTitle;
302 if ( pTmpDocH )
303 aTitle = pTmpDocH->getTitle();
305 frame::FeatureStateEvent aStateEvent;
306 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
307 aStateEvent.FeatureDescriptor = "Close and Return";
308 aStateEvent.IsEnabled = true;
309 aStateEvent.Requery = false;
310 aStateEvent.State <<= "($2) " + aTitle;
311 Control->statusChanged(aStateEvent);
315 osl::MutexGuard aGuard(m_aMutex);
316 if(!m_pStatCL)
317 m_pStatCL =
318 new StatusChangeListenerContainer(m_aMutex);
321 m_pStatCL->addInterface(URL.Complete,Control);
322 return;
325 if(URL.Complete == m_aInterceptedURL[5])
326 { // SaveAs
327 frame::FeatureStateEvent aStateEvent;
328 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
329 aStateEvent.FeatureDescriptor = "SaveCopyTo";
330 aStateEvent.IsEnabled = true;
331 aStateEvent.Requery = false;
332 aStateEvent.State <<= OUString("($3)");
333 Control->statusChanged(aStateEvent);
336 osl::MutexGuard aGuard(m_aMutex);
337 if(!m_pStatCL)
338 m_pStatCL =
339 new StatusChangeListenerContainer(m_aMutex);
342 m_pStatCL->addInterface(URL.Complete,Control);
343 return;
349 void SAL_CALL
350 Interceptor::removeStatusListener(
351 const uno::Reference<
352 frame::XStatusListener >& Control,
353 const util::URL& URL )
355 if(!(Control.is() && m_pStatCL))
356 return;
357 else {
358 m_pStatCL->removeInterface(URL.Complete,Control);
359 return;
364 //XInterceptorInfo
365 uno::Sequence< OUString >
366 SAL_CALL
367 Interceptor::getInterceptedURLs( )
369 // now implemented as update
370 if ( m_bLink )
371 return { m_aInterceptedURL[1], m_aInterceptedURL[5] };
373 return m_aInterceptedURL;
377 // XDispatchProvider
379 uno::Reference< frame::XDispatch > SAL_CALL
380 Interceptor::queryDispatch(
381 const util::URL& URL,
382 const OUString& TargetFrameName,
383 sal_Int32 SearchFlags )
385 osl::MutexGuard aGuard(m_aMutex);
386 if( !m_bLink && URL.Complete == m_aInterceptedURL[0] )
387 return static_cast<frame::XDispatch*>(this);
388 else if(URL.Complete == m_aInterceptedURL[1])
389 return nullptr;
390 else if( !m_bLink && URL.Complete == m_aInterceptedURL[2] )
391 return static_cast<frame::XDispatch*>(this);
392 else if( !m_bLink && URL.Complete == m_aInterceptedURL[3] )
393 return static_cast<frame::XDispatch*>(this);
394 else if( !m_bLink && URL.Complete == m_aInterceptedURL[4] )
395 return static_cast<frame::XDispatch*>(this);
396 else if(URL.Complete == m_aInterceptedURL[5])
397 return static_cast<frame::XDispatch*>(this);
398 else {
399 if(m_xSlaveDispatchProvider.is())
400 return m_xSlaveDispatchProvider->queryDispatch(
401 URL,TargetFrameName,SearchFlags);
402 else
403 return uno::Reference<frame::XDispatch>(nullptr);
407 uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
408 Interceptor::queryDispatches(
409 const uno::Sequence<frame::DispatchDescriptor >& Requests )
411 uno::Sequence< uno::Reference< frame::XDispatch > > aRet;
412 osl::MutexGuard aGuard(m_aMutex);
413 if(m_xSlaveDispatchProvider.is())
414 aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
415 else
416 aRet.realloc(Requests.getLength());
417 auto aRetRange = asNonConstRange(aRet);
418 for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
419 if ( !m_bLink && m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete )
420 aRetRange[i] = static_cast<frame::XDispatch*>(this);
421 else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
422 aRetRange[i] = nullptr;
423 else if( !m_bLink && m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete )
424 aRetRange[i] = static_cast<frame::XDispatch*>(this);
425 else if( !m_bLink && m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete )
426 aRetRange[i] = static_cast<frame::XDispatch*>(this);
427 else if( !m_bLink && m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete )
428 aRetRange[i] = static_cast<frame::XDispatch*>(this);
429 else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
430 aRetRange[i] = static_cast<frame::XDispatch*>(this);
432 return aRet;
436 //XDispatchProviderInterceptor
438 uno::Reference< frame::XDispatchProvider > SAL_CALL
439 Interceptor::getSlaveDispatchProvider( )
441 osl::MutexGuard aGuard(m_aMutex);
442 return m_xSlaveDispatchProvider;
445 void SAL_CALL
446 Interceptor::setSlaveDispatchProvider(
447 const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
449 osl::MutexGuard aGuard(m_aMutex);
450 m_xSlaveDispatchProvider = NewDispatchProvider;
454 uno::Reference< frame::XDispatchProvider > SAL_CALL
455 Interceptor::getMasterDispatchProvider( )
457 osl::MutexGuard aGuard(m_aMutex);
458 return m_xMasterDispatchProvider;
462 void SAL_CALL
463 Interceptor::setMasterDispatchProvider(
464 const uno::Reference< frame::XDispatchProvider >& NewSupplier )
466 osl::MutexGuard aGuard(m_aMutex);
467 m_xMasterDispatchProvider = NewSupplier;
470 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */