xref: /AOO41X/main/svx/source/xml/xmleohlp.cxx (revision f6e50924346d0b8c0b07c91832a97665dd718b0c)
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 alltogether 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