/src/libreoffice/svx/source/xml/xmleohlp.cxx
Line | Count | Source |
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 <com/sun/star/io/XStream.hpp> |
22 | | #include <com/sun/star/beans/XPropertySet.hpp> |
23 | | #include <com/sun/star/embed/XTransactedObject.hpp> |
24 | | #include <com/sun/star/embed/ElementModes.hpp> |
25 | | #include <com/sun/star/embed/XEmbeddedObject.hpp> |
26 | | #include <com/sun/star/embed/XEmbedPersist.hpp> |
27 | | #include <com/sun/star/embed/EmbedStates.hpp> |
28 | | #include <com/sun/star/embed/Aspects.hpp> |
29 | | #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> |
30 | | #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
31 | | #include <com/sun/star/util/XCancellable.hpp> |
32 | | #include <osl/diagnose.h> |
33 | | #include <sot/storage.hxx> |
34 | | #include <tools/debug.hxx> |
35 | | #include <tools/globname.hxx> |
36 | | #include <sal/log.hxx> |
37 | | #include <unotools/streamwrap.hxx> |
38 | | #include <unotools/tempfile.hxx> |
39 | | |
40 | | #include <svtools/embedhlp.hxx> |
41 | | #include <unotools/ucbstreamhelper.hxx> |
42 | | #include <comphelper/diagnose_ex.hxx> |
43 | | #include <comphelper/propertyvalue.hxx> |
44 | | #include <comphelper/storagehelper.hxx> |
45 | | #include <comphelper/embeddedobjectcontainer.hxx> |
46 | | |
47 | | #include <comphelper/fileformat.h> |
48 | | #include <cppuhelper/exc_hlp.hxx> |
49 | | #include <cppuhelper/implbase.hxx> |
50 | | #include <svx/xmleohlp.hxx> |
51 | | #include <xmloff/xmlgrhlp.hxx> |
52 | | #include <map> |
53 | | #include <memory> |
54 | | #include <mutex> |
55 | | |
56 | | using namespace ::cppu; |
57 | | using namespace ::utl; |
58 | | using namespace ::com::sun::star; |
59 | | using namespace ::com::sun::star::document; |
60 | | using namespace ::com::sun::star::uno; |
61 | | using namespace ::com::sun::star::container; |
62 | | using namespace ::com::sun::star::io; |
63 | | using namespace ::com::sun::star::lang; |
64 | | |
65 | | constexpr OUStringLiteral XML_CONTAINERSTORAGE_NAME_60 = u"Pictures"; |
66 | | constexpr OUStringLiteral XML_CONTAINERSTORAGE_NAME = u"ObjectReplacements"; |
67 | | constexpr OUString XML_EMBEDDEDOBJECT_URL_BASE = u"vnd.sun.star.EmbeddedObject:"_ustr; |
68 | | constexpr OUStringLiteral XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE = u"vnd.sun.star.GraphicObject:"; |
69 | | |
70 | | |
71 | | class OutputStorageWrapper_Impl : public ::cppu::WeakImplHelper<XOutputStream> |
72 | | { |
73 | | std::mutex maMutex; |
74 | | rtl::Reference < OOutputStreamWrapper > xOut; |
75 | | TempFileFast aTempFile; |
76 | | bool bStreamClosed : 1; |
77 | | SvStream* pStream; |
78 | | |
79 | | public: |
80 | | OutputStorageWrapper_Impl(); |
81 | | |
82 | | // css::io::XOutputStream |
83 | | virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) override; |
84 | | virtual void SAL_CALL flush() override; |
85 | | virtual void SAL_CALL closeOutput() override; |
86 | | |
87 | | SvStream* GetStream(); |
88 | | }; |
89 | | |
90 | | OutputStorageWrapper_Impl::OutputStorageWrapper_Impl() |
91 | 232 | : bStreamClosed( false ) |
92 | 232 | , pStream(nullptr) |
93 | 232 | { |
94 | 232 | pStream = aTempFile.GetStream( StreamMode::READWRITE ); |
95 | 232 | xOut = new OOutputStreamWrapper( *pStream ); |
96 | 232 | } |
97 | | |
98 | | SvStream *OutputStorageWrapper_Impl::GetStream() |
99 | 204 | { |
100 | 204 | if( bStreamClosed ) |
101 | 204 | return pStream; |
102 | 0 | return nullptr; |
103 | 204 | } |
104 | | |
105 | | void SAL_CALL OutputStorageWrapper_Impl::writeBytes( |
106 | | const Sequence< sal_Int8 >& aData) |
107 | 222 | { |
108 | 222 | std::scoped_lock aGuard( maMutex ); |
109 | 222 | xOut->writeBytes( aData ); |
110 | 222 | } |
111 | | |
112 | | void SAL_CALL OutputStorageWrapper_Impl::flush() |
113 | 0 | { |
114 | 0 | std::scoped_lock aGuard( maMutex ); |
115 | 0 | xOut->flush(); |
116 | 0 | } |
117 | | |
118 | | void SAL_CALL OutputStorageWrapper_Impl::closeOutput() |
119 | 207 | { |
120 | 207 | std::scoped_lock aGuard( maMutex ); |
121 | 207 | xOut->closeOutput(); |
122 | 207 | bStreamClosed = true; |
123 | 207 | } |
124 | | |
125 | | SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() : |
126 | 0 | mpDocPersist( nullptr ), |
127 | 0 | meCreateMode( SvXMLEmbeddedObjectHelperMode::Read ) |
128 | 0 | { |
129 | 0 | } Unexecuted instantiation: SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() Unexecuted instantiation: SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper() |
130 | | |
131 | | SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper( ::comphelper::IEmbeddedHelper& rDocPersist, SvXMLEmbeddedObjectHelperMode eCreateMode ) : |
132 | 33.9k | mpDocPersist( nullptr ), |
133 | 33.9k | meCreateMode( SvXMLEmbeddedObjectHelperMode::Read ) |
134 | 33.9k | { |
135 | 33.9k | Init( nullptr, rDocPersist, eCreateMode ); |
136 | 33.9k | } Unexecuted instantiation: SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper(comphelper::IEmbeddedHelper&, SvXMLEmbeddedObjectHelperMode) SvXMLEmbeddedObjectHelper::SvXMLEmbeddedObjectHelper(comphelper::IEmbeddedHelper&, SvXMLEmbeddedObjectHelperMode) Line | Count | Source | 132 | 33.9k | mpDocPersist( nullptr ), | 133 | 33.9k | meCreateMode( SvXMLEmbeddedObjectHelperMode::Read ) | 134 | 33.9k | { | 135 | 33.9k | Init( nullptr, rDocPersist, eCreateMode ); | 136 | 33.9k | } |
|
137 | | |
138 | | SvXMLEmbeddedObjectHelper::~SvXMLEmbeddedObjectHelper() |
139 | 33.9k | { |
140 | 33.9k | } |
141 | | |
142 | | void SvXMLEmbeddedObjectHelper::disposing(std::unique_lock<std::mutex>&) |
143 | 5.84k | { |
144 | 5.84k | if( mxTempStorage.is() ) |
145 | 0 | { |
146 | 0 | mxTempStorage->dispose(); |
147 | 0 | mxTempStorage.clear(); |
148 | 0 | } |
149 | 5.84k | } |
150 | | |
151 | | bool SvXMLEmbeddedObjectHelper::ImplGetStorageNames( |
152 | | const OUString& rURLStr, |
153 | | OUString& rContainerStorageName, |
154 | | OUString& rObjectStorageName, |
155 | | bool bInternalToExternal, |
156 | | bool *pGraphicRepl, |
157 | | bool *pOasisFormat ) const |
158 | 204 | { |
159 | | // internal URL: vnd.sun.star.EmbeddedObject:<object-name> |
160 | | // or: vnd.sun.star.EmbeddedObject:<path>/<object-name> |
161 | | // internal replacement images: |
162 | | // vnd.sun.star.EmbeddedObjectGraphic:<object-name> |
163 | | // or: vnd.sun.star.EmbeddedObjectGraphic:<path>/<object-name> |
164 | | // external URL: ./<path>/<object-name> |
165 | | // or: <path>/<object-name> |
166 | | // or: <object-name> |
167 | | // currently, path may only consist of a single directory name |
168 | | // it is also possible to have additional arguments at the end of URL: <main URL>[?<name>=<value>[,<name>=<value>]*] |
169 | | |
170 | 204 | if( pGraphicRepl ) |
171 | 0 | *pGraphicRepl = false; |
172 | | |
173 | 204 | if( pOasisFormat ) |
174 | 0 | *pOasisFormat = true; // the default value |
175 | | |
176 | 204 | if( rURLStr.isEmpty() ) |
177 | 0 | return false; |
178 | | |
179 | | // get rid of arguments |
180 | 204 | sal_Int32 nPos = rURLStr.indexOf( '?' ); |
181 | 204 | OUString aURLNoPar; |
182 | 204 | if ( nPos == -1 ) |
183 | 204 | aURLNoPar = rURLStr; |
184 | 0 | else |
185 | 0 | { |
186 | 0 | aURLNoPar = rURLStr.copy( 0, nPos ); |
187 | | |
188 | | // check the arguments |
189 | 0 | nPos++; |
190 | 0 | while( nPos >= 0 && nPos < rURLStr.getLength() ) |
191 | 0 | { |
192 | 0 | OUString aToken = rURLStr.getToken( 0, ',', nPos ); |
193 | 0 | if ( aToken.equalsIgnoreAsciiCase( "oasis=false" ) ) |
194 | 0 | { |
195 | 0 | if ( pOasisFormat ) |
196 | 0 | *pOasisFormat = false; |
197 | 0 | break; |
198 | 0 | } |
199 | 0 | else |
200 | 0 | { |
201 | 0 | SAL_WARN( "svx", "invalid arguments was found in URL!" ); |
202 | 0 | } |
203 | 0 | } |
204 | 0 | } |
205 | | |
206 | 204 | if( bInternalToExternal ) |
207 | 0 | { |
208 | 0 | nPos = aURLNoPar.indexOf( ':' ); |
209 | 0 | if( -1 == nPos ) |
210 | 0 | return false; |
211 | 0 | bool bObjUrl = aURLNoPar.startsWith( XML_EMBEDDEDOBJECT_URL_BASE ); |
212 | 0 | bool bGrUrl = !bObjUrl && |
213 | 0 | aURLNoPar.startsWith( XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE ); |
214 | 0 | if( !(bObjUrl || bGrUrl) ) |
215 | 0 | return false; |
216 | | |
217 | 0 | sal_Int32 nPathStart = nPos + 1; |
218 | 0 | nPos = aURLNoPar.lastIndexOf( '/' ); |
219 | 0 | if( -1 == nPos ) |
220 | 0 | { |
221 | 0 | rContainerStorageName.clear(); |
222 | 0 | rObjectStorageName = aURLNoPar.copy( nPathStart ); |
223 | 0 | } |
224 | 0 | else if( nPos > nPathStart ) |
225 | 0 | { |
226 | 0 | rContainerStorageName = aURLNoPar.copy( nPathStart, nPos-nPathStart); |
227 | 0 | rObjectStorageName = aURLNoPar.copy( nPos+1 ); |
228 | 0 | } |
229 | 0 | else |
230 | 0 | return false; |
231 | | |
232 | 0 | if( bGrUrl ) |
233 | 0 | { |
234 | 0 | bool bOASIS = mxRootStorage.is() && |
235 | 0 | ( SotStorage::GetVersion( mxRootStorage ) > SOFFICE_FILEFORMAT_60 ); |
236 | 0 | if (bOASIS) |
237 | 0 | rContainerStorageName = XML_CONTAINERSTORAGE_NAME; |
238 | 0 | else |
239 | 0 | rContainerStorageName = XML_CONTAINERSTORAGE_NAME_60; |
240 | |
|
241 | 0 | if( pGraphicRepl ) |
242 | 0 | *pGraphicRepl = true; |
243 | 0 | } |
244 | | |
245 | |
|
246 | 0 | } |
247 | 204 | else |
248 | 204 | { |
249 | 204 | SvXMLGraphicHelper::splitObjectURL(aURLNoPar, rContainerStorageName, rObjectStorageName); |
250 | 204 | } |
251 | | |
252 | 204 | if( -1 != rContainerStorageName.indexOf( '/' ) ) |
253 | 0 | { |
254 | 0 | OSL_FAIL( "SvXMLEmbeddedObjectHelper: invalid path name" ); |
255 | 0 | return false; |
256 | 0 | } |
257 | | |
258 | 204 | return true; |
259 | 204 | } |
260 | | |
261 | | uno::Reference < embed::XStorage > const & SvXMLEmbeddedObjectHelper::ImplGetContainerStorage( |
262 | | const OUString& rStorageName ) |
263 | 204 | { |
264 | 204 | DBG_ASSERT( -1 == rStorageName.indexOf( '/' ) && |
265 | 204 | -1 == rStorageName.indexOf( '\\' ), |
266 | 204 | "nested embedded storages aren't supported" ); |
267 | 204 | if( !mxContainerStorage.is() || |
268 | 0 | ( rStorageName != maCurContainerStorageName ) ) |
269 | 204 | { |
270 | 204 | if( mxContainerStorage.is() && |
271 | 0 | !maCurContainerStorageName.isEmpty() && |
272 | 0 | SvXMLEmbeddedObjectHelperMode::Write == meCreateMode ) |
273 | 0 | { |
274 | 0 | uno::Reference < embed::XTransactedObject > xTrans( mxContainerStorage, uno::UNO_QUERY ); |
275 | 0 | if ( xTrans.is() ) |
276 | 0 | xTrans->commit(); |
277 | 0 | } |
278 | | |
279 | 204 | if( !rStorageName.isEmpty() && mxRootStorage.is() ) |
280 | 0 | { |
281 | 0 | sal_Int32 nMode = SvXMLEmbeddedObjectHelperMode::Write == meCreateMode |
282 | 0 | ? ::embed::ElementModes::READWRITE |
283 | 0 | : ::embed::ElementModes::READ; |
284 | 0 | mxContainerStorage = mxRootStorage->openStorageElement( rStorageName, |
285 | 0 | nMode ); |
286 | 0 | } |
287 | 204 | else |
288 | 204 | { |
289 | 204 | mxContainerStorage = mxRootStorage; |
290 | 204 | } |
291 | 204 | maCurContainerStorageName = rStorageName; |
292 | 204 | } |
293 | | |
294 | 204 | return mxContainerStorage; |
295 | 204 | } |
296 | | |
297 | | void SvXMLEmbeddedObjectHelper::ImplReadObject( |
298 | | const OUString& rContainerStorageName, |
299 | | OUString& rObjName, |
300 | | const SvGlobalName *, // pClassId, see "TODO/LATER" below |
301 | | SvStream* pTemp ) |
302 | 204 | { |
303 | 204 | uno::Reference < embed::XStorage > xDocStor( mpDocPersist->getStorage() ); |
304 | 204 | uno::Reference < embed::XStorage > xCntnrStor( ImplGetContainerStorage( rContainerStorageName ) ); |
305 | | |
306 | 204 | if( !xCntnrStor.is() && !pTemp ) |
307 | 0 | return; |
308 | | |
309 | 204 | OUString aSrcObjName( rObjName ); |
310 | 204 | comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer(); |
311 | | |
312 | | // Is the object name unique? |
313 | | // if the object is already instantiated by GetEmbeddedObject |
314 | | // that means that the duplication is being loaded |
315 | 204 | bool bDuplicate = rContainer.HasInstantiatedEmbeddedObject( rObjName ); |
316 | 204 | DBG_ASSERT( !bDuplicate, "An object in the document is referenced twice!" ); |
317 | | |
318 | 204 | if( xDocStor != xCntnrStor || pTemp || bDuplicate ) |
319 | 204 | { |
320 | | // TODO/LATER: make this altogether a method in the EmbeddedObjectContainer |
321 | | |
322 | | // create a unique name for the duplicate object |
323 | 204 | if( bDuplicate ) |
324 | 0 | rObjName = rContainer.CreateUniqueObjectName(); |
325 | | |
326 | 204 | if( pTemp ) |
327 | 204 | { |
328 | 204 | try |
329 | 204 | { |
330 | 204 | pTemp->Seek( 0 ); |
331 | 204 | uno::Reference < io::XStream > xStm = xDocStor->openStreamElement( rObjName, |
332 | 204 | embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ); |
333 | 204 | std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( xStm )); |
334 | 204 | pTemp->ReadStream( *pStream ); |
335 | 204 | pStream.reset(); |
336 | | |
337 | | // TODO/LATER: what to do when other types of objects are based on substream persistence? |
338 | | // This is an ole object |
339 | 204 | uno::Reference< beans::XPropertySet > xProps( xStm, uno::UNO_QUERY ); |
340 | 204 | if (xProps) |
341 | 204 | { |
342 | 204 | xProps->setPropertyValue( |
343 | 204 | u"MediaType"_ustr, |
344 | 204 | uno::Any( u"application/vnd.sun.star.oleobject"_ustr ) ); |
345 | | |
346 | | |
347 | 204 | xStm->getOutputStream()->closeOutput(); |
348 | 204 | } |
349 | 204 | } |
350 | 204 | catch ( uno::Exception& ) |
351 | 204 | { |
352 | 0 | return; |
353 | 0 | } |
354 | 204 | } |
355 | 0 | else |
356 | 0 | { |
357 | 0 | try |
358 | 0 | { |
359 | 0 | xCntnrStor->copyElementTo( aSrcObjName, xDocStor, rObjName ); |
360 | 0 | } |
361 | 0 | catch ( uno::Exception& ) |
362 | 0 | { |
363 | 0 | return; |
364 | 0 | } |
365 | 0 | } |
366 | 204 | } |
367 | | |
368 | | // make object known to the container |
369 | | // TODO/LATER: could be done a little bit more efficient! |
370 | 204 | OUString aName( rObjName ); |
371 | | |
372 | | // TODO/LATER: The provided pClassId is ignored for now. |
373 | | // The stream contains OLE storage internally and this storage already has a class id specifying the |
374 | | // server that was used to create the object. pClassId could be used to specify the server that should |
375 | | // be used for the next opening, but this information seems to be out of the file format responsibility |
376 | | // area. |
377 | 204 | OUString const baseURL(mpDocPersist->getDocumentBaseURL()); |
378 | 204 | rContainer.GetEmbeddedObject(aName, &baseURL); |
379 | 204 | } |
380 | | |
381 | | OUString SvXMLEmbeddedObjectHelper::ImplInsertEmbeddedObjectURL( |
382 | | const OUString& rURLStr ) |
383 | 204 | { |
384 | 204 | OUString sRetURL; |
385 | | |
386 | 204 | OUString aContainerStorageName, aObjectStorageName; |
387 | 204 | if( !ImplGetStorageNames( rURLStr, aContainerStorageName, |
388 | 204 | aObjectStorageName, |
389 | 204 | SvXMLEmbeddedObjectHelperMode::Write == meCreateMode ) ) |
390 | 0 | return sRetURL; |
391 | | |
392 | 204 | if( SvXMLEmbeddedObjectHelperMode::Read == meCreateMode ) |
393 | 204 | { |
394 | 204 | OutputStorageWrapper_Impl *pOut = nullptr; |
395 | 204 | std::map< OUString, rtl::Reference<OutputStorageWrapper_Impl> >::iterator aIter; |
396 | | |
397 | 204 | if( mxStreamMap ) |
398 | 204 | { |
399 | 204 | aIter = mxStreamMap->find( rURLStr ); |
400 | 204 | if( aIter != mxStreamMap->end() && aIter->second.is() ) |
401 | 204 | pOut = aIter->second.get(); |
402 | 204 | } |
403 | | |
404 | 204 | SvGlobalName aClassId, *pClassId = nullptr; |
405 | 204 | sal_Int32 nPos = aObjectStorageName.lastIndexOf( '!' ); |
406 | 204 | if( -1 != nPos && aClassId.MakeId( aObjectStorageName.subView( nPos+1 ) ) ) |
407 | 0 | { |
408 | 0 | aObjectStorageName = aObjectStorageName.copy( 0, nPos ); |
409 | 0 | pClassId = &aClassId; |
410 | 0 | } |
411 | | |
412 | 204 | ImplReadObject( aContainerStorageName, aObjectStorageName, pClassId, pOut ? pOut->GetStream() : nullptr ); |
413 | 204 | sRetURL = XML_EMBEDDEDOBJECT_URL_BASE + aObjectStorageName; |
414 | | |
415 | 204 | if( pOut ) |
416 | 204 | { |
417 | 204 | mxStreamMap->erase( aIter ); |
418 | 204 | } |
419 | 204 | } |
420 | 0 | else |
421 | 0 | { |
422 | | // Objects are written using ::comphelper::IEmbeddedHelper::SaveAs |
423 | 0 | sRetURL = "./"; |
424 | 0 | if( !aContainerStorageName.isEmpty() ) |
425 | 0 | { |
426 | 0 | sRetURL += aContainerStorageName + "/"; |
427 | 0 | } |
428 | 0 | sRetURL += aObjectStorageName; |
429 | 0 | } |
430 | | |
431 | 204 | return sRetURL; |
432 | 204 | } |
433 | | |
434 | | uno::Reference< io::XInputStream > SvXMLEmbeddedObjectHelper::ImplGetReplacementImage( |
435 | | const uno::Reference< embed::XEmbeddedObject >& xObj ) |
436 | 0 | { |
437 | 0 | uno::Reference< io::XInputStream > xStream; |
438 | |
|
439 | 0 | if( xObj.is() ) |
440 | 0 | { |
441 | 0 | try |
442 | 0 | { |
443 | 0 | bool bSwitchBackToLoaded = false; |
444 | 0 | sal_Int32 nCurState = xObj->getCurrentState(); |
445 | 0 | if ( nCurState == embed::EmbedStates::LOADED || nCurState == embed::EmbedStates::RUNNING ) |
446 | 0 | { |
447 | | // means that the object is not active |
448 | | // copy replacement image from old to new container |
449 | 0 | OUString aMediaType; |
450 | 0 | xStream = mpDocPersist->getEmbeddedObjectContainer().GetGraphicStream( xObj, &aMediaType ); |
451 | 0 | } |
452 | |
|
453 | 0 | if ( !xStream.is() ) |
454 | 0 | { |
455 | | // the image must be regenerated |
456 | | // TODO/LATER: another aspect could be used |
457 | 0 | if ( nCurState == embed::EmbedStates::LOADED ) |
458 | 0 | bSwitchBackToLoaded = true; |
459 | |
|
460 | 0 | OUString aMediaType; |
461 | 0 | xStream = svt::EmbeddedObjectRef::GetGraphicReplacementStream( |
462 | 0 | embed::Aspects::MSOLE_CONTENT, |
463 | 0 | xObj, |
464 | 0 | &aMediaType ); |
465 | 0 | } |
466 | |
|
467 | 0 | if ( bSwitchBackToLoaded ) |
468 | | // switch back to loaded state; that way we have a minimum cache confusion |
469 | 0 | xObj->changeState( embed::EmbedStates::LOADED ); |
470 | 0 | } |
471 | 0 | catch( uno::Exception& ) |
472 | 0 | {} |
473 | 0 | } |
474 | |
|
475 | 0 | return xStream; |
476 | 0 | } |
477 | | |
478 | | void SvXMLEmbeddedObjectHelper::Init( |
479 | | const uno::Reference < embed::XStorage >& rRootStorage, |
480 | | ::comphelper::IEmbeddedHelper& rPersist, |
481 | | SvXMLEmbeddedObjectHelperMode eCreateMode ) |
482 | 33.9k | { |
483 | 33.9k | mxRootStorage = rRootStorage; |
484 | 33.9k | mpDocPersist = &rPersist; |
485 | 33.9k | meCreateMode = eCreateMode; |
486 | 33.9k | } |
487 | | |
488 | | rtl::Reference<SvXMLEmbeddedObjectHelper> SvXMLEmbeddedObjectHelper::Create( |
489 | | const uno::Reference < embed::XStorage >& rRootStorage, |
490 | | ::comphelper::IEmbeddedHelper& rDocPersist, |
491 | | SvXMLEmbeddedObjectHelperMode eCreateMode ) |
492 | 0 | { |
493 | 0 | rtl::Reference<SvXMLEmbeddedObjectHelper> pThis(new SvXMLEmbeddedObjectHelper); |
494 | |
|
495 | 0 | pThis->Init( rRootStorage, rDocPersist, eCreateMode ); |
496 | |
|
497 | 0 | return pThis; |
498 | 0 | } |
499 | | |
500 | | rtl::Reference<SvXMLEmbeddedObjectHelper> SvXMLEmbeddedObjectHelper::Create( |
501 | | ::comphelper::IEmbeddedHelper& rDocPersist, |
502 | | SvXMLEmbeddedObjectHelperMode eCreateMode ) |
503 | 0 | { |
504 | 0 | rtl::Reference<SvXMLEmbeddedObjectHelper> pThis(new SvXMLEmbeddedObjectHelper); |
505 | |
|
506 | 0 | pThis->Init( nullptr, rDocPersist, eCreateMode ); |
507 | |
|
508 | 0 | return pThis; |
509 | 0 | } |
510 | | |
511 | | OUString SAL_CALL SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL(const OUString& rURL) |
512 | 204 | { |
513 | 204 | std::unique_lock aGuard( m_aMutex ); |
514 | | |
515 | 204 | OUString sRet; |
516 | 204 | try |
517 | 204 | { |
518 | 204 | sRet = ImplInsertEmbeddedObjectURL(rURL); |
519 | 204 | } |
520 | 204 | catch (const RuntimeException&) |
521 | 204 | { |
522 | 0 | throw; |
523 | 0 | } |
524 | 204 | catch (const Exception&) |
525 | 204 | { |
526 | 0 | css::uno::Any anyEx = cppu::getCaughtException(); |
527 | 0 | throw WrappedTargetRuntimeException( |
528 | 0 | u"SvXMLEmbeddedObjectHelper::resolveEmbeddedObjectURL non-RuntimeException"_ustr, |
529 | 0 | getXWeak(), anyEx); |
530 | 0 | } |
531 | 204 | return sRet; |
532 | 204 | } |
533 | | |
534 | | // XNameAccess: alien objects! |
535 | | Any SAL_CALL SvXMLEmbeddedObjectHelper::getByName( |
536 | | const OUString& rURLStr ) |
537 | 232 | { |
538 | 232 | std::unique_lock aGuard( m_aMutex ); |
539 | 232 | Any aRet; |
540 | 232 | if( SvXMLEmbeddedObjectHelperMode::Read == meCreateMode ) |
541 | 232 | { |
542 | 232 | Reference < XOutputStream > xStrm; |
543 | 232 | if( mxStreamMap ) |
544 | 35 | { |
545 | 35 | auto aIter = mxStreamMap->find( rURLStr ); |
546 | 35 | if( aIter != mxStreamMap->end() && aIter->second.is() ) |
547 | 0 | xStrm = aIter->second.get(); |
548 | 35 | } |
549 | 232 | if( !xStrm.is() ) |
550 | 232 | { |
551 | 232 | rtl::Reference<OutputStorageWrapper_Impl> xOut = new OutputStorageWrapper_Impl; |
552 | 232 | if( !mxStreamMap ) |
553 | 197 | mxStreamMap.emplace(); |
554 | 232 | (*mxStreamMap)[rURLStr] = xOut; |
555 | 232 | xStrm = xOut.get(); |
556 | 232 | } |
557 | | |
558 | 232 | aRet <<= xStrm; |
559 | 232 | } |
560 | 0 | else |
561 | 0 | { |
562 | 0 | bool bGraphicRepl = false; |
563 | 0 | bool bOasisFormat = true; |
564 | 0 | Reference < XInputStream > xStrm; |
565 | 0 | OUString aContainerStorageName, aObjectStorageName; |
566 | 0 | if( ImplGetStorageNames( rURLStr, aContainerStorageName, |
567 | 0 | aObjectStorageName, |
568 | 0 | true, |
569 | 0 | &bGraphicRepl, |
570 | 0 | &bOasisFormat ) ) |
571 | 0 | { |
572 | 0 | try |
573 | 0 | { |
574 | 0 | comphelper::EmbeddedObjectContainer& rContainer = |
575 | 0 | mpDocPersist->getEmbeddedObjectContainer(); |
576 | |
|
577 | 0 | Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( aObjectStorageName ); |
578 | 0 | DBG_ASSERT( xObj.is(), "Didn't get object" ); |
579 | |
|
580 | 0 | if( xObj.is() ) |
581 | 0 | { |
582 | 0 | if( bGraphicRepl ) |
583 | 0 | { |
584 | 0 | xStrm = ImplGetReplacementImage( xObj ); |
585 | 0 | } |
586 | 0 | else |
587 | 0 | { |
588 | 0 | Reference < embed::XEmbedPersist > xPersist( xObj, UNO_QUERY ); |
589 | 0 | if( xPersist.is() ) |
590 | 0 | { |
591 | 0 | if( !mxTempStorage.is() ) |
592 | 0 | mxTempStorage = |
593 | 0 | comphelper::OStorageHelper::GetTemporaryStorage(); |
594 | 0 | Sequence < beans::PropertyValue > aDummy, |
595 | 0 | aEmbDescr{ comphelper::makePropertyValue(u"StoreVisualReplacement"_ustr, |
596 | 0 | !bOasisFormat) }; |
597 | 0 | if ( !bOasisFormat ) |
598 | 0 | { |
599 | 0 | uno::Reference< io::XInputStream > xGrInStream = ImplGetReplacementImage( xObj ); |
600 | 0 | if ( xGrInStream.is() ) |
601 | 0 | { |
602 | 0 | aEmbDescr.realloc( 2 ); |
603 | 0 | auto pEmbDescr = aEmbDescr.getArray(); |
604 | 0 | pEmbDescr[1].Name = "VisualReplacement"; |
605 | 0 | pEmbDescr[1].Value <<= xGrInStream; |
606 | 0 | } |
607 | 0 | } |
608 | |
|
609 | 0 | xPersist->storeToEntry( mxTempStorage, aObjectStorageName, |
610 | 0 | aDummy, aEmbDescr ); |
611 | 0 | Reference < io::XStream > xStream = |
612 | 0 | mxTempStorage->openStreamElement( |
613 | 0 | aObjectStorageName, |
614 | 0 | embed::ElementModes::READ); |
615 | 0 | if( xStream.is() ) |
616 | 0 | xStrm = xStream->getInputStream(); |
617 | 0 | } |
618 | 0 | } |
619 | 0 | } |
620 | 0 | } |
621 | 0 | catch ( uno::Exception& ) |
622 | 0 | { |
623 | 0 | } |
624 | 0 | } |
625 | |
|
626 | 0 | aRet <<= xStrm; |
627 | 0 | } |
628 | | |
629 | 232 | return aRet; |
630 | 232 | } |
631 | | |
632 | | Sequence< OUString > SAL_CALL SvXMLEmbeddedObjectHelper::getElementNames() |
633 | 0 | { |
634 | 0 | return {}; |
635 | 0 | } |
636 | | |
637 | | sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasByName( const OUString& rURLStr ) |
638 | 0 | { |
639 | 0 | std::unique_lock aGuard( m_aMutex ); |
640 | 0 | if( SvXMLEmbeddedObjectHelperMode::Read == meCreateMode ) |
641 | 0 | { |
642 | 0 | return true; |
643 | 0 | } |
644 | 0 | else |
645 | 0 | { |
646 | 0 | OUString aContainerStorageName, aObjectStorageName; |
647 | 0 | if( !ImplGetStorageNames( rURLStr, aContainerStorageName, |
648 | 0 | aObjectStorageName, |
649 | 0 | true ) ) |
650 | 0 | return false; |
651 | | |
652 | 0 | comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer(); |
653 | 0 | return !aObjectStorageName.isEmpty() && |
654 | 0 | rContainer.HasEmbeddedObject( aObjectStorageName ); |
655 | 0 | } |
656 | 0 | } |
657 | | |
658 | | // XNameAccess |
659 | | Type SAL_CALL SvXMLEmbeddedObjectHelper::getElementType() |
660 | 0 | { |
661 | 0 | std::unique_lock aGuard( m_aMutex ); |
662 | 0 | if( SvXMLEmbeddedObjectHelperMode::Read == meCreateMode ) |
663 | 0 | return cppu::UnoType<XOutputStream>::get(); |
664 | 0 | else |
665 | 0 | return cppu::UnoType<XInputStream>::get(); |
666 | 0 | } |
667 | | |
668 | | sal_Bool SAL_CALL SvXMLEmbeddedObjectHelper::hasElements() |
669 | 0 | { |
670 | 0 | std::unique_lock aGuard( m_aMutex ); |
671 | 0 | if( SvXMLEmbeddedObjectHelperMode::Read == meCreateMode ) |
672 | 0 | { |
673 | 0 | return true; |
674 | 0 | } |
675 | 0 | else |
676 | 0 | { |
677 | 0 | comphelper::EmbeddedObjectContainer& rContainer = mpDocPersist->getEmbeddedObjectContainer(); |
678 | 0 | return rContainer.HasEmbeddedObjects(); |
679 | 0 | } |
680 | 0 | } |
681 | | |
682 | | namespace svx { |
683 | | |
684 | | void DropUnusedNamedItems(css::uno::Reference<css::uno::XInterface> const& xModel) |
685 | 0 | { |
686 | 0 | uno::Reference<lang::XMultiServiceFactory> const xModelFactory(xModel, uno::UNO_QUERY); |
687 | 0 | assert(xModelFactory.is()); |
688 | 0 | try |
689 | 0 | { |
690 | 0 | uno::Reference<util::XCancellable> const xGradient( |
691 | 0 | xModelFactory->createInstance(u"com.sun.star.drawing.GradientTable"_ustr), |
692 | 0 | uno::UNO_QUERY ); |
693 | 0 | if (xGradient.is()) |
694 | 0 | { |
695 | 0 | xGradient->cancel(); |
696 | 0 | } |
697 | |
|
698 | 0 | uno::Reference<util::XCancellable> const xHatch( |
699 | 0 | xModelFactory->createInstance(u"com.sun.star.drawing.HatchTable"_ustr), |
700 | 0 | uno::UNO_QUERY ); |
701 | 0 | if (xHatch.is()) |
702 | 0 | { |
703 | 0 | xHatch->cancel(); |
704 | 0 | } |
705 | |
|
706 | 0 | uno::Reference<util::XCancellable> const xBitmap( |
707 | 0 | xModelFactory->createInstance(u"com.sun.star.drawing.BitmapTable"_ustr), |
708 | 0 | uno::UNO_QUERY ); |
709 | 0 | if (xBitmap.is()) |
710 | 0 | { |
711 | 0 | xBitmap->cancel(); |
712 | 0 | } |
713 | |
|
714 | 0 | uno::Reference<util::XCancellable> const xTransGradient( |
715 | 0 | xModelFactory->createInstance(u"com.sun.star.drawing.TransparencyGradientTable"_ustr), |
716 | 0 | uno::UNO_QUERY ); |
717 | 0 | if (xTransGradient.is()) |
718 | 0 | { |
719 | 0 | xTransGradient->cancel(); |
720 | 0 | } |
721 | |
|
722 | 0 | uno::Reference<util::XCancellable> const xMarker( |
723 | 0 | xModelFactory->createInstance(u"com.sun.star.drawing.MarkerTable"_ustr), |
724 | 0 | uno::UNO_QUERY ); |
725 | 0 | if (xMarker.is()) |
726 | 0 | { |
727 | 0 | xMarker->cancel(); |
728 | 0 | } |
729 | |
|
730 | 0 | uno::Reference<util::XCancellable> const xDashes( |
731 | 0 | xModelFactory->createInstance(u"com.sun.star.drawing.DashTable"_ustr), |
732 | 0 | uno::UNO_QUERY ); |
733 | 0 | if (xDashes.is()) |
734 | 0 | { |
735 | 0 | xDashes->cancel(); |
736 | 0 | } |
737 | 0 | } |
738 | 0 | catch (const Exception&) |
739 | 0 | { |
740 | 0 | TOOLS_WARN_EXCEPTION("svx", "dropUnusedNamedItems(): exception during clearing of unused named items"); |
741 | 0 | } |
742 | 0 | } |
743 | | |
744 | | } // namespace svx |
745 | | |
746 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |