/src/libreoffice/package/source/xstor/owriteablestream.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 | | #include <sal/config.h> |
21 | | |
22 | | #include <cassert> |
23 | | #include <memory> |
24 | | #include <sal/log.hxx> |
25 | | |
26 | | #include <com/sun/star/packages/NoEncryptionException.hpp> |
27 | | #include <com/sun/star/packages/WrongPasswordException.hpp> |
28 | | #include <com/sun/star/uno/XComponentContext.hpp> |
29 | | #include <com/sun/star/ucb/SimpleFileAccess.hpp> |
30 | | #include <com/sun/star/lang/DisposedException.hpp> |
31 | | #include <com/sun/star/lang/XTypeProvider.hpp> |
32 | | #include <com/sun/star/io/NotConnectedException.hpp> |
33 | | #include <com/sun/star/io/TempFile.hpp> |
34 | | #include <com/sun/star/io/XInputStream.hpp> |
35 | | #include <com/sun/star/io/IOException.hpp> |
36 | | #include <com/sun/star/embed/ElementModes.hpp> |
37 | | #include <com/sun/star/embed/StorageFormats.hpp> |
38 | | #include <com/sun/star/embed/StorageWrappedTargetException.hpp> |
39 | | #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> |
40 | | #include <cppuhelper/typeprovider.hxx> |
41 | | #include <cppuhelper/queryinterface.hxx> |
42 | | #include <cppuhelper/exc_hlp.hxx> |
43 | | #include <osl/diagnose.h> |
44 | | #include <tools/stream.hxx> |
45 | | |
46 | | #include <comphelper/memorystream.hxx> |
47 | | #include <comphelper/processfactory.hxx> |
48 | | #include <comphelper/servicehelper.hxx> |
49 | | #include <comphelper/storagehelper.hxx> |
50 | | #include <comphelper/ofopxmlhelper.hxx> |
51 | | #include <comphelper/refcountedmutex.hxx> |
52 | | #include <comphelper/sequence.hxx> |
53 | | |
54 | | #include <comphelper/diagnose_ex.hxx> |
55 | | |
56 | | #include <PackageConstants.hxx> |
57 | | #include <utility> |
58 | | |
59 | | #include "selfterminatefilestream.hxx" |
60 | | #include "owriteablestream.hxx" |
61 | | #include "oseekinstream.hxx" |
62 | | #include "xstorage.hxx" |
63 | | |
64 | | // since the copying uses 32000 blocks usually, it makes sense to have a smaller size |
65 | 33.3k | #define MAX_STORCACHE_SIZE 30000 |
66 | | |
67 | | using namespace ::com::sun::star; |
68 | | |
69 | | namespace package |
70 | | { |
71 | | |
72 | | static void CopyInputToOutput( |
73 | | const css::uno::Reference< css::io::XInputStream >& xInput, |
74 | | SvStream& rOutput ) |
75 | 717 | { |
76 | 717 | static const sal_Int32 nConstBufferSize = 32000; |
77 | | |
78 | 717 | if (auto pByteReader = dynamic_cast< comphelper::ByteReader* >( xInput.get() )) |
79 | 717 | { |
80 | 717 | sal_Int32 nRead; |
81 | 717 | sal_Int8 aTempBuf[ nConstBufferSize ]; |
82 | 717 | do |
83 | 1.42k | { |
84 | 1.42k | nRead = pByteReader->readSomeBytes ( aTempBuf, nConstBufferSize ); |
85 | 1.42k | rOutput.WriteBytes ( aTempBuf, nRead ); |
86 | 1.42k | } |
87 | 1.42k | while ( nRead == nConstBufferSize ); |
88 | 717 | } |
89 | 0 | else |
90 | 0 | { |
91 | 0 | sal_Int32 nRead; |
92 | 0 | uno::Sequence < sal_Int8 > aSequence ( nConstBufferSize ); |
93 | |
|
94 | 0 | do |
95 | 0 | { |
96 | 0 | nRead = xInput->readBytes ( aSequence, nConstBufferSize ); |
97 | 0 | rOutput.WriteBytes ( aSequence.getConstArray(), nRead ); |
98 | 0 | } |
99 | 0 | while ( nRead == nConstBufferSize ); |
100 | 0 | } |
101 | 717 | } |
102 | | |
103 | | bool PackageEncryptionDataLessOrEqual( const ::comphelper::SequenceAsHashMap& aHash1, const ::comphelper::SequenceAsHashMap& aHash2 ) |
104 | 0 | { |
105 | | // tdf#93389: aHash2 may contain more than in aHash1, if it contains also data for other package |
106 | | // formats (as in case of autorecovery) |
107 | 0 | bool bResult = !aHash1.empty() && aHash1.size() <= aHash2.size(); |
108 | 0 | for ( ::comphelper::SequenceAsHashMap::const_iterator aIter = aHash1.begin(); |
109 | 0 | bResult && aIter != aHash1.end(); |
110 | 0 | ++aIter ) |
111 | 0 | { |
112 | 0 | uno::Sequence< sal_Int8 > aKey1; |
113 | 0 | bResult = ( ( aIter->second >>= aKey1 ) && aKey1.hasElements() ); |
114 | 0 | if ( bResult ) |
115 | 0 | { |
116 | 0 | const uno::Sequence< sal_Int8 > aKey2 = aHash2.getUnpackedValueOrDefault( aIter->first.maString, uno::Sequence< sal_Int8 >() ); |
117 | 0 | bResult = aKey1.getLength() == aKey2.getLength() |
118 | 0 | && std::equal(std::cbegin(aKey1), std::cend(aKey1), aKey2.begin(), aKey2.end()); |
119 | 0 | } |
120 | 0 | } |
121 | |
|
122 | 0 | return bResult; |
123 | 0 | } |
124 | | |
125 | | } // namespace package |
126 | | |
127 | | namespace |
128 | | { |
129 | | |
130 | | void SetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet, |
131 | | const uno::Sequence< beans::NamedValue >& aKey ) |
132 | 0 | { |
133 | 0 | SAL_WARN_IF( !xPropertySet.is(), "package.xstor", "No property set is provided!" ); |
134 | 0 | if ( !xPropertySet.is() ) |
135 | 0 | throw uno::RuntimeException(); |
136 | | |
137 | 0 | try { |
138 | 0 | xPropertySet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY, uno::Any( aKey ) ); |
139 | 0 | } |
140 | 0 | catch ( const uno::Exception& ex ) |
141 | 0 | { |
142 | 0 | TOOLS_WARN_EXCEPTION( "package.xstor", "Can't write encryption related properties"); |
143 | 0 | throw io::IOException(ex.Message); // TODO |
144 | 0 | } |
145 | 0 | } |
146 | | |
147 | | uno::Any GetEncryptionKeyProperty_Impl( const uno::Reference< beans::XPropertySet >& xPropertySet ) |
148 | 0 | { |
149 | 0 | SAL_WARN_IF( !xPropertySet.is(), "package.xstor", "No property set is provided!" ); |
150 | 0 | if ( !xPropertySet.is() ) |
151 | 0 | throw uno::RuntimeException(); |
152 | | |
153 | 0 | try { |
154 | 0 | return xPropertySet->getPropertyValue(STORAGE_ENCRYPTION_KEYS_PROPERTY); |
155 | 0 | } |
156 | 0 | catch ( const uno::Exception& ex ) |
157 | 0 | { |
158 | 0 | TOOLS_WARN_EXCEPTION( "package.xstor", "Can't get encryption related properties"); |
159 | 0 | throw io::IOException(ex.Message); // TODO |
160 | 0 | } |
161 | 0 | } |
162 | | |
163 | | bool SequencesEqual( const uno::Sequence< sal_Int8 >& aSequence1, const uno::Sequence< sal_Int8 >& aSequence2 ) |
164 | 0 | { |
165 | 0 | return aSequence1.getLength() == aSequence2.getLength() |
166 | 0 | && std::equal(aSequence1.begin(), aSequence1.end(), aSequence2.begin(), aSequence2.end()); |
167 | 0 | } |
168 | | |
169 | | bool SequencesEqual( const uno::Sequence< beans::NamedValue >& aSequence1, const uno::Sequence< beans::NamedValue >& aSequence2 ) |
170 | 0 | { |
171 | 0 | if ( aSequence1.getLength() != aSequence2.getLength() ) |
172 | 0 | return false; |
173 | | |
174 | 0 | for ( const auto& rProp1 : aSequence1 ) |
175 | 0 | { |
176 | 0 | bool bHasMember = false; |
177 | 0 | uno::Sequence< sal_Int8 > aMember1; |
178 | 0 | sal_Int32 nMember1 = 0; |
179 | 0 | if ( rProp1.Value >>= aMember1 ) |
180 | 0 | { |
181 | 0 | for ( const auto& rProp2 : aSequence2 ) |
182 | 0 | { |
183 | 0 | if ( rProp1.Name == rProp2.Name ) |
184 | 0 | { |
185 | 0 | bHasMember = true; |
186 | |
|
187 | 0 | uno::Sequence< sal_Int8 > aMember2; |
188 | 0 | if ( !( rProp2.Value >>= aMember2 ) || !SequencesEqual( aMember1, aMember2 ) ) |
189 | 0 | return false; |
190 | 0 | } |
191 | 0 | } |
192 | 0 | } |
193 | 0 | else if ( rProp1.Value >>= nMember1 ) |
194 | 0 | { |
195 | 0 | for ( const auto& rProp2 : aSequence2 ) |
196 | 0 | { |
197 | 0 | if ( rProp1.Name == rProp2.Name ) |
198 | 0 | { |
199 | 0 | bHasMember = true; |
200 | |
|
201 | 0 | sal_Int32 nMember2 = 0; |
202 | 0 | if ( !( rProp2.Value >>= nMember2 ) || nMember1 != nMember2 ) |
203 | 0 | return false; |
204 | 0 | } |
205 | 0 | } |
206 | 0 | } |
207 | 0 | else |
208 | 0 | return false; |
209 | | |
210 | 0 | if ( !bHasMember ) |
211 | 0 | return false; |
212 | 0 | } |
213 | | |
214 | 0 | return true; |
215 | 0 | } |
216 | | |
217 | | const beans::StringPair* lcl_findPairByName(const uno::Sequence<beans::StringPair>& rSeq, const OUString& rName) |
218 | 0 | { |
219 | 0 | return std::find_if(rSeq.begin(), rSeq.end(), |
220 | 0 | [&rName](const beans::StringPair& rPair) { return rPair.First == rName; }); |
221 | 0 | } |
222 | | |
223 | | } // anonymous namespace |
224 | | |
225 | | OWriteStream_Impl::OWriteStream_Impl( OStorage_Impl* pParent, |
226 | | const uno::Reference< packages::XDataSinkEncrSupport >& xPackageStream, |
227 | | const uno::Reference< lang::XSingleServiceFactory >& xPackage, |
228 | | uno::Reference< uno::XComponentContext > xContext, |
229 | | bool bForceEncrypted, |
230 | | sal_Int32 nStorageType, |
231 | | bool bDefaultCompress, |
232 | | uno::Reference< io::XInputStream > xRelInfoStream ) |
233 | 153k | : m_xMutex( new comphelper::RefCountedMutex ) |
234 | 153k | , m_pAntiImpl( nullptr ) |
235 | 153k | , m_bHasDataToFlush( false ) |
236 | 153k | , m_bFlushed( false ) |
237 | 153k | , m_xPackageStream( xPackageStream ) |
238 | 153k | , m_xContext(std::move( xContext )) |
239 | 153k | , m_pParent( pParent ) |
240 | 153k | , m_bForceEncrypted( bForceEncrypted ) |
241 | 153k | , m_bUseCommonEncryption( !bForceEncrypted && nStorageType == embed::StorageFormats::PACKAGE ) |
242 | 153k | , m_bHasCachedEncryptionData( false ) |
243 | 153k | , m_bCompressedSetExplicit( !bDefaultCompress ) |
244 | 153k | , m_xPackage( xPackage ) |
245 | 153k | , m_bHasInsertedStreamOptimization( false ) |
246 | 153k | , m_nStorageType( nStorageType ) |
247 | 153k | , m_xOrigRelInfoStream(std::move( xRelInfoStream )) |
248 | 153k | , m_bOrigRelInfoBroken( false ) |
249 | 153k | , m_nRelInfoStatus( RELINFO_NO_INIT ) |
250 | 153k | , m_nRelId( 1 ) |
251 | 153k | { |
252 | 153k | SAL_WARN_IF( !xPackageStream.is(), "package.xstor", "No package stream is provided!" ); |
253 | 153k | SAL_WARN_IF( !xPackage.is(), "package.xstor", "No package component is provided!" ); |
254 | 153k | SAL_WARN_IF( !m_xContext.is(), "package.xstor", "No package stream is provided!" ); |
255 | 153k | OSL_ENSURE( pParent, "No parent storage is provided!" ); |
256 | 153k | OSL_ENSURE( m_nStorageType == embed::StorageFormats::OFOPXML || !m_xOrigRelInfoStream.is(), "The Relations info makes sense only for OFOPXML format!" ); |
257 | 153k | } |
258 | | |
259 | | OWriteStream_Impl::~OWriteStream_Impl() |
260 | 153k | { |
261 | 153k | DisposeWrappers(); |
262 | | |
263 | 153k | m_oTempFile.reset(); |
264 | | |
265 | 153k | CleanCacheStream(); |
266 | 153k | } |
267 | | |
268 | | void OWriteStream_Impl::CleanCacheStream() |
269 | 153k | { |
270 | 153k | if ( !m_xCacheStream.is() ) |
271 | 144k | return; |
272 | | |
273 | 8.98k | try |
274 | 8.98k | { |
275 | 8.98k | uno::Reference< io::XInputStream > xInputCache = m_xCacheStream->getInputStream(); |
276 | 8.98k | if ( xInputCache.is() ) |
277 | 8.98k | xInputCache->closeInput(); |
278 | 8.98k | } |
279 | 8.98k | catch( const uno::Exception& ) |
280 | 8.98k | {} |
281 | | |
282 | 8.98k | try |
283 | 8.98k | { |
284 | 8.98k | uno::Reference< io::XOutputStream > xOutputCache = m_xCacheStream->getOutputStream(); |
285 | 8.98k | if ( xOutputCache.is() ) |
286 | 8.98k | xOutputCache->closeOutput(); |
287 | 8.98k | } |
288 | 8.98k | catch( const uno::Exception& ) |
289 | 8.98k | {} |
290 | | |
291 | 8.98k | m_xCacheStream.clear(); |
292 | 8.98k | m_xCacheSeek.clear(); |
293 | 8.98k | } |
294 | | |
295 | | void OWriteStream_Impl::InsertIntoPackageFolder( const OUString& aName, |
296 | | const uno::Reference< container::XNameContainer >& xParentPackageFolder ) |
297 | 0 | { |
298 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); |
299 | |
|
300 | 0 | SAL_WARN_IF( !m_bFlushed, "package.xstor", "This method must not be called for nonflushed streams!" ); |
301 | 0 | if ( m_bFlushed ) |
302 | 0 | { |
303 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "An inserted stream is incomplete!" ); |
304 | 0 | uno::Reference< uno::XInterface > xTmp( m_xPackageStream, uno::UNO_QUERY_THROW ); |
305 | 0 | xParentPackageFolder->insertByName( aName, uno::Any( xTmp ) ); |
306 | |
|
307 | 0 | m_bFlushed = false; |
308 | 0 | m_bHasInsertedStreamOptimization = false; |
309 | 0 | } |
310 | 0 | } |
311 | | bool OWriteStream_Impl::IsEncrypted() |
312 | 174k | { |
313 | 174k | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
314 | 173k | return false; |
315 | | |
316 | 1.07k | if ( m_bForceEncrypted || m_bHasCachedEncryptionData ) |
317 | 0 | return true; |
318 | | |
319 | 1.07k | if ( m_oTempFile.has_value() || m_xCacheStream.is() ) |
320 | 0 | return false; |
321 | | |
322 | 1.07k | GetStreamProperties(); |
323 | | |
324 | | // the following value can not be cached since it can change after root commit |
325 | 1.07k | bool bWasEncr = false; |
326 | 1.07k | uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY ); |
327 | 1.07k | if ( xPropSet.is() ) |
328 | 1.07k | { |
329 | 1.07k | uno::Any aValue = xPropSet->getPropertyValue(u"WasEncrypted"_ustr); |
330 | 1.07k | if ( !( aValue >>= bWasEncr ) ) |
331 | 0 | { |
332 | 0 | SAL_WARN( "package.xstor", "The property WasEncrypted has wrong type!" ); |
333 | 0 | } |
334 | 1.07k | } |
335 | | |
336 | 1.07k | bool bToBeEncr = false; |
337 | 1.07k | for (const auto& rProp : m_aProps) |
338 | 4.31k | { |
339 | 4.31k | if ( rProp.Name == "Encrypted" ) |
340 | 1.07k | { |
341 | 1.07k | if ( !( rProp.Value >>= bToBeEncr ) ) |
342 | 0 | { |
343 | 0 | SAL_WARN( "package.xstor", "The property has wrong type!" ); |
344 | 0 | } |
345 | 1.07k | } |
346 | 4.31k | } |
347 | | |
348 | | // since a new key set to the package stream it should not be removed except the case when |
349 | | // the stream becomes nonencrypted |
350 | 1.07k | uno::Sequence< beans::NamedValue > aKey; |
351 | 1.07k | if ( bToBeEncr ) |
352 | 0 | GetEncryptionKeyProperty_Impl( xPropSet ) >>= aKey; |
353 | | |
354 | | // If the properties must be investigated the stream is either |
355 | | // was never changed or was changed, the parent was committed |
356 | | // and the stream was closed. |
357 | | // That means that if it is intended to use common storage key |
358 | | // it is already has no encryption but is marked to be stored |
359 | | // encrypted and the key is empty. |
360 | 1.07k | if ( !bWasEncr && bToBeEncr && !aKey.hasElements() ) |
361 | 0 | { |
362 | | // the stream is intended to use common storage password |
363 | 0 | m_bUseCommonEncryption = true; |
364 | 0 | return false; |
365 | 0 | } |
366 | 1.07k | else |
367 | 1.07k | return bToBeEncr; |
368 | 1.07k | } |
369 | | |
370 | | void OWriteStream_Impl::SetDecrypted() |
371 | 0 | { |
372 | 0 | SAL_WARN_IF( m_nStorageType != embed::StorageFormats::PACKAGE, "package.xstor", "The encryption is supported only for package storages!" ); |
373 | 0 | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
374 | 0 | throw uno::RuntimeException(); |
375 | | |
376 | 0 | GetStreamProperties(); |
377 | | |
378 | | // let the stream be modified |
379 | 0 | FillTempGetFileName(); |
380 | 0 | m_bHasDataToFlush = true; |
381 | | |
382 | | // remove encryption |
383 | 0 | m_bForceEncrypted = false; |
384 | 0 | m_bHasCachedEncryptionData = false; |
385 | 0 | m_aEncryptionData.clear(); |
386 | |
|
387 | 0 | for ( auto& rProp : asNonConstRange(m_aProps) ) |
388 | 0 | { |
389 | 0 | if ( rProp.Name == "Encrypted" ) |
390 | 0 | rProp.Value <<= false; |
391 | 0 | } |
392 | 0 | } |
393 | | |
394 | | void OWriteStream_Impl::SetEncrypted( const ::comphelper::SequenceAsHashMap& aEncryptionData ) |
395 | 0 | { |
396 | 0 | SAL_WARN_IF( m_nStorageType != embed::StorageFormats::PACKAGE, "package.xstor", "The encryption is supported only for package storages!" ); |
397 | 0 | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
398 | 0 | throw uno::RuntimeException(); |
399 | | |
400 | 0 | if ( aEncryptionData.empty() ) |
401 | 0 | throw uno::RuntimeException(); |
402 | | |
403 | 0 | GetStreamProperties(); |
404 | | |
405 | | // let the stream be modified |
406 | 0 | FillTempGetFileName(); |
407 | 0 | m_bHasDataToFlush = true; |
408 | | |
409 | | // introduce encryption info |
410 | 0 | for ( auto& rProp : asNonConstRange(m_aProps) ) |
411 | 0 | { |
412 | 0 | if ( rProp.Name == "Encrypted" ) |
413 | 0 | rProp.Value <<= true; |
414 | 0 | } |
415 | |
|
416 | 0 | m_bUseCommonEncryption = false; // very important to set it to false |
417 | |
|
418 | 0 | m_bHasCachedEncryptionData = true; |
419 | 0 | m_aEncryptionData = aEncryptionData; |
420 | 0 | } |
421 | | |
422 | | void OWriteStream_Impl::DisposeWrappers() |
423 | 153k | { |
424 | 153k | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); |
425 | 153k | if ( m_pAntiImpl ) |
426 | 0 | { |
427 | 0 | try { |
428 | 0 | m_pAntiImpl->dispose(); |
429 | 0 | } |
430 | 0 | catch ( const uno::RuntimeException& ) |
431 | 0 | { |
432 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception"); |
433 | 0 | } |
434 | | |
435 | 0 | m_pAntiImpl = nullptr; |
436 | 0 | } |
437 | 153k | m_pParent = nullptr; |
438 | | |
439 | 153k | if ( m_aInputStreamsVector.empty() ) |
440 | 153k | return; |
441 | | |
442 | 3 | for ( auto& pStream : m_aInputStreamsVector ) |
443 | 3 | { |
444 | 3 | if ( pStream ) |
445 | 3 | { |
446 | 3 | pStream->InternalDispose(); |
447 | 3 | pStream = nullptr; |
448 | 3 | } |
449 | 3 | } |
450 | | |
451 | 3 | m_aInputStreamsVector.clear(); |
452 | 3 | } |
453 | | |
454 | | void OWriteStream_Impl::GetFilledTempFileIfNo( const uno::Reference< io::XInputStream >& xStream ) |
455 | 4 | { |
456 | 4 | if ( !m_oTempFile.has_value() ) |
457 | 4 | { |
458 | 4 | m_oTempFile.emplace(); |
459 | | |
460 | 4 | try { |
461 | 4 | if ( xStream.is() ) |
462 | 4 | { |
463 | | // the current position of the original stream should be still OK, copy further |
464 | 4 | package::CopyInputToOutput( xStream, *m_oTempFile->GetStream(StreamMode::READWRITE) ); |
465 | 4 | } |
466 | 4 | } |
467 | 4 | catch( const packages::WrongPasswordException& ) |
468 | 4 | { |
469 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
470 | 0 | m_oTempFile.reset(); |
471 | 0 | throw; |
472 | 0 | } |
473 | 4 | catch( const uno::Exception& ) |
474 | 4 | { |
475 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
476 | 0 | m_oTempFile.reset(); |
477 | 0 | throw; |
478 | 0 | } |
479 | | |
480 | 4 | if ( m_oTempFile.has_value() ) |
481 | 4 | CleanCacheStream(); |
482 | 4 | } |
483 | 4 | } |
484 | | |
485 | | void OWriteStream_Impl::FillTempGetFileName() |
486 | 11.0k | { |
487 | | // should try to create cache first, if the amount of contents is too big, the temp file should be taken |
488 | 11.0k | if ( !m_xCacheStream.is() && !m_oTempFile.has_value() ) |
489 | 11.0k | { |
490 | 11.0k | uno::Reference< io::XInputStream > xOrigStream = m_xPackageStream->getDataStream(); |
491 | 11.0k | if ( !xOrigStream.is() ) |
492 | 54 | { |
493 | | // in case of new inserted package stream it is possible that input stream still was not set |
494 | 54 | rtl::Reference< comphelper::UNOMemoryStream > xCacheStream = new comphelper::UNOMemoryStream(); |
495 | 54 | m_xCacheSeek = xCacheStream; |
496 | 54 | m_xCacheStream = std::move(xCacheStream); |
497 | 54 | } |
498 | 11.0k | else |
499 | 11.0k | { |
500 | 11.0k | sal_Int32 nRead = 0; |
501 | 11.0k | uno::Sequence< sal_Int8 > aData( MAX_STORCACHE_SIZE + 1 ); |
502 | 11.0k | nRead = xOrigStream->readBytes( aData, MAX_STORCACHE_SIZE + 1 ); |
503 | 11.0k | if ( aData.getLength() > nRead ) |
504 | 0 | aData.realloc( nRead ); |
505 | | |
506 | 11.0k | if ( nRead <= MAX_STORCACHE_SIZE ) |
507 | 9.19k | { |
508 | 9.19k | rtl::Reference< comphelper::UNOMemoryStream > xCacheStream = new comphelper::UNOMemoryStream(); |
509 | | |
510 | 9.19k | if ( nRead ) |
511 | 9.19k | { |
512 | 9.19k | uno::Reference< io::XOutputStream > xOutStream( xCacheStream->getOutputStream(), uno::UNO_SET_THROW ); |
513 | 9.19k | xOutStream->writeBytes( aData ); |
514 | 9.19k | } |
515 | 9.19k | m_xCacheSeek = xCacheStream; |
516 | 9.19k | m_xCacheStream = std::move(xCacheStream); |
517 | 9.19k | m_xCacheSeek->seek( 0 ); |
518 | 9.19k | } |
519 | 1.81k | else if ( !m_oTempFile.has_value() ) |
520 | 713 | { |
521 | 713 | m_oTempFile.emplace(); |
522 | | |
523 | 713 | try { |
524 | | // copy stream contents to the file |
525 | 713 | SvStream* pStream = m_oTempFile->GetStream(StreamMode::READWRITE); |
526 | 713 | pStream->WriteBytes( aData.getConstArray(), aData.getLength() ); |
527 | | |
528 | | // the current position of the original stream should be still OK, copy further |
529 | 713 | package::CopyInputToOutput( xOrigStream, *pStream ); |
530 | 713 | } |
531 | 713 | catch( const packages::WrongPasswordException& ) |
532 | 713 | { |
533 | 0 | m_oTempFile.reset(); |
534 | 0 | throw; |
535 | 0 | } |
536 | 713 | catch( const uno::Exception& ) |
537 | 713 | { |
538 | 93 | m_oTempFile.reset(); |
539 | 93 | } |
540 | 713 | } |
541 | 11.0k | } |
542 | 11.0k | } |
543 | 11.0k | } |
544 | | |
545 | | uno::Reference< io::XStream > OWriteStream_Impl::GetTempFileAsStream() |
546 | 276 | { |
547 | 276 | uno::Reference< io::XStream > xTempStream; |
548 | | |
549 | 276 | if ( !m_xCacheStream.is() ) |
550 | 276 | { |
551 | 276 | if ( !m_oTempFile.has_value() ) |
552 | 272 | FillTempGetFileName(); |
553 | | |
554 | 276 | if ( m_oTempFile.has_value() ) |
555 | 8 | { |
556 | | // the temporary file is not used if the cache is used |
557 | 8 | try |
558 | 8 | { |
559 | 8 | SvStream* pStream = m_oTempFile->GetStream(StreamMode::READWRITE); |
560 | 8 | pStream->Seek(0); |
561 | 8 | xTempStream = new utl::OStreamWrapper(pStream, /*bOwner*/false); |
562 | 8 | } |
563 | 8 | catch( const uno::Exception& ) |
564 | 8 | { |
565 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception"); |
566 | 0 | } |
567 | 8 | } |
568 | 276 | } |
569 | | |
570 | 276 | if ( m_xCacheStream.is() ) |
571 | 268 | xTempStream = m_xCacheStream; |
572 | | |
573 | | // the method must always return a stream |
574 | | // in case the stream can not be open |
575 | | // an exception should be thrown |
576 | 276 | if ( !xTempStream.is() ) |
577 | 0 | throw io::IOException(u"no temp stream"_ustr); //TODO: |
578 | | |
579 | 276 | return xTempStream; |
580 | 276 | } |
581 | | |
582 | | uno::Reference< io::XInputStream > OWriteStream_Impl::GetTempFileAsInputStream() |
583 | 12.8k | { |
584 | 12.8k | uno::Reference< io::XInputStream > xInputStream; |
585 | | |
586 | 12.8k | if ( !m_xCacheStream.is() ) |
587 | 10.7k | { |
588 | 10.7k | if ( !m_oTempFile.has_value() ) |
589 | 10.7k | FillTempGetFileName(); |
590 | | |
591 | 10.7k | if ( m_oTempFile.has_value() ) |
592 | 616 | { |
593 | | // the temporary file is not used if the cache is used |
594 | 616 | try |
595 | 616 | { |
596 | 616 | SvStream* pStream = m_oTempFile->GetStream(StreamMode::READWRITE); |
597 | 616 | pStream->Seek(0); |
598 | 616 | xInputStream = new utl::OStreamWrapper(pStream, /*bOwner*/false); |
599 | 616 | } |
600 | 616 | catch( const uno::Exception& ) |
601 | 616 | { |
602 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception"); |
603 | 0 | } |
604 | 616 | } |
605 | 10.7k | } |
606 | | |
607 | 12.8k | if ( m_xCacheStream.is() ) |
608 | 11.0k | xInputStream = m_xCacheStream->getInputStream(); |
609 | | |
610 | | // the method must always return a stream |
611 | | // in case the stream can not be open |
612 | | // an exception should be thrown |
613 | 12.8k | if ( !xInputStream.is() ) |
614 | 93 | throw io::IOException(); // TODO: |
615 | | |
616 | 12.7k | return xInputStream; |
617 | 12.8k | } |
618 | | |
619 | | void OWriteStream_Impl::InsertStreamDirectly( const uno::Reference< io::XInputStream >& xInStream, |
620 | | const uno::Sequence< beans::PropertyValue >& aProps ) |
621 | 0 | { |
622 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
623 | | |
624 | | // this call can be made only during parent storage commit |
625 | | // the parent storage is responsible for the correct handling |
626 | | // of deleted and renamed contents |
627 | |
|
628 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "No package stream is set!" ); |
629 | | |
630 | 0 | if ( m_bHasDataToFlush ) |
631 | 0 | throw io::IOException(u"m_bHasDataToFlush==true"_ustr); |
632 | | |
633 | 0 | OSL_ENSURE( !m_oTempFile.has_value() && !m_xCacheStream.is(), "The temporary must not exist!" ); |
634 | | |
635 | | // use new file as current persistent representation |
636 | | // the new file will be removed after it's stream is closed |
637 | 0 | m_xPackageStream->setDataStream( xInStream ); |
638 | | |
639 | | // copy properties to the package stream |
640 | 0 | uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY_THROW ); |
641 | | |
642 | | // The storage-package communication has a problem |
643 | | // the storage caches properties, thus if the package changes one of them itself |
644 | | // the storage does not know about it |
645 | | |
646 | | // Depending from MediaType value the package can change the compressed property itself |
647 | | // Thus if Compressed property is provided it must be set as the latest one |
648 | 0 | bool bCompressedIsSet = false; |
649 | 0 | bool bCompressed = false; |
650 | 0 | OUString aComprPropName( u"Compressed"_ustr ); |
651 | 0 | OUString aMedTypePropName( u"MediaType"_ustr ); |
652 | 0 | for ( const auto& rProp : aProps ) |
653 | 0 | { |
654 | 0 | if ( rProp.Name == aComprPropName ) |
655 | 0 | { |
656 | 0 | bCompressedIsSet = true; |
657 | 0 | rProp.Value >>= bCompressed; |
658 | 0 | } |
659 | 0 | else if ( ( m_nStorageType == embed::StorageFormats::OFOPXML || m_nStorageType == embed::StorageFormats::PACKAGE ) |
660 | 0 | && rProp.Name == aMedTypePropName ) |
661 | 0 | { |
662 | 0 | xPropertySet->setPropertyValue( rProp.Name, rProp.Value ); |
663 | 0 | } |
664 | 0 | else if ( m_nStorageType == embed::StorageFormats::PACKAGE && rProp.Name == "UseCommonStoragePasswordEncryption" ) |
665 | 0 | rProp.Value >>= m_bUseCommonEncryption; |
666 | 0 | else |
667 | 0 | throw lang::IllegalArgumentException(); |
668 | | |
669 | | // if there are cached properties update them |
670 | 0 | if ( rProp.Name == aMedTypePropName || rProp.Name == aComprPropName ) |
671 | 0 | for ( auto& rMemProp : asNonConstRange(m_aProps) ) |
672 | 0 | { |
673 | 0 | if ( rProp.Name == rMemProp.Name ) |
674 | 0 | rMemProp.Value = rProp.Value; |
675 | 0 | } |
676 | 0 | } |
677 | | |
678 | 0 | if ( bCompressedIsSet ) |
679 | 0 | { |
680 | 0 | xPropertySet->setPropertyValue( aComprPropName, uno::Any( bCompressed ) ); |
681 | 0 | m_bCompressedSetExplicit = true; |
682 | 0 | } |
683 | |
|
684 | 0 | if ( m_bUseCommonEncryption ) |
685 | 0 | { |
686 | 0 | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
687 | 0 | throw uno::RuntimeException(); |
688 | | |
689 | | // set to be encrypted but do not use encryption key |
690 | 0 | xPropertySet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY, |
691 | 0 | uno::Any( uno::Sequence< beans::NamedValue >() ) ); |
692 | 0 | xPropertySet->setPropertyValue( u"Encrypted"_ustr, uno::Any( true ) ); |
693 | 0 | } |
694 | | |
695 | | // the stream should be free soon, after package is stored |
696 | 0 | m_bHasDataToFlush = false; |
697 | 0 | m_bFlushed = true; // will allow to use transaction on stream level if will need it |
698 | 0 | m_bHasInsertedStreamOptimization = true; |
699 | 0 | } |
700 | | |
701 | | void OWriteStream_Impl::Commit() |
702 | 480 | { |
703 | 480 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
704 | | |
705 | 480 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "No package stream is set!" ); |
706 | | |
707 | 480 | if ( !m_bHasDataToFlush ) |
708 | 0 | return; |
709 | | |
710 | 480 | uno::Reference< packages::XDataSinkEncrSupport > xNewPackageStream; |
711 | 480 | uno::Sequence< uno::Any > aSeq{ uno::Any(false) }; |
712 | | |
713 | 480 | if ( m_xCacheStream.is() ) |
714 | 472 | { |
715 | 472 | if ( m_pAntiImpl ) |
716 | 221 | m_pAntiImpl->DeInit(); |
717 | | |
718 | 472 | uno::Reference< io::XInputStream > xInStream( m_xCacheStream->getInputStream(), uno::UNO_SET_THROW ); |
719 | | |
720 | 472 | xNewPackageStream.set( m_xPackage->createInstanceWithArguments( aSeq ), uno::UNO_QUERY_THROW ); |
721 | | |
722 | 472 | xNewPackageStream->setDataStream( xInStream ); |
723 | | |
724 | 472 | m_xCacheStream.clear(); |
725 | 472 | m_xCacheSeek.clear(); |
726 | | |
727 | 472 | } |
728 | 8 | else if ( m_oTempFile.has_value() ) |
729 | 8 | { |
730 | 8 | if ( m_pAntiImpl ) |
731 | 4 | m_pAntiImpl->DeInit(); |
732 | | |
733 | 8 | rtl::Reference< OSelfTerminateFileStream > xInStream; |
734 | 8 | try |
735 | 8 | { |
736 | 8 | xInStream = new OSelfTerminateFileStream(m_xContext, std::move(*m_oTempFile)); |
737 | 8 | } |
738 | 8 | catch( const uno::Exception& ) |
739 | 8 | { |
740 | 0 | TOOLS_WARN_EXCEPTION("package", ""); |
741 | 0 | } |
742 | | |
743 | 8 | if ( !xInStream.is() ) |
744 | 0 | throw io::IOException(); |
745 | | |
746 | 8 | xNewPackageStream.set( m_xPackage->createInstanceWithArguments( aSeq ), uno::UNO_QUERY_THROW ); |
747 | | |
748 | | // TODO/NEW: Let the temporary file be removed after commit |
749 | 8 | xNewPackageStream->setDataStream( xInStream ); |
750 | 8 | m_oTempFile.reset(); |
751 | 8 | } |
752 | 0 | else // if ( m_bHasInsertedStreamOptimization ) |
753 | 0 | { |
754 | | // if the optimization is used the stream can be accessed directly |
755 | 0 | xNewPackageStream = m_xPackageStream; |
756 | 0 | } |
757 | | |
758 | | // copy properties to the package stream |
759 | 480 | uno::Reference< beans::XPropertySet > xPropertySet( xNewPackageStream, uno::UNO_QUERY_THROW ); |
760 | | |
761 | 480 | for ( auto& rProp : asNonConstRange(m_aProps) ) |
762 | 1.92k | { |
763 | 1.92k | if ( rProp.Name == "Size" ) |
764 | 480 | { |
765 | 480 | if ( m_pAntiImpl && !m_bHasInsertedStreamOptimization && m_pAntiImpl->m_xSeekable.is() ) |
766 | 0 | { |
767 | 0 | rProp.Value <<= m_pAntiImpl->m_xSeekable->getLength(); |
768 | 0 | xPropertySet->setPropertyValue( rProp.Name, rProp.Value ); |
769 | 0 | } |
770 | 480 | } |
771 | 1.44k | else |
772 | 1.44k | xPropertySet->setPropertyValue( rProp.Name, rProp.Value ); |
773 | 1.92k | } |
774 | | |
775 | 480 | if ( m_bUseCommonEncryption ) |
776 | 480 | { |
777 | 480 | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
778 | 0 | throw uno::RuntimeException(); |
779 | | |
780 | | // set to be encrypted but do not use encryption key |
781 | 480 | xPropertySet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY, |
782 | 480 | uno::Any( uno::Sequence< beans::NamedValue >() ) ); |
783 | 480 | xPropertySet->setPropertyValue( u"Encrypted"_ustr, |
784 | 480 | uno::Any( true ) ); |
785 | 480 | } |
786 | 0 | else if ( m_bHasCachedEncryptionData ) |
787 | 0 | { |
788 | 0 | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
789 | 0 | throw uno::RuntimeException(); |
790 | | |
791 | 0 | xPropertySet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY, |
792 | 0 | uno::Any( m_aEncryptionData.getAsConstNamedValueList() ) ); |
793 | 0 | } |
794 | | |
795 | | // the stream should be free soon, after package is stored |
796 | 480 | m_xPackageStream = std::move(xNewPackageStream); |
797 | 480 | m_bHasDataToFlush = false; |
798 | 480 | m_bFlushed = true; // will allow to use transaction on stream level if will need it |
799 | 480 | } |
800 | | |
801 | | void OWriteStream_Impl::Revert() |
802 | 0 | { |
803 | | // can be called only from parent storage |
804 | | // means complete reload of the stream |
805 | |
|
806 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
807 | |
|
808 | 0 | if ( !m_bHasDataToFlush ) |
809 | 0 | return; // nothing to do |
810 | | |
811 | 0 | OSL_ENSURE( m_oTempFile.has_value() || m_xCacheStream.is(), "The temporary must exist!" ); |
812 | |
|
813 | 0 | if ( m_xCacheStream.is() ) |
814 | 0 | { |
815 | 0 | m_xCacheStream.clear(); |
816 | 0 | m_xCacheSeek.clear(); |
817 | 0 | } |
818 | |
|
819 | 0 | m_oTempFile.reset(); |
820 | |
|
821 | 0 | m_aProps.realloc( 0 ); |
822 | |
|
823 | 0 | m_bHasDataToFlush = false; |
824 | |
|
825 | 0 | m_bUseCommonEncryption = true; |
826 | 0 | m_bHasCachedEncryptionData = false; |
827 | 0 | m_aEncryptionData.clear(); |
828 | |
|
829 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
830 | 0 | return; |
831 | | |
832 | | // currently the relations storage is changed only on commit |
833 | 0 | m_xNewRelInfoStream.clear(); |
834 | 0 | m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); |
835 | 0 | if ( m_xOrigRelInfoStream.is() ) |
836 | 0 | { |
837 | | // the original stream is still here, that means that it was not parsed |
838 | 0 | m_aOrigRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); |
839 | 0 | m_nRelInfoStatus = RELINFO_NO_INIT; |
840 | 0 | } |
841 | 0 | else |
842 | 0 | { |
843 | | // the original stream was already parsed |
844 | 0 | if ( !m_bOrigRelInfoBroken ) |
845 | 0 | m_nRelInfoStatus = RELINFO_READ; |
846 | 0 | else |
847 | 0 | m_nRelInfoStatus = RELINFO_BROKEN; |
848 | 0 | } |
849 | 0 | } |
850 | | |
851 | | uno::Sequence< beans::PropertyValue > const & OWriteStream_Impl::GetStreamProperties() |
852 | 176k | { |
853 | 176k | if ( !m_aProps.hasElements() ) |
854 | 153k | m_aProps = ReadPackageStreamProperties(); |
855 | | |
856 | 176k | return m_aProps; |
857 | 176k | } |
858 | | |
859 | | uno::Sequence< beans::PropertyValue > OWriteStream_Impl::InsertOwnProps( |
860 | | const uno::Sequence< beans::PropertyValue >& aProps, |
861 | | bool bUseCommonEncryption ) |
862 | 141k | { |
863 | 141k | uno::Sequence< beans::PropertyValue > aResult( aProps ); |
864 | 141k | beans::PropertyValue aPropVal; |
865 | | |
866 | 141k | if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
867 | 806 | { |
868 | 806 | aPropVal.Name = "UseCommonStoragePasswordEncryption"; |
869 | 806 | aPropVal.Value <<= bUseCommonEncryption; |
870 | 806 | } |
871 | 140k | else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) |
872 | 37.9k | { |
873 | 37.9k | ReadRelInfoIfNecessary(); |
874 | | |
875 | 37.9k | aPropVal.Name = "RelationsInfo"; |
876 | 37.9k | if ( m_nRelInfoStatus == RELINFO_READ ) |
877 | 37.9k | aPropVal.Value <<= m_aOrigRelInfo; |
878 | 0 | else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED ) |
879 | 0 | aPropVal.Value <<= m_aNewRelInfo; |
880 | 0 | else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN |
881 | 0 | throw io::IOException( u"Wrong relinfo stream!"_ustr ); |
882 | 37.9k | } |
883 | 141k | if (!aPropVal.Name.isEmpty()) |
884 | 38.7k | { |
885 | 38.7k | sal_Int32 i = 0; |
886 | 155k | for (auto p = aResult.getConstArray(); i < aResult.getLength(); ++i) |
887 | 117k | if (p[i].Name == aPropVal.Name) |
888 | 0 | break; |
889 | 38.7k | if (i == aResult.getLength()) |
890 | 38.7k | aResult.realloc(i + 1); |
891 | 38.7k | aResult.getArray()[i] = std::move(aPropVal); |
892 | 38.7k | } |
893 | | |
894 | 141k | return aResult; |
895 | 141k | } |
896 | | |
897 | | bool OWriteStream_Impl::IsTransacted() |
898 | 0 | { |
899 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
900 | 0 | return ( m_pAntiImpl && m_pAntiImpl->m_bTransacted ); |
901 | 0 | } |
902 | | |
903 | | void OWriteStream_Impl::ReadRelInfoIfNecessary() |
904 | 212k | { |
905 | 212k | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
906 | 125k | return; |
907 | | |
908 | 86.7k | if ( m_nRelInfoStatus == RELINFO_NO_INIT ) |
909 | 44.8k | { |
910 | 44.8k | try |
911 | 44.8k | { |
912 | | // Init from original stream |
913 | 44.8k | if ( m_xOrigRelInfoStream.is() ) |
914 | 3.42k | m_aOrigRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence( |
915 | 3.42k | m_xOrigRelInfoStream, |
916 | 3.42k | u"_rels/*.rels", |
917 | 3.42k | m_xContext ); |
918 | | |
919 | | // in case of success the stream must be thrown away, that means that the OrigRelInfo is initialized |
920 | | // the reason for this is that the original stream might not be seekable ( at the same time the new |
921 | | // provided stream must be seekable ), so it must be read only once |
922 | 44.8k | m_xOrigRelInfoStream.clear(); |
923 | 44.8k | m_nRelInfoStatus = RELINFO_READ; |
924 | 44.8k | } |
925 | 44.8k | catch( const uno::Exception& ) |
926 | 44.8k | { |
927 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception"); |
928 | | |
929 | 0 | m_nRelInfoStatus = RELINFO_BROKEN; |
930 | 0 | m_bOrigRelInfoBroken = true; |
931 | 0 | } |
932 | 44.8k | } |
933 | 41.9k | else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) |
934 | 0 | { |
935 | | // Init from the new stream |
936 | 0 | try |
937 | 0 | { |
938 | 0 | if ( m_xNewRelInfoStream.is() ) |
939 | 0 | m_aNewRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence( |
940 | 0 | m_xNewRelInfoStream, |
941 | 0 | u"_rels/*.rels", |
942 | 0 | m_xContext ); |
943 | |
|
944 | 0 | m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ; |
945 | 0 | } |
946 | 0 | catch( const uno::Exception& ) |
947 | 0 | { |
948 | 0 | m_nRelInfoStatus = RELINFO_CHANGED_BROKEN; |
949 | 0 | } |
950 | 0 | } |
951 | 86.7k | } |
952 | | |
953 | | uno::Sequence< beans::PropertyValue > OWriteStream_Impl::ReadPackageStreamProperties() |
954 | 153k | { |
955 | 153k | sal_Int32 nPropNum = 0; |
956 | 153k | if ( m_nStorageType == embed::StorageFormats::ZIP ) |
957 | 108k | nPropNum = 2; |
958 | 45.1k | else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) |
959 | 44.8k | nPropNum = 3; |
960 | 251 | else if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
961 | 251 | nPropNum = 4; |
962 | 153k | assert(nPropNum >= 2); |
963 | 153k | uno::Sequence< beans::PropertyValue > aResult( nPropNum ); |
964 | 153k | auto aResultRange = asNonConstRange(aResult); |
965 | | |
966 | | // The "Compressed" property must be set after "MediaType" property, |
967 | | // since the setting of the last one can change the value of the first one |
968 | 153k | static constexpr OUStringLiteral sMediaType = u"MediaType"; |
969 | 153k | static constexpr OUString sCompressed = u"Compressed"_ustr; |
970 | 153k | static constexpr OUString sSize = u"Size"_ustr; |
971 | 153k | static constexpr OUStringLiteral sEncrypted = u"Encrypted"; |
972 | 153k | if ( m_nStorageType == embed::StorageFormats::OFOPXML || m_nStorageType == embed::StorageFormats::PACKAGE ) |
973 | 45.1k | { |
974 | 45.1k | aResultRange[0].Name = sMediaType; |
975 | 45.1k | aResultRange[1].Name = sCompressed; |
976 | 45.1k | aResultRange[2].Name = sSize; |
977 | | |
978 | 45.1k | if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
979 | 251 | aResultRange[3].Name = sEncrypted; |
980 | 45.1k | } |
981 | 108k | else |
982 | 108k | { |
983 | 108k | aResultRange[0].Name = sCompressed; |
984 | 108k | aResultRange[1].Name = sSize; |
985 | 108k | } |
986 | | |
987 | | // TODO: may be also raw stream should be marked |
988 | | |
989 | 153k | uno::Reference< beans::XPropertySet > xPropSet( m_xPackageStream, uno::UNO_QUERY_THROW ); |
990 | 153k | for ( auto& rProp : aResultRange ) |
991 | 352k | { |
992 | 352k | try { |
993 | 352k | rProp.Value = xPropSet->getPropertyValue( rProp.Name ); |
994 | 352k | } |
995 | 352k | catch( const uno::Exception& ) |
996 | 352k | { |
997 | 0 | TOOLS_WARN_EXCEPTION( "package.xstor", "A property can't be retrieved" ); |
998 | 0 | } |
999 | 352k | } |
1000 | | |
1001 | 153k | return aResult; |
1002 | 153k | } |
1003 | | |
1004 | | void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream, |
1005 | | const ::comphelper::SequenceAsHashMap& aEncryptionData ) |
1006 | 0 | { |
1007 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1008 | |
|
1009 | 0 | SAL_WARN_IF( m_bUseCommonEncryption, "package.xstor", "The stream can not be encrypted!" ); |
1010 | | |
1011 | 0 | if ( m_nStorageType != embed::StorageFormats::PACKAGE ) |
1012 | 0 | throw packages::NoEncryptionException(); |
1013 | | |
1014 | 0 | if ( m_pAntiImpl ) |
1015 | 0 | { |
1016 | 0 | m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream ); |
1017 | 0 | } |
1018 | 0 | else |
1019 | 0 | { |
1020 | 0 | uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, aEncryptionData, false ); |
1021 | 0 | if ( !xOwnStream.is() ) |
1022 | 0 | throw io::IOException(); // TODO |
1023 | | |
1024 | 0 | OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() ); |
1025 | 0 | } |
1026 | | |
1027 | 0 | uno::Reference< embed::XEncryptionProtectedSource2 > xEncr( xDestStream, uno::UNO_QUERY ); |
1028 | 0 | if ( xEncr.is() ) |
1029 | 0 | xEncr->setEncryptionData( aEncryptionData.getAsConstNamedValueList() ); |
1030 | 0 | } |
1031 | | |
1032 | | uno::Sequence< uno::Sequence< beans::StringPair > > OWriteStream_Impl::GetAllRelationshipsIfAny() |
1033 | 11 | { |
1034 | 11 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
1035 | 11 | return uno::Sequence< uno::Sequence< beans::StringPair > >(); |
1036 | | |
1037 | 0 | ReadRelInfoIfNecessary(); |
1038 | |
|
1039 | 0 | if ( m_nRelInfoStatus == RELINFO_READ ) |
1040 | 0 | return m_aOrigRelInfo; |
1041 | 0 | else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ || m_nRelInfoStatus == RELINFO_CHANGED ) |
1042 | 0 | return m_aNewRelInfo; |
1043 | 0 | else // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN |
1044 | 0 | throw io::IOException( u"Wrong relinfo stream!"_ustr ); |
1045 | 0 | } |
1046 | | |
1047 | | void OWriteStream_Impl::CopyInternallyTo_Impl( const uno::Reference< io::XStream >& xDestStream ) |
1048 | 11 | { |
1049 | 11 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1050 | | |
1051 | 11 | if ( m_pAntiImpl ) |
1052 | 0 | { |
1053 | 0 | m_pAntiImpl->CopyToStreamInternally_Impl( xDestStream ); |
1054 | 0 | } |
1055 | 11 | else |
1056 | 11 | { |
1057 | 11 | uno::Reference< io::XStream > xOwnStream = GetStream( embed::ElementModes::READ, false ); |
1058 | 11 | if ( !xOwnStream.is() ) |
1059 | 0 | throw io::IOException(); // TODO |
1060 | | |
1061 | 11 | OStorage_Impl::completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() ); |
1062 | 11 | } |
1063 | 11 | } |
1064 | | |
1065 | | uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, const ::comphelper::SequenceAsHashMap& aEncryptionData, bool bHierarchyAccess ) |
1066 | 0 | { |
1067 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1068 | |
|
1069 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "No package stream is set!" ); |
1070 | | |
1071 | 0 | if ( m_pAntiImpl ) |
1072 | 0 | throw io::IOException(); // TODO: |
1073 | | |
1074 | 0 | if ( !IsEncrypted() ) |
1075 | 0 | throw packages::NoEncryptionException(); |
1076 | | |
1077 | 0 | uno::Reference< io::XStream > xResultStream; |
1078 | |
|
1079 | 0 | uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY_THROW ); |
1080 | |
|
1081 | 0 | if ( m_bHasCachedEncryptionData ) |
1082 | 0 | { |
1083 | 0 | if ( !::package::PackageEncryptionDataLessOrEqual( m_aEncryptionData, aEncryptionData ) ) |
1084 | 0 | throw packages::WrongPasswordException(); |
1085 | | |
1086 | | // the correct key must be set already |
1087 | 0 | xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); |
1088 | 0 | } |
1089 | 0 | else |
1090 | 0 | { |
1091 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() ); |
1092 | |
|
1093 | 0 | try { |
1094 | 0 | xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); |
1095 | |
|
1096 | 0 | m_bUseCommonEncryption = false; // very important to set it to false |
1097 | 0 | m_bHasCachedEncryptionData = true; |
1098 | 0 | m_aEncryptionData = aEncryptionData; |
1099 | 0 | } |
1100 | 0 | catch( const packages::WrongPasswordException& ) |
1101 | 0 | { |
1102 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
1103 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); |
1104 | 0 | throw; |
1105 | 0 | } |
1106 | 0 | catch ( const uno::Exception& ex ) |
1107 | 0 | { |
1108 | 0 | TOOLS_WARN_EXCEPTION("package.xstor", "GetStream: decrypting stream failed"); |
1109 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); |
1110 | 0 | throw io::IOException(ex.Message); // TODO: |
1111 | 0 | } |
1112 | 0 | } |
1113 | | |
1114 | 0 | SAL_WARN_IF( !xResultStream.is(), "package.xstor", "In case stream can not be retrieved an exception must be thrown!" ); |
1115 | | |
1116 | 0 | return xResultStream; |
1117 | 0 | } |
1118 | | |
1119 | | uno::Reference< io::XStream > OWriteStream_Impl::GetStream( sal_Int32 nStreamMode, bool bHierarchyAccess ) |
1120 | 174k | { |
1121 | 174k | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1122 | | |
1123 | 174k | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "No package stream is set!" ); |
1124 | | |
1125 | 174k | if ( m_pAntiImpl ) |
1126 | 0 | throw io::IOException(); // TODO: |
1127 | | |
1128 | 174k | uno::Reference< io::XStream > xResultStream; |
1129 | | |
1130 | 174k | if ( IsEncrypted() ) |
1131 | 0 | { |
1132 | 0 | ::comphelper::SequenceAsHashMap aGlobalEncryptionData; |
1133 | 0 | try |
1134 | 0 | { |
1135 | 0 | aGlobalEncryptionData = GetCommonRootEncryptionData(); |
1136 | 0 | } |
1137 | 0 | catch( const packages::NoEncryptionException& ) |
1138 | 0 | { |
1139 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
1140 | 0 | throw packages::WrongPasswordException(); |
1141 | 0 | } |
1142 | | |
1143 | 0 | xResultStream = GetStream( nStreamMode, aGlobalEncryptionData, bHierarchyAccess ); |
1144 | 0 | } |
1145 | 174k | else |
1146 | 174k | xResultStream = GetStream_Impl( nStreamMode, bHierarchyAccess ); |
1147 | | |
1148 | 174k | return xResultStream; |
1149 | 174k | } |
1150 | | |
1151 | | uno::Reference< io::XStream > OWriteStream_Impl::GetStream_Impl( sal_Int32 nStreamMode, bool bHierarchyAccess ) |
1152 | 174k | { |
1153 | | // private method, no mutex is used |
1154 | 174k | GetStreamProperties(); |
1155 | | |
1156 | | // TODO/LATER: this info might be read later, on demand in future |
1157 | 174k | ReadRelInfoIfNecessary(); |
1158 | | |
1159 | 174k | if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::READ ) |
1160 | 154k | { |
1161 | 154k | uno::Reference< io::XInputStream > xInStream; |
1162 | 154k | if ( m_xCacheStream.is() || m_oTempFile.has_value() ) |
1163 | 0 | xInStream = GetTempFileAsInputStream(); //TODO: |
1164 | 154k | else |
1165 | 154k | xInStream = m_xPackageStream->getDataStream(); |
1166 | | |
1167 | | // The stream does not exist in the storage |
1168 | 154k | if ( !xInStream.is() ) |
1169 | 0 | throw io::IOException(); |
1170 | | |
1171 | 154k | rtl::Reference<OInputCompStream> pStream = new OInputCompStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonEncryption ), m_nStorageType ); |
1172 | 154k | m_aInputStreamsVector.push_back( pStream.get() ); |
1173 | 154k | return pStream; |
1174 | 154k | } |
1175 | 20.0k | else if ( ( nStreamMode & embed::ElementModes::READWRITE ) == embed::ElementModes::SEEKABLEREAD ) |
1176 | 19.7k | { |
1177 | 19.7k | if ( !m_xCacheStream.is() && !m_oTempFile.has_value() && !( m_xPackageStream->getDataStream().is() ) ) |
1178 | 0 | { |
1179 | | // The stream does not exist in the storage |
1180 | 0 | throw io::IOException(); |
1181 | 0 | } |
1182 | | |
1183 | 19.7k | uno::Reference< io::XInputStream > xInStream = GetTempFileAsInputStream(); //TODO: |
1184 | | |
1185 | 19.7k | if ( !xInStream.is() ) |
1186 | 0 | throw io::IOException(); |
1187 | | |
1188 | 19.7k | rtl::Reference<OInputSeekStream> pStream = new OInputSeekStream( *this, xInStream, InsertOwnProps( m_aProps, m_bUseCommonEncryption ), m_nStorageType ); |
1189 | 19.7k | m_aInputStreamsVector.push_back( pStream.get() ); |
1190 | 19.7k | return pStream; |
1191 | 19.7k | } |
1192 | 262 | else if ( ( nStreamMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE ) |
1193 | 262 | { |
1194 | 262 | if ( !m_aInputStreamsVector.empty() ) |
1195 | 0 | throw io::IOException(); // TODO: |
1196 | | |
1197 | 262 | uno::Reference< io::XStream > xStream; |
1198 | 262 | if ( ( nStreamMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE ) |
1199 | 208 | { |
1200 | 208 | m_oTempFile.reset(); |
1201 | 208 | if ( m_xCacheStream.is() ) |
1202 | 0 | CleanCacheStream(); |
1203 | | |
1204 | 208 | m_bHasDataToFlush = true; |
1205 | | |
1206 | | // this call is triggered by the parent and it will recognize the change of the state |
1207 | 208 | if ( m_pParent ) |
1208 | 208 | m_pParent->m_bIsModified = true; |
1209 | | |
1210 | 208 | rtl::Reference<comphelper::UNOMemoryStream> xMemStream = new comphelper::UNOMemoryStream(); |
1211 | 208 | xStream = xMemStream; |
1212 | 208 | m_xCacheSeek = xMemStream; |
1213 | 208 | m_xCacheStream = xStream; |
1214 | 208 | } |
1215 | 54 | else if ( !m_bHasInsertedStreamOptimization ) |
1216 | 54 | { |
1217 | 54 | if ( !m_oTempFile.has_value() && !m_xCacheStream.is() && !( m_xPackageStream->getDataStream().is() ) ) |
1218 | 54 | { |
1219 | | // The stream does not exist in the storage |
1220 | 54 | m_bHasDataToFlush = true; |
1221 | | |
1222 | | // this call is triggered by the parent and it will recognize the change of the state |
1223 | 54 | if ( m_pParent ) |
1224 | 54 | m_pParent->m_bIsModified = true; |
1225 | 54 | xStream = GetTempFileAsStream(); |
1226 | 54 | } |
1227 | | |
1228 | | // if the stream exists the temporary file is created on demand |
1229 | | // xStream = GetTempFileAsStream(); |
1230 | 54 | } |
1231 | | |
1232 | 262 | rtl::Reference<OWriteStream> tmp; |
1233 | 262 | assert(m_xMutex.is() && "No mutex!"); |
1234 | 262 | if ( !xStream.is() ) |
1235 | 0 | tmp = new OWriteStream( *this, bHierarchyAccess ); |
1236 | 262 | else |
1237 | 262 | tmp = new OWriteStream( *this, xStream, bHierarchyAccess ); |
1238 | | |
1239 | 262 | m_pAntiImpl = tmp.get(); |
1240 | 262 | return tmp; |
1241 | 262 | } |
1242 | | |
1243 | 0 | throw lang::IllegalArgumentException(); // TODO |
1244 | 174k | } |
1245 | | |
1246 | | uno::Reference< io::XInputStream > OWriteStream_Impl::GetPlainRawInStream() |
1247 | 0 | { |
1248 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1249 | |
|
1250 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "No package stream is set!" ); |
1251 | | |
1252 | | // this method is used only internally, this stream object should not go outside of this implementation |
1253 | | // if ( m_pAntiImpl ) |
1254 | | // throw io::IOException(); // TODO: |
1255 | | |
1256 | 0 | return m_xPackageStream->getPlainRawStream(); |
1257 | 0 | } |
1258 | | |
1259 | | uno::Reference< io::XInputStream > OWriteStream_Impl::GetRawInStream() |
1260 | 0 | { |
1261 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1262 | |
|
1263 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "No package stream is set!" ); |
1264 | | |
1265 | 0 | if ( m_pAntiImpl ) |
1266 | 0 | throw io::IOException(); // TODO: |
1267 | | |
1268 | 0 | SAL_WARN_IF( !IsEncrypted(), "package.xstor", "Impossible to get raw representation for nonencrypted stream!" ); |
1269 | 0 | if ( !IsEncrypted() ) |
1270 | 0 | throw packages::NoEncryptionException(); |
1271 | | |
1272 | 0 | return m_xPackageStream->getRawStream(); |
1273 | 0 | } |
1274 | | |
1275 | | ::comphelper::SequenceAsHashMap OWriteStream_Impl::GetCommonRootEncryptionData() |
1276 | 0 | { |
1277 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ; |
1278 | |
|
1279 | 0 | if ( m_nStorageType != embed::StorageFormats::PACKAGE || !m_pParent ) |
1280 | 0 | throw packages::NoEncryptionException(); |
1281 | | |
1282 | 0 | return m_pParent->GetCommonRootEncryptionData(); |
1283 | 0 | } |
1284 | | |
1285 | | void OWriteStream_Impl::InputStreamDisposed( OInputCompStream* pStream ) |
1286 | 141k | { |
1287 | 141k | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); |
1288 | 141k | std::erase(m_aInputStreamsVector, pStream); |
1289 | 141k | } |
1290 | | |
1291 | | void OWriteStream_Impl::CreateReadonlyCopyBasedOnData( const uno::Reference< io::XInputStream >& xDataToCopy, const uno::Sequence< beans::PropertyValue >& aProps, uno::Reference< io::XStream >& xTargetStream ) |
1292 | 0 | { |
1293 | 0 | uno::Reference < io::XStream > xTempFile; |
1294 | 0 | if ( !xTargetStream.is() ) |
1295 | 0 | xTempFile = new utl::TempFileFastService; |
1296 | 0 | else |
1297 | 0 | xTempFile = xTargetStream; |
1298 | |
|
1299 | 0 | uno::Reference < io::XSeekable > xTempSeek( xTempFile, uno::UNO_QUERY_THROW ); |
1300 | |
|
1301 | 0 | uno::Reference < io::XOutputStream > xTempOut(xTempFile->getOutputStream(), uno::UNO_SET_THROW); |
1302 | |
|
1303 | 0 | if ( xDataToCopy.is() ) |
1304 | 0 | ::comphelper::OStorageHelper::CopyInputToOutput( xDataToCopy, xTempOut ); |
1305 | |
|
1306 | 0 | xTempOut->closeOutput(); |
1307 | 0 | xTempSeek->seek( 0 ); |
1308 | |
|
1309 | 0 | uno::Reference< io::XInputStream > xInStream = xTempFile->getInputStream(); |
1310 | 0 | if ( !xInStream.is() ) |
1311 | 0 | throw io::IOException(); |
1312 | | |
1313 | | // TODO: remember last state of m_bUseCommonEncryption |
1314 | 0 | if ( !xTargetStream.is() ) |
1315 | 0 | xTargetStream.set( |
1316 | 0 | new OInputSeekStream( xInStream, InsertOwnProps( aProps, m_bUseCommonEncryption ), m_nStorageType ) ); |
1317 | 0 | } |
1318 | | |
1319 | | void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream ) |
1320 | 0 | { |
1321 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); |
1322 | |
|
1323 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "The source stream for copying is incomplete!" ); |
1324 | 0 | if ( !m_xPackageStream.is() ) |
1325 | 0 | throw uno::RuntimeException(); |
1326 | | |
1327 | 0 | uno::Reference< io::XInputStream > xDataToCopy; |
1328 | 0 | if ( IsEncrypted() ) |
1329 | 0 | { |
1330 | | // an encrypted stream must contain input stream |
1331 | 0 | ::comphelper::SequenceAsHashMap aGlobalEncryptionData; |
1332 | 0 | try |
1333 | 0 | { |
1334 | 0 | aGlobalEncryptionData = GetCommonRootEncryptionData(); |
1335 | 0 | } |
1336 | 0 | catch( const packages::NoEncryptionException& ) |
1337 | 0 | { |
1338 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "No Element"); |
1339 | 0 | throw packages::WrongPasswordException(); |
1340 | 0 | } |
1341 | | |
1342 | 0 | GetCopyOfLastCommit( xTargetStream, aGlobalEncryptionData ); |
1343 | 0 | } |
1344 | 0 | else |
1345 | 0 | { |
1346 | 0 | xDataToCopy = m_xPackageStream->getDataStream(); |
1347 | | |
1348 | | // in case of new inserted package stream it is possible that input stream still was not set |
1349 | 0 | GetStreamProperties(); |
1350 | |
|
1351 | 0 | CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, xTargetStream ); |
1352 | 0 | } |
1353 | 0 | } |
1354 | | |
1355 | | void OWriteStream_Impl::GetCopyOfLastCommit( uno::Reference< io::XStream >& xTargetStream, const ::comphelper::SequenceAsHashMap& aEncryptionData ) |
1356 | 0 | { |
1357 | 0 | ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ); |
1358 | |
|
1359 | 0 | SAL_WARN_IF( !m_xPackageStream.is(), "package.xstor", "The source stream for copying is incomplete!" ); |
1360 | 0 | if ( !m_xPackageStream.is() ) |
1361 | 0 | throw uno::RuntimeException(); |
1362 | | |
1363 | 0 | if ( !IsEncrypted() ) |
1364 | 0 | throw packages::NoEncryptionException(); |
1365 | | |
1366 | 0 | uno::Reference< io::XInputStream > xDataToCopy; |
1367 | |
|
1368 | 0 | if ( m_bHasCachedEncryptionData ) |
1369 | 0 | { |
1370 | | // TODO: introduce last committed cashed password information and use it here |
1371 | | // that means "use common pass" also should be remembered on flash |
1372 | 0 | uno::Sequence< beans::NamedValue > aKey = aEncryptionData.getAsConstNamedValueList(); |
1373 | |
|
1374 | 0 | uno::Reference< beans::XPropertySet > xProps( m_xPackageStream, uno::UNO_QUERY_THROW ); |
1375 | |
|
1376 | 0 | bool bEncr = false; |
1377 | 0 | xProps->getPropertyValue( u"Encrypted"_ustr ) >>= bEncr; |
1378 | 0 | if ( !bEncr ) |
1379 | 0 | throw packages::NoEncryptionException(); |
1380 | | |
1381 | 0 | uno::Sequence< beans::NamedValue > aPackKey; |
1382 | 0 | xProps->getPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY ) >>= aPackKey; |
1383 | 0 | if ( !SequencesEqual( aKey, aPackKey ) ) |
1384 | 0 | throw packages::WrongPasswordException(); |
1385 | | |
1386 | | // the correct key must be set already |
1387 | 0 | xDataToCopy = m_xPackageStream->getDataStream(); |
1388 | 0 | } |
1389 | 0 | else |
1390 | 0 | { |
1391 | 0 | uno::Reference< beans::XPropertySet > xPropertySet( m_xPackageStream, uno::UNO_QUERY ); |
1392 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, aEncryptionData.getAsConstNamedValueList() ); |
1393 | |
|
1394 | 0 | try { |
1395 | 0 | xDataToCopy = m_xPackageStream->getDataStream(); |
1396 | |
|
1397 | 0 | if ( !xDataToCopy.is() ) |
1398 | 0 | { |
1399 | 0 | SAL_WARN( "package.xstor", "Encrypted ZipStream must already have input stream inside!" ); |
1400 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); |
1401 | 0 | } |
1402 | 0 | } |
1403 | 0 | catch( const uno::Exception& ) |
1404 | 0 | { |
1405 | 0 | TOOLS_WARN_EXCEPTION( "package.xstor", "Can't open encrypted stream"); |
1406 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); |
1407 | 0 | throw; |
1408 | 0 | } |
1409 | | |
1410 | 0 | SetEncryptionKeyProperty_Impl( xPropertySet, uno::Sequence< beans::NamedValue >() ); |
1411 | 0 | } |
1412 | | |
1413 | | // in case of new inserted package stream it is possible that input stream still was not set |
1414 | 0 | GetStreamProperties(); |
1415 | |
|
1416 | 0 | CreateReadonlyCopyBasedOnData( xDataToCopy, m_aProps, xTargetStream ); |
1417 | 0 | } |
1418 | | |
1419 | | void OWriteStream_Impl::CommitStreamRelInfo( const uno::Reference< embed::XStorage >& xRelStorage, std::u16string_view aOrigStreamName, std::u16string_view aNewStreamName ) |
1420 | 0 | { |
1421 | | // at this point of time the old stream must be already cleaned |
1422 | 0 | OSL_ENSURE( m_nStorageType == embed::StorageFormats::OFOPXML, "The method should be used only with OFOPXML format!" ); |
1423 | |
|
1424 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
1425 | 0 | return; |
1426 | | |
1427 | 0 | OSL_ENSURE( !aOrigStreamName.empty() && !aNewStreamName.empty() && xRelStorage.is(), |
1428 | 0 | "Wrong relation persistence information is provided!" ); |
1429 | |
|
1430 | 0 | if ( !xRelStorage.is() || aOrigStreamName.empty() || aNewStreamName.empty() ) |
1431 | 0 | throw uno::RuntimeException(); |
1432 | | |
1433 | 0 | if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN ) |
1434 | 0 | throw io::IOException(); // TODO: |
1435 | | |
1436 | 0 | OUString aOrigRelStreamName = OUString::Concat(aOrigStreamName) + ".rels"; |
1437 | 0 | OUString aNewRelStreamName = OUString::Concat(aNewStreamName) + ".rels"; |
1438 | |
|
1439 | 0 | bool bRenamed = aOrigRelStreamName != aNewRelStreamName; |
1440 | 0 | if ( m_nRelInfoStatus == RELINFO_CHANGED |
1441 | 0 | || m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ |
1442 | 0 | || m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) |
1443 | 0 | { |
1444 | 0 | if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) ) |
1445 | 0 | xRelStorage->removeElement( aOrigRelStreamName ); |
1446 | |
|
1447 | 0 | if ( m_nRelInfoStatus == RELINFO_CHANGED ) |
1448 | 0 | { |
1449 | 0 | if ( m_aNewRelInfo.hasElements() ) |
1450 | 0 | { |
1451 | 0 | uno::Reference< io::XStream > xRelsStream = |
1452 | 0 | xRelStorage->openStreamElement( aNewRelStreamName, |
1453 | 0 | embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE ); |
1454 | |
|
1455 | 0 | uno::Reference< io::XOutputStream > xOutStream = xRelsStream->getOutputStream(); |
1456 | 0 | if ( !xOutStream.is() ) |
1457 | 0 | throw uno::RuntimeException(); |
1458 | | |
1459 | 0 | ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence( xOutStream, m_aNewRelInfo, m_xContext ); |
1460 | | |
1461 | | // set the mediatype |
1462 | 0 | uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW ); |
1463 | 0 | xPropSet->setPropertyValue( |
1464 | 0 | u"MediaType"_ustr, |
1465 | 0 | uno::Any( u"application/vnd.openxmlformats-package.relationships+xml"_ustr ) ); |
1466 | |
|
1467 | 0 | m_nRelInfoStatus = RELINFO_READ; |
1468 | 0 | } |
1469 | 0 | } |
1470 | 0 | else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ |
1471 | 0 | || m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) |
1472 | 0 | { |
1473 | 0 | uno::Reference< io::XStream > xRelsStream = |
1474 | 0 | xRelStorage->openStreamElement( aNewRelStreamName, |
1475 | 0 | embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE ); |
1476 | |
|
1477 | 0 | uno::Reference< io::XOutputStream > xOutputStream = xRelsStream->getOutputStream(); |
1478 | 0 | if ( !xOutputStream.is() ) |
1479 | 0 | throw uno::RuntimeException(); |
1480 | | |
1481 | 0 | uno::Reference< io::XSeekable > xSeek( m_xNewRelInfoStream, uno::UNO_QUERY_THROW ); |
1482 | 0 | xSeek->seek( 0 ); |
1483 | 0 | ::comphelper::OStorageHelper::CopyInputToOutput( m_xNewRelInfoStream, xOutputStream ); |
1484 | 0 | xSeek->seek( 0 ); |
1485 | | |
1486 | | // set the mediatype |
1487 | 0 | uno::Reference< beans::XPropertySet > xPropSet( xRelsStream, uno::UNO_QUERY_THROW ); |
1488 | 0 | xPropSet->setPropertyValue(u"MediaType"_ustr, |
1489 | 0 | uno::Any( u"application/vnd.openxmlformats-package.relationships+xml"_ustr ) ); |
1490 | |
|
1491 | 0 | if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM ) |
1492 | 0 | m_nRelInfoStatus = RELINFO_NO_INIT; |
1493 | 0 | else |
1494 | 0 | { |
1495 | | // the information is already parsed and the stream is stored, no need in temporary stream any more |
1496 | 0 | m_xNewRelInfoStream.clear(); |
1497 | 0 | m_nRelInfoStatus = RELINFO_READ; |
1498 | 0 | } |
1499 | 0 | } |
1500 | | |
1501 | | // the original stream makes no sense after this step |
1502 | 0 | m_xOrigRelInfoStream = m_xNewRelInfoStream; |
1503 | 0 | m_aOrigRelInfo = m_aNewRelInfo; |
1504 | 0 | m_bOrigRelInfoBroken = false; |
1505 | 0 | m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); |
1506 | 0 | m_xNewRelInfoStream.clear(); |
1507 | 0 | } |
1508 | 0 | else |
1509 | 0 | { |
1510 | | // the stream is not changed but it might be renamed |
1511 | 0 | if ( bRenamed && xRelStorage->hasByName( aOrigRelStreamName ) ) |
1512 | 0 | xRelStorage->renameElement( aOrigRelStreamName, aNewRelStreamName ); |
1513 | 0 | } |
1514 | 0 | } |
1515 | | |
1516 | | // OWriteStream implementation |
1517 | | |
1518 | | OWriteStream::OWriteStream( OWriteStream_Impl& rImpl, bool bTransacted ) |
1519 | 0 | : m_pImpl( &rImpl ) |
1520 | 0 | , m_xSharedMutex( rImpl.m_xMutex ) |
1521 | 0 | , m_aListenersContainer( rImpl.m_xMutex->GetMutex() ) |
1522 | 0 | , m_nStorageType( m_pImpl->m_nStorageType ) |
1523 | 0 | , m_bInStreamDisconnected( false ) |
1524 | 0 | , m_bInitOnDemand( true ) |
1525 | 0 | , m_nInitPosition( 0 ) |
1526 | 0 | , m_bTransacted( bTransacted ) |
1527 | 0 | { |
1528 | 0 | } |
1529 | | |
1530 | | OWriteStream::OWriteStream( OWriteStream_Impl& rImpl, uno::Reference< io::XStream > const & xStream, bool bTransacted ) |
1531 | 262 | : m_pImpl( &rImpl ) |
1532 | 262 | , m_xSharedMutex( rImpl.m_xMutex ) |
1533 | 262 | , m_aListenersContainer( rImpl.m_xMutex->GetMutex() ) |
1534 | 262 | , m_nStorageType( m_pImpl->m_nStorageType ) |
1535 | 262 | , m_bInStreamDisconnected( false ) |
1536 | 262 | , m_bInitOnDemand( false ) |
1537 | 262 | , m_nInitPosition( 0 ) |
1538 | 262 | , m_bTransacted( bTransacted ) |
1539 | 262 | { |
1540 | 262 | if ( xStream.is() ) |
1541 | 262 | { |
1542 | 262 | m_xInStream = xStream->getInputStream(); |
1543 | 262 | m_xOutStream = xStream->getOutputStream(); |
1544 | 262 | m_xSeekable.set( xStream, uno::UNO_QUERY ); |
1545 | 262 | OSL_ENSURE( m_xInStream.is() && m_xOutStream.is() && m_xSeekable.is(), "Stream implementation is incomplete!" ); |
1546 | 262 | } |
1547 | 262 | } |
1548 | | |
1549 | | OWriteStream::~OWriteStream() |
1550 | 262 | { |
1551 | 262 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1552 | 262 | if ( m_pImpl ) |
1553 | 215 | { |
1554 | 215 | osl_atomic_increment(&m_refCount); |
1555 | 215 | try { |
1556 | 215 | dispose(); |
1557 | 215 | } |
1558 | 215 | catch( const uno::RuntimeException& ) |
1559 | 215 | { |
1560 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception"); |
1561 | 0 | } |
1562 | 215 | } |
1563 | 262 | } |
1564 | | |
1565 | | void OWriteStream::DeInit() |
1566 | 229 | { |
1567 | 229 | if ( !m_pImpl ) |
1568 | 0 | return; // do nothing |
1569 | | |
1570 | 229 | if ( m_xSeekable.is() ) |
1571 | 229 | m_nInitPosition = m_xSeekable->getPosition(); |
1572 | | |
1573 | 229 | m_xInStream.clear(); |
1574 | 229 | m_xOutStream.clear(); |
1575 | 229 | m_xSeekable.clear(); |
1576 | 229 | m_bInitOnDemand = true; |
1577 | 229 | } |
1578 | | |
1579 | | void OWriteStream::CheckInitOnDemand() |
1580 | 1.29k | { |
1581 | 1.29k | if ( !m_pImpl ) |
1582 | 0 | { |
1583 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
1584 | 0 | throw lang::DisposedException(); |
1585 | 0 | } |
1586 | | |
1587 | 1.29k | if ( !m_bInitOnDemand ) |
1588 | 1.07k | return; |
1589 | | |
1590 | 218 | SAL_INFO( "package.xstor", "package (mv76033) OWriteStream::CheckInitOnDemand, initializing" ); |
1591 | 218 | uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream(); |
1592 | 218 | if ( xStream.is() ) |
1593 | 218 | { |
1594 | 218 | m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW ); |
1595 | 218 | m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW ); |
1596 | 218 | m_xSeekable.set( xStream, uno::UNO_QUERY_THROW ); |
1597 | 218 | m_xSeekable->seek( m_nInitPosition ); |
1598 | | |
1599 | 218 | m_nInitPosition = 0; |
1600 | 218 | m_bInitOnDemand = false; |
1601 | 218 | } |
1602 | 218 | } |
1603 | | |
1604 | | void OWriteStream::CopyToStreamInternally_Impl( const uno::Reference< io::XStream >& xDest ) |
1605 | 0 | { |
1606 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1607 | |
|
1608 | 0 | CheckInitOnDemand(); |
1609 | |
|
1610 | 0 | if ( !m_xInStream.is() ) |
1611 | 0 | throw uno::RuntimeException(); |
1612 | | |
1613 | 0 | if ( !m_xSeekable.is() ) |
1614 | 0 | throw uno::RuntimeException(); |
1615 | | |
1616 | 0 | uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY_THROW ); |
1617 | |
|
1618 | 0 | uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream(); |
1619 | 0 | if ( !xDestOutStream.is() ) |
1620 | 0 | throw io::IOException(); // TODO |
1621 | | |
1622 | 0 | sal_Int64 nCurPos = m_xSeekable->getPosition(); |
1623 | 0 | m_xSeekable->seek( 0 ); |
1624 | |
|
1625 | 0 | uno::Exception eThrown; |
1626 | 0 | bool bThrown = false; |
1627 | 0 | try { |
1628 | 0 | ::comphelper::OStorageHelper::CopyInputToOutput( m_xInStream, xDestOutStream ); |
1629 | 0 | } |
1630 | 0 | catch ( const uno::Exception& e ) |
1631 | 0 | { |
1632 | 0 | eThrown = e; |
1633 | 0 | bThrown = true; |
1634 | 0 | } |
1635 | | |
1636 | | // position-related section below is critical |
1637 | | // if it fails the stream will become invalid |
1638 | 0 | try { |
1639 | 0 | m_xSeekable->seek( nCurPos ); |
1640 | 0 | } |
1641 | 0 | catch ( const uno::Exception& ) |
1642 | 0 | { |
1643 | | // TODO: set the stream in invalid state or dispose |
1644 | 0 | TOOLS_WARN_EXCEPTION( "package.xstor", "The stream become invalid during copying" ); |
1645 | 0 | throw uno::RuntimeException(); |
1646 | 0 | } |
1647 | | |
1648 | 0 | if ( bThrown ) |
1649 | 0 | throw eThrown; |
1650 | | |
1651 | | // now the properties can be copied |
1652 | | // the order of the properties setting is not important for StorageStream API |
1653 | 0 | OUString aPropName (u"Compressed"_ustr); |
1654 | 0 | xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) ); |
1655 | 0 | if ( m_nStorageType == embed::StorageFormats::PACKAGE || m_nStorageType == embed::StorageFormats::OFOPXML ) |
1656 | 0 | { |
1657 | 0 | aPropName = "MediaType"; |
1658 | 0 | xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) ); |
1659 | |
|
1660 | 0 | if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
1661 | 0 | { |
1662 | 0 | aPropName = "UseCommonStoragePasswordEncryption"; |
1663 | 0 | xDestProps->setPropertyValue( aPropName, getPropertyValue( aPropName ) ); |
1664 | 0 | } |
1665 | 0 | } |
1666 | 0 | } |
1667 | | |
1668 | | void OWriteStream::ModifyParentUnlockMutex_Impl(osl::ClearableMutexGuard& aGuard) |
1669 | 553 | { |
1670 | 553 | if ( m_pImpl->m_pParent ) |
1671 | 553 | { |
1672 | 553 | if ( m_pImpl->m_pParent->HasModifiedListener() ) |
1673 | 0 | { |
1674 | 0 | uno::Reference< util::XModifiable > xParentModif( static_cast<util::XModifiable*>(m_pImpl->m_pParent->m_pAntiImpl) ); |
1675 | 0 | aGuard.clear(); |
1676 | 0 | xParentModif->setModified( true ); |
1677 | 0 | } |
1678 | 553 | else |
1679 | 553 | m_pImpl->m_pParent->m_bIsModified = true; |
1680 | 553 | } |
1681 | 553 | } |
1682 | | |
1683 | | uno::Any SAL_CALL OWriteStream::queryInterface( const uno::Type& rType ) |
1684 | 560 | { |
1685 | | // common interfaces |
1686 | 560 | uno::Any aReturn = ::cppu::queryInterface |
1687 | 560 | ( rType |
1688 | 560 | , static_cast<lang::XTypeProvider*> ( this ) |
1689 | 560 | , static_cast<io::XInputStream*> ( this ) |
1690 | 560 | , static_cast<io::XOutputStream*> ( this ) |
1691 | 560 | , static_cast<io::XStream*> ( this ) |
1692 | 560 | , static_cast<embed::XExtendedStorageStream*> ( this ) |
1693 | 560 | , static_cast<io::XSeekable*> ( this ) |
1694 | 560 | , static_cast<io::XTruncate*> ( this ) |
1695 | 560 | , static_cast<lang::XComponent*> ( this ) |
1696 | 560 | , static_cast<beans::XPropertySet*> ( this ) ); |
1697 | | |
1698 | 560 | if ( aReturn.hasValue() ) |
1699 | 560 | return aReturn ; |
1700 | | |
1701 | 0 | if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
1702 | 0 | { |
1703 | 0 | aReturn = ::cppu::queryInterface |
1704 | 0 | ( rType |
1705 | 0 | , static_cast<embed::XEncryptionProtectedSource2*> ( this ) |
1706 | 0 | , static_cast<embed::XEncryptionProtectedSource*> ( this ) ); |
1707 | 0 | } |
1708 | 0 | else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) |
1709 | 0 | { |
1710 | 0 | aReturn = ::cppu::queryInterface |
1711 | 0 | ( rType |
1712 | 0 | , static_cast<embed::XRelationshipAccess*> ( this ) ); |
1713 | 0 | } |
1714 | |
|
1715 | 0 | if ( aReturn.hasValue() ) |
1716 | 0 | return aReturn ; |
1717 | | |
1718 | 0 | if ( m_bTransacted ) |
1719 | 0 | { |
1720 | 0 | aReturn = ::cppu::queryInterface |
1721 | 0 | ( rType |
1722 | 0 | , static_cast<embed::XTransactedObject*> ( this ) |
1723 | 0 | , static_cast<embed::XTransactionBroadcaster*> ( this ) ); |
1724 | |
|
1725 | 0 | if ( aReturn.hasValue() ) |
1726 | 0 | return aReturn ; |
1727 | 0 | } |
1728 | | |
1729 | 0 | return OWeakObject::queryInterface( rType ); |
1730 | 0 | } |
1731 | | |
1732 | | void SAL_CALL OWriteStream::acquire() noexcept |
1733 | 3.66k | { |
1734 | 3.66k | OWeakObject::acquire(); |
1735 | 3.66k | } |
1736 | | |
1737 | | void SAL_CALL OWriteStream::release() noexcept |
1738 | 3.66k | { |
1739 | 3.66k | OWeakObject::release(); |
1740 | 3.66k | } |
1741 | | |
1742 | | uno::Sequence< uno::Type > SAL_CALL OWriteStream::getTypes() |
1743 | 0 | { |
1744 | 0 | if (! m_oTypeCollection) |
1745 | 0 | { |
1746 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1747 | |
|
1748 | 0 | if (! m_oTypeCollection) |
1749 | 0 | { |
1750 | 0 | if ( m_bTransacted ) |
1751 | 0 | { |
1752 | 0 | if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
1753 | 0 | { |
1754 | 0 | ::cppu::OTypeCollection aTmpCollection |
1755 | 0 | ( cppu::UnoType<lang::XTypeProvider>::get() |
1756 | 0 | , cppu::UnoType<io::XInputStream>::get() |
1757 | 0 | , cppu::UnoType<io::XOutputStream>::get() |
1758 | 0 | , cppu::UnoType<io::XStream>::get() |
1759 | 0 | , cppu::UnoType<io::XSeekable>::get() |
1760 | 0 | , cppu::UnoType<io::XTruncate>::get() |
1761 | 0 | , cppu::UnoType<lang::XComponent>::get() |
1762 | 0 | , cppu::UnoType<embed::XEncryptionProtectedSource2>::get() |
1763 | 0 | , cppu::UnoType<embed::XEncryptionProtectedSource>::get() |
1764 | 0 | , cppu::UnoType<embed::XExtendedStorageStream>::get() |
1765 | 0 | , cppu::UnoType<embed::XTransactedObject>::get() |
1766 | 0 | , cppu::UnoType<embed::XTransactionBroadcaster>::get()); |
1767 | |
|
1768 | 0 | m_oTypeCollection.emplace( |
1769 | 0 | cppu::UnoType<beans::XPropertySet>::get() |
1770 | 0 | , aTmpCollection.getTypes()); |
1771 | 0 | } |
1772 | 0 | else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) |
1773 | 0 | { |
1774 | 0 | m_oTypeCollection.emplace( |
1775 | 0 | cppu::UnoType<lang::XTypeProvider>::get() |
1776 | 0 | , cppu::UnoType<io::XInputStream>::get() |
1777 | 0 | , cppu::UnoType<io::XOutputStream>::get() |
1778 | 0 | , cppu::UnoType<io::XStream>::get() |
1779 | 0 | , cppu::UnoType<io::XSeekable>::get() |
1780 | 0 | , cppu::UnoType<io::XTruncate>::get() |
1781 | 0 | , cppu::UnoType<lang::XComponent>::get() |
1782 | 0 | , cppu::UnoType<embed::XRelationshipAccess>::get() |
1783 | 0 | , cppu::UnoType<embed::XExtendedStorageStream>::get() |
1784 | 0 | , cppu::UnoType<embed::XTransactedObject>::get() |
1785 | 0 | , cppu::UnoType<embed::XTransactionBroadcaster>::get() |
1786 | 0 | , cppu::UnoType<beans::XPropertySet>::get()); |
1787 | 0 | } |
1788 | 0 | else // if ( m_pData->m_nStorageType == embed::StorageFormats::ZIP ) |
1789 | 0 | { |
1790 | 0 | m_oTypeCollection.emplace( |
1791 | 0 | cppu::UnoType<lang::XTypeProvider>::get() |
1792 | 0 | , cppu::UnoType<io::XInputStream>::get() |
1793 | 0 | , cppu::UnoType<io::XOutputStream>::get() |
1794 | 0 | , cppu::UnoType<io::XStream>::get() |
1795 | 0 | , cppu::UnoType<io::XSeekable>::get() |
1796 | 0 | , cppu::UnoType<io::XTruncate>::get() |
1797 | 0 | , cppu::UnoType<lang::XComponent>::get() |
1798 | 0 | , cppu::UnoType<embed::XExtendedStorageStream>::get() |
1799 | 0 | , cppu::UnoType<embed::XTransactedObject>::get() |
1800 | 0 | , cppu::UnoType<embed::XTransactionBroadcaster>::get() |
1801 | 0 | , cppu::UnoType<beans::XPropertySet>::get()); |
1802 | 0 | } |
1803 | 0 | } |
1804 | 0 | else |
1805 | 0 | { |
1806 | 0 | if ( m_nStorageType == embed::StorageFormats::PACKAGE ) |
1807 | 0 | { |
1808 | 0 | m_oTypeCollection.emplace( |
1809 | 0 | cppu::UnoType<lang::XTypeProvider>::get() |
1810 | 0 | , cppu::UnoType<io::XInputStream>::get() |
1811 | 0 | , cppu::UnoType<io::XOutputStream>::get() |
1812 | 0 | , cppu::UnoType<io::XStream>::get() |
1813 | 0 | , cppu::UnoType<io::XSeekable>::get() |
1814 | 0 | , cppu::UnoType<io::XTruncate>::get() |
1815 | 0 | , cppu::UnoType<lang::XComponent>::get() |
1816 | 0 | , cppu::UnoType<embed::XEncryptionProtectedSource2>::get() |
1817 | 0 | , cppu::UnoType<embed::XEncryptionProtectedSource>::get() |
1818 | 0 | , cppu::UnoType<beans::XPropertySet>::get()); |
1819 | 0 | } |
1820 | 0 | else if ( m_nStorageType == embed::StorageFormats::OFOPXML ) |
1821 | 0 | { |
1822 | 0 | m_oTypeCollection.emplace( |
1823 | 0 | cppu::UnoType<lang::XTypeProvider>::get() |
1824 | 0 | , cppu::UnoType<io::XInputStream>::get() |
1825 | 0 | , cppu::UnoType<io::XOutputStream>::get() |
1826 | 0 | , cppu::UnoType<io::XStream>::get() |
1827 | 0 | , cppu::UnoType<io::XSeekable>::get() |
1828 | 0 | , cppu::UnoType<io::XTruncate>::get() |
1829 | 0 | , cppu::UnoType<lang::XComponent>::get() |
1830 | 0 | , cppu::UnoType<embed::XRelationshipAccess>::get() |
1831 | 0 | , cppu::UnoType<beans::XPropertySet>::get()); |
1832 | 0 | } |
1833 | 0 | else // if ( m_pData->m_nStorageType == embed::StorageFormats::ZIP ) |
1834 | 0 | { |
1835 | 0 | m_oTypeCollection.emplace( |
1836 | 0 | cppu::UnoType<lang::XTypeProvider>::get() |
1837 | 0 | , cppu::UnoType<io::XInputStream>::get() |
1838 | 0 | , cppu::UnoType<io::XOutputStream>::get() |
1839 | 0 | , cppu::UnoType<io::XStream>::get() |
1840 | 0 | , cppu::UnoType<io::XSeekable>::get() |
1841 | 0 | , cppu::UnoType<io::XTruncate>::get() |
1842 | 0 | , cppu::UnoType<lang::XComponent>::get() |
1843 | 0 | , cppu::UnoType<beans::XPropertySet>::get()); |
1844 | 0 | } |
1845 | 0 | } |
1846 | 0 | } |
1847 | 0 | } |
1848 | |
|
1849 | 0 | return m_oTypeCollection->getTypes() ; |
1850 | 0 | } |
1851 | | |
1852 | | uno::Sequence< sal_Int8 > SAL_CALL OWriteStream::getImplementationId() |
1853 | 0 | { |
1854 | 0 | static const comphelper::UnoIdInit lcl_ImplId; |
1855 | 0 | return lcl_ImplId.getSeq(); |
1856 | 0 | } |
1857 | | |
1858 | | sal_Int32 SAL_CALL OWriteStream::readBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) |
1859 | 0 | { |
1860 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1861 | |
|
1862 | 0 | CheckInitOnDemand(); |
1863 | |
|
1864 | 0 | if ( !m_xInStream.is() ) |
1865 | 0 | throw io::NotConnectedException(); |
1866 | | |
1867 | 0 | return m_xInStream->readBytes( aData, nBytesToRead ); |
1868 | 0 | } |
1869 | | |
1870 | | sal_Int32 SAL_CALL OWriteStream::readSomeBytes( uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) |
1871 | 0 | { |
1872 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1873 | |
|
1874 | 0 | CheckInitOnDemand(); |
1875 | |
|
1876 | 0 | if ( !m_xInStream.is() ) |
1877 | 0 | throw io::NotConnectedException(); |
1878 | | |
1879 | 0 | return m_xInStream->readSomeBytes( aData, nMaxBytesToRead ); |
1880 | 0 | } |
1881 | | |
1882 | | sal_Int32 OWriteStream::readSomeBytes(sal_Int8* pData, sal_Int32 nBytesToRead) |
1883 | 7 | { |
1884 | 7 | osl::MutexGuard aGuard(m_xSharedMutex->GetMutex()); |
1885 | | |
1886 | 7 | CheckInitOnDemand(); |
1887 | | |
1888 | 7 | if (!m_xInStream.is()) |
1889 | 0 | throw io::NotConnectedException(); |
1890 | | |
1891 | 7 | if (auto pByteReader = dynamic_cast<comphelper::ByteReader*>(m_xInStream.get())) |
1892 | 7 | return pByteReader->readSomeBytes(pData, nBytesToRead); |
1893 | | |
1894 | 0 | uno::Sequence<sal_Int8> aData; |
1895 | 0 | sal_Int32 nRead = m_xInStream->readSomeBytes(aData, nBytesToRead); |
1896 | 0 | std::copy_n(aData.getConstArray(), nRead, pData); |
1897 | |
|
1898 | 0 | return nRead; |
1899 | 7 | } |
1900 | | |
1901 | | void SAL_CALL OWriteStream::skipBytes( sal_Int32 nBytesToSkip ) |
1902 | 0 | { |
1903 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1904 | |
|
1905 | 0 | CheckInitOnDemand(); |
1906 | |
|
1907 | 0 | if ( !m_xInStream.is() ) |
1908 | 0 | throw io::NotConnectedException(); |
1909 | | |
1910 | 0 | m_xInStream->skipBytes( nBytesToSkip ); |
1911 | 0 | } |
1912 | | |
1913 | | sal_Int32 SAL_CALL OWriteStream::available( ) |
1914 | 0 | { |
1915 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1916 | |
|
1917 | 0 | CheckInitOnDemand(); |
1918 | |
|
1919 | 0 | if ( !m_xInStream.is() ) |
1920 | 0 | throw io::NotConnectedException(); |
1921 | | |
1922 | 0 | return m_xInStream->available(); |
1923 | |
|
1924 | 0 | } |
1925 | | |
1926 | | void SAL_CALL OWriteStream::closeInput( ) |
1927 | 0 | { |
1928 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1929 | |
|
1930 | 0 | if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) ) |
1931 | 0 | throw io::NotConnectedException(); |
1932 | | |
1933 | | // the input part of the stream stays open for internal purposes (to allow reading during copying) |
1934 | | // since it can not be reopened until output part is closed, it will be closed with output part. |
1935 | 0 | m_bInStreamDisconnected = true; |
1936 | | // m_xInStream->closeInput(); |
1937 | | // m_xInStream.clear(); |
1938 | |
|
1939 | 0 | if ( !m_xOutStream.is() ) |
1940 | 0 | dispose(); |
1941 | 0 | } |
1942 | | |
1943 | | uno::Reference< io::XInputStream > SAL_CALL OWriteStream::getInputStream() |
1944 | 204 | { |
1945 | 204 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1946 | | |
1947 | 204 | if ( !m_bInitOnDemand && ( m_bInStreamDisconnected || !m_xInStream.is() ) ) |
1948 | 0 | return uno::Reference< io::XInputStream >(); |
1949 | | |
1950 | 204 | return this; |
1951 | 204 | } |
1952 | | |
1953 | | uno::Reference< io::XOutputStream > SAL_CALL OWriteStream::getOutputStream() |
1954 | 616 | { |
1955 | 616 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
1956 | | |
1957 | 616 | try |
1958 | 616 | { |
1959 | 616 | CheckInitOnDemand(); |
1960 | 616 | } |
1961 | 616 | catch( const io::IOException& r ) |
1962 | 616 | { |
1963 | 0 | throw lang::WrappedTargetRuntimeException(u"OWriteStream::getOutputStream: Could not create backing temp file"_ustr, |
1964 | 0 | getXWeak(), css::uno::Any ( r ) ); |
1965 | 0 | } |
1966 | | |
1967 | 616 | if ( !m_xOutStream.is() ) |
1968 | 0 | return uno::Reference< io::XOutputStream >(); |
1969 | | |
1970 | 616 | return this; |
1971 | 616 | } |
1972 | | |
1973 | | void OWriteStream::CheckInitOnWriteDemand(sal_Int32 dataSize) |
1974 | 316 | { |
1975 | | // write methods need a different initialization, since they depend on data length |
1976 | | |
1977 | 316 | if ( !m_pImpl ) |
1978 | 0 | { |
1979 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
1980 | 0 | throw lang::DisposedException(); |
1981 | 0 | } |
1982 | | |
1983 | 316 | if ( !m_bInitOnDemand ) |
1984 | 316 | { |
1985 | 316 | if ( !m_xOutStream.is() || !m_xSeekable.is()) |
1986 | 0 | throw io::NotConnectedException(); |
1987 | | |
1988 | 316 | if ( m_pImpl->m_xCacheStream.is() ) |
1989 | 284 | { |
1990 | | // check whether the cache should be turned off |
1991 | 284 | sal_Int64 nPos = m_xSeekable->getPosition(); |
1992 | 284 | if (nPos + dataSize > MAX_STORCACHE_SIZE) |
1993 | 4 | { |
1994 | | // disconnect the cache and copy the data to the temporary file |
1995 | 4 | m_xSeekable->seek( 0 ); |
1996 | | |
1997 | | // it is enough to copy the cached stream, the cache should already contain everything |
1998 | 4 | m_pImpl->GetFilledTempFileIfNo( m_xInStream ); |
1999 | 4 | if ( m_pImpl->m_oTempFile.has_value() ) |
2000 | 4 | { |
2001 | 4 | DeInit(); |
2002 | | // the last position is known and it is differs from the current stream position |
2003 | 4 | m_nInitPosition = nPos; |
2004 | 4 | } |
2005 | 4 | } |
2006 | 284 | } |
2007 | 316 | } |
2008 | | |
2009 | 316 | if ( m_bInitOnDemand ) |
2010 | 4 | { |
2011 | 4 | SAL_INFO("package.xstor", "OWriteStream::CheckInitOnWriteDemand: initializing"); |
2012 | 4 | uno::Reference< io::XStream > xStream = m_pImpl->GetTempFileAsStream(); |
2013 | 4 | if ( xStream.is() ) |
2014 | 4 | { |
2015 | 4 | m_xInStream.set( xStream->getInputStream(), uno::UNO_SET_THROW ); |
2016 | 4 | m_xOutStream.set( xStream->getOutputStream(), uno::UNO_SET_THROW ); |
2017 | 4 | m_xSeekable.set( xStream, uno::UNO_QUERY_THROW ); |
2018 | 4 | m_xSeekable->seek( m_nInitPosition ); |
2019 | | |
2020 | 4 | m_nInitPosition = 0; |
2021 | 4 | m_bInitOnDemand = false; |
2022 | 4 | } |
2023 | 4 | } |
2024 | 316 | } |
2025 | | |
2026 | | void SAL_CALL OWriteStream::writeBytes( const uno::Sequence< sal_Int8 >& aData ) |
2027 | 305 | { |
2028 | 305 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2029 | | |
2030 | 305 | CheckInitOnWriteDemand(aData.getLength()); |
2031 | | |
2032 | 305 | if ( !m_xOutStream.is() ) |
2033 | 0 | throw io::NotConnectedException(); |
2034 | | |
2035 | 305 | m_xOutStream->writeBytes( aData ); |
2036 | 305 | m_pImpl->m_bHasDataToFlush = true; |
2037 | | |
2038 | 305 | ModifyParentUnlockMutex_Impl( aGuard ); |
2039 | 305 | } |
2040 | | |
2041 | | void OWriteStream::writeBytes( const sal_Int8* pData, sal_Int32 nBytesToWrite ) |
2042 | 11 | { |
2043 | 11 | assert(nBytesToWrite >= 0); |
2044 | | |
2045 | 11 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2046 | | |
2047 | 11 | CheckInitOnWriteDemand(nBytesToWrite); |
2048 | | |
2049 | 11 | if ( !m_xOutStream.is() ) |
2050 | 0 | throw io::NotConnectedException(); |
2051 | | |
2052 | 11 | if (auto pByteWriter = dynamic_cast< comphelper::ByteWriter* >( m_xOutStream.get() )) |
2053 | 11 | pByteWriter->writeBytes(pData, nBytesToWrite); |
2054 | 0 | else |
2055 | 0 | { |
2056 | 0 | uno::Sequence<sal_Int8> aData(pData, nBytesToWrite); |
2057 | 0 | m_xOutStream->writeBytes( aData ); |
2058 | 0 | } |
2059 | 11 | m_pImpl->m_bHasDataToFlush = true; |
2060 | | |
2061 | 11 | ModifyParentUnlockMutex_Impl( aGuard ); |
2062 | 11 | } |
2063 | | |
2064 | | void SAL_CALL OWriteStream::flush() |
2065 | 232 | { |
2066 | | // In case stream is flushed its current version becomes visible |
2067 | | // to the parent storage. Usually parent storage flushes the stream |
2068 | | // during own commit but a user can explicitly flush the stream |
2069 | | // so the changes will be available through cloning functionality. |
2070 | | |
2071 | 232 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2072 | | |
2073 | 232 | if ( !m_pImpl ) |
2074 | 0 | { |
2075 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2076 | 0 | throw lang::DisposedException(); |
2077 | 0 | } |
2078 | | |
2079 | 232 | if ( !m_bInitOnDemand ) |
2080 | 225 | { |
2081 | 225 | if ( !m_xOutStream.is() ) |
2082 | 0 | throw io::NotConnectedException(); |
2083 | | |
2084 | 225 | m_xOutStream->flush(); |
2085 | 225 | m_pImpl->Commit(); |
2086 | 225 | } |
2087 | 232 | } |
2088 | | |
2089 | | void OWriteStream::CloseOutput_Impl() |
2090 | 255 | { |
2091 | | // all the checks must be done in calling method |
2092 | | |
2093 | 255 | m_xOutStream->closeOutput(); |
2094 | 255 | m_xOutStream.clear(); |
2095 | | |
2096 | 255 | if ( m_bInitOnDemand ) |
2097 | 0 | return; |
2098 | | |
2099 | | // after the stream is disposed it can be committed |
2100 | | // so transport correct size property |
2101 | 255 | if ( !m_xSeekable.is() ) |
2102 | 0 | throw uno::RuntimeException(); |
2103 | | |
2104 | 255 | for ( auto& rProp : asNonConstRange(m_pImpl->m_aProps) ) |
2105 | 1.02k | { |
2106 | 1.02k | if ( rProp.Name == "Size" ) |
2107 | 255 | rProp.Value <<= m_xSeekable->getLength(); |
2108 | 1.02k | } |
2109 | 255 | } |
2110 | | |
2111 | | void SAL_CALL OWriteStream::closeOutput() |
2112 | 197 | { |
2113 | 197 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2114 | | |
2115 | 197 | CheckInitOnDemand(); |
2116 | | |
2117 | 197 | if ( !m_xOutStream.is() ) |
2118 | 0 | throw io::NotConnectedException(); |
2119 | | |
2120 | 197 | CloseOutput_Impl(); |
2121 | | |
2122 | 197 | if ( m_bInStreamDisconnected || !m_xInStream.is() ) |
2123 | 0 | dispose(); |
2124 | 197 | } |
2125 | | |
2126 | | void SAL_CALL OWriteStream::seek( sal_Int64 location ) |
2127 | 312 | { |
2128 | 312 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2129 | | |
2130 | 312 | CheckInitOnDemand(); |
2131 | | |
2132 | 312 | if ( !m_xSeekable.is() ) |
2133 | 0 | throw uno::RuntimeException(); |
2134 | | |
2135 | 312 | m_xSeekable->seek( location ); |
2136 | 312 | } |
2137 | | |
2138 | | sal_Int64 SAL_CALL OWriteStream::getPosition() |
2139 | 0 | { |
2140 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2141 | |
|
2142 | 0 | CheckInitOnDemand(); |
2143 | |
|
2144 | 0 | if ( !m_xSeekable.is() ) |
2145 | 0 | throw uno::RuntimeException(); |
2146 | | |
2147 | 0 | return m_xSeekable->getPosition(); |
2148 | 0 | } |
2149 | | |
2150 | | sal_Int64 SAL_CALL OWriteStream::getLength() |
2151 | 161 | { |
2152 | 161 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2153 | | |
2154 | 161 | CheckInitOnDemand(); |
2155 | | |
2156 | 161 | if ( !m_xSeekable.is() ) |
2157 | 0 | throw uno::RuntimeException(); |
2158 | | |
2159 | 161 | return m_xSeekable->getLength(); |
2160 | 161 | } |
2161 | | |
2162 | | void SAL_CALL OWriteStream::truncate() |
2163 | 0 | { |
2164 | 0 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2165 | |
|
2166 | 0 | CheckInitOnDemand(); |
2167 | |
|
2168 | 0 | if ( !m_xOutStream.is() ) |
2169 | 0 | throw uno::RuntimeException(); |
2170 | | |
2171 | 0 | uno::Reference< io::XTruncate > xTruncate( m_xOutStream, uno::UNO_QUERY_THROW ); |
2172 | 0 | xTruncate->truncate(); |
2173 | |
|
2174 | 0 | m_pImpl->m_bHasDataToFlush = true; |
2175 | |
|
2176 | 0 | ModifyParentUnlockMutex_Impl( aGuard ); |
2177 | 0 | } |
2178 | | |
2179 | | void SAL_CALL OWriteStream::dispose() |
2180 | 262 | { |
2181 | | // should be an internal method since it can be called only from parent storage |
2182 | 262 | { |
2183 | 262 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2184 | | |
2185 | 262 | if ( !m_pImpl ) |
2186 | 0 | { |
2187 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2188 | 0 | throw lang::DisposedException(); |
2189 | 0 | } |
2190 | | |
2191 | 262 | if ( m_xOutStream.is() ) |
2192 | 58 | CloseOutput_Impl(); |
2193 | | |
2194 | 262 | if ( m_xInStream.is() ) |
2195 | 255 | { |
2196 | 255 | m_xInStream->closeInput(); |
2197 | 255 | m_xInStream.clear(); |
2198 | 255 | } |
2199 | | |
2200 | 262 | m_xSeekable.clear(); |
2201 | | |
2202 | 262 | m_pImpl->m_pAntiImpl = nullptr; |
2203 | | |
2204 | 262 | if ( !m_bInitOnDemand ) |
2205 | 255 | { |
2206 | 255 | try |
2207 | 255 | { |
2208 | 255 | if ( !m_bTransacted ) |
2209 | 255 | { |
2210 | 255 | m_pImpl->Commit(); |
2211 | 255 | } |
2212 | 0 | else |
2213 | 0 | { |
2214 | | // throw away all the changes |
2215 | 0 | m_pImpl->Revert(); |
2216 | 0 | } |
2217 | 255 | } |
2218 | 255 | catch( const uno::Exception& ) |
2219 | 255 | { |
2220 | 0 | uno::Any aCaught( ::cppu::getCaughtException() ); |
2221 | 0 | SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught)); |
2222 | 0 | throw lang::WrappedTargetRuntimeException(u"Can not commit/revert the storage!"_ustr, |
2223 | 0 | getXWeak(), |
2224 | 0 | aCaught ); |
2225 | 0 | } |
2226 | 255 | } |
2227 | | |
2228 | 262 | m_pImpl = nullptr; |
2229 | 262 | } |
2230 | | |
2231 | | // the listener might try to get rid of parent storage, and the storage would delete this object; |
2232 | | // for now the listener is just notified at the end of the method to workaround the problem |
2233 | | // in future a more elegant way should be found |
2234 | | |
2235 | 0 | lang::EventObject aSource( getXWeak() ); |
2236 | 262 | m_aListenersContainer.disposeAndClear( aSource ); |
2237 | 262 | } |
2238 | | |
2239 | | void SAL_CALL OWriteStream::addEventListener( |
2240 | | const uno::Reference< lang::XEventListener >& xListener ) |
2241 | 0 | { |
2242 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2243 | |
|
2244 | 0 | if ( !m_pImpl ) |
2245 | 0 | { |
2246 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2247 | 0 | throw lang::DisposedException(); |
2248 | 0 | } |
2249 | | |
2250 | 0 | m_aListenersContainer.addInterface( cppu::UnoType<lang::XEventListener>::get(), |
2251 | 0 | xListener ); |
2252 | 0 | } |
2253 | | |
2254 | | void SAL_CALL OWriteStream::removeEventListener( |
2255 | | const uno::Reference< lang::XEventListener >& xListener ) |
2256 | 0 | { |
2257 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2258 | |
|
2259 | 0 | if ( !m_pImpl ) |
2260 | 0 | { |
2261 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2262 | 0 | throw lang::DisposedException(); |
2263 | 0 | } |
2264 | | |
2265 | 0 | m_aListenersContainer.removeInterface( cppu::UnoType<lang::XEventListener>::get(), |
2266 | 0 | xListener ); |
2267 | 0 | } |
2268 | | |
2269 | | void SAL_CALL OWriteStream::setEncryptionPassword( const OUString& aPass ) |
2270 | 0 | { |
2271 | 0 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2272 | |
|
2273 | 0 | CheckInitOnDemand(); |
2274 | |
|
2275 | 0 | OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!" ); |
2276 | |
|
2277 | 0 | m_pImpl->SetEncrypted( ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) ); |
2278 | |
|
2279 | 0 | ModifyParentUnlockMutex_Impl( aGuard ); |
2280 | 0 | } |
2281 | | |
2282 | | void SAL_CALL OWriteStream::removeEncryption() |
2283 | 0 | { |
2284 | 0 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2285 | |
|
2286 | 0 | CheckInitOnDemand(); |
2287 | |
|
2288 | 0 | OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!" ); |
2289 | |
|
2290 | 0 | m_pImpl->SetDecrypted(); |
2291 | |
|
2292 | 0 | ModifyParentUnlockMutex_Impl( aGuard ); |
2293 | 0 | } |
2294 | | |
2295 | | void SAL_CALL OWriteStream::setEncryptionData( const uno::Sequence< beans::NamedValue >& aEncryptionData ) |
2296 | 0 | { |
2297 | 0 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2298 | |
|
2299 | 0 | CheckInitOnDemand(); |
2300 | |
|
2301 | 0 | OSL_ENSURE( m_pImpl->m_xPackageStream.is(), "No package stream is set!" ); |
2302 | |
|
2303 | 0 | m_pImpl->SetEncrypted( aEncryptionData ); |
2304 | |
|
2305 | 0 | ModifyParentUnlockMutex_Impl( aGuard ); |
2306 | 0 | } |
2307 | | |
2308 | | sal_Bool SAL_CALL OWriteStream::hasEncryptionData() |
2309 | 0 | { |
2310 | 0 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2311 | |
|
2312 | 0 | if (!m_pImpl) |
2313 | 0 | return false; |
2314 | | |
2315 | 0 | bool bRet = false; |
2316 | |
|
2317 | 0 | try |
2318 | 0 | { |
2319 | 0 | bRet = m_pImpl->IsEncrypted(); |
2320 | |
|
2321 | 0 | if (!bRet && m_pImpl->m_bUseCommonEncryption && m_pImpl->m_pParent) |
2322 | 0 | bRet = m_pImpl->m_pParent->m_bHasCommonEncryptionData; |
2323 | 0 | } |
2324 | 0 | catch( const uno::RuntimeException& ) |
2325 | 0 | { |
2326 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
2327 | 0 | throw; |
2328 | 0 | } |
2329 | 0 | catch( const uno::Exception& ) |
2330 | 0 | { |
2331 | 0 | uno::Any aCaught( ::cppu::getCaughtException() ); |
2332 | 0 | SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught)); |
2333 | 0 | throw lang::WrappedTargetRuntimeException( u"Problems on hasEncryptionData!"_ustr, |
2334 | 0 | getXWeak(), |
2335 | 0 | aCaught ); |
2336 | 0 | } |
2337 | | |
2338 | 0 | return bRet; |
2339 | 0 | } |
2340 | | |
2341 | | sal_Bool SAL_CALL OWriteStream::hasByID( const OUString& sID ) |
2342 | 0 | { |
2343 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2344 | |
|
2345 | 0 | if ( !m_pImpl ) |
2346 | 0 | { |
2347 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2348 | 0 | throw lang::DisposedException(); |
2349 | 0 | } |
2350 | | |
2351 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2352 | 0 | throw uno::RuntimeException(); |
2353 | | |
2354 | 0 | try |
2355 | 0 | { |
2356 | 0 | getRelationshipByID( sID ); |
2357 | 0 | return true; |
2358 | 0 | } |
2359 | 0 | catch( const container::NoSuchElementException& ) |
2360 | 0 | { |
2361 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "No Element"); |
2362 | 0 | } |
2363 | | |
2364 | 0 | return false; |
2365 | 0 | } |
2366 | | |
2367 | | OUString SAL_CALL OWriteStream::getTargetByID( const OUString& sID ) |
2368 | 0 | { |
2369 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2370 | |
|
2371 | 0 | if ( !m_pImpl ) |
2372 | 0 | { |
2373 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2374 | 0 | throw lang::DisposedException(); |
2375 | 0 | } |
2376 | | |
2377 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2378 | 0 | throw uno::RuntimeException(); |
2379 | | |
2380 | 0 | const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID ); |
2381 | 0 | auto pRel = lcl_findPairByName(aSeq, u"Target"_ustr); |
2382 | 0 | if (pRel != aSeq.end()) |
2383 | 0 | return pRel->Second; |
2384 | | |
2385 | 0 | return OUString(); |
2386 | 0 | } |
2387 | | |
2388 | | OUString SAL_CALL OWriteStream::getTypeByID( const OUString& sID ) |
2389 | 0 | { |
2390 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2391 | |
|
2392 | 0 | if ( !m_pImpl ) |
2393 | 0 | { |
2394 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2395 | 0 | throw lang::DisposedException(); |
2396 | 0 | } |
2397 | | |
2398 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2399 | 0 | throw uno::RuntimeException(); |
2400 | | |
2401 | 0 | const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID ); |
2402 | 0 | auto pRel = lcl_findPairByName(aSeq, u"Type"_ustr); |
2403 | 0 | if (pRel != aSeq.end()) |
2404 | 0 | return pRel->Second; |
2405 | | |
2406 | 0 | return OUString(); |
2407 | 0 | } |
2408 | | |
2409 | | uno::Sequence< beans::StringPair > SAL_CALL OWriteStream::getRelationshipByID( const OUString& sID ) |
2410 | 0 | { |
2411 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2412 | |
|
2413 | 0 | if ( !m_pImpl ) |
2414 | 0 | { |
2415 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2416 | 0 | throw lang::DisposedException(); |
2417 | 0 | } |
2418 | | |
2419 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2420 | 0 | throw uno::RuntimeException(); |
2421 | | |
2422 | | // TODO/LATER: in future the unification of the ID could be checked |
2423 | 0 | const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); |
2424 | 0 | const beans::StringPair aIDRel(u"Id"_ustr, sID); |
2425 | 0 | auto pRel = std::find_if(aSeq.begin(), aSeq.end(), |
2426 | 0 | [&aIDRel](const uno::Sequence<beans::StringPair>& rRel) { |
2427 | 0 | return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); }); |
2428 | 0 | if (pRel != aSeq.end()) |
2429 | 0 | return *pRel; |
2430 | | |
2431 | 0 | throw container::NoSuchElementException(); |
2432 | 0 | } |
2433 | | |
2434 | | uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getRelationshipsByType( const OUString& sType ) |
2435 | 0 | { |
2436 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2437 | |
|
2438 | 0 | if ( !m_pImpl ) |
2439 | 0 | { |
2440 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2441 | 0 | throw lang::DisposedException(); |
2442 | 0 | } |
2443 | | |
2444 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2445 | 0 | throw uno::RuntimeException(); |
2446 | | |
2447 | | // TODO/LATER: in future the unification of the ID could be checked |
2448 | 0 | const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); |
2449 | 0 | const beans::StringPair aTypeRel(u"Type"_ustr, sType); |
2450 | 0 | std::vector< uno::Sequence<beans::StringPair> > aResult; |
2451 | 0 | aResult.reserve(aSeq.getLength()); |
2452 | |
|
2453 | 0 | std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResult), |
2454 | 0 | [&aTypeRel](const uno::Sequence<beans::StringPair>& rRel) { |
2455 | 0 | return std::find(rRel.begin(), rRel.end(), aTypeRel) != rRel.end(); }); |
2456 | |
|
2457 | 0 | return comphelper::containerToSequence(aResult); |
2458 | 0 | } |
2459 | | |
2460 | | uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OWriteStream::getAllRelationships() |
2461 | 0 | { |
2462 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2463 | |
|
2464 | 0 | if ( !m_pImpl ) |
2465 | 0 | { |
2466 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2467 | 0 | throw lang::DisposedException(); |
2468 | 0 | } |
2469 | | |
2470 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2471 | 0 | throw uno::RuntimeException(); |
2472 | | |
2473 | 0 | return m_pImpl->GetAllRelationshipsIfAny(); |
2474 | 0 | } |
2475 | | |
2476 | | void SAL_CALL OWriteStream::insertRelationshipByID( const OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, sal_Bool bReplace ) |
2477 | 0 | { |
2478 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2479 | |
|
2480 | 0 | if ( !m_pImpl ) |
2481 | 0 | { |
2482 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2483 | 0 | throw lang::DisposedException(); |
2484 | 0 | } |
2485 | | |
2486 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2487 | 0 | throw uno::RuntimeException(); |
2488 | | |
2489 | 0 | const beans::StringPair aIDRel(u"Id"_ustr, sID); |
2490 | |
|
2491 | 0 | uno::Sequence<beans::StringPair>* pPair = nullptr; |
2492 | | |
2493 | | // TODO/LATER: in future the unification of the ID could be checked |
2494 | 0 | uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); |
2495 | 0 | for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) |
2496 | 0 | { |
2497 | 0 | const auto& rRel = aSeq[nInd]; |
2498 | 0 | if (std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end()) |
2499 | 0 | pPair = &aSeq.getArray()[nInd]; |
2500 | 0 | } |
2501 | |
|
2502 | 0 | if ( pPair && !bReplace ) |
2503 | 0 | throw container::ElementExistException(); // TODO |
2504 | | |
2505 | 0 | if ( !pPair ) |
2506 | 0 | { |
2507 | 0 | sal_Int32 nIDInd = aSeq.getLength(); |
2508 | 0 | aSeq.realloc( nIDInd + 1 ); |
2509 | 0 | pPair = &aSeq.getArray()[nIDInd]; |
2510 | 0 | } |
2511 | |
|
2512 | 0 | std::vector<beans::StringPair> aResult; |
2513 | 0 | aResult.reserve(aEntry.getLength() + 1); |
2514 | |
|
2515 | 0 | aResult.push_back(aIDRel); |
2516 | 0 | std::copy_if(aEntry.begin(), aEntry.end(), std::back_inserter(aResult), |
2517 | 0 | [](const beans::StringPair& rRel) { return rRel.First != "Id"; }); |
2518 | |
|
2519 | 0 | *pPair = comphelper::containerToSequence(aResult); |
2520 | |
|
2521 | 0 | m_pImpl->m_aNewRelInfo = std::move(aSeq); |
2522 | 0 | m_pImpl->m_xNewRelInfoStream.clear(); |
2523 | 0 | m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; |
2524 | 0 | } |
2525 | | |
2526 | | void SAL_CALL OWriteStream::removeRelationshipByID( const OUString& sID ) |
2527 | 0 | { |
2528 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2529 | |
|
2530 | 0 | if ( !m_pImpl ) |
2531 | 0 | { |
2532 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2533 | 0 | throw lang::DisposedException(); |
2534 | 0 | } |
2535 | | |
2536 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2537 | 0 | throw uno::RuntimeException(); |
2538 | | |
2539 | 0 | uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); |
2540 | 0 | const beans::StringPair aIDRel(u"Id"_ustr, sID); |
2541 | 0 | auto pRel = std::find_if(std::cbegin(aSeq), std::cend(aSeq), |
2542 | 0 | [&aIDRel](const uno::Sequence< beans::StringPair >& rRel) { |
2543 | 0 | return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); }); |
2544 | 0 | if (pRel != std::cend(aSeq)) |
2545 | 0 | { |
2546 | 0 | auto nInd = static_cast<sal_Int32>(std::distance(std::cbegin(aSeq), pRel)); |
2547 | 0 | comphelper::removeElementAt(aSeq, nInd); |
2548 | |
|
2549 | 0 | m_pImpl->m_aNewRelInfo = std::move(aSeq); |
2550 | 0 | m_pImpl->m_xNewRelInfoStream.clear(); |
2551 | 0 | m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; |
2552 | | |
2553 | | // TODO/LATER: in future the unification of the ID could be checked |
2554 | 0 | return; |
2555 | 0 | } |
2556 | | |
2557 | 0 | throw container::NoSuchElementException(); |
2558 | 0 | } |
2559 | | |
2560 | | void SAL_CALL OWriteStream::insertRelationships( const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, sal_Bool bReplace ) |
2561 | 0 | { |
2562 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2563 | |
|
2564 | 0 | if ( !m_pImpl ) |
2565 | 0 | { |
2566 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2567 | 0 | throw lang::DisposedException(); |
2568 | 0 | } |
2569 | | |
2570 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2571 | 0 | throw uno::RuntimeException(); |
2572 | | |
2573 | 0 | OUString aIDTag( u"Id"_ustr ); |
2574 | 0 | const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships(); |
2575 | 0 | std::vector< uno::Sequence<beans::StringPair> > aResultVec; |
2576 | 0 | aResultVec.reserve(aSeq.getLength() + aEntries.getLength()); |
2577 | |
|
2578 | 0 | std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResultVec), |
2579 | 0 | [&aIDTag, &aEntries, bReplace](const uno::Sequence<beans::StringPair>& rTargetRel) { |
2580 | 0 | auto pTargetPair = lcl_findPairByName(rTargetRel, aIDTag); |
2581 | 0 | if (pTargetPair == rTargetRel.end()) |
2582 | 0 | return false; |
2583 | | |
2584 | 0 | bool bIsSourceSame = std::any_of(aEntries.begin(), aEntries.end(), |
2585 | 0 | [&pTargetPair](const uno::Sequence<beans::StringPair>& rSourceEntry) { |
2586 | 0 | return std::find(rSourceEntry.begin(), rSourceEntry.end(), *pTargetPair) != rSourceEntry.end(); }); |
2587 | |
|
2588 | 0 | if ( bIsSourceSame && !bReplace ) |
2589 | 0 | throw container::ElementExistException(); |
2590 | | |
2591 | | // if no such element in the provided sequence |
2592 | 0 | return !bIsSourceSame; |
2593 | 0 | }); |
2594 | |
|
2595 | 0 | std::transform(aEntries.begin(), aEntries.end(), std::back_inserter(aResultVec), |
2596 | 0 | [&aIDTag](const uno::Sequence<beans::StringPair>& rEntry) -> uno::Sequence<beans::StringPair> { |
2597 | 0 | auto pPair = lcl_findPairByName(rEntry, aIDTag); |
2598 | 0 | if (pPair == rEntry.end()) |
2599 | 0 | throw io::IOException(); // TODO: illegal relation ( no ID ) |
2600 | | |
2601 | 0 | auto aResult = comphelper::sequenceToContainer<std::vector<beans::StringPair>>(rEntry); |
2602 | 0 | auto nIDInd = std::distance(rEntry.begin(), pPair); |
2603 | 0 | std::rotate(aResult.begin(), std::next(aResult.begin(), nIDInd), std::next(aResult.begin(), nIDInd + 1)); |
2604 | |
|
2605 | 0 | return comphelper::containerToSequence(aResult); |
2606 | 0 | }); |
2607 | |
|
2608 | 0 | m_pImpl->m_aNewRelInfo = comphelper::containerToSequence(aResultVec); |
2609 | 0 | m_pImpl->m_xNewRelInfoStream.clear(); |
2610 | 0 | m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; |
2611 | 0 | } |
2612 | | |
2613 | | void SAL_CALL OWriteStream::clearRelationships() |
2614 | 0 | { |
2615 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2616 | |
|
2617 | 0 | if ( !m_pImpl ) |
2618 | 0 | { |
2619 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2620 | 0 | throw lang::DisposedException(); |
2621 | 0 | } |
2622 | | |
2623 | 0 | if ( m_nStorageType != embed::StorageFormats::OFOPXML ) |
2624 | 0 | throw uno::RuntimeException(); |
2625 | | |
2626 | 0 | m_pImpl->m_aNewRelInfo.realloc( 0 ); |
2627 | 0 | m_pImpl->m_xNewRelInfoStream.clear(); |
2628 | 0 | m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED; |
2629 | 0 | } |
2630 | | |
2631 | | uno::Reference< beans::XPropertySetInfo > SAL_CALL OWriteStream::getPropertySetInfo() |
2632 | 0 | { |
2633 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2634 | | |
2635 | | //TODO: |
2636 | 0 | return uno::Reference< beans::XPropertySetInfo >(); |
2637 | 0 | } |
2638 | | |
2639 | | void SAL_CALL OWriteStream::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue ) |
2640 | 237 | { |
2641 | 237 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2642 | | |
2643 | 237 | if ( !m_pImpl ) |
2644 | 0 | { |
2645 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2646 | 0 | throw lang::DisposedException(); |
2647 | 0 | } |
2648 | | |
2649 | 237 | m_pImpl->GetStreamProperties(); |
2650 | 237 | static constexpr OUString aCompressedString( u"Compressed"_ustr ); |
2651 | 237 | static constexpr OUString aMediaTypeString( u"MediaType"_ustr ); |
2652 | 237 | if ( m_nStorageType == embed::StorageFormats::PACKAGE && aPropertyName == aMediaTypeString ) |
2653 | 215 | { |
2654 | | // if the "Compressed" property is not set explicitly, the MediaType can change the default value |
2655 | 215 | bool bCompressedValueFromType = true; |
2656 | 215 | OUString aType; |
2657 | 215 | aValue >>= aType; |
2658 | | |
2659 | 215 | if ( !m_pImpl->m_bCompressedSetExplicit ) |
2660 | 204 | { |
2661 | 204 | if ( aType == "image/jpeg" || aType == "image/png" || aType == "image/gif" ) |
2662 | 0 | bCompressedValueFromType = false; |
2663 | 204 | } |
2664 | | |
2665 | 215 | for ( auto& rProp : asNonConstRange(m_pImpl->m_aProps) ) |
2666 | 860 | { |
2667 | 860 | if ( aPropertyName == rProp.Name ) |
2668 | 215 | rProp.Value = aValue; |
2669 | 645 | else if ( !m_pImpl->m_bCompressedSetExplicit && aCompressedString == rProp.Name ) |
2670 | 204 | rProp.Value <<= bCompressedValueFromType; |
2671 | 860 | } |
2672 | 215 | } |
2673 | 22 | else if ( aPropertyName == aCompressedString ) |
2674 | 11 | { |
2675 | | // if the "Compressed" property is not set explicitly, the MediaType can change the default value |
2676 | 11 | m_pImpl->m_bCompressedSetExplicit = true; |
2677 | 11 | for ( auto& rProp : asNonConstRange(m_pImpl->m_aProps) ) |
2678 | 44 | { |
2679 | 44 | if ( aPropertyName == rProp.Name ) |
2680 | 11 | rProp.Value = aValue; |
2681 | 44 | } |
2682 | 11 | } |
2683 | 11 | else if ( m_nStorageType == embed::StorageFormats::PACKAGE |
2684 | 11 | && aPropertyName == "UseCommonStoragePasswordEncryption" ) |
2685 | 11 | { |
2686 | 11 | bool bUseCommonEncryption = false; |
2687 | 11 | if ( !(aValue >>= bUseCommonEncryption) ) |
2688 | 0 | throw lang::IllegalArgumentException(); //TODO |
2689 | | |
2690 | 11 | if ( m_bInitOnDemand && m_pImpl->m_bHasInsertedStreamOptimization ) |
2691 | 0 | { |
2692 | | // the data stream is provided to the packagestream directly |
2693 | 0 | m_pImpl->m_bUseCommonEncryption = bUseCommonEncryption; |
2694 | 0 | } |
2695 | 11 | else if ( bUseCommonEncryption ) |
2696 | 11 | { |
2697 | 11 | if ( !m_pImpl->m_bUseCommonEncryption ) |
2698 | 0 | { |
2699 | 0 | m_pImpl->SetDecrypted(); |
2700 | 0 | m_pImpl->m_bUseCommonEncryption = true; |
2701 | 0 | } |
2702 | 11 | } |
2703 | 0 | else |
2704 | 0 | m_pImpl->m_bUseCommonEncryption = false; |
2705 | 11 | } |
2706 | 0 | else if ( m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName == aMediaTypeString ) |
2707 | 0 | { |
2708 | 0 | for ( auto& rProp : asNonConstRange(m_pImpl->m_aProps) ) |
2709 | 0 | { |
2710 | 0 | if ( aPropertyName == rProp.Name ) |
2711 | 0 | rProp.Value = aValue; |
2712 | 0 | } |
2713 | 0 | } |
2714 | 0 | else if ( m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName == "RelationsInfoStream" ) |
2715 | 0 | { |
2716 | 0 | uno::Reference< io::XInputStream > xInRelStream; |
2717 | 0 | if ( !( aValue >>= xInRelStream ) || !xInRelStream.is() ) |
2718 | 0 | throw lang::IllegalArgumentException(); // TODO |
2719 | | |
2720 | 0 | uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY ); |
2721 | 0 | if ( !xSeek.is() ) |
2722 | 0 | { |
2723 | | // currently this is an internal property that is used for optimization |
2724 | | // and the stream must support XSeekable interface |
2725 | | // TODO/LATER: in future it can be changed if property is used from outside |
2726 | 0 | throw lang::IllegalArgumentException(); // TODO |
2727 | 0 | } |
2728 | | |
2729 | 0 | m_pImpl->m_xNewRelInfoStream = std::move(xInRelStream); |
2730 | 0 | m_pImpl->m_aNewRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >(); |
2731 | 0 | m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM; |
2732 | 0 | } |
2733 | 0 | else if ( m_nStorageType == embed::StorageFormats::OFOPXML && aPropertyName == "RelationsInfo" ) |
2734 | 0 | { |
2735 | 0 | if ( !(aValue >>= m_pImpl->m_aNewRelInfo) ) |
2736 | 0 | throw lang::IllegalArgumentException(); // TODO |
2737 | 0 | } |
2738 | 0 | else if ( aPropertyName == "Size" ) |
2739 | 0 | throw beans::PropertyVetoException(); // TODO |
2740 | 0 | else if ( m_nStorageType == embed::StorageFormats::PACKAGE |
2741 | 0 | && ( aPropertyName == "IsEncrypted" || aPropertyName == "Encrypted" ) ) |
2742 | 0 | throw beans::PropertyVetoException(); // TODO |
2743 | 0 | else if ( aPropertyName == "RelId" ) |
2744 | 0 | { |
2745 | 0 | aValue >>= m_pImpl->m_nRelId; |
2746 | 0 | } |
2747 | 0 | else |
2748 | 0 | throw beans::UnknownPropertyException(aPropertyName); // TODO |
2749 | | |
2750 | 237 | m_pImpl->m_bHasDataToFlush = true; |
2751 | 237 | ModifyParentUnlockMutex_Impl( aGuard ); |
2752 | 237 | } |
2753 | | |
2754 | | uno::Any SAL_CALL OWriteStream::getPropertyValue( const OUString& aProp ) |
2755 | 0 | { |
2756 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2757 | |
|
2758 | 0 | if ( !m_pImpl ) |
2759 | 0 | { |
2760 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2761 | 0 | throw lang::DisposedException(); |
2762 | 0 | } |
2763 | | |
2764 | 0 | if ( aProp == "RelId" ) |
2765 | 0 | { |
2766 | 0 | return uno::Any( m_pImpl->GetNewRelId() ); |
2767 | 0 | } |
2768 | | |
2769 | 0 | OUString aPropertyName; |
2770 | 0 | if ( aProp == "IsEncrypted" ) |
2771 | 0 | aPropertyName = "Encrypted"; |
2772 | 0 | else |
2773 | 0 | aPropertyName = aProp; |
2774 | |
|
2775 | 0 | if ( ( ( m_nStorageType == embed::StorageFormats::PACKAGE || m_nStorageType == embed::StorageFormats::OFOPXML ) |
2776 | 0 | && aPropertyName == "MediaType" ) |
2777 | 0 | || ( m_nStorageType == embed::StorageFormats::PACKAGE && aPropertyName == "Encrypted" ) |
2778 | 0 | || aPropertyName == "Compressed" ) |
2779 | 0 | { |
2780 | 0 | m_pImpl->GetStreamProperties(); |
2781 | |
|
2782 | 0 | auto pProp = std::find_if(std::cbegin(m_pImpl->m_aProps), std::cend(m_pImpl->m_aProps), |
2783 | 0 | [&aPropertyName](const css::beans::PropertyValue& rProp){ return aPropertyName == rProp.Name; }); |
2784 | 0 | if (pProp != std::cend(m_pImpl->m_aProps)) |
2785 | 0 | return pProp->Value; |
2786 | 0 | } |
2787 | 0 | else if ( m_nStorageType == embed::StorageFormats::PACKAGE |
2788 | 0 | && aPropertyName == "UseCommonStoragePasswordEncryption" ) |
2789 | 0 | return uno::Any( m_pImpl->m_bUseCommonEncryption ); |
2790 | 0 | else if ( aPropertyName == "Size" ) |
2791 | 0 | { |
2792 | 0 | bool bThrow = false; |
2793 | 0 | try |
2794 | 0 | { |
2795 | 0 | CheckInitOnDemand(); |
2796 | 0 | } |
2797 | 0 | catch (const io::IOException&) |
2798 | 0 | { |
2799 | 0 | bThrow = true; |
2800 | 0 | } |
2801 | 0 | if (bThrow || !m_xSeekable.is()) |
2802 | 0 | throw uno::RuntimeException(); |
2803 | | |
2804 | 0 | return uno::Any( m_xSeekable->getLength() ); |
2805 | 0 | } |
2806 | | |
2807 | 0 | throw beans::UnknownPropertyException(aPropertyName); // TODO |
2808 | 0 | } |
2809 | | |
2810 | | void SAL_CALL OWriteStream::addPropertyChangeListener( |
2811 | | const OUString& /*aPropertyName*/, |
2812 | | const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ ) |
2813 | 0 | { |
2814 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2815 | |
|
2816 | 0 | if ( !m_pImpl ) |
2817 | 0 | { |
2818 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2819 | 0 | throw lang::DisposedException(); |
2820 | 0 | } |
2821 | | |
2822 | | //TODO: |
2823 | 0 | } |
2824 | | |
2825 | | void SAL_CALL OWriteStream::removePropertyChangeListener( |
2826 | | const OUString& /*aPropertyName*/, |
2827 | | const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ ) |
2828 | 0 | { |
2829 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2830 | |
|
2831 | 0 | if ( !m_pImpl ) |
2832 | 0 | { |
2833 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2834 | 0 | throw lang::DisposedException(); |
2835 | 0 | } |
2836 | | |
2837 | | //TODO: |
2838 | 0 | } |
2839 | | |
2840 | | void SAL_CALL OWriteStream::addVetoableChangeListener( |
2841 | | const OUString& /*PropertyName*/, |
2842 | | const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) |
2843 | 0 | { |
2844 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2845 | |
|
2846 | 0 | if ( !m_pImpl ) |
2847 | 0 | { |
2848 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2849 | 0 | throw lang::DisposedException(); |
2850 | 0 | } |
2851 | | |
2852 | | //TODO: |
2853 | 0 | } |
2854 | | |
2855 | | void SAL_CALL OWriteStream::removeVetoableChangeListener( |
2856 | | const OUString& /*PropertyName*/, |
2857 | | const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ ) |
2858 | 0 | { |
2859 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
2860 | |
|
2861 | 0 | if ( !m_pImpl ) |
2862 | 0 | { |
2863 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2864 | 0 | throw lang::DisposedException(); |
2865 | 0 | } |
2866 | | |
2867 | | //TODO: |
2868 | 0 | } |
2869 | | |
2870 | | // XTransactedObject |
2871 | | |
2872 | | void OWriteStream::BroadcastTransaction( sal_Int8 nMessage ) |
2873 | | /* |
2874 | | 1 - preCommit |
2875 | | 2 - committed |
2876 | | 3 - preRevert |
2877 | | 4 - reverted |
2878 | | */ |
2879 | 0 | { |
2880 | | // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed |
2881 | 0 | if ( !m_pImpl ) |
2882 | 0 | { |
2883 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2884 | 0 | throw lang::DisposedException(); |
2885 | 0 | } |
2886 | | |
2887 | 0 | lang::EventObject aSource( getXWeak() ); |
2888 | |
|
2889 | 0 | comphelper::OInterfaceContainerHelper2* pContainer = |
2890 | 0 | m_aListenersContainer.getContainer( |
2891 | 0 | cppu::UnoType<embed::XTransactionListener>::get()); |
2892 | 0 | if ( !pContainer ) |
2893 | 0 | return; |
2894 | | |
2895 | 0 | comphelper::OInterfaceIteratorHelper2 pIterator( *pContainer ); |
2896 | 0 | while ( pIterator.hasMoreElements( ) ) |
2897 | 0 | { |
2898 | 0 | OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!" ); |
2899 | |
|
2900 | 0 | switch( nMessage ) |
2901 | 0 | { |
2902 | 0 | case STOR_MESS_PRECOMMIT: |
2903 | 0 | static_cast<embed::XTransactionListener*>( pIterator.next( ) )->preCommit( aSource ); |
2904 | 0 | break; |
2905 | 0 | case STOR_MESS_COMMITTED: |
2906 | 0 | static_cast<embed::XTransactionListener*>( pIterator.next( ) )->commited( aSource ); |
2907 | 0 | break; |
2908 | 0 | case STOR_MESS_PREREVERT: |
2909 | 0 | static_cast<embed::XTransactionListener*>( pIterator.next( ) )->preRevert( aSource ); |
2910 | 0 | break; |
2911 | 0 | case STOR_MESS_REVERTED: |
2912 | 0 | static_cast< embed::XTransactionListener*>( pIterator.next( ) )->reverted( aSource ); |
2913 | 0 | break; |
2914 | 0 | } |
2915 | 0 | } |
2916 | 0 | } |
2917 | | void SAL_CALL OWriteStream::commit() |
2918 | 0 | { |
2919 | 0 | SAL_INFO( "package.xstor", "package (mv76033) OWriteStream::commit" ); |
2920 | | |
2921 | 0 | if ( !m_pImpl ) |
2922 | 0 | { |
2923 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2924 | 0 | throw lang::DisposedException(); |
2925 | 0 | } |
2926 | | |
2927 | 0 | if ( !m_bTransacted ) |
2928 | 0 | throw uno::RuntimeException(); |
2929 | | |
2930 | 0 | try { |
2931 | 0 | BroadcastTransaction( STOR_MESS_PRECOMMIT ); |
2932 | |
|
2933 | 0 | osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2934 | |
|
2935 | 0 | if ( !m_pImpl ) |
2936 | 0 | { |
2937 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2938 | 0 | throw lang::DisposedException(); |
2939 | 0 | } |
2940 | | |
2941 | 0 | m_pImpl->Commit(); |
2942 | | |
2943 | | // when the storage is committed the parent is modified |
2944 | 0 | ModifyParentUnlockMutex_Impl( aGuard ); |
2945 | 0 | } |
2946 | 0 | catch( const io::IOException& ) |
2947 | 0 | { |
2948 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
2949 | 0 | throw; |
2950 | 0 | } |
2951 | 0 | catch( const embed::StorageWrappedTargetException& ) |
2952 | 0 | { |
2953 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
2954 | 0 | throw; |
2955 | 0 | } |
2956 | 0 | catch( const uno::RuntimeException& ) |
2957 | 0 | { |
2958 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
2959 | 0 | throw; |
2960 | 0 | } |
2961 | 0 | catch( const uno::Exception& ) |
2962 | 0 | { |
2963 | 0 | uno::Any aCaught( ::cppu::getCaughtException() ); |
2964 | 0 | SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught)); |
2965 | 0 | throw embed::StorageWrappedTargetException( u"Problems on commit!"_ustr, |
2966 | 0 | getXWeak(), |
2967 | 0 | aCaught ); |
2968 | 0 | } |
2969 | | |
2970 | 0 | BroadcastTransaction( STOR_MESS_COMMITTED ); |
2971 | 0 | } |
2972 | | |
2973 | | void SAL_CALL OWriteStream::revert() |
2974 | 0 | { |
2975 | 0 | SAL_INFO( "package.xstor", "package (mv76033) OWriteStream::revert" ); |
2976 | | |
2977 | | // the method removes all the changes done after last commit |
2978 | | |
2979 | 0 | if ( !m_pImpl ) |
2980 | 0 | { |
2981 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2982 | 0 | throw lang::DisposedException(); |
2983 | 0 | } |
2984 | | |
2985 | 0 | if ( !m_bTransacted ) |
2986 | 0 | throw uno::RuntimeException(); |
2987 | | |
2988 | 0 | BroadcastTransaction( STOR_MESS_PREREVERT ); |
2989 | |
|
2990 | 0 | { |
2991 | 0 | osl::MutexGuard aGuard(m_xSharedMutex->GetMutex()); |
2992 | |
|
2993 | 0 | if (!m_pImpl) |
2994 | 0 | { |
2995 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
2996 | 0 | throw lang::DisposedException(); |
2997 | 0 | } |
2998 | | |
2999 | 0 | try { |
3000 | 0 | m_pImpl->Revert(); |
3001 | 0 | } |
3002 | 0 | catch (const io::IOException&) |
3003 | 0 | { |
3004 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
3005 | 0 | throw; |
3006 | 0 | } |
3007 | 0 | catch (const embed::StorageWrappedTargetException&) |
3008 | 0 | { |
3009 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
3010 | 0 | throw; |
3011 | 0 | } |
3012 | 0 | catch (const uno::RuntimeException&) |
3013 | 0 | { |
3014 | 0 | TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow"); |
3015 | 0 | throw; |
3016 | 0 | } |
3017 | 0 | catch (const uno::Exception&) |
3018 | 0 | { |
3019 | 0 | uno::Any aCaught(::cppu::getCaughtException()); |
3020 | 0 | SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught)); |
3021 | 0 | throw embed::StorageWrappedTargetException(u"Problems on revert!"_ustr, |
3022 | 0 | getXWeak(), |
3023 | 0 | aCaught); |
3024 | 0 | } |
3025 | 0 | } |
3026 | | |
3027 | 0 | BroadcastTransaction( STOR_MESS_REVERTED ); |
3028 | 0 | } |
3029 | | |
3030 | | // XTransactionBroadcaster |
3031 | | |
3032 | | void SAL_CALL OWriteStream::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener ) |
3033 | 0 | { |
3034 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
3035 | |
|
3036 | 0 | if ( !m_pImpl ) |
3037 | 0 | { |
3038 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
3039 | 0 | throw lang::DisposedException(); |
3040 | 0 | } |
3041 | | |
3042 | 0 | if ( !m_bTransacted ) |
3043 | 0 | throw uno::RuntimeException(); |
3044 | | |
3045 | 0 | m_aListenersContainer.addInterface( cppu::UnoType<embed::XTransactionListener>::get(), |
3046 | 0 | aListener ); |
3047 | 0 | } |
3048 | | |
3049 | | void SAL_CALL OWriteStream::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener ) |
3050 | 0 | { |
3051 | 0 | ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() ); |
3052 | |
|
3053 | 0 | if ( !m_pImpl ) |
3054 | 0 | { |
3055 | 0 | SAL_INFO("package.xstor", "Disposed!"); |
3056 | 0 | throw lang::DisposedException(); |
3057 | 0 | } |
3058 | | |
3059 | 0 | if ( !m_bTransacted ) |
3060 | 0 | throw uno::RuntimeException(); |
3061 | | |
3062 | 0 | m_aListenersContainer.removeInterface( cppu::UnoType<embed::XTransactionListener>::get(), |
3063 | 0 | aListener ); |
3064 | 0 | } |
3065 | | |
3066 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |