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