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 // MARKER( update_precomp.py ): autogen include statement, do not remove
21 #include <com/sun/star/packages/zip/ZipConstants.hpp>
22 #include <com/sun/star/embed/StorageFormats.hpp>
23 #include <com/sun/star/packages/zip/ZipIOException.hpp>
24 #include <com/sun/star/io/TempFile.hpp>
25 #include <com/sun/star/io/XInputStream.hpp>
26 #include <com/sun/star/io/XOutputStream.hpp>
27 #include <com/sun/star/io/XStream.hpp>
28 #include <com/sun/star/io/XSeekable.hpp>
29 #include <com/sun/star/xml/crypto/DigestID.hpp>
30 #include <com/sun/star/xml/crypto/CipherID.hpp>
34 #include <ZipPackageStream.hxx>
35 #include <ZipPackage.hxx>
36 #include <ZipFile.hxx>
37 #include <EncryptedDataHeader.hxx>
38 #include <osl/diagnose.h>
39 #include "wrapstreamforshare.hxx"
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/seekableinput.hxx>
43 #include <comphelper/storagehelper.hxx>
45 #include <rtl/instance.hxx>
47 #include <PackageConstants.hxx>
49 using namespace com::sun::star::packages::zip::ZipConstants
;
50 using namespace com::sun::star::packages::zip
;
51 using namespace com::sun::star::uno
;
52 using namespace com::sun::star::lang
;
53 using namespace com::sun::star
;
56 namespace { struct lcl_CachedImplId
: public rtl::Static
< Sequence
< sal_Int8
>, lcl_CachedImplId
> {}; }
58 const ::com::sun::star::uno::Sequence
< sal_Int8
>& ZipPackageStream::static_getImplementationId()
60 return lcl_CachedImplId::get();
63 ZipPackageStream::ZipPackageStream ( ZipPackage
& rNewPackage
,
64 const uno::Reference
< XComponentContext
>& xContext
,
65 sal_Bool bAllowRemoveOnInsert
)
66 : m_xContext( xContext
)
67 , rZipPackage( rNewPackage
)
68 , bToBeCompressed ( sal_True
)
69 , bToBeEncrypted ( sal_False
)
70 , bHaveOwnKey ( sal_False
)
71 , bIsEncrypted ( sal_False
)
72 , m_nImportedStartKeyAlgorithm( 0 )
73 , m_nImportedEncryptionAlgorithm( 0 )
74 , m_nImportedChecksumAlgorithm( 0 )
75 , m_nImportedDerivedKeySize( 0 )
76 , m_nStreamMode( PACKAGE_STREAM_NOTSET
)
77 , m_nMagicalHackPos( 0 )
78 , m_nMagicalHackSize( 0 )
79 , m_bHasSeekable( sal_False
)
80 , m_bCompressedIsSetFromOutside( sal_False
)
81 , m_bFromManifest( sal_False
)
82 , m_bUseWinEncoding( false )
84 OSL_ENSURE( m_xContext
.is(), "No factory is provided to ZipPackageStream!\n" );
86 this->mbAllowRemoveOnInsert
= bAllowRemoveOnInsert
;
88 SetFolder ( sal_False
);
94 aEntry
.nCompressedSize
= -1;
98 aEntry
.nExtraLen
= -1;
100 Sequence
< sal_Int8
> &rCachedImplId
= lcl_CachedImplId::get();
101 if ( !rCachedImplId
.getLength() )
102 rCachedImplId
= getImplementationId();
105 ZipPackageStream::~ZipPackageStream( void )
109 void ZipPackageStream::setZipEntryOnLoading( const ZipEntry
&rInEntry
)
111 aEntry
.nVersion
= rInEntry
.nVersion
;
112 aEntry
.nFlag
= rInEntry
.nFlag
;
113 aEntry
.nMethod
= rInEntry
.nMethod
;
114 aEntry
.nTime
= rInEntry
.nTime
;
115 aEntry
.nCrc
= rInEntry
.nCrc
;
116 aEntry
.nCompressedSize
= rInEntry
.nCompressedSize
;
117 aEntry
.nSize
= rInEntry
.nSize
;
118 aEntry
.nOffset
= rInEntry
.nOffset
;
119 aEntry
.sPath
= rInEntry
.sPath
;
120 aEntry
.nPathLen
= rInEntry
.nPathLen
;
121 aEntry
.nExtraLen
= rInEntry
.nExtraLen
;
123 if ( aEntry
.nMethod
== STORED
)
124 bToBeCompressed
= sal_False
;
127 //--------------------------------------------------------------------------
128 void ZipPackageStream::CloseOwnStreamIfAny()
132 xStream
->closeInput();
133 xStream
= uno::Reference
< io::XInputStream
>();
134 m_bHasSeekable
= sal_False
;
138 //--------------------------------------------------------------------------
139 uno::Reference
< io::XInputStream
> ZipPackageStream::GetOwnSeekStream()
141 if ( !m_bHasSeekable
&& xStream
.is() )
143 // The package component requires that every stream either be FROM a package or it must support XSeekable!
144 // The only exception is a nonseekable stream that is provided only for storing, if such a stream
145 // is accessed before commit it MUST be wrapped.
146 // Wrap the stream in case it is not seekable
147 xStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( xStream
, m_xContext
);
148 uno::Reference
< io::XSeekable
> xSeek( xStream
, UNO_QUERY
);
150 throw RuntimeException( OSL_LOG_PREFIX
"The stream must support XSeekable!",
151 uno::Reference
< XInterface
>() );
153 m_bHasSeekable
= sal_True
;
159 //--------------------------------------------------------------------------
160 uno::Reference
< io::XInputStream
> ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
162 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
|| !GetOwnSeekStream().is() )
163 throw io::IOException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
165 if ( m_xBaseEncryptionData
.is() )
166 throw ZipIOException(OSL_LOG_PREFIX
"Encrypted stream without encryption data!\n",
167 uno::Reference
< XInterface
>() );
169 uno::Reference
< io::XSeekable
> xSeek( GetOwnSeekStream(), UNO_QUERY
);
171 throw ZipIOException(OSL_LOG_PREFIX
"The stream must be seekable!\n",
172 uno::Reference
< XInterface
>() );
175 xSeek
->seek( n_ConstHeaderSize
+ getInitialisationVector().getLength() +
176 getSalt().getLength() + getDigest().getLength() );
178 // create temporary stream
179 uno::Reference
< io::XTempFile
> xTempFile
= io::TempFile::create(m_xContext
);
180 uno::Reference
< io::XOutputStream
> xTempOut
= xTempFile
->getOutputStream();
181 uno::Reference
< io::XInputStream
> xTempIn
= xTempFile
->getInputStream();;
182 uno::Reference
< io::XSeekable
> xTempSeek( xTempOut
, UNO_QUERY_THROW
);
184 // copy the raw stream to the temporary file starting from the current position
185 ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut
);
186 xTempOut
->closeOutput();
187 xTempSeek
->seek( 0 );
192 //--------------------------------------------------------------------------
193 sal_Int32
ZipPackageStream::GetEncryptionAlgorithm() const
195 return m_nImportedEncryptionAlgorithm
? m_nImportedEncryptionAlgorithm
: rZipPackage
.GetEncAlgID();
198 //--------------------------------------------------------------------------
199 sal_Int32
ZipPackageStream::GetBlockSize() const
201 return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING
? 16 : 8;
204 //--------------------------------------------------------------------------
205 ::rtl::Reference
< EncryptionData
> ZipPackageStream::GetEncryptionData( bool bUseWinEncoding
)
207 ::rtl::Reference
< EncryptionData
> xResult
;
208 if ( m_xBaseEncryptionData
.is() )
209 xResult
= new EncryptionData(
210 *m_xBaseEncryptionData
,
211 GetEncryptionKey( bUseWinEncoding
),
212 GetEncryptionAlgorithm(),
213 m_nImportedChecksumAlgorithm
? m_nImportedChecksumAlgorithm
: rZipPackage
.GetChecksumAlgID(),
214 m_nImportedDerivedKeySize
? m_nImportedDerivedKeySize
: rZipPackage
.GetDefaultDerivedKeySize(),
215 GetStartKeyGenID() );
220 //--------------------------------------------------------------------------
221 uno::Sequence
< sal_Int8
> ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding
)
223 uno::Sequence
< sal_Int8
> aResult
;
224 sal_Int32 nKeyGenID
= GetStartKeyGenID();
225 bUseWinEncoding
= ( bUseWinEncoding
|| m_bUseWinEncoding
);
227 if ( bHaveOwnKey
&& m_aStorageEncryptionKeys
.getLength() )
229 OUString aNameToFind
;
230 if ( nKeyGenID
== xml::crypto::DigestID::SHA256
)
231 aNameToFind
= PACKAGE_ENCRYPTIONDATA_SHA256UTF8
;
232 else if ( nKeyGenID
== xml::crypto::DigestID::SHA1
)
234 aNameToFind
= bUseWinEncoding
? PACKAGE_ENCRYPTIONDATA_SHA1MS1252
: PACKAGE_ENCRYPTIONDATA_SHA1UTF8
;
237 throw uno::RuntimeException(OSL_LOG_PREFIX
"No expected key is provided!", uno::Reference
< uno::XInterface
>() );
239 for ( sal_Int32 nInd
= 0; nInd
< m_aStorageEncryptionKeys
.getLength(); nInd
++ )
240 if ( m_aStorageEncryptionKeys
[nInd
].Name
.equals( aNameToFind
) )
241 m_aStorageEncryptionKeys
[nInd
].Value
>>= aResult
;
243 // empty keys are not allowed here
244 // so it is not important whether there is no key, or the key is empty, it is an error
245 if ( !aResult
.getLength() )
246 throw uno::RuntimeException(OSL_LOG_PREFIX
"No expected key is provided!", uno::Reference
< uno::XInterface
>() );
249 aResult
= m_aEncryptionKey
;
251 if ( !aResult
.getLength() || !bHaveOwnKey
)
252 aResult
= rZipPackage
.GetEncryptionKey();
257 //--------------------------------------------------------------------------
258 sal_Int32
ZipPackageStream::GetStartKeyGenID()
260 // generally should all the streams use the same Start Key
261 // but if raw copy without password takes place, we should preserve the imported algorithm
262 return m_nImportedStartKeyAlgorithm
? m_nImportedStartKeyAlgorithm
: rZipPackage
.GetStartKeyGenID();
265 //--------------------------------------------------------------------------
266 uno::Reference
< io::XInputStream
> ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr
)
268 if ( m_nStreamMode
!= PACKAGE_STREAM_DATA
|| !GetOwnSeekStream().is() || ( bAddHeaderForEncr
&& !bToBeEncrypted
) )
269 throw packages::NoEncryptionException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
271 Sequence
< sal_Int8
> aKey
;
273 if ( bToBeEncrypted
)
275 aKey
= GetEncryptionKey();
276 if ( !aKey
.getLength() )
277 throw packages::NoEncryptionException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
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(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
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(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
302 xNewPackStream
->setDataStream( static_cast< io::XInputStream
* >(
303 new WrapStreamForShare( GetOwnSeekStream(), rZipPackage
.GetSharedMutexRef() ) ) );
305 uno::Reference
< XPropertySet
> xNewPSProps( xNewPackStream
, UNO_QUERY
);
306 if ( !xNewPSProps
.is() )
307 throw RuntimeException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
309 // copy all the properties of this stream to the new stream
310 xNewPSProps
->setPropertyValue("MediaType", makeAny( sMediaType
) );
311 xNewPSProps
->setPropertyValue("Compressed", makeAny( bToBeCompressed
) );
312 if ( bToBeEncrypted
)
314 xNewPSProps
->setPropertyValue(ENCRYPTION_KEY_PROPERTY
, makeAny( aKey
) );
315 xNewPSProps
->setPropertyValue("Encrypted", makeAny( sal_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(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
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(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
373 //--------------------------------------------------------------------------
374 sal_Bool
ZipPackageStream::ParsePackageRawStream()
376 OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
378 if ( !GetOwnSeekStream().is() )
381 sal_Bool bOk
= sal_False
;
383 ::rtl::Reference
< BaseEncryptionData
> xTempEncrData
;
384 sal_Int32 nMagHackSize
= 0;
385 Sequence
< sal_Int8
> aHeader ( 4 );
389 if ( GetOwnSeekStream()->readBytes ( aHeader
, 4 ) == 4 )
391 const sal_Int8
*pHeader
= aHeader
.getConstArray();
392 sal_uInt32 nHeader
= ( pHeader
[0] & 0xFF ) |
393 ( pHeader
[1] & 0xFF ) << 8 |
394 ( pHeader
[2] & 0xFF ) << 16 |
395 ( pHeader
[3] & 0xFF ) << 24;
396 if ( nHeader
== n_ConstHeader
)
398 // this is one of our god-awful, but extremely devious hacks, everyone cheer
399 xTempEncrData
= new BaseEncryptionData
;
402 sal_Int32 nEncAlgorithm
= 0;
403 sal_Int32 nChecksumAlgorithm
= 0;
404 sal_Int32 nDerivedKeySize
= 0;
405 sal_Int32 nStartKeyGenID
= 0;
406 if ( ZipFile::StaticFillData( xTempEncrData
, nEncAlgorithm
, nChecksumAlgorithm
, nDerivedKeySize
, nStartKeyGenID
, nMagHackSize
, aMediaType
, GetOwnSeekStream() ) )
408 // We'll want to skip the data we've just read, so calculate how much we just read
410 m_nMagicalHackPos
= n_ConstHeaderSize
+ xTempEncrData
->m_aSalt
.getLength()
411 + xTempEncrData
->m_aInitVector
.getLength()
412 + xTempEncrData
->m_aDigest
.getLength()
413 + aMediaType
.getLength() * sizeof( sal_Unicode
);
414 m_nImportedEncryptionAlgorithm
= nEncAlgorithm
;
415 m_nImportedChecksumAlgorithm
= nChecksumAlgorithm
;
416 m_nImportedDerivedKeySize
= nDerivedKeySize
;
417 m_nImportedStartKeyAlgorithm
= nStartKeyGenID
;
418 m_nMagicalHackSize
= nMagHackSize
;
419 sMediaType
= aMediaType
;
432 // the provided stream is not a raw stream
436 m_xBaseEncryptionData
= xTempEncrData
;
437 SetIsEncrypted ( sal_True
);
438 // it's already compressed and encrypted
439 bToBeEncrypted
= bToBeCompressed
= sal_False
;
444 void ZipPackageStream::SetPackageMember( sal_Bool bNewValue
)
448 m_nStreamMode
= PACKAGE_STREAM_PACKAGEMEMBER
;
449 m_nMagicalHackPos
= 0;
450 m_nMagicalHackSize
= 0;
452 else if ( m_nStreamMode
== PACKAGE_STREAM_PACKAGEMEMBER
)
453 m_nStreamMode
= PACKAGE_STREAM_NOTSET
; // must be reset
457 //--------------------------------------------------------------------------
458 void SAL_CALL
ZipPackageStream::setInputStream( const uno::Reference
< io::XInputStream
>& aStream
)
459 throw( RuntimeException
)
461 // if seekable access is required the wrapping will be done on demand
463 m_nImportedEncryptionAlgorithm
= 0;
464 m_bHasSeekable
= sal_False
;
465 SetPackageMember ( sal_False
);
467 m_nStreamMode
= PACKAGE_STREAM_DETECT
;
470 //--------------------------------------------------------------------------
471 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getRawData()
472 throw( RuntimeException
)
476 if ( IsPackageMember() )
478 return rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), bIsEncrypted
, rZipPackage
.GetSharedMutexRef() );
480 else if ( GetOwnSeekStream().is() )
482 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage
.GetSharedMutexRef() );
485 return uno::Reference
< io::XInputStream
> ();
487 catch ( ZipException
& )//rException )
489 OSL_FAIL( "ZipException thrown" );//rException.Message);
490 return uno::Reference
< io::XInputStream
> ();
492 catch ( Exception
& )
494 OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
495 return uno::Reference
< io::XInputStream
> ();
499 //--------------------------------------------------------------------------
500 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getInputStream()
501 throw( RuntimeException
)
505 if ( IsPackageMember() )
507 return rZipPackage
.getZipFile().getInputStream( aEntry
, GetEncryptionData(), bIsEncrypted
, rZipPackage
.GetSharedMutexRef() );
509 else if ( GetOwnSeekStream().is() )
511 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage
.GetSharedMutexRef() );
514 return uno::Reference
< io::XInputStream
> ();
516 catch ( ZipException
& )//rException )
518 OSL_FAIL( "ZipException thrown" );//rException.Message);
519 return uno::Reference
< io::XInputStream
> ();
521 catch ( Exception
&ex
)
523 OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
524 OSL_FAIL(OUStringToOString(ex
.Message
, RTL_TEXTENCODING_UTF8
).getStr());
526 return uno::Reference
< io::XInputStream
> ();
530 // XDataSinkEncrSupport
531 //--------------------------------------------------------------------------
532 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getDataStream()
533 throw ( packages::WrongPasswordException
,
537 // There is no stream attached to this object
538 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
539 return uno::Reference
< io::XInputStream
>();
541 // this method can not be used together with old approach
542 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
543 throw packages::zip::ZipIOException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
545 if ( IsPackageMember() )
547 uno::Reference
< io::XInputStream
> xResult
;
550 xResult
= rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(), bIsEncrypted
, rZipPackage
.GetSharedMutexRef() );
552 catch( const packages::WrongPasswordException
& )
554 if ( rZipPackage
.GetStartKeyGenID() == xml::crypto::DigestID::SHA1
)
558 // rhbz#1013844 / fdo#47482 workaround for the encrypted
559 // OpenOffice.org 1.0 documents generated by Libreoffice <=
560 // 3.6 with the new encryption format and using SHA256, but
561 // missing a specified startkey of SHA256
563 // force SHA256 and see if that works
564 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA256
;
565 xResult
= rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData(), bIsEncrypted
, rZipPackage
.GetSharedMutexRef() );
568 catch (const packages::WrongPasswordException
&)
570 // if that didn't work, restore to SHA1 and trundle through the *other* earlier
572 m_nImportedStartKeyAlgorithm
= xml::crypto::DigestID::SHA1
;
575 // workaround for the encrypted documents generated with the old OOo1.x bug.
576 if ( !m_bUseWinEncoding
)
578 xResult
= rZipPackage
.getZipFile().getDataStream( aEntry
, GetEncryptionData( true ), bIsEncrypted
, rZipPackage
.GetSharedMutexRef() );
579 m_bUseWinEncoding
= true;
589 else if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
590 return ZipFile::StaticGetDataFromRawStream( m_xContext
, GetOwnSeekStream(), GetEncryptionData() );
591 else if ( GetOwnSeekStream().is() )
593 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage
.GetSharedMutexRef() );
596 return uno::Reference
< io::XInputStream
>();
599 //--------------------------------------------------------------------------
600 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getRawStream()
601 throw ( packages::NoEncryptionException
,
603 uno::RuntimeException
)
605 // There is no stream attached to this object
606 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
607 return uno::Reference
< io::XInputStream
>();
609 // this method can not be used together with old approach
610 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
611 throw packages::zip::ZipIOException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
613 if ( IsPackageMember() )
615 if ( !bIsEncrypted
|| !GetEncryptionData().is() )
616 throw packages::NoEncryptionException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
618 return rZipPackage
.getZipFile().getWrappedRawStream( aEntry
, GetEncryptionData(), sMediaType
, rZipPackage
.GetSharedMutexRef() );
620 else if ( GetOwnSeekStream().is() )
622 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
624 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage
.GetSharedMutexRef() );
626 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
&& bToBeEncrypted
)
627 return TryToGetRawFromDataStream( sal_True
);
630 throw packages::NoEncryptionException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
634 //--------------------------------------------------------------------------
635 void SAL_CALL
ZipPackageStream::setDataStream( const uno::Reference
< io::XInputStream
>& aStream
)
636 throw ( io::IOException
,
639 setInputStream( aStream
);
640 m_nStreamMode
= PACKAGE_STREAM_DATA
;
643 //--------------------------------------------------------------------------
644 void SAL_CALL
ZipPackageStream::setRawStream( const uno::Reference
< io::XInputStream
>& aStream
)
645 throw ( packages::EncryptionNotAllowedException
,
646 packages::NoRawFormatException
,
650 // wrap the stream in case it is not seekable
651 uno::Reference
< io::XInputStream
> xNewStream
= ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream
, m_xContext
);
652 uno::Reference
< io::XSeekable
> xSeek( xNewStream
, UNO_QUERY
);
654 throw RuntimeException(OSL_LOG_PREFIX
"The stream must support XSeekable!",
655 uno::Reference
< XInterface
>() );
658 uno::Reference
< io::XInputStream
> xOldStream
= xStream
;
659 xStream
= xNewStream
;
660 if ( !ParsePackageRawStream() )
662 xStream
= xOldStream
;
663 throw packages::NoRawFormatException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
666 // the raw stream MUST have seekable access
667 m_bHasSeekable
= sal_True
;
669 SetPackageMember ( sal_False
);
671 m_nStreamMode
= PACKAGE_STREAM_RAW
;
674 //--------------------------------------------------------------------------
675 uno::Reference
< io::XInputStream
> SAL_CALL
ZipPackageStream::getPlainRawStream()
676 throw ( io::IOException
,
677 uno::RuntimeException
)
679 // There is no stream attached to this object
680 if ( m_nStreamMode
== PACKAGE_STREAM_NOTSET
)
681 return uno::Reference
< io::XInputStream
>();
683 // this method can not be used together with old approach
684 if ( m_nStreamMode
== PACKAGE_STREAM_DETECT
)
685 throw packages::zip::ZipIOException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
687 if ( IsPackageMember() )
689 return rZipPackage
.getZipFile().getRawData( aEntry
, GetEncryptionData(), bIsEncrypted
, rZipPackage
.GetSharedMutexRef() );
691 else if ( GetOwnSeekStream().is() )
693 if ( m_nStreamMode
== PACKAGE_STREAM_RAW
)
695 // the header should not be returned here
696 return GetRawEncrStreamNoHeaderCopy();
698 else if ( m_nStreamMode
== PACKAGE_STREAM_DATA
)
699 return TryToGetRawFromDataStream( sal_False
);
702 return uno::Reference
< io::XInputStream
>();
707 //--------------------------------------------------------------------------
708 sal_Int64 SAL_CALL
ZipPackageStream::getSomething( const Sequence
< sal_Int8
>& aIdentifier
)
709 throw( RuntimeException
)
712 if ( aIdentifier
.getLength() == 16 &&
713 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier
.getConstArray(), 16 ) )
714 nMe
= reinterpret_cast < sal_Int64
> ( this );
719 //--------------------------------------------------------------------------
720 void SAL_CALL
ZipPackageStream::setPropertyValue( const OUString
& aPropertyName
, const Any
& aValue
)
721 throw( beans::UnknownPropertyException
, beans::PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
723 if ( aPropertyName
== "MediaType" )
725 if ( rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
&& rZipPackage
.getFormat() != embed::StorageFormats::OFOPXML
)
726 throw beans::PropertyVetoException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
728 if ( aValue
>>= sMediaType
)
730 if ( !sMediaType
.isEmpty() )
732 if ( sMediaType
.indexOf ( "text" ) != -1
733 || sMediaType
== "application/vnd.sun.star.oleobject" )
734 bToBeCompressed
= sal_True
;
735 else if ( !m_bCompressedIsSetFromOutside
)
736 bToBeCompressed
= sal_False
;
740 throw IllegalArgumentException(OSL_LOG_PREFIX
"MediaType must be a string!\n",
741 uno::Reference
< XInterface
>(),
745 else if ( aPropertyName
== "Size" )
747 if ( !( aValue
>>= aEntry
.nSize
) )
748 throw IllegalArgumentException(OSL_LOG_PREFIX
"Wrong type for Size property!\n",
749 uno::Reference
< XInterface
>(),
752 else if ( aPropertyName
== "Encrypted" )
754 if ( rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
755 throw beans::PropertyVetoException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
757 sal_Bool bEnc
= sal_False
;
758 if ( aValue
>>= bEnc
)
760 // In case of new raw stream, the stream must not be encrypted on storing
761 if ( bEnc
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
762 throw IllegalArgumentException(OSL_LOG_PREFIX
"Raw stream can not be encrypted on storing",
763 uno::Reference
< XInterface
>(),
766 bToBeEncrypted
= bEnc
;
767 if ( bToBeEncrypted
&& !m_xBaseEncryptionData
.is() )
768 m_xBaseEncryptionData
= new BaseEncryptionData
;
771 throw IllegalArgumentException(OSL_LOG_PREFIX
"Wrong type for Encrypted property!\n",
772 uno::Reference
< XInterface
>(),
776 else if ( aPropertyName
== ENCRYPTION_KEY_PROPERTY
)
778 if ( rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
779 throw beans::PropertyVetoException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
781 uno::Sequence
< sal_Int8
> aNewKey
;
783 if ( !( aValue
>>= aNewKey
) )
785 OUString sTempString
;
786 if ( ( aValue
>>= sTempString
) )
788 sal_Int32 nPathLength
= sTempString
.getLength();
789 Sequence
< sal_Int8
> aSequence ( nPathLength
);
790 sal_Int8
*pArray
= aSequence
.getArray();
791 const sal_Unicode
*pChar
= sTempString
.getStr();
792 for ( sal_Int16 i
= 0; i
< nPathLength
; i
++ )
793 pArray
[i
] = static_cast < const sal_Int8
> ( pChar
[i
] );
797 throw IllegalArgumentException(OSL_LOG_PREFIX
"Wrong type for EncryptionKey property!\n",
798 uno::Reference
< XInterface
>(),
802 if ( aNewKey
.getLength() )
804 if ( !m_xBaseEncryptionData
.is() )
805 m_xBaseEncryptionData
= new BaseEncryptionData
;
807 m_aEncryptionKey
= aNewKey
;
808 // In case of new raw stream, the stream must not be encrypted on storing
809 bHaveOwnKey
= sal_True
;
810 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
811 bToBeEncrypted
= sal_True
;
815 bHaveOwnKey
= sal_False
;
816 m_aEncryptionKey
.realloc( 0 );
819 m_aStorageEncryptionKeys
.realloc( 0 );
821 else if ( aPropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
823 if ( rZipPackage
.getFormat() != embed::StorageFormats::PACKAGE
)
824 throw beans::PropertyVetoException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
826 uno::Sequence
< beans::NamedValue
> aKeys
;
827 if ( !( aValue
>>= aKeys
) )
829 throw IllegalArgumentException(OSL_LOG_PREFIX
"Wrong type for StorageEncryptionKeys property!\n",
830 uno::Reference
< XInterface
>(),
834 if ( aKeys
.getLength() )
836 if ( !m_xBaseEncryptionData
.is() )
837 m_xBaseEncryptionData
= new BaseEncryptionData
;
839 m_aStorageEncryptionKeys
= aKeys
;
841 // In case of new raw stream, the stream must not be encrypted on storing
842 bHaveOwnKey
= sal_True
;
843 if ( m_nStreamMode
!= PACKAGE_STREAM_RAW
)
844 bToBeEncrypted
= sal_True
;
848 bHaveOwnKey
= sal_False
;
849 m_aStorageEncryptionKeys
.realloc( 0 );
852 m_aEncryptionKey
.realloc( 0 );
854 else if ( aPropertyName
== "Compressed" )
856 sal_Bool bCompr
= sal_False
;
858 if ( aValue
>>= bCompr
)
860 // In case of new raw stream, the stream must not be encrypted on storing
861 if ( bCompr
&& m_nStreamMode
== PACKAGE_STREAM_RAW
)
862 throw IllegalArgumentException(OSL_LOG_PREFIX
"Raw stream can not be encrypted on storing",
863 uno::Reference
< XInterface
>(),
866 bToBeCompressed
= bCompr
;
867 m_bCompressedIsSetFromOutside
= sal_True
;
870 throw IllegalArgumentException(OSL_LOG_PREFIX
"Wrong type for Compressed property!\n",
871 uno::Reference
< XInterface
>(),
875 throw beans::UnknownPropertyException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
878 //--------------------------------------------------------------------------
879 Any SAL_CALL
ZipPackageStream::getPropertyValue( const OUString
& PropertyName
)
880 throw( beans::UnknownPropertyException
, WrappedTargetException
, RuntimeException
)
883 if ( PropertyName
== "MediaType" )
888 else if ( PropertyName
== "Size" )
890 aAny
<<= aEntry
.nSize
;
893 else if ( PropertyName
== "Encrypted" )
895 aAny
<<= ((m_nStreamMode
== PACKAGE_STREAM_RAW
) ? sal_True
: bToBeEncrypted
);
898 else if ( PropertyName
== "WasEncrypted" )
900 aAny
<<= bIsEncrypted
;
903 else if ( PropertyName
== "Compressed" )
905 aAny
<<= bToBeCompressed
;
908 else if ( PropertyName
== ENCRYPTION_KEY_PROPERTY
)
910 aAny
<<= m_aEncryptionKey
;
913 else if ( PropertyName
== STORAGE_ENCRYPTION_KEYS_PROPERTY
)
915 aAny
<<= m_aStorageEncryptionKeys
;
919 throw beans::UnknownPropertyException(OSL_LOG_PREFIX
, uno::Reference
< uno::XInterface
>() );
922 //--------------------------------------------------------------------------
923 void ZipPackageStream::setSize ( const sal_Int64 nNewSize
)
925 if ( aEntry
.nCompressedSize
!= nNewSize
)
926 aEntry
.nMethod
= DEFLATED
;
927 aEntry
.nSize
= nNewSize
;
929 //--------------------------------------------------------------------------
930 OUString
ZipPackageStream::getImplementationName()
931 throw ( RuntimeException
)
933 return OUString ("ZipPackageStream");
936 //--------------------------------------------------------------------------
937 Sequence
< OUString
> ZipPackageStream::getSupportedServiceNames()
938 throw ( RuntimeException
)
940 Sequence
< OUString
> aNames( 1 );
941 aNames
[0] = "com.sun.star.packages.PackageStream";
944 //--------------------------------------------------------------------------
945 sal_Bool SAL_CALL
ZipPackageStream::supportsService( OUString
const & rServiceName
)
946 throw ( RuntimeException
)
948 return rServiceName
== getSupportedServiceNames()[0];
951 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */