Bump version to 5.0-14
[LibreOffice.git] / package / source / zippackage / ZipPackageStream.cxx
blob76d8efc18d8901d4663003c71fca3556ebf6a921
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
34 #include <string.h>
36 #include <CRC32.hxx>
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;
63 using namespace cppu;
65 #if OSL_DEBUG_LEVEL > 0
66 #define THROW_WHERE SAL_WHERE
67 #else
68 #define THROW_WHERE ""
69 #endif
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,
80 sal_Int32 nFormat,
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;
102 m_nFormat = nFormat;
103 mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
104 SetFolder ( false );
105 aEntry.nVersion = -1;
106 aEntry.nFlag = 0;
107 aEntry.nMethod = -1;
108 aEntry.nTime = -1;
109 aEntry.nCrc = -1;
110 aEntry.nCompressedSize = -1;
111 aEntry.nSize = -1;
112 aEntry.nOffset = -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 );
159 if ( !xSeek.is() )
160 throw RuntimeException( THROW_WHERE "The stream must support XSeekable!" );
162 m_bHasSeekable = true;
165 return m_xStream;
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 );
177 if ( !xSeek.is() )
178 throw ZipIOException(THROW_WHERE "The stream must be seekable!" );
180 // skip header
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 );
195 return xTempIn;
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() );
220 return xResult;
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);
238 else
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!" );
250 else
251 aResult = m_aEncryptionKey;
253 if ( !aResult.getLength() || !m_bHaveOwnKey )
254 aResult = m_rZipPackage.GetEncryptionKey();
256 return aResult;
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("/");
321 aRoot >>= xTunnel;
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();
336 else
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
360 return xTempIn;
362 catch ( RuntimeException& )
364 throw;
366 catch ( Exception& )
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() )
378 return false;
380 bool bOk = false;
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;
400 OUString aMediaType;
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
408 // and remember it
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;
420 bOk = true;
425 catch( Exception& )
429 if ( !bOk )
431 // the provided stream is not a raw stream
432 return false;
435 m_xBaseEncryptionData = xTempEncrData;
436 SetIsEncrypted ( true );
437 // it's already compressed and encrypted
438 m_bToBeEncrypted = m_bToBeCompressed = false;
440 return true;
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;
465 public:
466 DeflateThread( ZipOutputEntry *pEntry,
467 const uno::Reference< io::XInputStream >& xInStream )
468 : mpEntry(pEntry)
469 , mxInStream(xInStream)
472 private:
473 virtual void doWork() SAL_OVERRIDE
477 mpEntry->createBufferFile();
478 deflateZipEntry(mpEntry, mxInStream);
479 mxInStream.clear();
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
494 // write them !
495 CRC32 aCRC32;
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 )
553 m_bRawStream = true;
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
569 xStream = m_xStream;
570 uno::Reference < io::XSeekable > xSeek ( xStream, uno::UNO_QUERY );
572 bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
575 if ( !bUseNonSeekableAccess )
577 xStream = getRawData();
579 if ( !xStream.is() )
581 OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
582 bSuccess = false;
583 return bSuccess;
586 uno::Reference < io::XSeekable > xSeek ( xStream, uno::UNO_QUERY );
589 if ( xSeek.is() )
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;
609 xSeek->seek ( 0 );
611 else
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;
632 else
634 bSuccess = false;
635 return bSuccess;
639 catch ( uno::Exception& )
641 bSuccess = false;
642 return bSuccess;
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 );
661 setSalt ( aSalt );
662 setIterationCount ( nIterationCount );
665 // last property is digest, which is inserted later if we didn't have
666 // a magic header
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();
714 if ( !xStream.is() )
716 // Make sure that we actually _got_ a new one !
717 bSuccess = false;
718 return bSuccess;
724 if ( m_bRawStream )
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 );
733 sal_Int32 nLength;
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& )
749 bSuccess = false;
751 catch ( io::IOException& )
753 bSuccess = false;
756 else
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();
771 if ( !xStream.is() )
773 // Make sure that we actually _got_ a new one !
774 bSuccess = false;
775 return bSuccess;
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);
792 xSeek->seek(0);
797 ZipOutputStream::setEntry(pTempEntry);
798 // the entry is provided to the ZipOutputStream that will delete it
799 pAutoTempEntry.release();
801 if (pTempEntry->nMethod == STORED)
803 sal_Int32 nLength;
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);
817 else
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) );
831 else
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& )
842 bSuccess = false;
844 catch ( io::IOException& )
846 bSuccess = false;
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 );
877 return bSuccess;
880 void ZipPackageStream::successfullyWritten( ZipEntry *pEntry )
882 if ( !IsPackageMember() )
884 CloseOwnStreamIfAny();
885 SetPackageMember ( true );
888 if ( m_bRawStream )
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 )
899 if ( IsEncrypted() )
900 setSize( m_nOwnStreamOrigSize );
902 aEntry.nOffset *= -1;
905 void ZipPackageStream::SetPackageMember( bool bNewValue )
907 if ( 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
917 // XActiveDataSink
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
922 m_xStream = aStream;
923 m_nImportedEncryptionAlgorithm = 0;
924 m_bHasSeekable = false;
925 SetPackageMember ( false );
926 aEntry.nTime = -1;
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() );
943 else
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() );
971 else
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());
983 (void)ex;
984 return uno::Reference < io::XInputStream > ();
988 // XDataSinkEncrSupport
989 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
990 throw ( packages::WrongPasswordException, ZipException,
991 io::IOException,
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() );
1023 return xResult;
1025 catch (const packages::WrongPasswordException&)
1027 // if that didn't work, restore to SHA1 and trundle through the *other* earlier
1028 // bug fix
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;
1038 else
1039 throw;
1041 else
1042 throw;
1044 return xResult;
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() );
1052 else
1053 return uno::Reference< io::XInputStream >();
1056 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
1057 throw ( packages::NoEncryptionException,
1058 io::IOException,
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,
1100 io::IOException,
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 );
1106 if ( !xSeek.is() )
1107 throw RuntimeException(THROW_WHERE "The stream must support XSeekable!" );
1109 xSeek->seek( 0 );
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 );
1122 aEntry.nTime = -1;
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 >();
1156 // XUnoTunnel
1158 sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
1159 throw( RuntimeException, std::exception )
1161 sal_Int64 nMe = 0;
1162 if ( aIdentifier.getLength() == 16 &&
1163 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
1164 nMe = reinterpret_cast < sal_Int64 > ( this );
1165 return nMe;
1168 // XPropertySet
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;
1188 else
1189 throw IllegalArgumentException(THROW_WHERE "MediaType must be a string!",
1190 uno::Reference< XInterface >(),
1191 2 );
1194 else if ( aPropertyName == "Size" )
1196 if ( !( aValue >>= aEntry.nSize ) )
1197 throw IllegalArgumentException(THROW_WHERE "Wrong type for Size property!",
1198 uno::Reference< XInterface >(),
1199 2 );
1201 else if ( aPropertyName == "Encrypted" )
1203 if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
1204 throw beans::PropertyVetoException(THROW_WHERE );
1206 bool bEnc = false;
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 >(),
1213 2 );
1215 m_bToBeEncrypted = bEnc;
1216 if ( m_bToBeEncrypted && !m_xBaseEncryptionData.is() )
1217 m_xBaseEncryptionData = new BaseEncryptionData;
1219 else
1220 throw IllegalArgumentException(THROW_WHERE "Wrong type for Encrypted property!",
1221 uno::Reference< XInterface >(),
1222 2 );
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;
1245 else
1246 throw IllegalArgumentException(THROW_WHERE "Wrong type for EncryptionKey property!",
1247 uno::Reference< XInterface >(),
1248 2 );
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;
1262 else
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 >(),
1280 2 );
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;
1295 else
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 >(),
1313 2 );
1315 m_bToBeCompressed = bCompr;
1316 m_bCompressedIsSetFromOutside = true;
1318 else
1319 throw IllegalArgumentException(THROW_WHERE "Wrong type for Compressed property!",
1320 uno::Reference< XInterface >(),
1321 2 );
1323 else
1324 throw beans::UnknownPropertyException(THROW_WHERE );
1327 Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
1328 throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
1330 Any aAny;
1331 if ( PropertyName == "MediaType" )
1333 aAny <<= msMediaType;
1334 return aAny;
1336 else if ( PropertyName == "Size" )
1338 aAny <<= aEntry.nSize;
1339 return aAny;
1341 else if ( PropertyName == "Encrypted" )
1343 aAny <<= ((m_nStreamMode == PACKAGE_STREAM_RAW) || m_bToBeEncrypted);
1344 return aAny;
1346 else if ( PropertyName == "WasEncrypted" )
1348 aAny <<= m_bIsEncrypted;
1349 return aAny;
1351 else if ( PropertyName == "Compressed" )
1353 aAny <<= m_bToBeCompressed;
1354 return aAny;
1356 else if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
1358 aAny <<= m_aEncryptionKey;
1359 return aAny;
1361 else if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
1363 aAny <<= m_aStorageEncryptionKeys;
1364 return aAny;
1366 else
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";
1387 return aNames;
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: */