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 .
21 #include <ZipPackageStream.hxx>
23 #include <com/sun/star/beans/PropertyValue.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/io/TempFile.hpp>
29 #include <com/sun/star/io/XInputStream.hpp>
30 #include <com/sun/star/io/XOutputStream.hpp>
31 #include <com/sun/star/io/XStream.hpp>
32 #include <com/sun/star/io/XSeekable.hpp>
33 #include <com/sun/star/xml/crypto/DigestID.hpp>
34 #include <com/sun/star/xml/crypto/CipherID.hpp>
39 #include <ZipOutputEntry.hxx>
40 #include <ZipOutputStream.hxx>
41 #include <ZipPackage.hxx>
42 #include <ZipPackageFolder.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/storagehelper.hxx>
50 #include <cppuhelper/exc_hlp.hxx>
51 #include <cppuhelper/supportsservice.hxx>
52 #include <cppuhelper/typeprovider.hxx>
54 #include <rtl/instance.hxx>
55 #include <rtl/random.h>
57 #include <PackageConstants.hxx>
62 using namespace com::sun::star::packages::zip::ZipConstants
;
63 using namespace com::sun::star::packages::zip
;
64 using namespace com::sun::star::uno
;
65 using namespace com::sun::star::lang
;
66 using namespace com::sun::star
;
69 #if OSL_DEBUG_LEVEL > 0
70 #define THROW_WHERE SAL_WHERE
72 #define THROW_WHERE ""
75 namespace { struct lcl_CachedImplId
: public rtl::Static
< cppu::OImplementationId
, lcl_CachedImplId
> {}; }
77 css::uno::Sequence
< sal_Int8
> ZipPackageStream::static_getImplementationId()
79 return lcl_CachedImplId::get().getImplementationId();
82 ZipPackageStream::ZipPackageStream ( ZipPackage
& rNewPackage
,
83 const uno::Reference
< XComponentContext
>& xContext
,
85 bool bAllowRemoveOnInsert
)
86 : m_rZipPackage( rNewPackage
)
87 , m_bToBeCompressed ( true )
88 , m_bToBeEncrypted ( false )
89 , m_bHaveOwnKey ( false )
90 , m_bIsEncrypted ( false )
91 , m_nImportedStartKeyAlgorithm( 0 )
92 , m_nImportedEncryptionAlgorithm( 0 )
93 , m_nImportedChecksumAlgorithm( 0 )
94 , m_nImportedDerivedKeySize( 0 )
95 , m_nStreamMode( PACKAGE_STREAM_NOTSET
)
96 , m_nMagicalHackPos( 0 )
97 , m_nMagicalHackSize( 0 )
98 , m_nOwnStreamOrigSize( 0 )
99 , m_bHasSeekable( false )
100 , m_bCompressedIsSetFromOutside( false )
101 , m_bFromManifest( false )
102 , m_bUseWinEncoding( false )
103 , m_bRawStream( false )
105 m_xContext
= xContext
;
107 mbAllowRemoveOnInsert
= bAllowRemoveOnInsert
;
109 aEntry
.nVersion
= -1;
114 aEntry
.nCompressedSize
= -1;
117 aEntry
.nPathLen
= -1;
118 aEntry
.nExtraLen
= -1;
121 ZipPackageStream::~ZipPackageStream()
125 void ZipPackageStream::setZipEntryOnLoading( const ZipEntry
&rInEntry
)
127 aEntry
.nVersion
= rInEntry
.nVersion
;
128 aEntry
.nFlag
= rInEntry
.nFlag
;
129 aEntry
.nMethod
= rInEntry
.nMethod
;
130 aEntry
.nTime
= rInEntry
.nTime
;
131 aEntry
.nCrc
= rInEntry
.nCrc
;
132 aEntry
.nCompressedSize
= rInEntry
.nCompressedSize
;
133 aEntry
.nSize
= rInEntry
.nSize
;
134 aEntry
.nOffset
= rInEntry
.nOffset
;
135 aEntry
.sPath
= rInEntry
.sPath
;
136 aEntry
.nPathLen
= rInEntry
.nPathLen
;
137 aEntry
.nExtraLen
= rInEntry
.nExtraLen
;
139 if ( aEntry
.nMethod
== STORED
)
140 m_bToBeCompressed
= false;
143 uno::Reference
< io::XInputStream
> const & ZipPackageStream::GetOwnSeekStream()
145 if ( !m_bHasSeekable
&& m_xStream
.is() )
147 // The package component requires that every stream either be FROM a package or it must support XSeekable!
148 // The only exception is a nonseekable stream that is provided only for storing, if such a stream
149 // is accessed before commit it MUST be wrapped.
150 // Wrap the stream in case it is not seekable
151 m_xStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xStream
, m_xContext
);
152 uno::Reference
< io::XSeekable
> xSeek( m_xStream
, UNO_QUERY_THROW
);
154 m_bHasSeekable
= true;
160 uno::Reference
< io::XInputStream
> ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
162 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
|| !GetOwnSeekStream().is() )
163 throw io::IOException(THROW_WHERE
);
165 if ( m_xBaseEncryptionData
.is() )
166 throw ZipIOException(THROW_WHERE
"Encrypted stream without encryption data!" );
168 uno::Reference
< io::XSeekable
> xSeek( GetOwnSeekStream(), UNO_QUERY
);
170 throw ZipIOException(THROW_WHERE
"The stream must be seekable!" );
173 xSeek
->seek( n_ConstHeaderSize
+ m_xBaseEncryptionData
->m_aInitVector
.getLength() +
174 m_xBaseEncryptionData
->m_aSalt
.getLength() + m_xBaseEncryptionData
->m_aDigest
.getLength() );
176 // create temporary stream
177 uno::Reference
< io::XTempFile
> xTempFile
= io::TempFile::create(m_xContext
);
178 uno::Reference
< io::XOutputStream
> xTempOut
= xTempFile
->getOutputStream();
179 uno::Reference
< io::XInputStream
> xTempIn
= xTempFile
->getInputStream();
180 uno::Reference
< io::XSeekable
> xTempSeek( xTempOut
, UNO_QUERY_THROW
);
182 // copy the raw stream to the temporary file starting from the current position
183 ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut
);
184 xTempOut
->closeOutput();
185 xTempSeek
->seek( 0 );
190 sal_Int32
ZipPackageStream::GetEncryptionAlgorithm() const
192 return m_nImportedEncryptionAlgorithm
? m_nImportedEncryptionAlgorithm
: m_rZipPackage
.GetEncAlgID();
195 sal_Int32
ZipPackageStream::GetBlockSize() const
197 return GetEncryptionAlgorithm() == css::xml::crypto::CipherID::AES_CBC_W3C_PADDING
? 16 : 8;
200 ::rtl::Reference
<EncryptionData
> ZipPackageStream::GetEncryptionData(Bugs
const bugs
)
202 ::rtl::Reference
< EncryptionData
> xResult
;
203 if ( m_xBaseEncryptionData
.is() )
204 xResult
= new EncryptionData(
205 *m_xBaseEncryptionData
,
206 GetEncryptionKey(bugs
),
207 GetEncryptionAlgorithm(),
208 m_nImportedChecksumAlgorithm
? m_nImportedChecksumAlgorithm
: m_rZipPackage
.GetChecksumAlgID(),
209 m_nImportedDerivedKeySize
? m_nImportedDerivedKeySize
: m_rZipPackage
.GetDefaultDerivedKeySize(),
216 uno::Sequence
<sal_Int8
> ZipPackageStream::GetEncryptionKey(Bugs
const bugs
)
218 uno::Sequence
< sal_Int8
> aResult
;
219 sal_Int32 nKeyGenID
= GetStartKeyGenID();
220 bool const bUseWinEncoding
= (bugs
== Bugs::WinEncodingWrongSHA1
|| m_bUseWinEncoding
);
222 if ( m_bHaveOwnKey
&& m_aStorageEncryptionKeys
.getLength() )
224 OUString aNameToFind
;
225 if ( nKeyGenID
== xml::crypto::DigestID::SHA256
)
226 aNameToFind
= PACKAGE_ENCRYPTIONDATA_SHA256UTF8
;
227 else if ( nKeyGenID
== xml::crypto::DigestID::SHA1
)
229 aNameToFind
= bUseWinEncoding
230 ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1MS1252
)
231 : (bugs
== Bugs::WrongSHA1
)
232 ? OUString(PACKAGE_ENCRYPTIONDATA_SHA1UTF8
)
233 : OUString(PACKAGE_ENCRYPTIONDATA_SHA1CORRECT
);
236 throw uno::RuntimeException(THROW_WHERE
"No expected key is provided!" );
238 for ( sal_Int32 nInd
= 0; nInd
< m_aStorageEncryptionKeys
.getLength(); nInd
++ )
239 if ( m_aStorageEncryptionKeys
[nInd
].Name
== aNameToFind
)
240 m_aStorageEncryptionKeys
[nInd
].Value
>>= aResult
;
242 // empty keys are not allowed here
243 // so it is not important whether there is no key, or the key is empty, it is an error
244 if ( !aResult
.getLength() )
245 throw uno::RuntimeException(THROW_WHERE
"No expected key is provided!" );
248 aResult
= m_aEncryptionKey
;
250 if ( !aResult
.getLength() || !m_bHaveOwnKey
)
251 aResult
= m_rZipPackage
.GetEncryptionKey();
256 sal_Int32
ZipPackageStream::GetStartKeyGenID()
258 // generally should all the streams use the same Start Key
259 // but if raw copy without password takes place, we should preserve the imported algorithm
260 return m_nImportedStartKeyAlgorithm
? m_nImportedStartKeyAlgorithm
: m_rZipPackage
.GetStartKeyGenID();
263 uno::Reference
< io::XInputStream
> ZipPackageStream::TryToGetRawFromDataStream( bool bAddHeaderForEncr
)
265 if ( m_nStreamMode
!= PACKAGE_STREAM_DATA
|| !GetOwnSeekStream().is() || ( bAddHeaderForEncr
&& !m_bToBeEncrypted
) )
266 throw packages::NoEncryptionException(THROW_WHERE
);
268 Sequence
< sal_Int8
> aKey
;
270 if ( m_bToBeEncrypted
)
272 aKey
= GetEncryptionKey();
273 if ( !aKey
.getLength() )
274 throw packages::NoEncryptionException(THROW_WHERE
);
279 // create temporary file
280 uno::Reference
< io::XStream
> xTempStream(
281 io::TempFile::create(m_xContext
),
282 uno::UNO_QUERY_THROW
);
284 // create a package based on it
285 ZipPackage
* pPackage
= new ZipPackage( m_xContext
);
286 uno::Reference
< XSingleServiceFactory
> xPackageAsFactory( static_cast< XSingleServiceFactory
* >( pPackage
) );
287 if ( !xPackageAsFactory
.is() )
288 throw RuntimeException(THROW_WHERE
);
290 Sequence
< Any
> aArgs( 1 );
291 aArgs
[0] <<= xTempStream
;
292 pPackage
->initialize( aArgs
);
294 // create a new package stream
295 uno::Reference
< XDataSinkEncrSupport
> xNewPackStream( xPackageAsFactory
->createInstance(), UNO_QUERY_THROW
);
296 xNewPackStream
->setDataStream( static_cast< io::XInputStream
* >(
297 new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() ) ) );
299 uno::Reference
< XPropertySet
> xNewPSProps( xNewPackStream
, UNO_QUERY_THROW
);
301 // copy all the properties of this stream to the new stream
302 xNewPSProps
->setPropertyValue("MediaType", makeAny( msMediaType
) );
303 xNewPSProps
->setPropertyValue("Compressed", makeAny( m_bToBeCompressed
) );
304 if ( m_bToBeEncrypted
)
306 xNewPSProps
->setPropertyValue(ENCRYPTION_KEY_PROPERTY
, makeAny( aKey
) );
307 xNewPSProps
->setPropertyValue("Encrypted", makeAny( true ) );
310 // insert a new stream in the package
311 uno::Reference
< XUnoTunnel
> xTunnel
;
312 Any aRoot
= pPackage
->getByHierarchicalName("/");
314 uno::Reference
< container::XNameContainer
> xRootNameContainer( xTunnel
, UNO_QUERY_THROW
);
316 uno::Reference
< XUnoTunnel
> xNPSTunnel( xNewPackStream
, UNO_QUERY
);
317 xRootNameContainer
->insertByName("dummy", makeAny( xNPSTunnel
) );
319 // commit the temporary package
320 pPackage
->commitChanges();
322 // get raw stream from the temporary package
323 uno::Reference
< io::XInputStream
> xInRaw
;
324 if ( bAddHeaderForEncr
)
325 xInRaw
= xNewPackStream
->getRawStream();
327 xInRaw
= xNewPackStream
->getPlainRawStream();
329 // create another temporary file
330 uno::Reference
< io::XOutputStream
> xTempOut(
331 io::TempFile::create(m_xContext
),
332 uno::UNO_QUERY_THROW
);
333 uno::Reference
< io::XInputStream
> xTempIn( xTempOut
, UNO_QUERY_THROW
);
334 uno::Reference
< io::XSeekable
> xTempSeek( xTempOut
, UNO_QUERY_THROW
);
336 // copy the raw stream to the temporary file
337 ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw
, xTempOut
);
338 xTempOut
->closeOutput();
339 xTempSeek
->seek( 0 );
341 // close raw stream, package stream and folder
345 xNewPackStream
.clear();
347 xRootNameContainer
.clear();
349 // return the stream representing the first temporary file
352 catch ( RuntimeException
& )
360 throw io::IOException(THROW_WHERE
);
363 bool ZipPackageStream::ParsePackageRawStream()
365 OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!" );
367 if ( !GetOwnSeekStream().is() )
372 ::rtl::Reference
< BaseEncryptionData
> xTempEncrData
;
373 sal_Int32 nMagHackSize
= 0;
374 Sequence
< sal_Int8
> aHeader ( 4 );
378 if ( GetOwnSeekStream()->readBytes ( aHeader
, 4 ) == 4 )
380 const sal_Int8
*pHeader
= aHeader
.getConstArray();
381 sal_uInt32 nHeader
= ( pHeader
[0] & 0xFF ) |
382 ( pHeader
[1] & 0xFF ) << 8 |
383 ( pHeader
[2] & 0xFF ) << 16 |
384 ( pHeader
[3] & 0xFF ) << 24;
385 if ( nHeader
== n_ConstHeader
)
387 // this is one of our god-awful, but extremely devious hacks, everyone cheer
388 xTempEncrData
= new BaseEncryptionData
;
391 sal_Int32 nEncAlgorithm
= 0;
392 sal_Int32 nChecksumAlgorithm
= 0;
393 sal_Int32 nDerivedKeySize
= 0;
394 sal_Int32 nStartKeyGenID
= 0;
395 if ( ZipFile::StaticFillData( xTempEncrData
, nEncAlgorithm
, nChecksumAlgorithm
, nDerivedKeySize
, nStartKeyGenID
, nMagHackSize
, aMediaType
, GetOwnSeekStream() ) )
397 // We'll want to skip the data we've just read, so calculate how much we just read
399 m_nMagicalHackPos
= n_ConstHeaderSize
+ xTempEncrData
->m_aSalt
.getLength()
400 + xTempEncrData
->m_aInitVector
.getLength()
401 + xTempEncrData
->m_aDigest
.getLength()
402 + aMediaType
.getLength() * sizeof( sal_Unicode
);
403 m_nImportedEncryptionAlgorithm
= nEncAlgorithm
;
404 m_nImportedChecksumAlgorithm
= nChecksumAlgorithm
;
405 m_nImportedDerivedKeySize
= nDerivedKeySize
;
406 m_nImportedStartKeyAlgorithm
= nStartKeyGenID
;
407 m_nMagicalHackSize
= nMagHackSize
;
408 msMediaType
= aMediaType
;
421 // the provided stream is not a raw stream
425 m_xBaseEncryptionData
= xTempEncrData
;
426 SetIsEncrypted ( true );
427 // it's already compressed and encrypted
428 m_bToBeEncrypted
= m_bToBeCompressed
= false;
433 static void deflateZipEntry(ZipOutputEntry
*pZipEntry
,
434 const uno::Reference
< io::XInputStream
>& xInStream
)
436 sal_Int32 nLength
= 0;
437 uno::Sequence
< sal_Int8
> aSeq(n_ConstBufferSize
);
440 nLength
= xInStream
->readBytes(aSeq
, n_ConstBufferSize
);
441 if (nLength
!= n_ConstBufferSize
)
442 aSeq
.realloc(nLength
);
444 pZipEntry
->write(aSeq
);
446 while (nLength
== n_ConstBufferSize
);
447 pZipEntry
->closeEntry();
450 class DeflateThread
: public comphelper::ThreadTask
452 ZipOutputEntry
*mpEntry
;
453 uno::Reference
< io::XInputStream
> mxInStream
;
456 DeflateThread( const std::shared_ptr
<comphelper::ThreadTaskTag
>& pTag
, ZipOutputEntry
*pEntry
,
457 const uno::Reference
< io::XInputStream
>& xInStream
)
458 : comphelper::ThreadTask(pTag
)
460 , mxInStream(xInStream
)
464 virtual void doWork() override
468 mpEntry
->createBufferFile();
469 deflateZipEntry(mpEntry
, mxInStream
);
471 mpEntry
->closeBufferFile();
472 mpEntry
->setFinished();
474 catch (const uno::Exception
&)
476 mpEntry
->setParallelDeflateException(::cppu::getCaughtException());
479 if (mpEntry
->m_xOutStream
.is())
480 mpEntry
->closeBufferFile();
481 if (!mpEntry
->m_aTempURL
.isEmpty())
482 mpEntry
->deleteBufferFile();
484 catch (uno::Exception
const&)
487 mpEntry
->setFinished();
492 static void ImplSetStoredData( ZipEntry
& rEntry
, uno::Reference
< io::XInputStream
> const & rStream
)
494 // It's very annoying that we have to do this, but lots of zip packages
495 // don't allow data descriptors for STORED streams, meaning we have to
496 // know the size and CRC32 of uncompressed streams before we actually
499 rEntry
.nMethod
= STORED
;
500 rEntry
.nCompressedSize
= rEntry
.nSize
= aCRC32
.updateStream ( rStream
);
501 rEntry
.nCrc
= aCRC32
.getValue();
504 bool ZipPackageStream::saveChild(
505 const OUString
&rPath
,
506 std::vector
< uno::Sequence
< beans::PropertyValue
> > &rManList
,
507 ZipOutputStream
& rZipOut
,
508 const uno::Sequence
< sal_Int8
>& rEncryptionKey
,
509 sal_Int32 nPBKDF2IterationCount
,
510 const rtlRandomPool
&rRandomPool
)
512 bool bSuccess
= true;
514 const OUString
sMediaTypeProperty ("MediaType");
515 const OUString
sVersionProperty ("Version");
516 const OUString
sFullPathProperty ("FullPath");
517 const OUString
sInitialisationVectorProperty ("InitialisationVector");
518 const OUString
sSaltProperty ("Salt");
519 const OUString
sIterationCountProperty ("IterationCount");
520 const OUString
sSizeProperty ("Size");
521 const OUString
sDigestProperty ("Digest");
522 const OUString
sEncryptionAlgProperty ("EncryptionAlgorithm");
523 const OUString
sStartKeyAlgProperty ("StartKeyAlgorithm");
524 const OUString
sDigestAlgProperty ("DigestAlgorithm");
525 const OUString
sDerivedKeySizeProperty ("DerivedKeySize");
527 uno::Sequence
< beans::PropertyValue
> aPropSet (PKG_SIZE_NOENCR_MNFST
);
529 // In case the entry we are reading is also the entry we are writing, we will
530 // store the ZipEntry data in pTempEntry
532 // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
533 // and be deleted in the ZipOutputStream destructor
534 std::unique_ptr
< ZipEntry
> pAutoTempEntry ( new ZipEntry(aEntry
) );
535 ZipEntry
* pTempEntry
= pAutoTempEntry
.get();
537 pTempEntry
->sPath
= rPath
;
538 pTempEntry
->nPathLen
= static_cast<sal_Int16
>( OUStringToOString( pTempEntry
->sPath
, RTL_TEXTENCODING_UTF8
).getLength() );
540 const bool bToBeEncrypted
= m_bToBeEncrypted
&& (rEncryptionKey
.getLength() || m_bHaveOwnKey
);
541 const bool bToBeCompressed
= bToBeEncrypted
|| m_bToBeCompressed
;
543 aPropSet
[PKG_MNFST_MEDIATYPE
].Name
= sMediaTypeProperty
;
544 aPropSet
[PKG_MNFST_MEDIATYPE
].Value
<<= GetMediaType( );
545 aPropSet
[PKG_MNFST_VERSION
].Name
= sVersionProperty
;
546 aPropSet
[PKG_MNFST_VERSION
].Value
<<= OUString(); // no version is stored for streams currently
547 aPropSet
[PKG_MNFST_FULLPATH
].Name
= sFullPathProperty
;
548 aPropSet
[PKG_MNFST_FULLPATH
].Value
<<= pTempEntry
->sPath
;
550 OSL_ENSURE( m_nStreamMode
!= PACKAGE_STREAM_NOTSET
, "Unacceptable ZipPackageStream mode!" );
552 m_bRawStream
= false;
553 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
554 m_bRawStream
= ParsePackageRawStream();
555 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
558 bool bParallelDeflate
= false;
559 bool bTransportOwnEncrStreamAsRaw
= false;
560 // During the storing the original size of the stream can be changed
561 // TODO/LATER: get rid of this hack
562 m_nOwnStreamOrigSize
= m_bRawStream
? m_nMagicalHackSize
: aEntry
.nSize
;
564 bool bUseNonSeekableAccess
= false;
565 uno::Reference
< io::XInputStream
> xStream
;
566 if ( !IsPackageMember() && !m_bRawStream
&& !bToBeEncrypted
&& bToBeCompressed
)
568 // the stream is not a package member, not a raw stream,
569 // it should not be encrypted and it should be compressed,
570 // in this case nonseekable access can be used
573 uno::Reference
< io::XSeekable
> xSeek ( xStream
, uno::UNO_QUERY
);
575 bUseNonSeekableAccess
= ( xStream
.is() && !xSeek
.is() );
578 if ( !bUseNonSeekableAccess
)
580 xStream
= getRawData();
584 OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
589 uno::Reference
< io::XSeekable
> xSeek ( xStream
, uno::UNO_QUERY
);
594 // If the stream is a raw one, then we should be positioned
595 // at the beginning of the actual data
596 if ( !bToBeCompressed
|| m_bRawStream
)
598 // The raw stream can neither be encrypted nor connected
599 OSL_ENSURE( !m_bRawStream
|| !(bToBeCompressed
|| bToBeEncrypted
), "The stream is already encrypted!" );
600 xSeek
->seek ( m_bRawStream
? m_nMagicalHackPos
: 0 );
601 ImplSetStoredData ( *pTempEntry
, xStream
);
603 // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
605 else if ( bToBeEncrypted
)
607 // this is the correct original size
608 pTempEntry
->nSize
= xSeek
->getLength();
609 m_nOwnStreamOrigSize
= pTempEntry
->nSize
;
616 // Okay, we don't have an xSeekable stream. This is possibly bad.
617 // check if it's one of our own streams, if it is then we know that
618 // each time we ask for it we'll get a new stream that will be
619 // at position zero...otherwise, assert and skip this stream...
620 if ( IsPackageMember() )
622 // if the password has been changed than the stream should not be package member any more
623 if ( m_bIsEncrypted
&& m_bToBeEncrypted
)
625 // Should be handled close to the raw stream handling
626 bTransportOwnEncrStreamAsRaw
= true;
627 pTempEntry
->nMethod
= STORED
;
629 // TODO/LATER: get rid of this situation
630 // this size should be different from the one that will be stored in manifest.xml
631 // it is used in storing algorithms and after storing the correct size will be set
632 pTempEntry
->nSize
= pTempEntry
->nCompressedSize
;
642 catch ( uno::Exception
& )
648 if ( bToBeEncrypted
|| m_bRawStream
|| bTransportOwnEncrStreamAsRaw
)
650 if ( bToBeEncrypted
&& !bTransportOwnEncrStreamAsRaw
)
652 uno::Sequence
< sal_Int8
> aSalt( 16 ), aVector( GetBlockSize() );
653 rtl_random_getBytes ( rRandomPool
, aSalt
.getArray(), 16 );
654 rtl_random_getBytes ( rRandomPool
, aVector
.getArray(), aVector
.getLength() );
655 if ( !m_bHaveOwnKey
)
657 m_aEncryptionKey
= rEncryptionKey
;
658 m_aStorageEncryptionKeys
.realloc( 0 );
661 setInitialisationVector ( aVector
);
663 setIterationCount(nPBKDF2IterationCount
);
666 // last property is digest, which is inserted later if we didn't have
668 aPropSet
.realloc(PKG_SIZE_ENCR_MNFST
);
670 aPropSet
[PKG_MNFST_INIVECTOR
].Name
= sInitialisationVectorProperty
;
671 aPropSet
[PKG_MNFST_INIVECTOR
].Value
<<= m_xBaseEncryptionData
->m_aInitVector
;
672 aPropSet
[PKG_MNFST_SALT
].Name
= sSaltProperty
;
673 aPropSet
[PKG_MNFST_SALT
].Value
<<= m_xBaseEncryptionData
->m_aSalt
;
674 aPropSet
[PKG_MNFST_ITERATION
].Name
= sIterationCountProperty
;
675 aPropSet
[PKG_MNFST_ITERATION
].Value
<<= m_xBaseEncryptionData
->m_nIterationCount
;
677 // Need to store the uncompressed size in the manifest
678 OSL_ENSURE( m_nOwnStreamOrigSize
>= 0, "The stream size was not correctly initialized!" );
679 aPropSet
[PKG_MNFST_UCOMPSIZE
].Name
= sSizeProperty
;
680 aPropSet
[PKG_MNFST_UCOMPSIZE
].Value
<<= m_nOwnStreamOrigSize
;
682 if ( m_bRawStream
|| bTransportOwnEncrStreamAsRaw
)
684 ::rtl::Reference
< EncryptionData
> xEncData
= GetEncryptionData();
685 if ( !xEncData
.is() )
686 throw uno::RuntimeException();
688 aPropSet
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
689 aPropSet
[PKG_MNFST_DIGEST
].Value
<<= m_xBaseEncryptionData
->m_aDigest
;
690 aPropSet
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
691 aPropSet
[PKG_MNFST_ENCALG
].Value
<<= xEncData
->m_nEncAlg
;
692 aPropSet
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
693 aPropSet
[PKG_MNFST_STARTALG
].Value
<<= xEncData
->m_nStartKeyGenID
;
694 aPropSet
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
695 aPropSet
[PKG_MNFST_DIGESTALG
].Value
<<= xEncData
->m_nCheckAlg
;
696 aPropSet
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
697 aPropSet
[PKG_MNFST_DERKEYSIZE
].Value
<<= xEncData
->m_nDerivedKeySize
;
702 // If the entry is already stored in the zip file in the format we
703 // want for this write...copy it raw
704 if ( !bUseNonSeekableAccess
705 && ( m_bRawStream
|| bTransportOwnEncrStreamAsRaw
706 || ( IsPackageMember() && !bToBeEncrypted
707 && ( ( aEntry
.nMethod
== DEFLATED
&& bToBeCompressed
)
708 || ( aEntry
.nMethod
== STORED
&& !bToBeCompressed
) ) ) ) )
710 // If it's a PackageMember, then it's an unbuffered stream and we need
711 // to get a new version of it as we can't seek backwards.
712 if ( IsPackageMember() )
714 xStream
= getRawData();
717 // Make sure that we actually _got_ a new one !
726 xStream
->skipBytes( m_nMagicalHackPos
);
728 ZipOutputStream::setEntry(pTempEntry
);
729 rZipOut
.writeLOC(pTempEntry
);
730 // the entry is provided to the ZipOutputStream that will delete it
731 pAutoTempEntry
.release();
733 uno::Sequence
< sal_Int8
> aSeq ( n_ConstBufferSize
);
738 nLength
= xStream
->readBytes( aSeq
, n_ConstBufferSize
);
739 if (nLength
!= n_ConstBufferSize
)
740 aSeq
.realloc(nLength
);
742 rZipOut
.rawWrite(aSeq
);
744 while ( nLength
== n_ConstBufferSize
);
746 rZipOut
.rawCloseEntry();
748 catch ( ZipException
& )
752 catch ( io::IOException
& )
759 // This stream is definitely not a raw stream
761 // If nonseekable access is used the stream should be at the beginning and
762 // is useless after the storing. Thus if the storing fails the package should
763 // be thrown away ( as actually it is done currently )!
764 // To allow to reuse the package after the error, the optimization must be removed!
766 // If it's a PackageMember, then our previous reference held a 'raw' stream
767 // so we need to re-get it, unencrypted, uncompressed and positioned at the
768 // beginning of the stream
769 if ( IsPackageMember() )
771 xStream
= getInputStream();
774 // Make sure that we actually _got_ a new one !
780 if ( bToBeCompressed
)
782 pTempEntry
->nMethod
= DEFLATED
;
783 pTempEntry
->nCrc
= -1;
784 pTempEntry
->nCompressedSize
= pTempEntry
->nSize
= -1;
787 uno::Reference
< io::XSeekable
> xSeek(xStream
, uno::UNO_QUERY
);
788 // It's not worth to deflate jpegs to save ~1% in a slow process
789 // Unfortunately, does not work for streams protected by password
790 if (xSeek
.is() && msMediaType
.endsWith("/jpeg") && !m_bToBeEncrypted
&& !m_bToBeCompressed
)
792 ImplSetStoredData(*pTempEntry
, xStream
);
798 ZipOutputStream::setEntry(pTempEntry
);
799 // the entry is provided to the ZipOutputStream that will delete it
800 pAutoTempEntry
.release();
802 if (pTempEntry
->nMethod
== STORED
)
805 uno::Sequence
< sal_Int8
> aSeq(n_ConstBufferSize
);
806 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
809 nLength
= xStream
->readBytes(aSeq
, n_ConstBufferSize
);
810 if (nLength
!= n_ConstBufferSize
)
811 aSeq
.realloc(nLength
);
813 rZipOut
.rawWrite(aSeq
);
815 while ( nLength
== n_ConstBufferSize
);
816 rZipOut
.rawCloseEntry(bToBeEncrypted
);
820 // tdf#89236 Encrypting in parallel does not work
821 bParallelDeflate
= !bToBeEncrypted
;
822 // Do not deflate small streams in a thread
823 if (xSeek
.is() && xSeek
->getLength() < 100000)
824 bParallelDeflate
= false;
826 if (bParallelDeflate
)
828 // tdf#93553 limit to a useful amount of threads. Taking number of available
829 // cores and allow 4-times the amount for having the queue well filled. The
830 // 2nd parameter is the time to wait between cleanups in 10th of a second.
831 // Both values may be added to the configuration settings if needed.
832 static sal_Int32
nAllowedThreads(comphelper::ThreadPool::getPreferredConcurrency() * 4);
833 rZipOut
.reduceScheduledThreadsToGivenNumberOrLess(nAllowedThreads
);
835 // Start a new thread deflating this zip entry
836 ZipOutputEntry
*pZipEntry
= new ZipOutputEntry(
837 m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
838 rZipOut
.addDeflatingThread( pZipEntry
, new DeflateThread(rZipOut
.getThreadTaskTag(), pZipEntry
, xStream
) );
842 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
843 ZipOutputEntry
aZipEntry(rZipOut
.getStream(), m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
844 deflateZipEntry(&aZipEntry
, xStream
);
845 rZipOut
.rawCloseEntry(bToBeEncrypted
);
849 catch ( ZipException
& )
853 catch ( io::IOException
& )
858 if ( bToBeEncrypted
)
860 ::rtl::Reference
< EncryptionData
> xEncData
= GetEncryptionData();
861 if ( !xEncData
.is() )
862 throw uno::RuntimeException();
864 aPropSet
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
865 aPropSet
[PKG_MNFST_DIGEST
].Value
<<= m_xBaseEncryptionData
->m_aDigest
;
866 aPropSet
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
867 aPropSet
[PKG_MNFST_ENCALG
].Value
<<= xEncData
->m_nEncAlg
;
868 aPropSet
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
869 aPropSet
[PKG_MNFST_STARTALG
].Value
<<= xEncData
->m_nStartKeyGenID
;
870 aPropSet
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
871 aPropSet
[PKG_MNFST_DIGESTALG
].Value
<<= xEncData
->m_nCheckAlg
;
872 aPropSet
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
873 aPropSet
[PKG_MNFST_DERKEYSIZE
].Value
<<= xEncData
->m_nDerivedKeySize
;
875 SetIsEncrypted ( true );
879 if (bSuccess
&& !bParallelDeflate
)
880 successfullyWritten(pTempEntry
);
882 if ( aPropSet
.getLength()
883 && ( m_nFormat
== embed::StorageFormats::PACKAGE
|| m_nFormat
== embed::StorageFormats::OFOPXML
) )
884 rManList
.push_back( aPropSet
);
889 void ZipPackageStream::successfullyWritten( ZipEntry
const *pEntry
)
891 if ( !IsPackageMember() )
893 if ( m_xStream
.is() )
895 m_xStream
->closeInput();
897 m_bHasSeekable
= false;
899 SetPackageMember ( true );
904 // the raw stream was integrated and now behaves
905 // as usual encrypted stream
906 SetToBeEncrypted( true );
909 // Then copy it back afterwards...
912 // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
913 if ( m_bIsEncrypted
)
914 setSize( m_nOwnStreamOrigSize
);
916 aEntry
.nOffset
*= -1;
919 void ZipPackageStream::SetPackageMember( bool bNewValue
)
923 m_nStreamMode
= PACKAGE_STREAM_PACKAGEMEMBER
;
924 m_nMagicalHackPos
= 0;
925 m_nMagicalHackSize
= 0;
927 else if ( m_nStreamMode
== PACKAGE_STREAM_PACKAGEMEMBER
)
928 m_nStreamMode
= PACKAGE_STREAM_NOTSET
; // must be reset
932 void SAL_CALL
ZipPackageStream::setInputStream( const uno::Reference
< io::XInputStream
>& aStream
)
934 // if seekable access is required the wrapping will be done on demand
936 m_nImportedEncryptionAlgorithm
= 0;
937 m_bHasSeekable
= false;
938 SetPackageMember ( false );
940 m_nStreamMode
= PACKAGE_STREAM_DETECT
;
943 uno::Reference
< io::XInputStream
> ZipPackageStream::getRawData()
947 if ( IsPackageMember() )
949 return m_rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef(), false/*bUseBufferedStream*/ );
951 else if ( GetOwnSeekStream().is() )
953 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
956 return uno::Reference
< io::XInputStream
> ();
958 catch ( ZipException
& )//rException )
960 OSL_FAIL( "ZipException thrown" );//rException.Message);
961 return uno::Reference
< io::XInputStream
> ();
963 catch ( Exception
& )
965 OSL_FAIL( "Exception is thrown during stream wrapping!" );
966 return uno::Reference
< io::XInputStream
> ();
970 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getInputStream()
974 if ( IsPackageMember() )
976 return m_rZipPackage
.getZipFile().getInputStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
978 else if ( GetOwnSeekStream().is() )
980 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
983 return uno::Reference
< io::XInputStream
> ();
985 catch ( ZipException
& )//rException )
987 OSL_FAIL( "ZipException thrown" );//rException.Message);
988 return uno::Reference
< io::XInputStream
> ();
990 catch ( Exception
&ex
)
992 SAL_WARN( "package", "Exception is thrown during stream wrapping!" << ex
);
993 return uno::Reference
< io::XInputStream
> ();
997 // XDataSinkEncrSupport
998 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getDataStream()
1000 // There is no stream attached to this object
1001 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1002 return uno::Reference
< io::XInputStream
>();
1004 // this method can not be used together with old approach
1005 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1006 throw packages::zip::ZipIOException(THROW_WHERE
);
1008 if ( IsPackageMember() )
1010 uno::Reference
< io::XInputStream
> xResult
;
1013 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(Bugs::None
), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1015 catch( const packages::WrongPasswordException
& )
1017 if ( m_rZipPackage
.GetStartKeyGenID() == xml::crypto::DigestID::SHA1
)
1019 SAL_WARN("package", "ZipPackageStream::getDataStream(): SHA1 mismatch, trying fallbacks...");
1021 { // tdf#114939 try with legacy StarOffice SHA1 bug
1022 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(Bugs::WrongSHA1
), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1025 catch (const packages::WrongPasswordException
&)
1027 /* ignore and try next... */
1032 // rhbz#1013844 / fdo#47482 workaround for the encrypted
1033 // OpenOffice.org 1.0 documents generated by Libreoffice <=
1034 // 3.6 with the new encryption format and using SHA256, but
1035 // missing a specified startkey of SHA256
1037 // force SHA256 and see if that works
1038 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA256
;
1039 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1042 catch (const packages::WrongPasswordException
&)
1044 // if that didn't work, restore to SHA1 and trundle through the *other* earlier
1046 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA1
;
1049 // workaround for the encrypted documents generated with the old OOo1.x bug.
1050 if ( !m_bUseWinEncoding
)
1052 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(Bugs::WinEncodingWrongSHA1
), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1053 m_bUseWinEncoding
= true;
1063 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1064 return ZipFile::StaticGetDataFromRawStream( m_rZipPackage
.GetSharedMutexRef(), m_xContext
, GetOwnSeekStream(), GetEncryptionData() );
1065 else if ( GetOwnSeekStream().is() )
1067 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
1070 return uno::Reference
< io::XInputStream
>();
1073 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getRawStream()
1075 // There is no stream attached to this object
1076 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1077 return uno::Reference
< io::XInputStream
>();
1079 // this method can not be used together with old approach
1080 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1081 throw packages::zip::ZipIOException(THROW_WHERE
);
1083 if ( IsPackageMember() )
1085 if ( !m_bIsEncrypted
|| !GetEncryptionData().is() )
1086 throw packages::NoEncryptionException(THROW_WHERE
);
1088 return m_rZipPackage
.getZipFile().getWrappedRawStream( aEntry
, GetEncryptionData(), msMediaType
, m_rZipPackage
.GetSharedMutexRef() );
1090 else if ( GetOwnSeekStream().is() )
1092 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1094 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
1096 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
&& m_bToBeEncrypted
)
1097 return TryToGetRawFromDataStream( true );
1100 throw packages::NoEncryptionException(THROW_WHERE
);
1103 void SAL_CALL
ZipPackageStream::setDataStream( const uno::Reference
< io::XInputStream
>& aStream
)
1105 setInputStream( aStream
);
1106 m_nStreamMode
= PACKAGE_STREAM_DATA
;
1109 void SAL_CALL
ZipPackageStream::setRawStream( const uno::Reference
< io::XInputStream
>& aStream
)
1111 // wrap the stream in case it is not seekable
1112 uno::Reference
< io::XInputStream
> xNewStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream
, m_xContext
);
1113 uno::Reference
< io::XSeekable
> xSeek( xNewStream
, UNO_QUERY_THROW
);
1115 uno::Reference
< io::XInputStream
> xOldStream
= m_xStream
;
1116 m_xStream
= xNewStream
;
1117 if ( !ParsePackageRawStream() )
1119 m_xStream
= xOldStream
;
1120 throw packages::NoRawFormatException(THROW_WHERE
);
1123 // the raw stream MUST have seekable access
1124 m_bHasSeekable
= true;
1126 SetPackageMember ( false );
1128 m_nStreamMode
= PACKAGE_STREAM_RAW
;
1131 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getPlainRawStream()
1133 // There is no stream attached to this object
1134 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1135 return uno::Reference
< io::XInputStream
>();
1137 // this method can not be used together with old approach
1138 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1139 throw packages::zip::ZipIOException(THROW_WHERE
);
1141 if ( IsPackageMember() )
1143 return m_rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1145 else if ( GetOwnSeekStream().is() )
1147 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1149 // the header should not be returned here
1150 return GetRawEncrStreamNoHeaderCopy();
1152 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
)
1153 return TryToGetRawFromDataStream( false );
1156 return uno::Reference
< io::XInputStream
>();
1161 sal_Int64 SAL_CALL
ZipPackageStream::getSomething( const Sequence
< sal_Int8
>& aIdentifier
)
1164 if ( aIdentifier
.getLength() == 16 &&
1165 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier
.getConstArray(), 16 ) )
1166 nMe
= reinterpret_cast < sal_Int64
> ( this );
1171 void SAL_CALL
ZipPackageStream::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
1173 if ( aPropertyName
== "MediaType" )
1175 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
&& m_rZipPackage
.getFormat() != embed::StorageFormats::OFOPXML
)
1176 throw beans::PropertyVetoException(THROW_WHERE
);
1178 if ( !(aValue
>>= msMediaType
) )
1179 throw IllegalArgumentException(THROW_WHERE
"MediaType must be a string!",
1180 uno::Reference
< XInterface
>(),
1183 if ( !msMediaType
.isEmpty() )
1185 if ( msMediaType
.indexOf ( "text" ) != -1
1186 || msMediaType
== "application/vnd.sun.star.oleobject" )
1187 m_bToBeCompressed
= true;
1188 else if ( !m_bCompressedIsSetFromOutside
)
1189 m_bToBeCompressed
= false;
1192 else if ( aPropertyName
== "Size" )
1194 if ( !( aValue
>>= aEntry
.nSize
) )
1195 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Size property!",
1196 uno::Reference
< XInterface
>(),
1199 else if ( aPropertyName
== "Encrypted" )
1201 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1202 throw beans::PropertyVetoException(THROW_WHERE
);
1205 if ( !(aValue
>>= bEnc
) )
1206 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Encrypted property!",
1207 uno::Reference
< XInterface
>(),
1210 // In case of new raw stream, the stream must not be encrypted on storing
1211 if ( bEnc
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
1212 throw IllegalArgumentException(THROW_WHERE
"Raw stream can not be encrypted on storing",
1213 uno::Reference
< XInterface
>(),
1216 m_bToBeEncrypted
= bEnc
;
1217 if ( m_bToBeEncrypted
&& !m_xBaseEncryptionData
.is() )
1218 m_xBaseEncryptionData
= new BaseEncryptionData
;
1221 else if ( aPropertyName
== ENCRYPTION_KEY_PROPERTY
)
1223 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1224 throw beans::PropertyVetoException(THROW_WHERE
);
1226 uno::Sequence
< sal_Int8
> aNewKey
;
1228 if ( !( aValue
>>= aNewKey
) )
1230 OUString sTempString
;
1231 if ( !(aValue
>>= sTempString
) )
1232 throw IllegalArgumentException(THROW_WHERE
"Wrong type for EncryptionKey property!",
1233 uno::Reference
< XInterface
>(),
1236 sal_Int32 nPathLength
= sTempString
.getLength();
1237 Sequence
< sal_Int8
> aSequence ( nPathLength
);
1238 sal_Int8
*pArray
= aSequence
.getArray();
1239 const sal_Unicode
*pChar
= sTempString
.getStr();
1240 for ( sal_Int32 i
= 0; i
< nPathLength
; i
++ )
1241 pArray
[i
] = static_cast < sal_Int8
> ( pChar
[i
] );
1242 aNewKey
= aSequence
;
1245 if ( aNewKey
.getLength() )
1247 if ( !m_xBaseEncryptionData
.is() )
1248 m_xBaseEncryptionData
= new BaseEncryptionData
;
1250 m_aEncryptionKey
= aNewKey
;
1251 // In case of new raw stream, the stream must not be encrypted on storing
1252 m_bHaveOwnKey
= true;
1253 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
1254 m_bToBeEncrypted
= true;
1258 m_bHaveOwnKey
= false;
1259 m_aEncryptionKey
.realloc( 0 );
1262 m_aStorageEncryptionKeys
.realloc( 0 );
1264 else if ( aPropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
1266 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1267 throw beans::PropertyVetoException(THROW_WHERE
);
1269 uno::Sequence
< beans::NamedValue
> aKeys
;
1270 if ( !( aValue
>>= aKeys
) )
1272 throw IllegalArgumentException(THROW_WHERE
"Wrong type for StorageEncryptionKeys property!",
1273 uno::Reference
< XInterface
>(),
1277 if ( aKeys
.getLength() )
1279 if ( !m_xBaseEncryptionData
.is() )
1280 m_xBaseEncryptionData
= new BaseEncryptionData
;
1282 m_aStorageEncryptionKeys
= aKeys
;
1284 // In case of new raw stream, the stream must not be encrypted on storing
1285 m_bHaveOwnKey
= true;
1286 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
1287 m_bToBeEncrypted
= true;
1291 m_bHaveOwnKey
= false;
1292 m_aStorageEncryptionKeys
.realloc( 0 );
1295 m_aEncryptionKey
.realloc( 0 );
1297 else if ( aPropertyName
== "Compressed" )
1299 bool bCompr
= false;
1301 if ( !(aValue
>>= bCompr
) )
1302 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Compressed property!",
1303 uno::Reference
< XInterface
>(),
1306 // In case of new raw stream, the stream must not be encrypted on storing
1307 if ( bCompr
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
1308 throw IllegalArgumentException(THROW_WHERE
"Raw stream can not be encrypted on storing",
1309 uno::Reference
< XInterface
>(),
1312 m_bToBeCompressed
= bCompr
;
1313 m_bCompressedIsSetFromOutside
= true;
1316 throw beans::UnknownPropertyException(THROW_WHERE
);
1319 Any SAL_CALL
ZipPackageStream::getPropertyValue( const OUString
& PropertyName
)
1321 if ( PropertyName
== "MediaType" )
1323 return Any(msMediaType
);
1325 else if ( PropertyName
== "Size" )
1327 return Any(aEntry
.nSize
);
1329 else if ( PropertyName
== "Encrypted" )
1331 return Any((m_nStreamMode
== PACKAGE_STREAM_RAW
) || m_bToBeEncrypted
);
1333 else if ( PropertyName
== "WasEncrypted" )
1335 return Any(m_bIsEncrypted
);
1337 else if ( PropertyName
== "Compressed" )
1339 return Any(m_bToBeCompressed
);
1341 else if ( PropertyName
== ENCRYPTION_KEY_PROPERTY
)
1343 return Any(m_aEncryptionKey
);
1345 else if ( PropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
1347 return Any(m_aStorageEncryptionKeys
);
1350 throw beans::UnknownPropertyException(THROW_WHERE
);
1353 void ZipPackageStream::setSize ( const sal_Int64 nNewSize
)
1355 if ( aEntry
.nCompressedSize
!= nNewSize
)
1356 aEntry
.nMethod
= DEFLATED
;
1357 aEntry
.nSize
= nNewSize
;
1359 OUString
ZipPackageStream::getImplementationName()
1361 return OUString ("ZipPackageStream");
1364 Sequence
< OUString
> ZipPackageStream::getSupportedServiceNames()
1366 Sequence
<OUString
> aNames
{ "com.sun.star.packages.PackageStream" };
1370 sal_Bool SAL_CALL
ZipPackageStream::supportsService( OUString
const & rServiceName
)
1372 return cppu::supportsService(this, rServiceName
);
1375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */