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