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