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