1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <ZipPackageStream.hxx>
22 #include <com/sun/star/beans/PropertyValue.hpp>
23 #include <com/sun/star/container/XNameContainer.hpp>
24 #include <com/sun/star/packages/NoRawFormatException.hpp>
25 #include <com/sun/star/packages/zip/ZipConstants.hpp>
26 #include <com/sun/star/embed/StorageFormats.hpp>
27 #include <com/sun/star/packages/zip/ZipIOException.hpp>
28 #include <com/sun/star/packages/NoEncryptionException.hpp>
29 #include <com/sun/star/packages/zip/ZipException.hpp>
30 #include <com/sun/star/packages/WrongPasswordException.hpp>
31 #include <com/sun/star/io/TempFile.hpp>
32 #include <com/sun/star/io/XInputStream.hpp>
33 #include <com/sun/star/io/XOutputStream.hpp>
34 #include <com/sun/star/io/XStream.hpp>
35 #include <com/sun/star/io/XSeekable.hpp>
36 #include <com/sun/star/xml/crypto/DigestID.hpp>
37 #include <com/sun/star/xml/crypto/CipherID.hpp>
40 #include <ZipOutputEntry.hxx>
41 #include <ZipOutputStream.hxx>
42 #include <ZipPackage.hxx>
43 #include <ZipFile.hxx>
44 #include <EncryptedDataHeader.hxx>
45 #include <osl/diagnose.h>
46 #include "wrapstreamforshare.hxx"
48 #include <comphelper/seekableinput.hxx>
49 #include <comphelper/servicehelper.hxx>
50 #include <comphelper/storagehelper.hxx>
51 #include <cppuhelper/supportsservice.hxx>
52 #include <unotools/tempfile.hxx>
54 #include <rtl/random.h>
55 #include <sal/log.hxx>
56 #include <comphelper/diagnose_ex.hxx>
58 #include <PackageConstants.hxx>
63 using namespace com::sun::star::packages::zip::ZipConstants
;
64 using namespace com::sun::star::packages::zip
;
65 using namespace com::sun::star::uno
;
66 using namespace com::sun::star::lang
;
67 using namespace com::sun::star
;
70 #if OSL_DEBUG_LEVEL > 0
71 #define THROW_WHERE SAL_WHERE
73 #define THROW_WHERE ""
76 ZipPackageStream::ZipPackageStream ( ZipPackage
& rNewPackage
,
77 const uno::Reference
< XComponentContext
>& xContext
,
79 bool bAllowRemoveOnInsert
)
80 : m_rZipPackage( rNewPackage
)
81 , m_bToBeCompressed ( true )
82 , m_bToBeEncrypted ( false )
83 , m_bHaveOwnKey ( false )
84 , m_bIsEncrypted ( false )
85 , m_nImportedStartKeyAlgorithm( 0 )
86 , m_nImportedEncryptionAlgorithm( 0 )
87 , m_nImportedChecksumAlgorithm( 0 )
88 , m_nImportedDerivedKeySize( 0 )
89 , m_nStreamMode( PACKAGE_STREAM_NOTSET
)
90 , m_nMagicalHackPos( 0 )
91 , m_nMagicalHackSize( 0 )
92 , m_nOwnStreamOrigSize( 0 )
93 , m_bHasSeekable( false )
94 , m_bCompressedIsSetFromOutside( false )
95 , m_bFromManifest( false )
96 , m_bUseWinEncoding( false )
97 , m_bRawStream( false )
99 m_xContext
= xContext
;
101 mbAllowRemoveOnInsert
= bAllowRemoveOnInsert
;
103 aEntry
.nVersion
= -1;
108 aEntry
.nCompressedSize
= -1;
111 aEntry
.nPathLen
= -1;
112 aEntry
.nExtraLen
= -1;
115 ZipPackageStream::~ZipPackageStream()
119 void ZipPackageStream::setZipEntryOnLoading( const ZipEntry
&rInEntry
)
121 aEntry
.nVersion
= rInEntry
.nVersion
;
122 aEntry
.nFlag
= rInEntry
.nFlag
;
123 aEntry
.nMethod
= rInEntry
.nMethod
;
124 aEntry
.nTime
= rInEntry
.nTime
;
125 aEntry
.nCrc
= rInEntry
.nCrc
;
126 aEntry
.nCompressedSize
= rInEntry
.nCompressedSize
;
127 aEntry
.nSize
= rInEntry
.nSize
;
128 aEntry
.nOffset
= rInEntry
.nOffset
;
129 aEntry
.sPath
= rInEntry
.sPath
;
130 aEntry
.nPathLen
= rInEntry
.nPathLen
;
131 aEntry
.nExtraLen
= rInEntry
.nExtraLen
;
133 if ( aEntry
.nMethod
== STORED
)
134 m_bToBeCompressed
= false;
137 uno::Reference
< io::XInputStream
> const & ZipPackageStream::GetOwnSeekStream()
139 if ( !m_bHasSeekable
&& m_xStream
.is() )
141 // The package component requires that every stream either be FROM a package or it must support XSeekable!
142 // The only exception is a nonseekable stream that is provided only for storing, if such a stream
143 // is accessed before commit it MUST be wrapped.
144 // Wrap the stream in case it is not seekable
145 m_xStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xStream
, m_xContext
);
146 uno::Reference
< io::XSeekable
> xSeek( m_xStream
, UNO_QUERY_THROW
);
148 m_bHasSeekable
= true;
154 uno::Reference
< io::XInputStream
> ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
156 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
|| !GetOwnSeekStream().is() )
157 throw io::IOException(THROW_WHERE
);
159 if ( m_xBaseEncryptionData
.is() )
160 throw ZipIOException(THROW_WHERE
"Encrypted stream without encryption data!" );
162 uno::Reference
< io::XSeekable
> xSeek( GetOwnSeekStream(), UNO_QUERY
);
164 throw ZipIOException(THROW_WHERE
"The stream must be seekable!" );
167 xSeek
->seek( n_ConstHeaderSize
+ m_xBaseEncryptionData
->m_aInitVector
.getLength() +
168 m_xBaseEncryptionData
->m_aSalt
.getLength() + m_xBaseEncryptionData
->m_aDigest
.getLength() );
170 // create temporary stream
171 rtl::Reference
< utl::TempFileFastService
> xTempFile
= new utl::TempFileFastService
;
172 uno::Reference
< io::XInputStream
> xTempIn
= xTempFile
->getInputStream();
174 // copy the raw stream to the temporary file starting from the current position
175 ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempFile
);
176 xTempFile
->closeOutput();
177 xTempFile
->seek( 0 );
182 sal_Int32
ZipPackageStream::GetEncryptionAlgorithm() const
184 return m_nImportedEncryptionAlgorithm
? m_nImportedEncryptionAlgorithm
: m_rZipPackage
.GetEncAlgID();
187 sal_Int32
ZipPackageStream::GetBlockSize() const
189 return GetEncryptionAlgorithm() == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING
? 16 : 8;
192 ::rtl::Reference
<EncryptionData
> ZipPackageStream::GetEncryptionData(Bugs
const bugs
)
194 ::rtl::Reference
< EncryptionData
> xResult
;
195 if ( m_xBaseEncryptionData
.is() )
196 xResult
= new EncryptionData(
197 *m_xBaseEncryptionData
,
198 GetEncryptionKey(bugs
),
199 GetEncryptionAlgorithm(),
200 m_nImportedChecksumAlgorithm
? m_nImportedChecksumAlgorithm
: m_rZipPackage
.GetChecksumAlgID(),
201 m_nImportedDerivedKeySize
? m_nImportedDerivedKeySize
: m_rZipPackage
.GetDefaultDerivedKeySize(),
208 uno::Sequence
<sal_Int8
> ZipPackageStream::GetEncryptionKey(Bugs
const bugs
)
210 uno::Sequence
< sal_Int8
> aResult
;
211 sal_Int32 nKeyGenID
= GetStartKeyGenID();
212 bool const bUseWinEncoding
= (bugs
== Bugs::WinEncodingWrongSHA1
|| m_bUseWinEncoding
);
214 if ( m_bHaveOwnKey
&& m_aStorageEncryptionKeys
.hasElements() )
216 OUString aNameToFind
;
217 if ( nKeyGenID
== xml::crypto::DigestID::SHA256
)
218 aNameToFind
= PACKAGE_ENCRYPTIONDATA_SHA256UTF8
;
219 else if ( nKeyGenID
== xml::crypto::DigestID::SHA1
)
221 aNameToFind
= bUseWinEncoding
222 ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1MS1252
)
223 : (bugs
== Bugs::WrongSHA1
)
224 ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1UTF8
)
225 : OUString(PACKAGE_ENCRYPTIONDATA_SHA1CORRECT
);
228 throw uno::RuntimeException(THROW_WHERE
"No expected key is provided!" );
230 for ( const auto& rKey
: std::as_const(m_aStorageEncryptionKeys
) )
231 if ( rKey
.Name
== aNameToFind
)
232 rKey
.Value
>>= aResult
;
234 // empty keys are not allowed here
235 // so it is not important whether there is no key, or the key is empty, it is an error
236 if ( !aResult
.hasElements() )
237 throw uno::RuntimeException(THROW_WHERE
"No expected key is provided!" );
240 aResult
= m_aEncryptionKey
;
242 if ( !aResult
.hasElements() || !m_bHaveOwnKey
)
243 aResult
= m_rZipPackage
.GetEncryptionKey();
248 sal_Int32
ZipPackageStream::GetStartKeyGenID() const
250 // generally should all the streams use the same Start Key
251 // but if raw copy without password takes place, we should preserve the imported algorithm
252 return m_nImportedStartKeyAlgorithm
? m_nImportedStartKeyAlgorithm
: m_rZipPackage
.GetStartKeyGenID();
255 uno::Reference
< io::XInputStream
> ZipPackageStream::TryToGetRawFromDataStream( bool bAddHeaderForEncr
)
257 if ( m_nStreamMode
!= PACKAGE_STREAM_DATA
|| !GetOwnSeekStream().is() || ( bAddHeaderForEncr
&& !m_bToBeEncrypted
) )
258 throw packages::NoEncryptionException(THROW_WHERE
);
260 Sequence
< sal_Int8
> aKey
;
262 if ( m_bToBeEncrypted
)
264 aKey
= GetEncryptionKey();
265 if ( !aKey
.hasElements() )
266 throw packages::NoEncryptionException(THROW_WHERE
);
271 // create temporary file
272 uno::Reference
< io::XStream
> xTempStream(new utl::TempFileFastService
);
274 // create a package based on it
275 rtl::Reference
<ZipPackage
> pPackage
= new ZipPackage( m_xContext
);
277 Sequence
< Any
> aArgs
{ Any(xTempStream
) };
278 pPackage
->initialize( aArgs
);
280 // create a new package stream
281 uno::Reference
< XDataSinkEncrSupport
> xNewPackStream( pPackage
->createInstance(), UNO_QUERY_THROW
);
282 xNewPackStream
->setDataStream(
283 new WrapStreamForShare(GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef()));
285 uno::Reference
< XPropertySet
> xNewPSProps( xNewPackStream
, UNO_QUERY_THROW
);
287 // copy all the properties of this stream to the new stream
288 xNewPSProps
->setPropertyValue("MediaType", Any( msMediaType
) );
289 xNewPSProps
->setPropertyValue("Compressed", Any( m_bToBeCompressed
) );
290 if ( m_bToBeEncrypted
)
292 xNewPSProps
->setPropertyValue(ENCRYPTION_KEY_PROPERTY
, Any( aKey
) );
293 xNewPSProps
->setPropertyValue("Encrypted", Any( true ) );
296 // insert a new stream in the package
297 uno::Reference
< XInterface
> xTmp
;
298 Any aRoot
= pPackage
->getByHierarchicalName("/");
300 uno::Reference
< container::XNameContainer
> xRootNameContainer( xTmp
, UNO_QUERY_THROW
);
302 uno::Reference
< XInterface
> xNPSDummy( xNewPackStream
, UNO_QUERY
);
303 xRootNameContainer
->insertByName("dummy", Any( xNPSDummy
) );
305 // commit the temporary package
306 pPackage
->commitChanges();
308 // get raw stream from the temporary package
309 uno::Reference
< io::XInputStream
> xInRaw
;
310 if ( bAddHeaderForEncr
)
311 xInRaw
= xNewPackStream
->getRawStream();
313 xInRaw
= xNewPackStream
->getPlainRawStream();
315 // create another temporary file
316 rtl::Reference
< utl::TempFileFastService
> xTempOut
= new utl::TempFileFastService
;
317 uno::Reference
< io::XInputStream
> xTempIn( xTempOut
);
319 // copy the raw stream to the temporary file
320 ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw
, xTempOut
);
321 xTempOut
->closeOutput();
324 // close raw stream, package stream and folder
328 xNewPackStream
.clear();
330 xRootNameContainer
.clear();
332 // return the stream representing the first temporary file
335 catch ( RuntimeException
& )
343 throw io::IOException(THROW_WHERE
);
346 bool ZipPackageStream::ParsePackageRawStream()
348 OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!" );
350 if ( !GetOwnSeekStream().is() )
355 ::rtl::Reference
< BaseEncryptionData
> xTempEncrData
;
356 Sequence
< sal_Int8
> aHeader ( 4 );
360 if ( GetOwnSeekStream()->readBytes ( aHeader
, 4 ) == 4 )
362 const sal_Int8
*pHeader
= aHeader
.getConstArray();
363 sal_uInt32 nHeader
= ( pHeader
[0] & 0xFF ) |
364 ( pHeader
[1] & 0xFF ) << 8 |
365 ( pHeader
[2] & 0xFF ) << 16 |
366 ( pHeader
[3] & 0xFF ) << 24;
367 if ( nHeader
== n_ConstHeader
)
369 // this is one of our god-awful, but extremely devious hacks, everyone cheer
370 xTempEncrData
= new BaseEncryptionData
;
373 sal_Int32 nEncAlgorithm
= 0;
374 sal_Int32 nChecksumAlgorithm
= 0;
375 sal_Int32 nDerivedKeySize
= 0;
376 sal_Int32 nStartKeyGenID
= 0;
377 sal_Int32 nMagHackSize
= 0;
378 if ( ZipFile::StaticFillData( xTempEncrData
, nEncAlgorithm
, nChecksumAlgorithm
, nDerivedKeySize
, nStartKeyGenID
, nMagHackSize
, aMediaType
, GetOwnSeekStream() ) )
380 // We'll want to skip the data we've just read, so calculate how much we just read
382 m_nMagicalHackPos
= n_ConstHeaderSize
+ xTempEncrData
->m_aSalt
.getLength()
383 + xTempEncrData
->m_aInitVector
.getLength()
384 + xTempEncrData
->m_aDigest
.getLength()
385 + aMediaType
.getLength() * sizeof( sal_Unicode
);
386 m_nImportedEncryptionAlgorithm
= nEncAlgorithm
;
387 m_nImportedChecksumAlgorithm
= nChecksumAlgorithm
;
388 m_nImportedDerivedKeySize
= nDerivedKeySize
;
389 m_nImportedStartKeyAlgorithm
= nStartKeyGenID
;
390 m_nMagicalHackSize
= nMagHackSize
;
391 msMediaType
= aMediaType
;
404 // the provided stream is not a raw stream
408 m_xBaseEncryptionData
= xTempEncrData
;
409 SetIsEncrypted ( true );
410 // it's already compressed and encrypted
411 m_bToBeEncrypted
= m_bToBeCompressed
= false;
416 static void ImplSetStoredData( ZipEntry
& rEntry
, uno::Reference
< io::XInputStream
> const & rStream
)
418 // It's very annoying that we have to do this, but lots of zip packages
419 // don't allow data descriptors for STORED streams, meaning we have to
420 // know the size and CRC32 of uncompressed streams before we actually
423 rEntry
.nMethod
= STORED
;
424 rEntry
.nCompressedSize
= rEntry
.nSize
= aCRC32
.updateStream ( rStream
);
425 rEntry
.nCrc
= aCRC32
.getValue();
428 bool ZipPackageStream::saveChild(
429 const OUString
&rPath
,
430 std::vector
< uno::Sequence
< beans::PropertyValue
> > &rManList
,
431 ZipOutputStream
& rZipOut
,
432 const uno::Sequence
< sal_Int8
>& rEncryptionKey
,
433 sal_Int32 nPBKDF2IterationCount
,
434 const rtlRandomPool
&rRandomPool
)
436 bool bSuccess
= true;
438 static const OUStringLiteral
sDigestProperty (u
"Digest");
439 static const OUStringLiteral
sEncryptionAlgProperty (u
"EncryptionAlgorithm");
440 static const OUStringLiteral
sStartKeyAlgProperty (u
"StartKeyAlgorithm");
441 static const OUStringLiteral
sDigestAlgProperty (u
"DigestAlgorithm");
442 static const OUStringLiteral
sDerivedKeySizeProperty (u
"DerivedKeySize");
444 uno::Sequence
< beans::PropertyValue
> aPropSet (PKG_SIZE_NOENCR_MNFST
);
446 // In case the entry we are reading is also the entry we are writing, we will
447 // store the ZipEntry data in pTempEntry
449 // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
450 // and be deleted in the ZipOutputStream destructor
451 std::unique_ptr
< ZipEntry
> pAutoTempEntry ( new ZipEntry(aEntry
) );
452 ZipEntry
* pTempEntry
= pAutoTempEntry
.get();
454 pTempEntry
->sPath
= rPath
;
455 pTempEntry
->nPathLen
= static_cast<sal_Int16
>( OUStringToOString( pTempEntry
->sPath
, RTL_TEXTENCODING_UTF8
).getLength() );
457 const bool bToBeEncrypted
= m_bToBeEncrypted
&& (rEncryptionKey
.hasElements() || m_bHaveOwnKey
);
458 const bool bToBeCompressed
= bToBeEncrypted
|| m_bToBeCompressed
;
460 auto pPropSet
= aPropSet
.getArray();
461 pPropSet
[PKG_MNFST_MEDIATYPE
].Name
= "MediaType";
462 pPropSet
[PKG_MNFST_MEDIATYPE
].Value
<<= GetMediaType( );
463 pPropSet
[PKG_MNFST_VERSION
].Name
= "Version";
464 pPropSet
[PKG_MNFST_VERSION
].Value
<<= OUString(); // no version is stored for streams currently
465 pPropSet
[PKG_MNFST_FULLPATH
].Name
= "FullPath";
466 pPropSet
[PKG_MNFST_FULLPATH
].Value
<<= pTempEntry
->sPath
;
468 OSL_ENSURE( m_nStreamMode
!= PACKAGE_STREAM_NOTSET
, "Unacceptable ZipPackageStream mode!" );
470 m_bRawStream
= false;
471 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
472 m_bRawStream
= ParsePackageRawStream();
473 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
476 bool bBackgroundThreadDeflate
= false;
477 bool bTransportOwnEncrStreamAsRaw
= false;
478 // During the storing the original size of the stream can be changed
479 // TODO/LATER: get rid of this hack
480 m_nOwnStreamOrigSize
= m_bRawStream
? m_nMagicalHackSize
: aEntry
.nSize
;
482 bool bUseNonSeekableAccess
= false;
483 uno::Reference
< io::XInputStream
> xStream
;
484 if ( !IsPackageMember() && !m_bRawStream
&& !bToBeEncrypted
&& bToBeCompressed
)
486 // the stream is not a package member, not a raw stream,
487 // it should not be encrypted and it should be compressed,
488 // in this case nonseekable access can be used
491 uno::Reference
< io::XSeekable
> xSeek ( xStream
, uno::UNO_QUERY
);
493 bUseNonSeekableAccess
= ( xStream
.is() && !xSeek
.is() );
496 if ( !bUseNonSeekableAccess
)
498 xStream
= getRawData();
502 OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
507 uno::Reference
< io::XSeekable
> xSeek ( xStream
, uno::UNO_QUERY
);
512 // If the stream is a raw one, then we should be positioned
513 // at the beginning of the actual data
514 if ( !bToBeCompressed
|| m_bRawStream
)
516 // The raw stream can neither be encrypted nor connected
517 OSL_ENSURE( !m_bRawStream
|| !(bToBeCompressed
|| bToBeEncrypted
), "The stream is already encrypted!" );
518 xSeek
->seek ( m_bRawStream
? m_nMagicalHackPos
: 0 );
519 ImplSetStoredData ( *pTempEntry
, xStream
);
521 // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
523 else if ( bToBeEncrypted
)
525 // this is the correct original size
526 pTempEntry
->nSize
= xSeek
->getLength();
527 m_nOwnStreamOrigSize
= pTempEntry
->nSize
;
534 // Okay, we don't have an xSeekable stream. This is possibly bad.
535 // check if it's one of our own streams, if it is then we know that
536 // each time we ask for it we'll get a new stream that will be
537 // at position zero...otherwise, assert and skip this stream...
538 if ( IsPackageMember() )
540 // if the password has been changed then the stream should not be package member any more
541 if ( m_bIsEncrypted
&& m_bToBeEncrypted
)
543 // Should be handled close to the raw stream handling
544 bTransportOwnEncrStreamAsRaw
= true;
545 pTempEntry
->nMethod
= STORED
;
547 // TODO/LATER: get rid of this situation
548 // this size should be different from the one that will be stored in manifest.xml
549 // it is used in storing algorithms and after storing the correct size will be set
550 pTempEntry
->nSize
= pTempEntry
->nCompressedSize
;
560 catch ( uno::Exception
& )
566 if ( bToBeEncrypted
|| m_bRawStream
|| bTransportOwnEncrStreamAsRaw
)
568 if ( bToBeEncrypted
&& !bTransportOwnEncrStreamAsRaw
)
570 uno::Sequence
< sal_Int8
> aSalt( 16 ), aVector( GetBlockSize() );
571 rtl_random_getBytes ( rRandomPool
, aSalt
.getArray(), 16 );
572 rtl_random_getBytes ( rRandomPool
, aVector
.getArray(), aVector
.getLength() );
573 if ( !m_bHaveOwnKey
)
575 m_aEncryptionKey
= rEncryptionKey
;
576 m_aStorageEncryptionKeys
.realloc( 0 );
579 setInitialisationVector ( aVector
);
581 setIterationCount(nPBKDF2IterationCount
);
584 // last property is digest, which is inserted later if we didn't have
586 aPropSet
.realloc(PKG_SIZE_ENCR_MNFST
);
587 pPropSet
= aPropSet
.getArray();
588 pPropSet
[PKG_MNFST_INIVECTOR
].Name
= "InitialisationVector";
589 pPropSet
[PKG_MNFST_INIVECTOR
].Value
<<= m_xBaseEncryptionData
->m_aInitVector
;
590 pPropSet
[PKG_MNFST_SALT
].Name
= "Salt";
591 pPropSet
[PKG_MNFST_SALT
].Value
<<= m_xBaseEncryptionData
->m_aSalt
;
592 pPropSet
[PKG_MNFST_ITERATION
].Name
= "IterationCount";
593 pPropSet
[PKG_MNFST_ITERATION
].Value
<<= m_xBaseEncryptionData
->m_nIterationCount
;
595 // Need to store the uncompressed size in the manifest
596 OSL_ENSURE( m_nOwnStreamOrigSize
>= 0, "The stream size was not correctly initialized!" );
597 pPropSet
[PKG_MNFST_UCOMPSIZE
].Name
= "Size";
598 pPropSet
[PKG_MNFST_UCOMPSIZE
].Value
<<= m_nOwnStreamOrigSize
;
600 if ( m_bRawStream
|| bTransportOwnEncrStreamAsRaw
)
602 ::rtl::Reference
< EncryptionData
> xEncData
= GetEncryptionData();
603 if ( !xEncData
.is() )
604 throw uno::RuntimeException();
606 pPropSet
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
607 pPropSet
[PKG_MNFST_DIGEST
].Value
<<= m_xBaseEncryptionData
->m_aDigest
;
608 pPropSet
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
609 pPropSet
[PKG_MNFST_ENCALG
].Value
<<= xEncData
->m_nEncAlg
;
610 pPropSet
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
611 pPropSet
[PKG_MNFST_STARTALG
].Value
<<= xEncData
->m_nStartKeyGenID
;
612 pPropSet
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
613 pPropSet
[PKG_MNFST_DIGESTALG
].Value
<<= xEncData
->m_nCheckAlg
;
614 pPropSet
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
615 pPropSet
[PKG_MNFST_DERKEYSIZE
].Value
<<= xEncData
->m_nDerivedKeySize
;
620 // If the entry is already stored in the zip file in the format we
621 // want for this write...copy it raw
622 if ( !bUseNonSeekableAccess
623 && ( m_bRawStream
|| bTransportOwnEncrStreamAsRaw
624 || ( IsPackageMember() && !bToBeEncrypted
625 && ( ( aEntry
.nMethod
== DEFLATED
&& bToBeCompressed
)
626 || ( aEntry
.nMethod
== STORED
&& !bToBeCompressed
) ) ) ) )
628 // If it's a PackageMember, then it's an unbuffered stream and we need
629 // to get a new version of it as we can't seek backwards.
630 if ( IsPackageMember() )
632 xStream
= getRawData();
635 // Make sure that we actually _got_ a new one !
644 xStream
->skipBytes( m_nMagicalHackPos
);
646 ZipOutputStream::setEntry(pTempEntry
);
647 rZipOut
.writeLOC(pTempEntry
);
648 // coverity[leaked_storage] - the entry is provided to the ZipOutputStream that will delete it
649 pAutoTempEntry
.release();
651 uno::Sequence
< sal_Int8
> aSeq ( n_ConstBufferSize
);
656 nLength
= xStream
->readBytes( aSeq
, n_ConstBufferSize
);
657 if (nLength
!= n_ConstBufferSize
)
658 aSeq
.realloc(nLength
);
660 rZipOut
.rawWrite(aSeq
);
662 while ( nLength
== n_ConstBufferSize
);
664 rZipOut
.rawCloseEntry();
666 catch ( ZipException
& )
670 catch ( io::IOException
& )
677 // This stream is definitely not a raw stream
679 // If nonseekable access is used the stream should be at the beginning and
680 // is useless after the storing. Thus if the storing fails the package should
681 // be thrown away ( as actually it is done currently )!
682 // To allow to reuse the package after the error, the optimization must be removed!
684 // If it's a PackageMember, then our previous reference held a 'raw' stream
685 // so we need to re-get it, unencrypted, uncompressed and positioned at the
686 // beginning of the stream
687 if ( IsPackageMember() )
689 xStream
= getInputStream();
692 // Make sure that we actually _got_ a new one !
698 if ( bToBeCompressed
)
700 pTempEntry
->nMethod
= DEFLATED
;
701 pTempEntry
->nCrc
= -1;
702 pTempEntry
->nCompressedSize
= pTempEntry
->nSize
= -1;
705 uno::Reference
< io::XSeekable
> xSeek(xStream
, uno::UNO_QUERY
);
706 // It's not worth to deflate jpegs to save ~1% in a slow process
707 // Unfortunately, does not work for streams protected by password
708 if (xSeek
.is() && msMediaType
.endsWith("/jpeg") && !m_bToBeEncrypted
&& !m_bToBeCompressed
)
710 ImplSetStoredData(*pTempEntry
, xStream
);
716 ZipOutputStream::setEntry(pTempEntry
);
717 // the entry is provided to the ZipOutputStream that will delete it
718 pAutoTempEntry
.release();
720 if (pTempEntry
->nMethod
== STORED
)
723 uno::Sequence
< sal_Int8
> aSeq(n_ConstBufferSize
);
724 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
727 nLength
= xStream
->readBytes(aSeq
, n_ConstBufferSize
);
728 if (nLength
!= n_ConstBufferSize
)
729 aSeq
.realloc(nLength
);
731 rZipOut
.rawWrite(aSeq
);
733 while ( nLength
== n_ConstBufferSize
);
734 rZipOut
.rawCloseEntry(bToBeEncrypted
);
738 // tdf#89236 Encrypting in a background thread does not work
739 bBackgroundThreadDeflate
= !bToBeEncrypted
;
740 // Do not deflate small streams using threads. XSeekable's getLength()
741 // gives the full size, XInputStream's available() may not be
742 // the full size, but it appears that at this point it usually is.
743 sal_Int64 estimatedSize
= xSeek
.is() ? xSeek
->getLength() : xStream
->available();
745 if (estimatedSize
> 1000000)
747 // Use ThreadDeflater which will split the stream into blocks and compress
748 // them in threads, but not in background (i.e. writeStream() will block).
749 // This is suitable for large data.
750 bBackgroundThreadDeflate
= false;
751 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
752 ZipOutputEntryParallel
aZipEntry(rZipOut
.getStream(), m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
753 aZipEntry
.writeStream(xStream
);
754 rZipOut
.rawCloseEntry(bToBeEncrypted
);
756 else if (bBackgroundThreadDeflate
&& estimatedSize
> 100000)
758 // tdf#93553 limit to a useful amount of pending tasks. Having way too many
759 // tasks pending may use a lot of memory. Take number of available
760 // cores and allow 4-times the amount for having the queue well filled. The
761 // 2nd parameter is the time to wait between cleanups in 10th of a second.
762 // Both values may be added to the configuration settings if needed.
763 static std::size_t nAllowedTasks(comphelper::ThreadPool::getPreferredConcurrency() * 4); //TODO: overflow
764 rZipOut
.reduceScheduledThreadTasksToGivenNumberOrLess(nAllowedTasks
);
766 // Start a new thread task deflating this zip entry
767 ZipOutputEntryInThread
*pZipEntry
= new ZipOutputEntryInThread(
768 m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
769 rZipOut
.addDeflatingThreadTask( pZipEntry
,
770 pZipEntry
->createTask( rZipOut
.getThreadTaskTag(), xStream
) );
774 bBackgroundThreadDeflate
= false;
775 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
776 ZipOutputEntry
aZipEntry(rZipOut
.getStream(), m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
777 aZipEntry
.writeStream(xStream
);
778 rZipOut
.rawCloseEntry(bToBeEncrypted
);
782 catch ( ZipException
& )
786 catch ( io::IOException
& )
791 if ( bToBeEncrypted
)
793 ::rtl::Reference
< EncryptionData
> xEncData
= GetEncryptionData();
794 if ( !xEncData
.is() )
795 throw uno::RuntimeException();
797 pPropSet
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
798 pPropSet
[PKG_MNFST_DIGEST
].Value
<<= m_xBaseEncryptionData
->m_aDigest
;
799 pPropSet
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
800 pPropSet
[PKG_MNFST_ENCALG
].Value
<<= xEncData
->m_nEncAlg
;
801 pPropSet
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
802 pPropSet
[PKG_MNFST_STARTALG
].Value
<<= xEncData
->m_nStartKeyGenID
;
803 pPropSet
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
804 pPropSet
[PKG_MNFST_DIGESTALG
].Value
<<= xEncData
->m_nCheckAlg
;
805 pPropSet
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
806 pPropSet
[PKG_MNFST_DERKEYSIZE
].Value
<<= xEncData
->m_nDerivedKeySize
;
808 SetIsEncrypted ( true );
812 if (bSuccess
&& !bBackgroundThreadDeflate
)
813 successfullyWritten(pTempEntry
);
815 if ( aPropSet
.hasElements()
816 && ( m_nFormat
== embed::StorageFormats::PACKAGE
|| m_nFormat
== embed::StorageFormats::OFOPXML
) )
817 rManList
.push_back( aPropSet
);
822 void ZipPackageStream::successfullyWritten( ZipEntry
const *pEntry
)
824 if ( !IsPackageMember() )
826 if ( m_xStream
.is() )
828 m_xStream
->closeInput();
830 m_bHasSeekable
= false;
832 SetPackageMember ( true );
837 // the raw stream was integrated and now behaves
838 // as usual encrypted stream
839 SetToBeEncrypted( true );
842 // Then copy it back afterwards...
845 // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
846 if ( m_bIsEncrypted
)
847 setSize( m_nOwnStreamOrigSize
);
849 aEntry
.nOffset
*= -1;
852 void ZipPackageStream::SetPackageMember( bool bNewValue
)
856 m_nStreamMode
= PACKAGE_STREAM_PACKAGEMEMBER
;
857 m_nMagicalHackPos
= 0;
858 m_nMagicalHackSize
= 0;
860 else if ( m_nStreamMode
== PACKAGE_STREAM_PACKAGEMEMBER
)
861 m_nStreamMode
= PACKAGE_STREAM_NOTSET
; // must be reset
865 void SAL_CALL
ZipPackageStream::setInputStream( const uno::Reference
< io::XInputStream
>& aStream
)
867 // if seekable access is required the wrapping will be done on demand
869 m_nImportedEncryptionAlgorithm
= 0;
870 m_bHasSeekable
= false;
871 SetPackageMember ( false );
873 m_nStreamMode
= PACKAGE_STREAM_DETECT
;
876 uno::Reference
< io::XInputStream
> ZipPackageStream::getRawData()
880 if ( IsPackageMember() )
882 return m_rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef(), false/*bUseBufferedStream*/ );
884 else if ( GetOwnSeekStream().is() )
886 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
889 return uno::Reference
< io::XInputStream
> ();
891 catch ( ZipException
& )//rException )
893 TOOLS_WARN_EXCEPTION( "package", "" );
894 return uno::Reference
< io::XInputStream
> ();
896 catch ( Exception
& )
898 TOOLS_WARN_EXCEPTION( "package", "Exception is thrown during stream wrapping!" );
899 return uno::Reference
< io::XInputStream
> ();
903 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getInputStream()
907 if ( IsPackageMember() )
909 return m_rZipPackage
.getZipFile().getInputStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
911 else if ( GetOwnSeekStream().is() )
913 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
916 return uno::Reference
< io::XInputStream
> ();
918 catch ( ZipException
& )//rException )
920 TOOLS_WARN_EXCEPTION( "package", "" );
921 return uno::Reference
< io::XInputStream
> ();
923 catch ( const Exception
& )
925 TOOLS_WARN_EXCEPTION( "package", "Exception is thrown during stream wrapping!");
926 return uno::Reference
< io::XInputStream
> ();
930 // XDataSinkEncrSupport
931 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getDataStream()
933 // There is no stream attached to this object
934 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
935 return uno::Reference
< io::XInputStream
>();
937 // this method can not be used together with old approach
938 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
939 throw packages::zip::ZipIOException(THROW_WHERE
);
941 if ( IsPackageMember() )
943 uno::Reference
< io::XInputStream
> xResult
;
946 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(Bugs::None
), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
948 catch( const packages::WrongPasswordException
& )
950 if ( m_rZipPackage
.GetStartKeyGenID() == xml::crypto::DigestID::SHA1
)
952 SAL_WARN("package", "ZipPackageStream::getDataStream(): SHA1 mismatch, trying fallbacks...");
954 { // tdf#114939 try with legacy StarOffice SHA1 bug
955 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(Bugs::WrongSHA1
), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
958 catch (const packages::WrongPasswordException
&)
960 /* ignore and try next... */
965 // rhbz#1013844 / fdo#47482 workaround for the encrypted
966 // OpenOffice.org 1.0 documents generated by Libreoffice <=
967 // 3.6 with the new encryption format and using SHA256, but
968 // missing a specified startkey of SHA256
970 // force SHA256 and see if that works
971 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA256
;
972 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
975 catch (const packages::WrongPasswordException
&)
977 // if that didn't work, restore to SHA1 and trundle through the *other* earlier
979 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA1
;
982 // workaround for the encrypted documents generated with the old OOo1.x bug.
983 if ( !m_bUseWinEncoding
)
985 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(Bugs::WinEncodingWrongSHA1
), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
986 m_bUseWinEncoding
= true;
996 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
997 return ZipFile::StaticGetDataFromRawStream( m_rZipPackage
.GetSharedMutexRef(), m_xContext
, GetOwnSeekStream(), GetEncryptionData() );
998 else if ( GetOwnSeekStream().is() )
1000 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
1003 return uno::Reference
< io::XInputStream
>();
1006 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getRawStream()
1008 // There is no stream attached to this object
1009 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1010 return uno::Reference
< io::XInputStream
>();
1012 // this method can not be used together with old approach
1013 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1014 throw packages::zip::ZipIOException(THROW_WHERE
);
1016 if ( IsPackageMember() )
1018 if ( !m_bIsEncrypted
|| !GetEncryptionData().is() )
1019 throw packages::NoEncryptionException(THROW_WHERE
);
1021 return m_rZipPackage
.getZipFile().getWrappedRawStream( aEntry
, GetEncryptionData(), msMediaType
, m_rZipPackage
.GetSharedMutexRef() );
1023 else if ( GetOwnSeekStream().is() )
1025 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1027 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
1029 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
&& m_bToBeEncrypted
)
1030 return TryToGetRawFromDataStream( true );
1033 throw packages::NoEncryptionException(THROW_WHERE
);
1036 void SAL_CALL
ZipPackageStream::setDataStream( const uno::Reference
< io::XInputStream
>& aStream
)
1038 setInputStream( aStream
);
1039 m_nStreamMode
= PACKAGE_STREAM_DATA
;
1042 void SAL_CALL
ZipPackageStream::setRawStream( const uno::Reference
< io::XInputStream
>& aStream
)
1044 // wrap the stream in case it is not seekable
1045 uno::Reference
< io::XInputStream
> xNewStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream
, m_xContext
);
1046 uno::Reference
< io::XSeekable
> xSeek( xNewStream
, UNO_QUERY_THROW
);
1048 uno::Reference
< io::XInputStream
> xOldStream
= m_xStream
;
1049 m_xStream
= xNewStream
;
1050 if ( !ParsePackageRawStream() )
1052 m_xStream
= xOldStream
;
1053 throw packages::NoRawFormatException(THROW_WHERE
);
1056 // the raw stream MUST have seekable access
1057 m_bHasSeekable
= true;
1059 SetPackageMember ( false );
1061 m_nStreamMode
= PACKAGE_STREAM_RAW
;
1064 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getPlainRawStream()
1066 // There is no stream attached to this object
1067 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1068 return uno::Reference
< io::XInputStream
>();
1070 // this method can not be used together with old approach
1071 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1072 throw packages::zip::ZipIOException(THROW_WHERE
);
1074 if ( IsPackageMember() )
1076 return m_rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1078 else if ( GetOwnSeekStream().is() )
1080 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1082 // the header should not be returned here
1083 return GetRawEncrStreamNoHeaderCopy();
1085 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
)
1086 return TryToGetRawFromDataStream( false );
1089 return uno::Reference
< io::XInputStream
>();
1093 void SAL_CALL
ZipPackageStream::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
1095 if ( aPropertyName
== "MediaType" )
1097 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
&& m_rZipPackage
.getFormat() != embed::StorageFormats::OFOPXML
)
1098 throw beans::PropertyVetoException(THROW_WHERE
);
1100 if ( !(aValue
>>= msMediaType
) )
1101 throw IllegalArgumentException(THROW_WHERE
"MediaType must be a string!",
1102 uno::Reference
< XInterface
>(),
1105 if ( !msMediaType
.isEmpty() )
1107 if ( msMediaType
.indexOf ( "text" ) != -1
1108 || msMediaType
== "application/vnd.sun.star.oleobject" )
1109 m_bToBeCompressed
= true;
1110 else if ( !m_bCompressedIsSetFromOutside
)
1111 m_bToBeCompressed
= false;
1114 else if ( aPropertyName
== "Size" )
1116 if ( !( aValue
>>= aEntry
.nSize
) )
1117 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Size property!",
1118 uno::Reference
< XInterface
>(),
1121 else if ( aPropertyName
== "Encrypted" )
1123 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1124 throw beans::PropertyVetoException(THROW_WHERE
);
1127 if ( !(aValue
>>= bEnc
) )
1128 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Encrypted property!",
1129 uno::Reference
< XInterface
>(),
1132 // In case of new raw stream, the stream must not be encrypted on storing
1133 if ( bEnc
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
1134 throw IllegalArgumentException(THROW_WHERE
"Raw stream can not be encrypted on storing",
1135 uno::Reference
< XInterface
>(),
1138 m_bToBeEncrypted
= bEnc
;
1139 if ( m_bToBeEncrypted
&& !m_xBaseEncryptionData
.is() )
1140 m_xBaseEncryptionData
= new BaseEncryptionData
;
1143 else if ( aPropertyName
== ENCRYPTION_KEY_PROPERTY
)
1145 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1146 throw beans::PropertyVetoException(THROW_WHERE
);
1148 uno::Sequence
< sal_Int8
> aNewKey
;
1150 if ( !( aValue
>>= aNewKey
) )
1152 OUString sTempString
;
1153 if ( !(aValue
>>= sTempString
) )
1154 throw IllegalArgumentException(THROW_WHERE
"Wrong type for EncryptionKey property!",
1155 uno::Reference
< XInterface
>(),
1158 sal_Int32 nPathLength
= sTempString
.getLength();
1159 Sequence
< sal_Int8
> aSequence ( nPathLength
);
1160 sal_Int8
*pArray
= aSequence
.getArray();
1161 const sal_Unicode
*pChar
= sTempString
.getStr();
1162 for ( sal_Int32 i
= 0; i
< nPathLength
; i
++ )
1163 pArray
[i
] = static_cast < sal_Int8
> ( pChar
[i
] );
1164 aNewKey
= aSequence
;
1167 if ( aNewKey
.hasElements() )
1169 if ( !m_xBaseEncryptionData
.is() )
1170 m_xBaseEncryptionData
= new BaseEncryptionData
;
1172 m_aEncryptionKey
= aNewKey
;
1173 // In case of new raw stream, the stream must not be encrypted on storing
1174 m_bHaveOwnKey
= true;
1175 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
1176 m_bToBeEncrypted
= true;
1180 m_bHaveOwnKey
= false;
1181 m_aEncryptionKey
.realloc( 0 );
1184 m_aStorageEncryptionKeys
.realloc( 0 );
1186 else if ( aPropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
1188 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1189 throw beans::PropertyVetoException(THROW_WHERE
);
1191 uno::Sequence
< beans::NamedValue
> aKeys
;
1192 if ( !( aValue
>>= aKeys
) )
1194 throw IllegalArgumentException(THROW_WHERE
"Wrong type for StorageEncryptionKeys property!",
1195 uno::Reference
< XInterface
>(),
1199 if ( aKeys
.hasElements() )
1201 if ( !m_xBaseEncryptionData
.is() )
1202 m_xBaseEncryptionData
= new BaseEncryptionData
;
1204 m_aStorageEncryptionKeys
= aKeys
;
1206 // In case of new raw stream, the stream must not be encrypted on storing
1207 m_bHaveOwnKey
= true;
1208 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
1209 m_bToBeEncrypted
= true;
1213 m_bHaveOwnKey
= false;
1214 m_aStorageEncryptionKeys
.realloc( 0 );
1217 m_aEncryptionKey
.realloc( 0 );
1219 else if ( aPropertyName
== "Compressed" )
1221 bool bCompr
= false;
1223 if ( !(aValue
>>= bCompr
) )
1224 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Compressed property!",
1225 uno::Reference
< XInterface
>(),
1228 // In case of new raw stream, the stream must not be encrypted on storing
1229 if ( bCompr
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
1230 throw IllegalArgumentException(THROW_WHERE
"Raw stream can not be encrypted on storing",
1231 uno::Reference
< XInterface
>(),
1234 m_bToBeCompressed
= bCompr
;
1235 m_bCompressedIsSetFromOutside
= true;
1238 throw beans::UnknownPropertyException(aPropertyName
);
1241 Any SAL_CALL
ZipPackageStream::getPropertyValue( const OUString
& PropertyName
)
1243 if ( PropertyName
== "MediaType" )
1245 return Any(msMediaType
);
1247 else if ( PropertyName
== "Size" )
1249 return Any(aEntry
.nSize
);
1251 else if ( PropertyName
== "Encrypted" )
1253 return Any((m_nStreamMode
== PACKAGE_STREAM_RAW
) || m_bToBeEncrypted
);
1255 else if ( PropertyName
== "WasEncrypted" )
1257 return Any(m_bIsEncrypted
);
1259 else if ( PropertyName
== "Compressed" )
1261 return Any(m_bToBeCompressed
);
1263 else if ( PropertyName
== ENCRYPTION_KEY_PROPERTY
)
1265 return Any(m_aEncryptionKey
);
1267 else if ( PropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
1269 return Any(m_aStorageEncryptionKeys
);
1272 throw beans::UnknownPropertyException(PropertyName
);
1275 void ZipPackageStream::setSize ( const sal_Int64 nNewSize
)
1277 if ( aEntry
.nCompressedSize
!= nNewSize
)
1278 aEntry
.nMethod
= DEFLATED
;
1279 aEntry
.nSize
= nNewSize
;
1281 OUString
ZipPackageStream::getImplementationName()
1283 return "ZipPackageStream";
1286 Sequence
< OUString
> ZipPackageStream::getSupportedServiceNames()
1288 return { "com.sun.star.packages.PackageStream" };
1291 sal_Bool SAL_CALL
ZipPackageStream::supportsService( OUString
const & rServiceName
)
1293 return cppu::supportsService(this, rServiceName
);
1296 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */