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