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/packages/zip/ZipConstants.hpp>
24 #include <com/sun/star/embed/StorageFormats.hpp>
25 #include <com/sun/star/packages/zip/ZipIOException.hpp>
26 #include <com/sun/star/io/TempFile.hpp>
27 #include <com/sun/star/io/XInputStream.hpp>
28 #include <com/sun/star/io/XOutputStream.hpp>
29 #include <com/sun/star/io/XStream.hpp>
30 #include <com/sun/star/io/XSeekable.hpp>
31 #include <com/sun/star/xml/crypto/DigestID.hpp>
32 #include <com/sun/star/xml/crypto/CipherID.hpp>
37 #include <ZipOutputEntry.hxx>
38 #include <ZipOutputStream.hxx>
39 #include <ZipPackage.hxx>
40 #include <ZipPackageFolder.hxx>
41 #include <ZipFile.hxx>
42 #include <EncryptedDataHeader.hxx>
43 #include <osl/diagnose.h>
44 #include "wrapstreamforshare.hxx"
46 #include <comphelper/processfactory.hxx>
47 #include <comphelper/seekableinput.hxx>
48 #include <comphelper/storagehelper.hxx>
49 #include <cppuhelper/exc_hlp.hxx>
50 #include <cppuhelper/supportsservice.hxx>
51 #include <cppuhelper/typeprovider.hxx>
53 #include <rtl/instance.hxx>
54 #include <rtl/random.h>
56 #include <PackageConstants.hxx>
58 using namespace com::sun::star::packages::zip::ZipConstants
;
59 using namespace com::sun::star::packages::zip
;
60 using namespace com::sun::star::uno
;
61 using namespace com::sun::star::lang
;
62 using namespace com::sun::star
;
65 #if OSL_DEBUG_LEVEL > 0
66 #define THROW_WHERE SAL_WHERE
68 #define THROW_WHERE ""
71 namespace { struct lcl_CachedImplId
: public rtl::Static
< cppu::OImplementationId
, lcl_CachedImplId
> {}; }
73 ::com::sun::star::uno::Sequence
< sal_Int8
> ZipPackageStream::static_getImplementationId()
75 return lcl_CachedImplId::get().getImplementationId();
78 ZipPackageStream::ZipPackageStream ( ZipPackage
& rNewPackage
,
79 const uno::Reference
< XComponentContext
>& xContext
,
81 bool bAllowRemoveOnInsert
)
82 : m_rZipPackage( rNewPackage
)
83 , m_bToBeCompressed ( true )
84 , m_bToBeEncrypted ( false )
85 , m_bHaveOwnKey ( false )
86 , m_bIsEncrypted ( false )
87 , m_nImportedStartKeyAlgorithm( 0 )
88 , m_nImportedEncryptionAlgorithm( 0 )
89 , m_nImportedChecksumAlgorithm( 0 )
90 , m_nImportedDerivedKeySize( 0 )
91 , m_nStreamMode( PACKAGE_STREAM_NOTSET
)
92 , m_nMagicalHackPos( 0 )
93 , m_nMagicalHackSize( 0 )
94 , m_nOwnStreamOrigSize( 0 )
95 , m_bHasSeekable( false )
96 , m_bCompressedIsSetFromOutside( false )
97 , m_bFromManifest( false )
98 , m_bUseWinEncoding( false )
99 , m_bRawStream( false )
101 m_xContext
= xContext
;
103 mbAllowRemoveOnInsert
= bAllowRemoveOnInsert
;
105 aEntry
.nVersion
= -1;
110 aEntry
.nCompressedSize
= -1;
113 aEntry
.nPathLen
= -1;
114 aEntry
.nExtraLen
= -1;
117 ZipPackageStream::~ZipPackageStream()
121 void ZipPackageStream::setZipEntryOnLoading( const ZipEntry
&rInEntry
)
123 aEntry
.nVersion
= rInEntry
.nVersion
;
124 aEntry
.nFlag
= rInEntry
.nFlag
;
125 aEntry
.nMethod
= rInEntry
.nMethod
;
126 aEntry
.nTime
= rInEntry
.nTime
;
127 aEntry
.nCrc
= rInEntry
.nCrc
;
128 aEntry
.nCompressedSize
= rInEntry
.nCompressedSize
;
129 aEntry
.nSize
= rInEntry
.nSize
;
130 aEntry
.nOffset
= rInEntry
.nOffset
;
131 aEntry
.sPath
= rInEntry
.sPath
;
132 aEntry
.nPathLen
= rInEntry
.nPathLen
;
133 aEntry
.nExtraLen
= rInEntry
.nExtraLen
;
135 if ( aEntry
.nMethod
== STORED
)
136 m_bToBeCompressed
= false;
139 void ZipPackageStream::CloseOwnStreamIfAny()
141 if ( m_xStream
.is() )
143 m_xStream
->closeInput();
144 m_xStream
= uno::Reference
< io::XInputStream
>();
145 m_bHasSeekable
= false;
149 uno::Reference
< io::XInputStream
> ZipPackageStream::GetOwnSeekStream()
151 if ( !m_bHasSeekable
&& m_xStream
.is() )
153 // The package component requires that every stream either be FROM a package or it must support XSeekable!
154 // The only exception is a nonseekable stream that is provided only for storing, if such a stream
155 // is accessed before commit it MUST be wrapped.
156 // Wrap the stream in case it is not seekable
157 m_xStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xStream
, m_xContext
);
158 uno::Reference
< io::XSeekable
> xSeek( m_xStream
, UNO_QUERY
);
160 throw RuntimeException( THROW_WHERE
"The stream must support XSeekable!" );
162 m_bHasSeekable
= true;
168 uno::Reference
< io::XInputStream
> ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
170 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
|| !GetOwnSeekStream().is() )
171 throw io::IOException(THROW_WHERE
);
173 if ( m_xBaseEncryptionData
.is() )
174 throw ZipIOException(THROW_WHERE
"Encrypted stream without encryption data!" );
176 uno::Reference
< io::XSeekable
> xSeek( GetOwnSeekStream(), UNO_QUERY
);
178 throw ZipIOException(THROW_WHERE
"The stream must be seekable!" );
181 xSeek
->seek( n_ConstHeaderSize
+ m_xBaseEncryptionData
->m_aInitVector
.getLength() +
182 m_xBaseEncryptionData
->m_aSalt
.getLength() + m_xBaseEncryptionData
->m_aDigest
.getLength() );
184 // create temporary stream
185 uno::Reference
< io::XTempFile
> xTempFile
= io::TempFile::create(m_xContext
);
186 uno::Reference
< io::XOutputStream
> xTempOut
= xTempFile
->getOutputStream();
187 uno::Reference
< io::XInputStream
> xTempIn
= xTempFile
->getInputStream();;
188 uno::Reference
< io::XSeekable
> xTempSeek( xTempOut
, UNO_QUERY_THROW
);
190 // copy the raw stream to the temporary file starting from the current position
191 ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut
);
192 xTempOut
->closeOutput();
193 xTempSeek
->seek( 0 );
198 sal_Int32
ZipPackageStream::GetEncryptionAlgorithm() const
200 return m_nImportedEncryptionAlgorithm
? m_nImportedEncryptionAlgorithm
: m_rZipPackage
.GetEncAlgID();
203 sal_Int32
ZipPackageStream::GetBlockSize() const
205 return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING
? 16 : 8;
208 ::rtl::Reference
< EncryptionData
> ZipPackageStream::GetEncryptionData( bool bUseWinEncoding
)
210 ::rtl::Reference
< EncryptionData
> xResult
;
211 if ( m_xBaseEncryptionData
.is() )
212 xResult
= new EncryptionData(
213 *m_xBaseEncryptionData
,
214 GetEncryptionKey( bUseWinEncoding
),
215 GetEncryptionAlgorithm(),
216 m_nImportedChecksumAlgorithm
? m_nImportedChecksumAlgorithm
: m_rZipPackage
.GetChecksumAlgID(),
217 m_nImportedDerivedKeySize
? m_nImportedDerivedKeySize
: m_rZipPackage
.GetDefaultDerivedKeySize(),
218 GetStartKeyGenID() );
223 uno::Sequence
< sal_Int8
> ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding
)
225 uno::Sequence
< sal_Int8
> aResult
;
226 sal_Int32 nKeyGenID
= GetStartKeyGenID();
227 bUseWinEncoding
= ( bUseWinEncoding
|| m_bUseWinEncoding
);
229 if ( m_bHaveOwnKey
&& m_aStorageEncryptionKeys
.getLength() )
231 OUString aNameToFind
;
232 if ( nKeyGenID
== xml::crypto::DigestID::SHA256
)
233 aNameToFind
= PACKAGE_ENCRYPTIONDATA_SHA256UTF8
;
234 else if ( nKeyGenID
== xml::crypto::DigestID::SHA1
)
236 aNameToFind
= bUseWinEncoding
? OUString(PACKAGE_ENCRYPTIONDATA_SHA1MS1252
) : OUString(PACKAGE_ENCRYPTIONDATA_SHA1UTF8
);
239 throw uno::RuntimeException(THROW_WHERE
"No expected key is provided!" );
241 for ( sal_Int32 nInd
= 0; nInd
< m_aStorageEncryptionKeys
.getLength(); nInd
++ )
242 if ( m_aStorageEncryptionKeys
[nInd
].Name
.equals( aNameToFind
) )
243 m_aStorageEncryptionKeys
[nInd
].Value
>>= aResult
;
245 // empty keys are not allowed here
246 // so it is not important whether there is no key, or the key is empty, it is an error
247 if ( !aResult
.getLength() )
248 throw uno::RuntimeException(THROW_WHERE
"No expected key is provided!" );
251 aResult
= m_aEncryptionKey
;
253 if ( !aResult
.getLength() || !m_bHaveOwnKey
)
254 aResult
= m_rZipPackage
.GetEncryptionKey();
259 sal_Int32
ZipPackageStream::GetStartKeyGenID()
261 // generally should all the streams use the same Start Key
262 // but if raw copy without password takes place, we should preserve the imported algorithm
263 return m_nImportedStartKeyAlgorithm
? m_nImportedStartKeyAlgorithm
: m_rZipPackage
.GetStartKeyGenID();
266 uno::Reference
< io::XInputStream
> ZipPackageStream::TryToGetRawFromDataStream( bool bAddHeaderForEncr
)
268 if ( m_nStreamMode
!= PACKAGE_STREAM_DATA
|| !GetOwnSeekStream().is() || ( bAddHeaderForEncr
&& !m_bToBeEncrypted
) )
269 throw packages::NoEncryptionException(THROW_WHERE
);
271 Sequence
< sal_Int8
> aKey
;
273 if ( m_bToBeEncrypted
)
275 aKey
= GetEncryptionKey();
276 if ( !aKey
.getLength() )
277 throw packages::NoEncryptionException(THROW_WHERE
);
282 // create temporary file
283 uno::Reference
< io::XStream
> xTempStream(
284 io::TempFile::create(m_xContext
),
285 uno::UNO_QUERY_THROW
);
287 // create a package based on it
288 ZipPackage
* pPackage
= new ZipPackage( m_xContext
);
289 uno::Reference
< XSingleServiceFactory
> xPackageAsFactory( static_cast< XSingleServiceFactory
* >( pPackage
) );
290 if ( !xPackageAsFactory
.is() )
291 throw RuntimeException(THROW_WHERE
);
293 Sequence
< Any
> aArgs( 1 );
294 aArgs
[0] <<= xTempStream
;
295 pPackage
->initialize( aArgs
);
297 // create a new package stream
298 uno::Reference
< XDataSinkEncrSupport
> xNewPackStream( xPackageAsFactory
->createInstance(), UNO_QUERY
);
299 if ( !xNewPackStream
.is() )
300 throw RuntimeException(THROW_WHERE
);
302 xNewPackStream
->setDataStream( static_cast< io::XInputStream
* >(
303 new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() ) ) );
305 uno::Reference
< XPropertySet
> xNewPSProps( xNewPackStream
, UNO_QUERY
);
306 if ( !xNewPSProps
.is() )
307 throw RuntimeException(THROW_WHERE
);
309 // copy all the properties of this stream to the new stream
310 xNewPSProps
->setPropertyValue("MediaType", makeAny( msMediaType
) );
311 xNewPSProps
->setPropertyValue("Compressed", makeAny( m_bToBeCompressed
) );
312 if ( m_bToBeEncrypted
)
314 xNewPSProps
->setPropertyValue(ENCRYPTION_KEY_PROPERTY
, makeAny( aKey
) );
315 xNewPSProps
->setPropertyValue("Encrypted", makeAny( true ) );
318 // insert a new stream in the package
319 uno::Reference
< XUnoTunnel
> xTunnel
;
320 Any aRoot
= pPackage
->getByHierarchicalName("/");
322 uno::Reference
< container::XNameContainer
> xRootNameContainer( xTunnel
, UNO_QUERY
);
323 if ( !xRootNameContainer
.is() )
324 throw RuntimeException(THROW_WHERE
);
326 uno::Reference
< XUnoTunnel
> xNPSTunnel( xNewPackStream
, UNO_QUERY
);
327 xRootNameContainer
->insertByName("dummy", makeAny( xNPSTunnel
) );
329 // commit the temporary package
330 pPackage
->commitChanges();
332 // get raw stream from the temporary package
333 uno::Reference
< io::XInputStream
> xInRaw
;
334 if ( bAddHeaderForEncr
)
335 xInRaw
= xNewPackStream
->getRawStream();
337 xInRaw
= xNewPackStream
->getPlainRawStream();
339 // create another temporary file
340 uno::Reference
< io::XOutputStream
> xTempOut(
341 io::TempFile::create(m_xContext
),
342 uno::UNO_QUERY_THROW
);
343 uno::Reference
< io::XInputStream
> xTempIn( xTempOut
, UNO_QUERY_THROW
);
344 uno::Reference
< io::XSeekable
> xTempSeek( xTempOut
, UNO_QUERY_THROW
);
346 // copy the raw stream to the temporary file
347 ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw
, xTempOut
);
348 xTempOut
->closeOutput();
349 xTempSeek
->seek( 0 );
351 // close raw stream, package stream and folder
352 xInRaw
= uno::Reference
< io::XInputStream
>();
353 xNewPSProps
= uno::Reference
< XPropertySet
>();
354 xNPSTunnel
= uno::Reference
< XUnoTunnel
>();
355 xNewPackStream
= uno::Reference
< XDataSinkEncrSupport
>();
356 xTunnel
= uno::Reference
< XUnoTunnel
>();
357 xRootNameContainer
= uno::Reference
< container::XNameContainer
>();
359 // return the stream representing the first temporary file
362 catch ( RuntimeException
& )
370 throw io::IOException(THROW_WHERE
);
373 bool ZipPackageStream::ParsePackageRawStream()
375 OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
377 if ( !GetOwnSeekStream().is() )
382 ::rtl::Reference
< BaseEncryptionData
> xTempEncrData
;
383 sal_Int32 nMagHackSize
= 0;
384 Sequence
< sal_Int8
> aHeader ( 4 );
388 if ( GetOwnSeekStream()->readBytes ( aHeader
, 4 ) == 4 )
390 const sal_Int8
*pHeader
= aHeader
.getConstArray();
391 sal_uInt32 nHeader
= ( pHeader
[0] & 0xFF ) |
392 ( pHeader
[1] & 0xFF ) << 8 |
393 ( pHeader
[2] & 0xFF ) << 16 |
394 ( pHeader
[3] & 0xFF ) << 24;
395 if ( nHeader
== n_ConstHeader
)
397 // this is one of our god-awful, but extremely devious hacks, everyone cheer
398 xTempEncrData
= new BaseEncryptionData
;
401 sal_Int32 nEncAlgorithm
= 0;
402 sal_Int32 nChecksumAlgorithm
= 0;
403 sal_Int32 nDerivedKeySize
= 0;
404 sal_Int32 nStartKeyGenID
= 0;
405 if ( ZipFile::StaticFillData( xTempEncrData
, nEncAlgorithm
, nChecksumAlgorithm
, nDerivedKeySize
, nStartKeyGenID
, nMagHackSize
, aMediaType
, GetOwnSeekStream() ) )
407 // We'll want to skip the data we've just read, so calculate how much we just read
409 m_nMagicalHackPos
= n_ConstHeaderSize
+ xTempEncrData
->m_aSalt
.getLength()
410 + xTempEncrData
->m_aInitVector
.getLength()
411 + xTempEncrData
->m_aDigest
.getLength()
412 + aMediaType
.getLength() * sizeof( sal_Unicode
);
413 m_nImportedEncryptionAlgorithm
= nEncAlgorithm
;
414 m_nImportedChecksumAlgorithm
= nChecksumAlgorithm
;
415 m_nImportedDerivedKeySize
= nDerivedKeySize
;
416 m_nImportedStartKeyAlgorithm
= nStartKeyGenID
;
417 m_nMagicalHackSize
= nMagHackSize
;
418 msMediaType
= aMediaType
;
431 // the provided stream is not a raw stream
435 m_xBaseEncryptionData
= xTempEncrData
;
436 SetIsEncrypted ( true );
437 // it's already compressed and encrypted
438 m_bToBeEncrypted
= m_bToBeCompressed
= false;
443 static void deflateZipEntry(ZipOutputEntry
*pZipEntry
,
444 const uno::Reference
< io::XInputStream
>& xInStream
)
446 sal_Int32 nLength
= 0;
447 uno::Sequence
< sal_Int8
> aSeq(n_ConstBufferSize
);
450 nLength
= xInStream
->readBytes(aSeq
, n_ConstBufferSize
);
451 if (nLength
!= n_ConstBufferSize
)
452 aSeq
.realloc(nLength
);
454 pZipEntry
->write(aSeq
);
456 while (nLength
== n_ConstBufferSize
);
457 pZipEntry
->closeEntry();
460 class DeflateThread
: public comphelper::ThreadTask
462 ZipOutputEntry
*mpEntry
;
463 uno::Reference
< io::XInputStream
> mxInStream
;
466 DeflateThread( ZipOutputEntry
*pEntry
,
467 const uno::Reference
< io::XInputStream
>& xInStream
)
469 , mxInStream(xInStream
)
473 virtual void doWork() SAL_OVERRIDE
477 mpEntry
->createBufferFile();
478 deflateZipEntry(mpEntry
, mxInStream
);
480 mpEntry
->closeBufferFile();
482 catch (const uno::Exception
&)
484 mpEntry
->setParallelDeflateException(::cppu::getCaughtException());
489 static void ImplSetStoredData( ZipEntry
& rEntry
, uno::Reference
< io::XInputStream
> & rStream
)
491 // It's very annoying that we have to do this, but lots of zip packages
492 // don't allow data descriptors for STORED streams, meaning we have to
493 // know the size and CRC32 of uncompressed streams before we actually
496 rEntry
.nMethod
= STORED
;
497 rEntry
.nCompressedSize
= rEntry
.nSize
= aCRC32
.updateStream ( rStream
);
498 rEntry
.nCrc
= aCRC32
.getValue();
501 bool ZipPackageStream::saveChild(
502 const OUString
&rPath
,
503 std::vector
< uno::Sequence
< beans::PropertyValue
> > &rManList
,
504 ZipOutputStream
& rZipOut
,
505 const uno::Sequence
< sal_Int8
>& rEncryptionKey
,
506 const rtlRandomPool
&rRandomPool
)
508 bool bSuccess
= true;
510 const OUString
sMediaTypeProperty ("MediaType");
511 const OUString
sVersionProperty ("Version");
512 const OUString
sFullPathProperty ("FullPath");
513 const OUString
sInitialisationVectorProperty ("InitialisationVector");
514 const OUString
sSaltProperty ("Salt");
515 const OUString
sIterationCountProperty ("IterationCount");
516 const OUString
sSizeProperty ("Size");
517 const OUString
sDigestProperty ("Digest");
518 const OUString
sEncryptionAlgProperty ("EncryptionAlgorithm");
519 const OUString
sStartKeyAlgProperty ("StartKeyAlgorithm");
520 const OUString
sDigestAlgProperty ("DigestAlgorithm");
521 const OUString
sDerivedKeySizeProperty ("DerivedKeySize");
523 uno::Sequence
< beans::PropertyValue
> aPropSet (PKG_SIZE_NOENCR_MNFST
);
525 // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
526 // and be deleted in the ZipOutputStream destructor
527 std::unique_ptr
< ZipEntry
> pAutoTempEntry ( new ZipEntry
);
528 ZipEntry
* pTempEntry
= pAutoTempEntry
.get();
530 // In case the entry we are reading is also the entry we are writing, we will
531 // store the ZipEntry data in pTempEntry
533 ZipPackageFolder::copyZipEntry ( *pTempEntry
, aEntry
);
534 pTempEntry
->sPath
= rPath
;
535 pTempEntry
->nPathLen
= (sal_Int16
)( OUStringToOString( pTempEntry
->sPath
, RTL_TEXTENCODING_UTF8
).getLength() );
537 const bool bToBeEncrypted
= m_bToBeEncrypted
&& (rEncryptionKey
.getLength() || m_bHaveOwnKey
);
538 const bool bToBeCompressed
= bToBeEncrypted
|| m_bToBeCompressed
;
540 aPropSet
[PKG_MNFST_MEDIATYPE
].Name
= sMediaTypeProperty
;
541 aPropSet
[PKG_MNFST_MEDIATYPE
].Value
<<= GetMediaType( );
542 aPropSet
[PKG_MNFST_VERSION
].Name
= sVersionProperty
;
543 aPropSet
[PKG_MNFST_VERSION
].Value
<<= OUString(); // no version is stored for streams currently
544 aPropSet
[PKG_MNFST_FULLPATH
].Name
= sFullPathProperty
;
545 aPropSet
[PKG_MNFST_FULLPATH
].Value
<<= pTempEntry
->sPath
;
547 OSL_ENSURE( m_nStreamMode
!= PACKAGE_STREAM_NOTSET
, "Unacceptable ZipPackageStream mode!" );
549 m_bRawStream
= false;
550 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
551 m_bRawStream
= ParsePackageRawStream();
552 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
555 bool bParallelDeflate
= false;
556 bool bTransportOwnEncrStreamAsRaw
= false;
557 // During the storing the original size of the stream can be changed
558 // TODO/LATER: get rid of this hack
559 m_nOwnStreamOrigSize
= m_bRawStream
? m_nMagicalHackSize
: aEntry
.nSize
;
561 bool bUseNonSeekableAccess
= false;
562 uno::Reference
< io::XInputStream
> xStream
;
563 if ( !IsPackageMember() && !m_bRawStream
&& !bToBeEncrypted
&& bToBeCompressed
)
565 // the stream is not a package member, not a raw stream,
566 // it should not be encrypted and it should be compressed,
567 // in this case nonseekable access can be used
570 uno::Reference
< io::XSeekable
> xSeek ( xStream
, uno::UNO_QUERY
);
572 bUseNonSeekableAccess
= ( xStream
.is() && !xSeek
.is() );
575 if ( !bUseNonSeekableAccess
)
577 xStream
= getRawData();
581 OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
586 uno::Reference
< io::XSeekable
> xSeek ( xStream
, uno::UNO_QUERY
);
591 // If the stream is a raw one, then we should be positioned
592 // at the beginning of the actual data
593 if ( !bToBeCompressed
|| m_bRawStream
)
595 // The raw stream can neither be encrypted nor connected
596 OSL_ENSURE( !m_bRawStream
|| !(bToBeCompressed
|| bToBeEncrypted
), "The stream is already encrypted!\n" );
597 xSeek
->seek ( m_bRawStream
? m_nMagicalHackPos
: 0 );
598 ImplSetStoredData ( *pTempEntry
, xStream
);
600 // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
602 else if ( bToBeEncrypted
)
604 // this is the correct original size
605 pTempEntry
->nSize
= xSeek
->getLength();
606 m_nOwnStreamOrigSize
= pTempEntry
->nSize
;
613 // Okay, we don't have an xSeekable stream. This is possibly bad.
614 // check if it's one of our own streams, if it is then we know that
615 // each time we ask for it we'll get a new stream that will be
616 // at position zero...otherwise, assert and skip this stream...
617 if ( IsPackageMember() )
619 // if the password has been changed than the stream should not be package member any more
620 if ( m_bIsEncrypted
&& m_bToBeEncrypted
)
622 // Should be handled close to the raw stream handling
623 bTransportOwnEncrStreamAsRaw
= true;
624 pTempEntry
->nMethod
= STORED
;
626 // TODO/LATER: get rid of this situation
627 // this size should be different from the one that will be stored in manifest.xml
628 // it is used in storing algorithms and after storing the correct size will be set
629 pTempEntry
->nSize
= pTempEntry
->nCompressedSize
;
639 catch ( uno::Exception
& )
645 if ( bToBeEncrypted
|| m_bRawStream
|| bTransportOwnEncrStreamAsRaw
)
647 if ( bToBeEncrypted
&& !bTransportOwnEncrStreamAsRaw
)
649 uno::Sequence
< sal_Int8
> aSalt( 16 ), aVector( GetBlockSize() );
650 rtl_random_getBytes ( rRandomPool
, aSalt
.getArray(), 16 );
651 rtl_random_getBytes ( rRandomPool
, aVector
.getArray(), aVector
.getLength() );
652 sal_Int32 nIterationCount
= 1024;
654 if ( !m_bHaveOwnKey
)
656 m_aEncryptionKey
= rEncryptionKey
;
657 m_aStorageEncryptionKeys
.realloc( 0 );
660 setInitialisationVector ( aVector
);
662 setIterationCount ( nIterationCount
);
665 // last property is digest, which is inserted later if we didn't have
667 aPropSet
.realloc(PKG_SIZE_ENCR_MNFST
);
669 aPropSet
[PKG_MNFST_INIVECTOR
].Name
= sInitialisationVectorProperty
;
670 aPropSet
[PKG_MNFST_INIVECTOR
].Value
<<= m_xBaseEncryptionData
->m_aInitVector
;
671 aPropSet
[PKG_MNFST_SALT
].Name
= sSaltProperty
;
672 aPropSet
[PKG_MNFST_SALT
].Value
<<= m_xBaseEncryptionData
->m_aSalt
;
673 aPropSet
[PKG_MNFST_ITERATION
].Name
= sIterationCountProperty
;
674 aPropSet
[PKG_MNFST_ITERATION
].Value
<<= m_xBaseEncryptionData
->m_nIterationCount
;
676 // Need to store the uncompressed size in the manifest
677 OSL_ENSURE( m_nOwnStreamOrigSize
>= 0, "The stream size was not correctly initialized!\n" );
678 aPropSet
[PKG_MNFST_UCOMPSIZE
].Name
= sSizeProperty
;
679 aPropSet
[PKG_MNFST_UCOMPSIZE
].Value
<<= m_nOwnStreamOrigSize
;
681 if ( m_bRawStream
|| bTransportOwnEncrStreamAsRaw
)
683 ::rtl::Reference
< EncryptionData
> xEncData
= GetEncryptionData();
684 if ( !xEncData
.is() )
685 throw uno::RuntimeException();
687 aPropSet
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
688 aPropSet
[PKG_MNFST_DIGEST
].Value
<<= m_xBaseEncryptionData
->m_aDigest
;
689 aPropSet
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
690 aPropSet
[PKG_MNFST_ENCALG
].Value
<<= xEncData
->m_nEncAlg
;
691 aPropSet
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
692 aPropSet
[PKG_MNFST_STARTALG
].Value
<<= xEncData
->m_nStartKeyGenID
;
693 aPropSet
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
694 aPropSet
[PKG_MNFST_DIGESTALG
].Value
<<= xEncData
->m_nCheckAlg
;
695 aPropSet
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
696 aPropSet
[PKG_MNFST_DERKEYSIZE
].Value
<<= xEncData
->m_nDerivedKeySize
;
701 // If the entry is already stored in the zip file in the format we
702 // want for this write...copy it raw
703 if ( !bUseNonSeekableAccess
704 && ( m_bRawStream
|| bTransportOwnEncrStreamAsRaw
705 || ( IsPackageMember() && !bToBeEncrypted
706 && ( ( aEntry
.nMethod
== DEFLATED
&& bToBeCompressed
)
707 || ( aEntry
.nMethod
== STORED
&& !bToBeCompressed
) ) ) ) )
709 // If it's a PackageMember, then it's an unbuffered stream and we need
710 // to get a new version of it as we can't seek backwards.
711 if ( IsPackageMember() )
713 xStream
= getRawData();
716 // Make sure that we actually _got_ a new one !
725 xStream
->skipBytes( m_nMagicalHackPos
);
727 ZipOutputStream::setEntry(pTempEntry
);
728 rZipOut
.writeLOC(pTempEntry
);
729 // the entry is provided to the ZipOutputStream that will delete it
730 pAutoTempEntry
.release();
732 uno::Sequence
< sal_Int8
> aSeq ( n_ConstBufferSize
);
737 nLength
= xStream
->readBytes( aSeq
, n_ConstBufferSize
);
738 if (nLength
!= n_ConstBufferSize
)
739 aSeq
.realloc(nLength
);
741 rZipOut
.rawWrite(aSeq
);
743 while ( nLength
== n_ConstBufferSize
);
745 rZipOut
.rawCloseEntry();
747 catch ( ZipException
& )
751 catch ( io::IOException
& )
758 // This stream is defenitly not a raw stream
760 // If nonseekable access is used the stream should be at the beginning and
761 // is useless after the storing. Thus if the storing fails the package should
762 // be thrown away ( as actually it is done currently )!
763 // To allow to reuse the package after the error, the optimization must be removed!
765 // If it's a PackageMember, then our previous reference held a 'raw' stream
766 // so we need to re-get it, unencrypted, uncompressed and positioned at the
767 // beginning of the stream
768 if ( IsPackageMember() )
770 xStream
= getInputStream();
773 // Make sure that we actually _got_ a new one !
779 if ( bToBeCompressed
)
781 pTempEntry
->nMethod
= DEFLATED
;
782 pTempEntry
->nCrc
= -1;
783 pTempEntry
->nCompressedSize
= pTempEntry
->nSize
= -1;
786 uno::Reference
< io::XSeekable
> xSeek(xStream
, uno::UNO_QUERY
);
787 // It's not worth to deflate jpegs to save ~1% in a slow process
788 // Unfortunately, does not work for streams protected by password
789 if (xSeek
.is() && msMediaType
.endsWith("/jpeg") && !m_bToBeEncrypted
)
791 ImplSetStoredData(*pTempEntry
, xStream
);
797 ZipOutputStream::setEntry(pTempEntry
);
798 // the entry is provided to the ZipOutputStream that will delete it
799 pAutoTempEntry
.release();
801 if (pTempEntry
->nMethod
== STORED
)
804 uno::Sequence
< sal_Int8
> aSeq(n_ConstBufferSize
);
805 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
808 nLength
= xStream
->readBytes(aSeq
, n_ConstBufferSize
);
809 if (nLength
!= n_ConstBufferSize
)
810 aSeq
.realloc(nLength
);
812 rZipOut
.rawWrite(aSeq
);
814 while ( nLength
== n_ConstBufferSize
);
815 rZipOut
.rawCloseEntry(bToBeEncrypted
);
819 bParallelDeflate
= true;
820 // Do not deflate small streams in a thread
821 if (xSeek
.is() && xSeek
->getLength() < 100000)
822 bParallelDeflate
= false;
824 if (bParallelDeflate
)
826 // Start a new thread deflating this zip entry
827 ZipOutputEntry
*pZipEntry
= new ZipOutputEntry(
828 m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
829 rZipOut
.addDeflatingThread( pZipEntry
, new DeflateThread(pZipEntry
, xStream
) );
833 rZipOut
.writeLOC(pTempEntry
, bToBeEncrypted
);
834 ZipOutputEntry
aZipEntry(rZipOut
.getStream(), m_xContext
, *pTempEntry
, this, bToBeEncrypted
);
835 deflateZipEntry(&aZipEntry
, xStream
);
836 rZipOut
.rawCloseEntry(bToBeEncrypted
);
840 catch ( ZipException
& )
844 catch ( io::IOException
& )
849 if ( bToBeEncrypted
)
851 ::rtl::Reference
< EncryptionData
> xEncData
= GetEncryptionData();
852 if ( !xEncData
.is() )
853 throw uno::RuntimeException();
855 aPropSet
[PKG_MNFST_DIGEST
].Name
= sDigestProperty
;
856 aPropSet
[PKG_MNFST_DIGEST
].Value
<<= m_xBaseEncryptionData
->m_aDigest
;
857 aPropSet
[PKG_MNFST_ENCALG
].Name
= sEncryptionAlgProperty
;
858 aPropSet
[PKG_MNFST_ENCALG
].Value
<<= xEncData
->m_nEncAlg
;
859 aPropSet
[PKG_MNFST_STARTALG
].Name
= sStartKeyAlgProperty
;
860 aPropSet
[PKG_MNFST_STARTALG
].Value
<<= xEncData
->m_nStartKeyGenID
;
861 aPropSet
[PKG_MNFST_DIGESTALG
].Name
= sDigestAlgProperty
;
862 aPropSet
[PKG_MNFST_DIGESTALG
].Value
<<= xEncData
->m_nCheckAlg
;
863 aPropSet
[PKG_MNFST_DERKEYSIZE
].Name
= sDerivedKeySizeProperty
;
864 aPropSet
[PKG_MNFST_DERKEYSIZE
].Value
<<= xEncData
->m_nDerivedKeySize
;
866 SetIsEncrypted ( true );
870 if (bSuccess
&& !bParallelDeflate
)
871 successfullyWritten(pTempEntry
);
873 if ( aPropSet
.getLength()
874 && ( m_nFormat
== embed::StorageFormats::PACKAGE
|| m_nFormat
== embed::StorageFormats::OFOPXML
) )
875 rManList
.push_back( aPropSet
);
880 void ZipPackageStream::successfullyWritten( ZipEntry
*pEntry
)
882 if ( !IsPackageMember() )
884 CloseOwnStreamIfAny();
885 SetPackageMember ( true );
890 // the raw stream was integrated and now behaves
891 // as usual encrypted stream
892 SetToBeEncrypted( true );
895 // Then copy it back afterwards...
896 ZipPackageFolder::copyZipEntry( aEntry
, *pEntry
);
898 // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
900 setSize( m_nOwnStreamOrigSize
);
902 aEntry
.nOffset
*= -1;
905 void ZipPackageStream::SetPackageMember( bool bNewValue
)
909 m_nStreamMode
= PACKAGE_STREAM_PACKAGEMEMBER
;
910 m_nMagicalHackPos
= 0;
911 m_nMagicalHackSize
= 0;
913 else if ( m_nStreamMode
== PACKAGE_STREAM_PACKAGEMEMBER
)
914 m_nStreamMode
= PACKAGE_STREAM_NOTSET
; // must be reset
918 void SAL_CALL
ZipPackageStream::setInputStream( const uno::Reference
< io::XInputStream
>& aStream
)
919 throw( RuntimeException
, std::exception
)
921 // if seekable access is required the wrapping will be done on demand
923 m_nImportedEncryptionAlgorithm
= 0;
924 m_bHasSeekable
= false;
925 SetPackageMember ( false );
927 m_nStreamMode
= PACKAGE_STREAM_DETECT
;
930 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getRawData()
931 throw( RuntimeException
)
935 if ( IsPackageMember() )
937 return m_rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
939 else if ( GetOwnSeekStream().is() )
941 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
944 return uno::Reference
< io::XInputStream
> ();
946 catch ( ZipException
& )//rException )
948 OSL_FAIL( "ZipException thrown" );//rException.Message);
949 return uno::Reference
< io::XInputStream
> ();
951 catch ( Exception
& )
953 OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
954 return uno::Reference
< io::XInputStream
> ();
958 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getInputStream()
959 throw( RuntimeException
, std::exception
)
963 if ( IsPackageMember() )
965 return m_rZipPackage
.getZipFile().getInputStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
967 else if ( GetOwnSeekStream().is() )
969 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
972 return uno::Reference
< io::XInputStream
> ();
974 catch ( ZipException
& )//rException )
976 OSL_FAIL( "ZipException thrown" );//rException.Message);
977 return uno::Reference
< io::XInputStream
> ();
979 catch ( Exception
&ex
)
981 OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
982 OSL_FAIL(OUStringToOString(ex
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
984 return uno::Reference
< io::XInputStream
> ();
988 // XDataSinkEncrSupport
989 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getDataStream()
990 throw ( packages::WrongPasswordException
, ZipException
,
992 RuntimeException
, std::exception
)
994 // There is no stream attached to this object
995 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
996 return uno::Reference
< io::XInputStream
>();
998 // this method can not be used together with old approach
999 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1000 throw packages::zip::ZipIOException(THROW_WHERE
);
1002 if ( IsPackageMember() )
1004 uno::Reference
< io::XInputStream
> xResult
;
1007 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1009 catch( const packages::WrongPasswordException
& )
1011 if ( m_rZipPackage
.GetStartKeyGenID() == xml::crypto::DigestID::SHA1
)
1015 // rhbz#1013844 / fdo#47482 workaround for the encrypted
1016 // OpenOffice.org 1.0 documents generated by Libreoffice <=
1017 // 3.6 with the new encryption format and using SHA256, but
1018 // missing a specified startkey of SHA256
1020 // force SHA256 and see if that works
1021 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA256
;
1022 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1025 catch (const packages::WrongPasswordException
&)
1027 // if that didn't work, restore to SHA1 and trundle through the *other* earlier
1029 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA1
;
1032 // workaround for the encrypted documents generated with the old OOo1.x bug.
1033 if ( !m_bUseWinEncoding
)
1035 xResult
= m_rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData( true ), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1036 m_bUseWinEncoding
= true;
1046 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1047 return ZipFile::StaticGetDataFromRawStream( m_xContext
, GetOwnSeekStream(), GetEncryptionData() );
1048 else if ( GetOwnSeekStream().is() )
1050 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
1053 return uno::Reference
< io::XInputStream
>();
1056 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getRawStream()
1057 throw ( packages::NoEncryptionException
,
1059 uno::RuntimeException
, std::exception
)
1061 // There is no stream attached to this object
1062 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1063 return uno::Reference
< io::XInputStream
>();
1065 // this method can not be used together with old approach
1066 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1067 throw packages::zip::ZipIOException(THROW_WHERE
);
1069 if ( IsPackageMember() )
1071 if ( !m_bIsEncrypted
|| !GetEncryptionData().is() )
1072 throw packages::NoEncryptionException(THROW_WHERE
);
1074 return m_rZipPackage
.getZipFile().getWrappedRawStream( aEntry
, GetEncryptionData(), msMediaType
, m_rZipPackage
.GetSharedMutexRef() );
1076 else if ( GetOwnSeekStream().is() )
1078 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1080 return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage
.GetSharedMutexRef() );
1082 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
&& m_bToBeEncrypted
)
1083 return TryToGetRawFromDataStream( true );
1086 throw packages::NoEncryptionException(THROW_WHERE
);
1089 void SAL_CALL
ZipPackageStream::setDataStream( const uno::Reference
< io::XInputStream
>& aStream
)
1090 throw ( io::IOException
,
1091 RuntimeException
, std::exception
)
1093 setInputStream( aStream
);
1094 m_nStreamMode
= PACKAGE_STREAM_DATA
;
1097 void SAL_CALL
ZipPackageStream::setRawStream( const uno::Reference
< io::XInputStream
>& aStream
)
1098 throw ( packages::EncryptionNotAllowedException
,
1099 packages::NoRawFormatException
,
1101 RuntimeException
, std::exception
)
1103 // wrap the stream in case it is not seekable
1104 uno::Reference
< io::XInputStream
> xNewStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream
, m_xContext
);
1105 uno::Reference
< io::XSeekable
> xSeek( xNewStream
, UNO_QUERY
);
1107 throw RuntimeException(THROW_WHERE
"The stream must support XSeekable!" );
1110 uno::Reference
< io::XInputStream
> xOldStream
= m_xStream
;
1111 m_xStream
= xNewStream
;
1112 if ( !ParsePackageRawStream() )
1114 m_xStream
= xOldStream
;
1115 throw packages::NoRawFormatException(THROW_WHERE
);
1118 // the raw stream MUST have seekable access
1119 m_bHasSeekable
= true;
1121 SetPackageMember ( false );
1123 m_nStreamMode
= PACKAGE_STREAM_RAW
;
1126 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getPlainRawStream()
1127 throw ( io::IOException
, packages::NoEncryptionException
,
1128 uno::RuntimeException
, std::exception
)
1130 // There is no stream attached to this object
1131 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
1132 return uno::Reference
< io::XInputStream
>();
1134 // this method can not be used together with old approach
1135 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
1136 throw packages::zip::ZipIOException(THROW_WHERE
);
1138 if ( IsPackageMember() )
1140 return m_rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), m_bIsEncrypted
, m_rZipPackage
.GetSharedMutexRef() );
1142 else if ( GetOwnSeekStream().is() )
1144 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
1146 // the header should not be returned here
1147 return GetRawEncrStreamNoHeaderCopy();
1149 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
)
1150 return TryToGetRawFromDataStream( false );
1153 return uno::Reference
< io::XInputStream
>();
1158 sal_Int64 SAL_CALL
ZipPackageStream::getSomething( const Sequence
< sal_Int8
>& aIdentifier
)
1159 throw( RuntimeException
, std::exception
)
1162 if ( aIdentifier
.getLength() == 16 &&
1163 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier
.getConstArray(), 16 ) )
1164 nMe
= reinterpret_cast < sal_Int64
> ( this );
1169 void SAL_CALL
ZipPackageStream::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
1170 throw( beans::UnknownPropertyException
, beans::PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
, std::exception
)
1172 if ( aPropertyName
== "MediaType" )
1174 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
&& m_rZipPackage
.getFormat() != embed::StorageFormats::OFOPXML
)
1175 throw beans::PropertyVetoException(THROW_WHERE
);
1177 if ( aValue
>>= msMediaType
)
1179 if ( !msMediaType
.isEmpty() )
1181 if ( msMediaType
.indexOf ( "text" ) != -1
1182 || msMediaType
== "application/vnd.sun.star.oleobject" )
1183 m_bToBeCompressed
= true;
1184 else if ( !m_bCompressedIsSetFromOutside
)
1185 m_bToBeCompressed
= false;
1189 throw IllegalArgumentException(THROW_WHERE
"MediaType must be a string!",
1190 uno::Reference
< XInterface
>(),
1194 else if ( aPropertyName
== "Size" )
1196 if ( !( aValue
>>= aEntry
.nSize
) )
1197 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Size property!",
1198 uno::Reference
< XInterface
>(),
1201 else if ( aPropertyName
== "Encrypted" )
1203 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1204 throw beans::PropertyVetoException(THROW_WHERE
);
1207 if ( aValue
>>= bEnc
)
1209 // In case of new raw stream, the stream must not be encrypted on storing
1210 if ( bEnc
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
1211 throw IllegalArgumentException(THROW_WHERE
"Raw stream can not be encrypted on storing",
1212 uno::Reference
< XInterface
>(),
1215 m_bToBeEncrypted
= bEnc
;
1216 if ( m_bToBeEncrypted
&& !m_xBaseEncryptionData
.is() )
1217 m_xBaseEncryptionData
= new BaseEncryptionData
;
1220 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Encrypted property!",
1221 uno::Reference
< XInterface
>(),
1225 else if ( aPropertyName
== ENCRYPTION_KEY_PROPERTY
)
1227 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1228 throw beans::PropertyVetoException(THROW_WHERE
);
1230 uno::Sequence
< sal_Int8
> aNewKey
;
1232 if ( !( aValue
>>= aNewKey
) )
1234 OUString sTempString
;
1235 if ( ( aValue
>>= sTempString
) )
1237 sal_Int32 nPathLength
= sTempString
.getLength();
1238 Sequence
< sal_Int8
> aSequence ( nPathLength
);
1239 sal_Int8
*pArray
= aSequence
.getArray();
1240 const sal_Unicode
*pChar
= sTempString
.getStr();
1241 for ( sal_Int16 i
= 0; i
< nPathLength
; i
++ )
1242 pArray
[i
] = static_cast < const sal_Int8
> ( pChar
[i
] );
1243 aNewKey
= aSequence
;
1246 throw IllegalArgumentException(THROW_WHERE
"Wrong type for EncryptionKey property!",
1247 uno::Reference
< XInterface
>(),
1251 if ( aNewKey
.getLength() )
1253 if ( !m_xBaseEncryptionData
.is() )
1254 m_xBaseEncryptionData
= new BaseEncryptionData
;
1256 m_aEncryptionKey
= aNewKey
;
1257 // In case of new raw stream, the stream must not be encrypted on storing
1258 m_bHaveOwnKey
= true;
1259 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
1260 m_bToBeEncrypted
= true;
1264 m_bHaveOwnKey
= false;
1265 m_aEncryptionKey
.realloc( 0 );
1268 m_aStorageEncryptionKeys
.realloc( 0 );
1270 else if ( aPropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
1272 if ( m_rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
1273 throw beans::PropertyVetoException(THROW_WHERE
);
1275 uno::Sequence
< beans::NamedValue
> aKeys
;
1276 if ( !( aValue
>>= aKeys
) )
1278 throw IllegalArgumentException(THROW_WHERE
"Wrong type for StorageEncryptionKeys property!",
1279 uno::Reference
< XInterface
>(),
1283 if ( aKeys
.getLength() )
1285 if ( !m_xBaseEncryptionData
.is() )
1286 m_xBaseEncryptionData
= new BaseEncryptionData
;
1288 m_aStorageEncryptionKeys
= aKeys
;
1290 // In case of new raw stream, the stream must not be encrypted on storing
1291 m_bHaveOwnKey
= true;
1292 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
1293 m_bToBeEncrypted
= true;
1297 m_bHaveOwnKey
= false;
1298 m_aStorageEncryptionKeys
.realloc( 0 );
1301 m_aEncryptionKey
.realloc( 0 );
1303 else if ( aPropertyName
== "Compressed" )
1305 bool bCompr
= false;
1307 if ( aValue
>>= bCompr
)
1309 // In case of new raw stream, the stream must not be encrypted on storing
1310 if ( bCompr
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
1311 throw IllegalArgumentException(THROW_WHERE
"Raw stream can not be encrypted on storing",
1312 uno::Reference
< XInterface
>(),
1315 m_bToBeCompressed
= bCompr
;
1316 m_bCompressedIsSetFromOutside
= true;
1319 throw IllegalArgumentException(THROW_WHERE
"Wrong type for Compressed property!",
1320 uno::Reference
< XInterface
>(),
1324 throw beans::UnknownPropertyException(THROW_WHERE
);
1327 Any SAL_CALL
ZipPackageStream::getPropertyValue( const OUString
& PropertyName
)
1328 throw( beans::UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
1331 if ( PropertyName
== "MediaType" )
1333 aAny
<<= msMediaType
;
1336 else if ( PropertyName
== "Size" )
1338 aAny
<<= aEntry
.nSize
;
1341 else if ( PropertyName
== "Encrypted" )
1343 aAny
<<= ((m_nStreamMode
== PACKAGE_STREAM_RAW
) || m_bToBeEncrypted
);
1346 else if ( PropertyName
== "WasEncrypted" )
1348 aAny
<<= m_bIsEncrypted
;
1351 else if ( PropertyName
== "Compressed" )
1353 aAny
<<= m_bToBeCompressed
;
1356 else if ( PropertyName
== ENCRYPTION_KEY_PROPERTY
)
1358 aAny
<<= m_aEncryptionKey
;
1361 else if ( PropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
1363 aAny
<<= m_aStorageEncryptionKeys
;
1367 throw beans::UnknownPropertyException(THROW_WHERE
);
1370 void ZipPackageStream::setSize ( const sal_Int64 nNewSize
)
1372 if ( aEntry
.nCompressedSize
!= nNewSize
)
1373 aEntry
.nMethod
= DEFLATED
;
1374 aEntry
.nSize
= nNewSize
;
1376 OUString
ZipPackageStream::getImplementationName()
1377 throw ( RuntimeException
, std::exception
)
1379 return OUString ("ZipPackageStream");
1382 Sequence
< OUString
> ZipPackageStream::getSupportedServiceNames()
1383 throw ( RuntimeException
, std::exception
)
1385 Sequence
< OUString
> aNames( 1 );
1386 aNames
[0] = "com.sun.star.packages.PackageStream";
1390 sal_Bool SAL_CALL
ZipPackageStream::supportsService( OUString
const & rServiceName
)
1391 throw ( RuntimeException
, std::exception
)
1393 return cppu::supportsService(this, rServiceName
);
1396 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */