Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <stdio.h>
31 : : #include <com/sun/star/io/XStream.hpp>
32 : : #include <com/sun/star/embed/XTransactedObject.hpp>
33 : : #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
34 : : #include <com/sun/star/embed/XEmbedObjectFactory.hpp>
35 : : #include <com/sun/star/embed/ElementModes.hpp>
36 : : #include <com/sun/star/embed/XEmbeddedObject.hpp>
37 : : #include <com/sun/star/embed/XEmbedPersist.hpp>
38 : : #include <com/sun/star/embed/EntryInitModes.hpp>
39 : : #include <com/sun/star/embed/EmbedStates.hpp>
40 : : #include <com/sun/star/embed/Aspects.hpp>
41 : : #include <com/sun/star/beans/XPropertySet.hpp>
42 : : #include <tools/debug.hxx>
43 : : #include <unotools/streamwrap.hxx>
44 : : #include <unotools/tempfile.hxx>
45 : :
46 : : #include <svtools/embedhlp.hxx>
47 : : #include <unotools/ucbstreamhelper.hxx>
48 : : #include <comphelper/processfactory.hxx>
49 : : #include <comphelper/storagehelper.hxx>
50 : : #include <comphelper/embeddedobjectcontainer.hxx>
51 : :
52 : : #include <sot/clsids.hxx>
53 : : #include <map>
54 : : #include "svx/xmleohlp.hxx"
55 : :
56 : : // -----------
57 : : // - Defines -
58 : : // -----------
59 : :
60 : : using namespace ::osl;
61 : : using namespace ::cppu;
62 : : using namespace ::utl;
63 : : using namespace ::com::sun::star;
64 : : using namespace ::com::sun::star::document;
65 : : using namespace ::com::sun::star::uno;
66 : : using namespace ::com::sun::star::container;
67 : : using namespace ::com::sun::star::io;
68 : : using namespace ::com::sun::star::lang;
69 : :
70 : : #define XML_CONTAINERSTORAGE_NAME_60 "Pictures"
71 : : #define XML_CONTAINERSTORAGE_NAME "ObjectReplacements"
72 : : #define XML_EMBEDDEDOBJECT_URL_BASE "vnd.sun.star.EmbeddedObject:"
73 : : #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "vnd.sun.star.GraphicObject:"
74 : :
75 : : // -----------------------------------------------------------------------------
76 : :
77 : : // -----------------------------------------------------------------------------
78 : :
79 : : class OutputStorageWrapper_Impl : public ::cppu::WeakImplHelper1<XOutputStream>
80 : : {
81 : : ::osl::Mutex maMutex;
82 : : Reference < XOutputStream > xOut;
83 : : TempFile aTempFile;
84 : : sal_Bool bStreamClosed : 1;
85 : : SvStream* pStream;
86 : :
87 : : public:
88 : : OutputStorageWrapper_Impl();
89 : : virtual ~OutputStorageWrapper_Impl();
90 : :
91 : : // stario::XOutputStream
92 : : virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
93 : : virtual void SAL_CALL flush() throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
94 : : virtual void SAL_CALL closeOutput() throw(NotConnectedException, BufferSizeExceededException, RuntimeException);
95 : :
96 : : SvStream* GetStream();
97 : : };
98 : :
99 : 0 : OutputStorageWrapper_Impl::OutputStorageWrapper_Impl()
100 : : : bStreamClosed( sal_False )
101 [ # # ][ # # ]: 0 : , pStream(0)
102 : : {
103 : 0 : aTempFile.EnableKillingFile();
104 [ # # ]: 0 : pStream = aTempFile.GetStream( STREAM_READWRITE );
105 [ # # ][ # # ]: 0 : xOut = new OOutputStreamWrapper( *pStream );
[ # # ]
106 : 0 : }
107 : :
108 [ # # ][ # # ]: 0 : OutputStorageWrapper_Impl::~OutputStorageWrapper_Impl()
109 : : {
110 [ # # ]: 0 : }
111 : :
112 : 0 : SvStream *OutputStorageWrapper_Impl::GetStream()
113 : : {
114 [ # # ]: 0 : if( bStreamClosed )
115 : 0 : return pStream;
116 : 0 : return NULL;
117 : : }
118 : :
119 : 0 : void SAL_CALL OutputStorageWrapper_Impl::writeBytes(
120 : : const Sequence< sal_Int8 >& aData)
121 : : throw(NotConnectedException, BufferSizeExceededException, RuntimeException)
122 : : {
123 [ # # ]: 0 : MutexGuard aGuard( maMutex );
124 [ # # ][ # # ]: 0 : xOut->writeBytes( aData );
[ # # ]
125 : 0 : }
126 : :
127 : 0 : void SAL_CALL OutputStorageWrapper_Impl::flush()
128 : : throw(NotConnectedException, BufferSizeExceededException, RuntimeException)
129 : : {
130 [ # # ]: 0 : MutexGuard aGuard( maMutex );
131 [ # # ][ # # ]: 0 : xOut->flush();
[ # # ]
132 : 0 : }
133 : :
134 : 0 : void SAL_CALL OutputStorageWrapper_Impl::closeOutput()
135 : : throw(NotConnectedException, BufferSizeExceededException, RuntimeException)
136 : : {
137 [ # # ]: 0 : MutexGuard aGuard( maMutex );
138 [ # # ][ # # ]: 0 : xOut->closeOutput();
139 [ # # ]: 0 : bStreamClosed = sal_True;
140 : 0 : }
141 : :
142 : : // -----------------------------------------------------------------------------
143 : :
144 : : struct OUStringLess
145 : : {
146 : 0 : bool operator() ( const ::rtl::OUString& r1, const ::rtl::OUString& r2 ) const
147 : : {
148 : 0 : return (r1 < r2) != sal_False;
149 : : }
150 : : };
151 : :
152 : : // -----------------------------------------------------------------------------
153 : :
154 : : // -----------------------------
155 : : // - SvXMLEmbeddedObjectHelper -
156 : : // -----------------------------
157 : : DBG_NAME(SvXMLEmbeddedObjectHelper)
158 : 240 : SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() :
159 : : WeakComponentImplHelper2< XEmbeddedObjectResolver, XNameAccess >( maMutex ),
160 : : maReplacementGraphicsContainerStorageName( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME) ),
161 : : maReplacementGraphicsContainerStorageName60( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME_60) ),
162 : : mpDocPersist( 0 ),
163 : : meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ ),
164 [ + - ][ + - ]: 240 : mpStreamMap( 0 )
[ + - ]
165 : : {
166 : : DBG_CTOR(SvXMLEmbeddedObjectHelper,NULL);
167 : 240 : }
168 : :
169 : 210 : SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper( ::comphelper::IEmbeddedHelper& rDocPersist, SvXMLEmbeddedObjectHelperMode eCreateMode ) :
170 : : WeakComponentImplHelper2< XEmbeddedObjectResolver, XNameAccess >( maMutex ),
171 : : maReplacementGraphicsContainerStorageName( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME) ),
172 : : maReplacementGraphicsContainerStorageName60( RTL_CONSTASCII_USTRINGPARAM(XML_CONTAINERSTORAGE_NAME_60) ),
173 : : mpDocPersist( 0 ),
174 : : meCreateMode( EMBEDDEDOBJECTHELPER_MODE_READ ),
175 [ + - ][ + - ]: 210 : mpStreamMap( 0 )
[ + - ]
176 : : {
177 : : DBG_CTOR(SvXMLEmbeddedObjectHelper,NULL);
178 [ + - ][ + - ]: 210 : Init( 0, rDocPersist, eCreateMode );
179 : 210 : }
180 : :
181 : :
182 : : // -----------------------------------------------------------------------------
183 : :
184 [ + - ]: 450 : SvXMLEmbeddedObjectHelper::~SvXMLEmbeddedObjectHelper()
185 : : {
186 : : DBG_DTOR(SvXMLEmbeddedObjectHelper,NULL);
187 [ - + ]: 450 : if( mpStreamMap )
188 : : {
189 : 0 : SvXMLEmbeddedObjectHelper_Impl::iterator aIter = mpStreamMap->begin();
190 : 0 : SvXMLEmbeddedObjectHelper_Impl::iterator aEnd = mpStreamMap->end();
191 [ # # ]: 0 : for( ; aIter != aEnd; ++aIter )
192 : : {
193 [ # # ]: 0 : if( aIter->second )
194 : : {
195 : 0 : aIter->second->release();
196 : 0 : aIter->second = 0;
197 : : }
198 : : }
199 [ # # ]: 0 : delete mpStreamMap;
200 : : }
201 [ - + ]: 900 : }
202 : :
203 : : // -----------------------------------------------------------------------------
204 : :
205 : 450 : void SAL_CALL SvXMLEmbeddedObjectHelper::disposing()
206 : : {
207 : 450 : Flush();
208 : 450 : }
209 : :
210 : :
211 : 182 : void SvXMLEmbeddedObjectHelper::splitObjectURL(::rtl::OUString aURLNoPar,
212 : : ::rtl::OUString& rContainerStorageName,
213 : : ::rtl::OUString& rObjectStorageName)
214 : : {
215 : : DBG_ASSERT( '#' != aURLNoPar[0], "invalid object URL" );
216 : :
217 : 182 : sal_Int32 _nPos = aURLNoPar.lastIndexOf( '/' );
218 [ - + ]: 182 : if( -1 == _nPos )
219 : : {
220 : 0 : rContainerStorageName = ::rtl::OUString();
221 : 0 : rObjectStorageName = aURLNoPar;
222 : : }
223 : : else
224 : : {
225 : : //eliminate 'superfluous' slashes at start and end
226 : : //#i103076# load objects with all allowed xlink:href syntaxes
227 : : {
228 : : //eliminate './' at start
229 : 182 : sal_Int32 nStart = 0;
230 : 182 : sal_Int32 nCount = aURLNoPar.getLength();
231 [ + + ]: 182 : if( 0 == aURLNoPar.compareToAscii( "./", 2 ) )
232 : : {
233 : 2 : nStart = 2;
234 : 2 : nCount -= 2;
235 : : }
236 : :
237 : : //eliminate '/' at end
238 : 182 : sal_Int32 nEnd = aURLNoPar.lastIndexOf( '/' );
239 [ # # ][ - + ]: 182 : if( nEnd == aURLNoPar.getLength()-1 && nEnd != (nStart-1) )
[ - + ]
240 : 0 : nCount--;
241 : :
242 : 182 : aURLNoPar = aURLNoPar.copy( nStart, nCount );
243 : : }
244 : :
245 : 182 : _nPos = aURLNoPar.lastIndexOf( '/' );
246 [ + + ]: 182 : if( _nPos >= 0 )
247 : 180 : rContainerStorageName = aURLNoPar.copy( 0, _nPos );
248 : 182 : rObjectStorageName = aURLNoPar.copy( _nPos+1 );
249 : : }
250 : 182 : }
251 : :
252 : : // -----------------------------------------------------------------------------
253 : :
254 : 2 : sal_Bool SvXMLEmbeddedObjectHelper::ImplGetStorageNames(
255 : : const ::rtl::OUString& rURLStr,
256 : : ::rtl::OUString& rContainerStorageName,
257 : : ::rtl::OUString& rObjectStorageName,
258 : : sal_Bool bInternalToExternal,
259 : : sal_Bool *pGraphicRepl,
260 : : sal_Bool *pOasisFormat ) const
261 : : {
262 : : // internal URL: vnd.sun.star.EmbeddedObject:<object-name>
263 : : // or: vnd.sun.star.EmbeddedObject:<path>/<object-name>
264 : : // internal replacement images:
265 : : // vnd.sun.star.EmbeddedObjectGraphic:<object-name>
266 : : // or: vnd.sun.star.EmbeddedObjectGraphic:<path>/<object-name>
267 : : // external URL: ./<path>/<object-name>
268 : : // or: <path>/<object-name>
269 : : // or: <object-name>
270 : : // currently, path may only consist of a single directory name
271 : : // it is also possible to have additional arguments at the end of URL: <main URL>[?<name>=<value>[,<name>=<value>]*]
272 : :
273 [ - + ]: 2 : if( pGraphicRepl )
274 : 0 : *pGraphicRepl = sal_False;
275 : :
276 [ - + ]: 2 : if( pOasisFormat )
277 : 0 : *pOasisFormat = sal_True; // the default value
278 : :
279 [ - + ]: 2 : if( rURLStr.isEmpty() )
280 : 0 : return sal_False;
281 : :
282 : : // get rid of arguments
283 : 2 : sal_Int32 nPos = rURLStr.indexOf( '?' );
284 : 2 : ::rtl::OUString aURLNoPar;
285 [ + - ]: 2 : if ( nPos == -1 )
286 : 2 : aURLNoPar = rURLStr;
287 : : else
288 : : {
289 : 0 : aURLNoPar = rURLStr.copy( 0, nPos );
290 : :
291 : : // check the arguments
292 : 0 : nPos++;
293 [ # # ][ # # ]: 0 : while( nPos >= 0 && nPos < rURLStr.getLength() )
[ # # ]
294 : : {
295 : 0 : ::rtl::OUString aToken = rURLStr.getToken( 0, ',', nPos );
296 [ # # ][ # # ]: 0 : if ( aToken.equalsIgnoreAsciiCase( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "oasis=false" ) ) ) )
297 : : {
298 [ # # ]: 0 : if ( pOasisFormat )
299 : 0 : *pOasisFormat = sal_False;
300 : : break;
301 : : }
302 : : else
303 : : {
304 : : DBG_ASSERT( sal_False, "invalid arguments was found in URL!" );
305 : : }
306 [ # # ]: 0 : }
307 : : }
308 : :
309 [ - + ]: 2 : if( bInternalToExternal )
310 : : {
311 : 0 : nPos = aURLNoPar.indexOf( ':' );
312 [ # # ]: 0 : if( -1 == nPos )
313 : 0 : return sal_False;
314 : : sal_Bool bObjUrl =
315 : : 0 == aURLNoPar.compareToAscii( XML_EMBEDDEDOBJECT_URL_BASE,
316 : 0 : sizeof( XML_EMBEDDEDOBJECT_URL_BASE ) -1 );
317 : : sal_Bool bGrUrl = !bObjUrl &&
318 : : 0 == aURLNoPar.compareToAscii( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE,
319 [ # # ][ # # ]: 0 : sizeof( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE ) -1 );
320 [ # # ][ # # ]: 0 : if( !(bObjUrl || bGrUrl) )
321 : 0 : return sal_False;
322 : :
323 : 0 : sal_Int32 nPathStart = nPos + 1;
324 : 0 : nPos = aURLNoPar.lastIndexOf( '/' );
325 [ # # ]: 0 : if( -1 == nPos )
326 : : {
327 : 0 : rContainerStorageName = ::rtl::OUString();
328 : 0 : rObjectStorageName = aURLNoPar.copy( nPathStart );
329 : : }
330 [ # # ]: 0 : else if( nPos > nPathStart )
331 : : {
332 : 0 : rContainerStorageName = aURLNoPar.copy( nPathStart, nPos-nPathStart);
333 : 0 : rObjectStorageName = aURLNoPar.copy( nPos+1 );
334 : : }
335 : : else
336 : 0 : return sal_False;
337 : :
338 [ # # ]: 0 : if( bGrUrl )
339 : : {
340 : 0 : sal_Bool bOASIS = mxRootStorage.is() &&
341 [ # # ][ # # ]: 0 : ( SotStorage::GetVersion( mxRootStorage ) > SOFFICE_FILEFORMAT_60 );
[ # # ]
342 : : rContainerStorageName = bOASIS
343 : : ? maReplacementGraphicsContainerStorageName
344 [ # # ]: 0 : : maReplacementGraphicsContainerStorageName60;
345 : :
346 [ # # ]: 0 : if( pGraphicRepl )
347 : 0 : *pGraphicRepl = sal_True;
348 : : }
349 : :
350 : :
351 : : }
352 : : else
353 : : {
354 [ + - ]: 2 : splitObjectURL(aURLNoPar, rContainerStorageName, rObjectStorageName);
355 : : }
356 : :
357 [ - + ]: 2 : if( -1 != rContainerStorageName.indexOf( '/' ) )
358 : : {
359 : : OSL_FAIL( "SvXMLEmbeddedObjectHelper: invalid path name" );
360 : 0 : return sal_False;
361 : : }
362 : :
363 : 2 : return sal_True;
364 : : }
365 : :
366 : :
367 : : // -----------------------------------------------------------------------------
368 : :
369 : 2 : uno::Reference < embed::XStorage > SvXMLEmbeddedObjectHelper::ImplGetContainerStorage(
370 : : const ::rtl::OUString& rStorageName )
371 : : {
372 : : DBG_ASSERT( -1 == rStorageName.indexOf( '/' ) &&
373 : : -1 == rStorageName.indexOf( '\\' ),
374 : : "nested embedded storages aren't supported" );
375 [ - + # # ]: 2 : if( !mxContainerStorage.is() ||
[ + - ]
376 : 0 : ( rStorageName != maCurContainerStorageName ) )
377 : : {
378 [ - + # # ]: 2 : if( mxContainerStorage.is() &&
[ # # ][ - + ]
379 : 0 : !maCurContainerStorageName.isEmpty() &&
380 : : EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode )
381 : : {
382 [ # # ]: 0 : uno::Reference < embed::XTransactedObject > xTrans( mxContainerStorage, uno::UNO_QUERY );
383 [ # # ]: 0 : if ( xTrans.is() )
384 [ # # ][ # # ]: 0 : xTrans->commit();
385 : : }
386 : :
387 [ - + ][ # # ]: 2 : if( !rStorageName.isEmpty() && mxRootStorage.is() )
[ - + ]
388 : : {
389 : : sal_Int32 nMode = EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode
390 : : ? ::embed::ElementModes::READWRITE
391 [ # # ]: 0 : : ::embed::ElementModes::READ;
392 : 0 : mxContainerStorage = mxRootStorage->openStorageElement( rStorageName,
393 [ # # ]: 0 : nMode );
394 : : }
395 : : else
396 : : {
397 : 2 : mxContainerStorage = mxRootStorage;
398 : : }
399 : 2 : maCurContainerStorageName = rStorageName;
400 : : }
401 : :
402 : 2 : return mxContainerStorage;
403 : : }
404 : :
405 : : // -----------------------------------------------------------------------------
406 : :
407 : 2 : sal_Bool SvXMLEmbeddedObjectHelper::ImplReadObject(
408 : : const ::rtl::OUString& rContainerStorageName,
409 : : ::rtl::OUString& rObjName,
410 : : const SvGlobalName *pClassId,
411 : : SvStream* pTemp )
412 : : {
413 : : (void)pClassId;
414 : :
415 [ + - ]: 2 : uno::Reference < embed::XStorage > xDocStor( mpDocPersist->getStorage() );
416 [ + - ]: 2 : uno::Reference < embed::XStorage > xCntnrStor( ImplGetContainerStorage( rContainerStorageName ) );
417 : :
418 [ - + ][ # # ]: 2 : if( !xCntnrStor.is() && !pTemp )
[ - + ]
419 : 0 : return sal_False;
420 : :
421 [ + - ]: 2 : String aSrcObjName( rObjName );
422 [ + - ]: 2 : comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer();
423 : :
424 : : // Is the object name unique?
425 : : // if the object is already instantiated by GetEmbeddedObject
426 : : // that means that the duplication is being loaded
427 [ + - ]: 2 : sal_Bool bDuplicate = rContainer.HasInstantiatedEmbeddedObject( rObjName );
428 : : DBG_ASSERT( !bDuplicate, "An object in the document is referenced twice!" );
429 : :
430 [ + - ][ + - ]: 2 : if( xDocStor != xCntnrStor || pTemp || bDuplicate )
[ + - ][ - + ]
[ - + ]
431 : : {
432 : : // TODO/LATER: make this alltogether a method in the EmbeddedObjectContainer
433 : :
434 : : // create a unique name for the duplicate object
435 [ # # ]: 0 : if( bDuplicate )
436 [ # # ]: 0 : rObjName = rContainer.CreateUniqueObjectName();
437 : :
438 [ # # ]: 0 : if( pTemp )
439 : : {
440 : : try
441 : : {
442 [ # # ]: 0 : pTemp->Seek( 0 );
443 [ # # ]: 0 : uno::Reference < io::XStream > xStm = xDocStor->openStreamElement( rObjName,
444 [ # # ]: 0 : embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
445 [ # # ]: 0 : SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStm );
446 [ # # ]: 0 : *pTemp >> *pStream;
447 [ # # ][ # # ]: 0 : delete pStream;
448 : :
449 : : // TODO/LATER: what to do when other types of objects are based on substream persistence?
450 : : // This is an ole object
451 [ # # ]: 0 : uno::Reference< beans::XPropertySet > xProps( xStm, uno::UNO_QUERY_THROW );
452 [ # # ]: 0 : xProps->setPropertyValue(
453 : : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
454 [ # # ][ # # ]: 0 : uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.sun.star.oleobject" ) ) ) );
[ # # ][ # # ]
455 : :
456 [ # # ][ # # ]: 0 : xStm->getOutputStream()->closeOutput();
[ # # ][ # # ]
[ # # ]
457 : : }
458 [ # # ]: 0 : catch ( uno::Exception& )
459 : : {
460 : 0 : return sal_False;
461 : : }
462 : : }
463 : : else
464 : : {
465 : : try
466 : : {
467 [ # # ][ # # ]: 0 : xCntnrStor->copyElementTo( aSrcObjName, xDocStor, rObjName );
[ # # ][ # # ]
468 : : }
469 [ # # ]: 0 : catch ( uno::Exception& )
470 : : {
471 : 0 : return sal_False;
472 : : }
473 : : }
474 : : }
475 : :
476 : : // make object known to the container
477 : : // TODO/LATER: could be done a little bit more efficient!
478 : 2 : ::rtl::OUString aName( rObjName );
479 : :
480 : : // TODO/LATER: The provided pClassId is ignored for now.
481 : : // The stream contains OLE storage internally and this storage already has a class id specifying the
482 : : // server that was used to create the object. pClassId could be used to specify the server that should
483 : : // be used for the next opening, but this information seems to be out of the file format responsibility
484 : : // area.
485 [ + - ]: 2 : rContainer.GetEmbeddedObject( aName );
486 : :
487 [ + - ]: 2 : return sal_True;
488 : : }
489 : :
490 : : // -----------------------------------------------------------------------------
491 : :
492 : 2 : ::rtl::OUString SvXMLEmbeddedObjectHelper::ImplInsertEmbeddedObjectURL(
493 : : const ::rtl::OUString& rURLStr )
494 : : {
495 : 2 : ::rtl::OUString sRetURL;
496 : :
497 : 2 : ::rtl::OUString aContainerStorageName, aObjectStorageName;
498 [ + - ]: 2 : if( !ImplGetStorageNames( rURLStr, aContainerStorageName,
499 : : aObjectStorageName,
500 [ + - ]: 2 : EMBEDDEDOBJECTHELPER_MODE_WRITE == meCreateMode ) )
501 : : return sRetURL;
502 : :
503 [ + - ]: 2 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
504 : : {
505 : 2 : OutputStorageWrapper_Impl *pOut = 0;
506 : 2 : SvXMLEmbeddedObjectHelper_Impl::iterator aIter;
507 : :
508 [ - + ]: 2 : if( mpStreamMap )
509 : : {
510 [ # # ]: 0 : aIter = mpStreamMap->find( rURLStr );
511 [ # # ][ # # ]: 0 : if( aIter != mpStreamMap->end() && aIter->second )
[ # # ][ # # ]
512 : 0 : pOut = aIter->second;
513 : : }
514 : :
515 [ + - ]: 2 : SvGlobalName aClassId, *pClassId = 0;
516 : 2 : sal_Int32 nPos = aObjectStorageName.lastIndexOf( '!' );
517 [ # # ][ # # ]: 2 : if( -1 != nPos && aClassId.MakeId( aObjectStorageName.copy( nPos+1 ) ) )
[ # # ][ - + ]
[ # # ][ - + ]
[ - + # #
# # ][ - + ]
518 : : {
519 : 0 : aObjectStorageName = aObjectStorageName.copy( 0, nPos );
520 : 0 : pClassId = &aClassId;
521 : : }
522 : :
523 [ - + ][ + - ]: 2 : ImplReadObject( aContainerStorageName, aObjectStorageName, pClassId, pOut ? pOut->GetStream() : 0 );
524 [ + - ]: 2 : sRetURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(XML_EMBEDDEDOBJECT_URL_BASE) );
525 : 2 : sRetURL += aObjectStorageName;
526 : :
527 [ - + ]: 2 : if( pOut )
528 : : {
529 [ # # ]: 0 : mpStreamMap->erase( aIter );
530 : 0 : pOut->release();
531 [ + - ]: 2 : }
532 : : }
533 : : else
534 : : {
535 : : // Objects are written using ::comphelper::IEmbeddedHelper::SaveAs
536 [ # # ]: 0 : sRetURL = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("./") );
537 [ # # ]: 0 : if( !aContainerStorageName.isEmpty() )
538 : : {
539 : 0 : sRetURL += aContainerStorageName;
540 : 0 : sRetURL += ::rtl::OUString( '/' );
541 : : }
542 : 0 : sRetURL += aObjectStorageName;
543 : : }
544 : :
545 : 2 : return sRetURL;
546 : : }
547 : :
548 : : // -----------------------------------------------------------------------------
549 : :
550 : 0 : uno::Reference< io::XInputStream > SvXMLEmbeddedObjectHelper::ImplGetReplacementImage(
551 : : const uno::Reference< embed::XEmbeddedObject >& xObj )
552 : : {
553 : 0 : uno::Reference< io::XInputStream > xStream;
554 : :
555 [ # # ]: 0 : if( xObj.is() )
556 : : {
557 : : try
558 : : {
559 : 0 : sal_Bool bSwitchBackToLoaded = sal_False;
560 [ # # ][ # # ]: 0 : sal_Int32 nCurState = xObj->getCurrentState();
561 [ # # ][ # # ]: 0 : if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING )
562 : : {
563 : : // means that the object is not active
564 : : // copy replacement image from old to new container
565 : 0 : ::rtl::OUString aMediaType;
566 [ # # ][ # # ]: 0 : xStream = mpDocPersist->getEmbeddedObjectContainer().GetGraphicStream( xObj, &aMediaType );
[ # # ]
567 : : }
568 : :
569 [ # # ]: 0 : if ( !xStream.is() )
570 : : {
571 : : // the image must be regenerated
572 : : // TODO/LATER: another aspect could be used
573 [ # # ]: 0 : if ( nCurState == embed::EmbedStates::LOADED )
574 : 0 : bSwitchBackToLoaded = sal_True;
575 : :
576 : 0 : ::rtl::OUString aMediaType;
577 : : xStream = svt::EmbeddedObjectRef::GetGraphicReplacementStream(
578 : : embed::Aspects::MSOLE_CONTENT,
579 : : xObj,
580 [ # # ][ # # ]: 0 : &aMediaType );
581 : : }
582 : :
583 [ # # ]: 0 : if ( bSwitchBackToLoaded )
584 : : // switch back to loaded state; that way we have a minimum cache confusion
585 [ # # ][ # # ]: 0 : xObj->changeState( embed::EmbedStates::LOADED );
586 : : }
587 [ # # ]: 0 : catch( uno::Exception& )
588 : : {}
589 : : }
590 : :
591 : 0 : return xStream;
592 : : }
593 : :
594 : : // -----------------------------------------------------------------------------
595 : :
596 : 450 : void SvXMLEmbeddedObjectHelper::Init(
597 : : const uno::Reference < embed::XStorage >& rRootStorage,
598 : : ::comphelper::IEmbeddedHelper& rPersist,
599 : : SvXMLEmbeddedObjectHelperMode eCreateMode )
600 : : {
601 : 450 : mxRootStorage = rRootStorage;
602 : 450 : mpDocPersist = &rPersist;
603 : 450 : meCreateMode = eCreateMode;
604 : 450 : }
605 : :
606 : : // -----------------------------------------------------------------------------
607 : :
608 : 200 : SvXMLEmbeddedObjectHelper* SvXMLEmbeddedObjectHelper::Create(
609 : : const uno::Reference < embed::XStorage >& rRootStorage,
610 : : ::comphelper::IEmbeddedHelper& rDocPersist,
611 : : SvXMLEmbeddedObjectHelperMode eCreateMode,
612 : : sal_Bool bDirect )
613 : : {
614 : : (void)bDirect;
615 : :
616 [ + - ]: 200 : SvXMLEmbeddedObjectHelper* pThis = new SvXMLEmbeddedObjectHelper;
617 : :
618 : 200 : pThis->acquire();
619 : 200 : pThis->Init( rRootStorage, rDocPersist, eCreateMode );
620 : :
621 : 200 : return pThis;
622 : : }
623 : :
624 : 40 : SvXMLEmbeddedObjectHelper* SvXMLEmbeddedObjectHelper::Create(
625 : : ::comphelper::IEmbeddedHelper& rDocPersist,
626 : : SvXMLEmbeddedObjectHelperMode eCreateMode )
627 : : {
628 [ + - ]: 40 : SvXMLEmbeddedObjectHelper* pThis = new SvXMLEmbeddedObjectHelper;
629 : :
630 : 40 : pThis->acquire();
631 [ + - ]: 40 : pThis->Init( 0, rDocPersist, eCreateMode );
632 : :
633 : 40 : return pThis;
634 : : }
635 : :
636 : : // -----------------------------------------------------------------------------
637 : :
638 : 240 : void SvXMLEmbeddedObjectHelper::Destroy(
639 : : SvXMLEmbeddedObjectHelper* pSvXMLEmbeddedObjectHelper )
640 : : {
641 [ + - ]: 240 : if( pSvXMLEmbeddedObjectHelper )
642 : : {
643 : 240 : pSvXMLEmbeddedObjectHelper->dispose();
644 : 240 : pSvXMLEmbeddedObjectHelper->release();
645 : : }
646 : 240 : }
647 : :
648 : : // -----------------------------------------------------------------------------
649 : :
650 : 450 : void SvXMLEmbeddedObjectHelper::Flush()
651 : : {
652 [ - + ]: 450 : if( mxTempStorage.is() )
653 : : {
654 [ # # ]: 0 : Reference < XComponent > xComp( mxTempStorage, UNO_QUERY );
655 [ # # ][ # # ]: 0 : xComp->dispose();
656 : : }
657 : 450 : }
658 : :
659 : : // XGraphicObjectResolver: alien objects!
660 : 2 : ::rtl::OUString SAL_CALL SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL( const ::rtl::OUString& aURL )
661 : : throw(RuntimeException)
662 : : {
663 [ + - ]: 2 : MutexGuard aGuard( maMutex );
664 : :
665 [ + - ][ + - ]: 2 : return ImplInsertEmbeddedObjectURL( aURL );
666 : : }
667 : :
668 : : // XNameAccess: alien objects!
669 : 0 : Any SAL_CALL SvXMLEmbeddedObjectHelper::getByName(
670 : : const ::rtl::OUString& rURLStr )
671 : : throw (NoSuchElementException, WrappedTargetException, RuntimeException)
672 : : {
673 [ # # ]: 0 : MutexGuard aGuard( maMutex );
674 : 0 : Any aRet;
675 [ # # ]: 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
676 : : {
677 : 0 : Reference < XOutputStream > xStrm;
678 [ # # ]: 0 : if( mpStreamMap )
679 : : {
680 : : SvXMLEmbeddedObjectHelper_Impl::iterator aIter =
681 [ # # ]: 0 : mpStreamMap->find( rURLStr );
682 [ # # ][ # # ]: 0 : if( aIter != mpStreamMap->end() && aIter->second )
[ # # ][ # # ]
683 [ # # ][ # # ]: 0 : xStrm = aIter->second;
684 : : }
685 [ # # ]: 0 : if( !xStrm.is() )
686 : : {
687 [ # # ]: 0 : OutputStorageWrapper_Impl *pOut = new OutputStorageWrapper_Impl;
688 : 0 : pOut->acquire();
689 [ # # ]: 0 : if( !mpStreamMap )
690 [ # # ][ # # ]: 0 : mpStreamMap = new SvXMLEmbeddedObjectHelper_Impl;
691 [ # # ]: 0 : (*mpStreamMap)[rURLStr] = pOut;
692 [ # # ][ # # ]: 0 : xStrm = pOut;
693 : : }
694 : :
695 [ # # ]: 0 : aRet <<= xStrm;
696 : : }
697 : : else
698 : : {
699 : 0 : sal_Bool bGraphicRepl = sal_False;
700 : 0 : sal_Bool bOasisFormat = sal_True;
701 : 0 : Reference < XInputStream > xStrm;
702 : 0 : ::rtl::OUString aContainerStorageName, aObjectStorageName;
703 [ # # ]: 0 : if( ImplGetStorageNames( rURLStr, aContainerStorageName,
704 : : aObjectStorageName,
705 : : sal_True,
706 : : &bGraphicRepl,
707 [ # # ]: 0 : &bOasisFormat ) )
708 : : {
709 : : try
710 : : {
711 : : comphelper::EmbeddedObjectContainer& rContainer =
712 [ # # ]: 0 : mpDocPersist->getEmbeddedObjectContainer();
713 : :
714 [ # # ]: 0 : Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( aObjectStorageName );
715 : : DBG_ASSERT( xObj.is(), "Didn't get object" );
716 : :
717 [ # # ]: 0 : if( xObj.is() )
718 : : {
719 [ # # ]: 0 : if( bGraphicRepl )
720 : : {
721 [ # # ][ # # ]: 0 : xStrm = ImplGetReplacementImage( xObj );
722 : : }
723 : : else
724 : : {
725 [ # # ]: 0 : Reference < embed::XEmbedPersist > xPersist( xObj, UNO_QUERY );
726 [ # # ]: 0 : if( xPersist.is() )
727 : : {
728 [ # # ]: 0 : if( !mxTempStorage.is() )
729 : : mxTempStorage =
730 [ # # ][ # # ]: 0 : comphelper::OStorageHelper::GetTemporaryStorage();
731 [ # # ][ # # ]: 0 : Sequence < beans::PropertyValue > aDummy( 0 ), aEmbDescr( 1 );
732 [ # # ][ # # ]: 0 : aEmbDescr[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StoreVisualReplacement" ) );
733 [ # # ][ # # ]: 0 : aEmbDescr[0].Value <<= (sal_Bool)(!bOasisFormat);
734 [ # # ]: 0 : if ( !bOasisFormat )
735 : : {
736 [ # # ]: 0 : uno::Reference< io::XInputStream > xGrInStream = ImplGetReplacementImage( xObj );
737 [ # # ]: 0 : if ( xGrInStream.is() )
738 : : {
739 [ # # ]: 0 : aEmbDescr.realloc( 2 );
740 [ # # ][ # # ]: 0 : aEmbDescr[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VisualReplacement" ) );
741 [ # # ][ # # ]: 0 : aEmbDescr[1].Value <<= xGrInStream;
742 : 0 : }
743 : : }
744 : :
745 [ # # ]: 0 : xPersist->storeToEntry( mxTempStorage, aObjectStorageName,
746 [ # # ]: 0 : aDummy, aEmbDescr );
747 : : Reference < io::XStream > xStream =
748 [ # # ]: 0 : mxTempStorage->openStreamElement(
749 : : aObjectStorageName,
750 [ # # ]: 0 : embed::ElementModes::READ);
751 [ # # ]: 0 : if( xStream.is() )
752 [ # # ][ # # ]: 0 : xStrm = xStream->getInputStream();
[ # # ][ # # ]
[ # # ]
753 : 0 : }
754 : : }
755 [ # # ]: 0 : }
756 : : }
757 [ # # ]: 0 : catch ( uno::Exception& )
758 : : {
759 : : }
760 : : }
761 : :
762 [ # # ]: 0 : aRet <<= xStrm;
763 : : }
764 : :
765 [ # # ]: 0 : return aRet;
766 : : }
767 : :
768 : 0 : Sequence< ::rtl::OUString > SAL_CALL SvXMLEmbeddedObjectHelper::getElementNames()
769 : : throw (RuntimeException)
770 : : {
771 [ # # ]: 0 : MutexGuard aGuard( maMutex );
772 [ # # ][ # # ]: 0 : return Sequence< ::rtl::OUString >(0);
773 : : }
774 : :
775 : 0 : sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasByName( const ::rtl::OUString& rURLStr )
776 : : throw (RuntimeException)
777 : : {
778 [ # # ]: 0 : MutexGuard aGuard( maMutex );
779 [ # # ]: 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
780 : : {
781 : 0 : return sal_True;
782 : : }
783 : : else
784 : : {
785 : 0 : ::rtl::OUString aContainerStorageName, aObjectStorageName;
786 [ # # ]: 0 : if( !ImplGetStorageNames( rURLStr, aContainerStorageName,
787 : : aObjectStorageName,
788 [ # # ]: 0 : sal_True ) )
789 : 0 : return sal_False;
790 : :
791 [ # # ]: 0 : comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer();
792 : 0 : return !aObjectStorageName.isEmpty() &&
793 [ # # ][ # # ]: 0 : rContainer.HasEmbeddedObject( aObjectStorageName );
[ # # ]
794 [ # # ]: 0 : }
795 : : }
796 : :
797 : : // XNameAccess
798 : 0 : Type SAL_CALL SvXMLEmbeddedObjectHelper::getElementType()
799 : : throw (RuntimeException)
800 : : {
801 [ # # ]: 0 : MutexGuard aGuard( maMutex );
802 [ # # ]: 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
803 [ # # ]: 0 : return ::getCppuType((const Reference<XOutputStream>*)0);
804 : : else
805 [ # # ][ # # ]: 0 : return ::getCppuType((const Reference<XInputStream>*)0);
806 : : }
807 : :
808 : 0 : sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasElements()
809 : : throw (RuntimeException)
810 : : {
811 [ # # ]: 0 : MutexGuard aGuard( maMutex );
812 [ # # ]: 0 : if( EMBEDDEDOBJECTHELPER_MODE_READ == meCreateMode )
813 : : {
814 : 0 : return sal_True;
815 : : }
816 : : else
817 : : {
818 [ # # ]: 0 : comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer();
819 [ # # ]: 0 : return rContainer.HasEmbeddedObjects();
820 [ # # ]: 0 : }
821 : : }
822 : :
823 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|