1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * ( a copy is included in the LICENSE file that accompanied this code ).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER( update_precomp.py ): autogen include statement, do not remove
29 #include "precompiled_package.hxx"
30 #include <com/sun/star/packages/zip/ZipConstants.hpp>
31 #include <com/sun/star/embed/StorageFormats.hpp>
32 #include <com/sun/star/packages/zip/ZipIOException.hpp>
33 #include <com/sun/star/io/XInputStream.hpp>
34 #include <com/sun/star/io/XOutputStream.hpp>
35 #include <com/sun/star/io/XStream.hpp>
36 #include <com/sun/star/io/XSeekable.hpp>
37 #include <com/sun/star/xml/crypto/DigestID.hpp>
38 #include <com/sun/star/xml/crypto/CipherID.hpp>
39 
40 
41 #include <ZipPackageStream.hxx>
42 #include <ZipPackage.hxx>
43 #include <ZipFile.hxx>
44 #include <EncryptedDataHeader.hxx>
45 #include <vos/diagnose.hxx>
46 #include "wrapstreamforshare.hxx"
47 
48 #include <comphelper/seekableinput.hxx>
49 #include <comphelper/storagehelper.hxx>
50 
51 #include <rtl/instance.hxx>
52 
53 #include <PackageConstants.hxx>
54 
55 using namespace com::sun::star::packages::zip::ZipConstants;
56 using namespace com::sun::star::packages::zip;
57 using namespace com::sun::star::uno;
58 using namespace com::sun::star::lang;
59 using namespace com::sun::star;
60 using namespace cppu;
61 using namespace rtl;
62 
63 namespace { struct lcl_CachedImplId : public rtl::Static< Sequence < sal_Int8 >, lcl_CachedImplId > {}; }
64 
65 const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageStream::static_getImplementationId()
66 {
67     return lcl_CachedImplId::get();
68 }
69 
70 ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
71 									const uno::Reference< XMultiServiceFactory >& xFactory,
72 									sal_Bool bAllowRemoveOnInsert )
73 : m_xFactory( xFactory )
74 , rZipPackage( rNewPackage )
75 , bToBeCompressed ( sal_True )
76 , bToBeEncrypted ( sal_False )
77 , bHaveOwnKey ( sal_False )
78 , bIsEncrypted ( sal_False )
79 , m_nImportedStartKeyAlgorithm( 0 )
80 , m_nImportedEncryptionAlgorithm( 0 )
81 , m_nImportedChecksumAlgorithm( 0 )
82 , m_nImportedDerivedKeySize( 0 )
83 , m_nStreamMode( PACKAGE_STREAM_NOTSET )
84 , m_nMagicalHackPos( 0 )
85 , m_nMagicalHackSize( 0 )
86 , m_bHasSeekable( sal_False )
87 , m_bCompressedIsSetFromOutside( sal_False )
88 , m_bFromManifest( sal_False )
89 , m_bUseWinEncoding( false )
90 {
91 	OSL_ENSURE( m_xFactory.is(), "No factory is provided to ZipPackageStream!\n" );
92 
93 	this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
94 
95 	SetFolder ( sal_False );
96 	aEntry.nVersion		= -1;
97 	aEntry.nFlag		= 0;
98 	aEntry.nMethod		= -1;
99 	aEntry.nTime		= -1;
100 	aEntry.nCrc			= -1;
101 	aEntry.nCompressedSize	= -1;
102 	aEntry.nSize		= -1;
103 	aEntry.nOffset		= -1;
104 	aEntry.nPathLen		= -1;
105 	aEntry.nExtraLen	= -1;
106 
107 	Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
108 	if ( !rCachedImplId.getLength() )
109 	    rCachedImplId = getImplementationId();
110 }
111 
112 ZipPackageStream::~ZipPackageStream( void )
113 {
114 }
115 
116 void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
117 {
118 	aEntry.nVersion = rInEntry.nVersion;
119 	aEntry.nFlag = rInEntry.nFlag;
120 	aEntry.nMethod = rInEntry.nMethod;
121 	aEntry.nTime = rInEntry.nTime;
122 	aEntry.nCrc = rInEntry.nCrc;
123 	aEntry.nCompressedSize = rInEntry.nCompressedSize;
124 	aEntry.nSize = rInEntry.nSize;
125 	aEntry.nOffset = rInEntry.nOffset;
126 	aEntry.sPath = rInEntry.sPath;
127 	aEntry.nPathLen = rInEntry.nPathLen;
128 	aEntry.nExtraLen = rInEntry.nExtraLen;
129 
130 	if ( aEntry.nMethod == STORED )
131 		bToBeCompressed = sal_False;
132 }
133 
134 //--------------------------------------------------------------------------
135 void ZipPackageStream::CloseOwnStreamIfAny()
136 {
137 	if ( xStream.is() )
138 	{
139 		xStream->closeInput();
140 		xStream = uno::Reference< io::XInputStream >();
141 		m_bHasSeekable = sal_False;
142 	}
143 }
144 
145 //--------------------------------------------------------------------------
146 uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream()
147 {
148 	if ( !m_bHasSeekable && xStream.is() )
149 	{
150 		// The package component requires that every stream either be FROM a package or it must support XSeekable!
151 		// The only exception is a nonseekable stream that is provided only for storing, if such a stream
152 		// is accessed before commit it MUST be wrapped.
153 		// Wrap the stream in case it is not seekable
154 		xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( xStream, m_xFactory );
155 		uno::Reference< io::XSeekable > xSeek( xStream, UNO_QUERY );
156 		if ( !xSeek.is() )
157 			throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must support XSeekable!" ) ),
158 									uno::Reference< XInterface >() );
159 
160 		m_bHasSeekable = sal_True;
161 	}
162 
163 	return xStream;
164 }
165 
166 //--------------------------------------------------------------------------
167 uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
168 {
169 	if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() )
170 		throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
171 
172 	if ( m_xBaseEncryptionData.is() )
173 		throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Encrypted stream without encryption data!\n" ) ),
174 							uno::Reference< XInterface >() );
175 
176 	uno::Reference< io::XSeekable > xSeek( GetOwnSeekStream(), UNO_QUERY );
177 	if ( !xSeek.is() )
178 		throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must be seekable!\n" ) ),
179 							uno::Reference< XInterface >() );
180 
181 	// skip header
182 	xSeek->seek( n_ConstHeaderSize + getInitialisationVector().getLength() +
183 					getSalt().getLength() + getDigest().getLength() );
184 
185 	// create temporary stream
186 	uno::Reference < io::XOutputStream > xTempOut(
187 						m_xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
188 						uno::UNO_QUERY );
189 	uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY );
190 	uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY );
191 	if ( !xTempOut.is() || !xTempIn.is() || !xTempSeek.is() )
192 		throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
193 
194 	// copy the raw stream to the temporary file starting from the current position
195 	::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
196 	xTempOut->closeOutput();
197 	xTempSeek->seek( 0 );
198 
199 	return xTempIn;
200 }
201 
202 //--------------------------------------------------------------------------
203 sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
204 {
205     return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : rZipPackage.GetEncAlgID();
206 }
207 
208 //--------------------------------------------------------------------------
209 sal_Int32 ZipPackageStream::GetBlockSize() const
210 {
211     return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
212 }
213 
214 //--------------------------------------------------------------------------
215 ::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding )
216 {
217     ::rtl::Reference< EncryptionData > xResult;
218     if ( m_xBaseEncryptionData.is() )
219         xResult = new EncryptionData(
220             *m_xBaseEncryptionData,
221             GetEncryptionKey( bUseWinEncoding ),
222             GetEncryptionAlgorithm(),
223             m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : rZipPackage.GetChecksumAlgID(),
224             m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : rZipPackage.GetDefaultDerivedKeySize(),
225             GetStartKeyGenID() );
226 
227     return xResult;
228 }
229 
230 //--------------------------------------------------------------------------
231 void ZipPackageStream::SetBaseEncryptionData( const ::rtl::Reference< BaseEncryptionData >& xData )
232 {
233     m_xBaseEncryptionData = xData;
234 }
235 
236 //--------------------------------------------------------------------------
237 uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding )
238 {
239     uno::Sequence< sal_Int8 > aResult;
240     sal_Int32 nKeyGenID = GetStartKeyGenID();
241     bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding );
242 
243     if ( bHaveOwnKey && m_aStorageEncryptionKeys.getLength() )
244     {
245         ::rtl::OUString aNameToFind;
246         if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
247             aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
248         else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
249         {
250             aNameToFind = bUseWinEncoding ? PACKAGE_ENCRYPTIONDATA_SHA1MS1252 : PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
251         }
252         else
253             throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() );
254 
255         for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
256             if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) )
257                 m_aStorageEncryptionKeys[nInd].Value >>= aResult;
258 
259         // empty keys are not allowed here
260         // so it is not important whether there is no key, or the key is empty, it is an error
261         if ( !aResult.getLength() )
262             throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() );
263     }
264     else
265         aResult = m_aEncryptionKey;
266 
267     if ( !aResult.getLength() || !bHaveOwnKey )
268         aResult = rZipPackage.GetEncryptionKey();
269 
270     return aResult;
271 }
272 
273 //--------------------------------------------------------------------------
274 sal_Int32 ZipPackageStream::GetStartKeyGenID()
275 {
276     // generally should all the streams use the same Start Key
277     // but if raw copy without password takes place, we should preserve the imported algorithm
278     return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : rZipPackage.GetStartKeyGenID();
279 }
280 
281 //--------------------------------------------------------------------------
282 uno::Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr )
283 {
284 	if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || ( bAddHeaderForEncr && !bToBeEncrypted ) )
285 		throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
286 
287 	Sequence< sal_Int8 > aKey;
288 
289 	if ( bToBeEncrypted )
290 	{
291 		aKey = GetEncryptionKey();
292 		if ( !aKey.getLength() )
293 			throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
294 	}
295 
296 	try
297 	{
298 		// create temporary file
299 		uno::Reference < io::XStream > xTempStream(
300 							m_xFactory->createInstance ( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
301 							uno::UNO_QUERY );
302 		if ( !xTempStream.is() )
303 			throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
304 
305 		// create a package based on it
306 		ZipPackage* pPackage = new ZipPackage( m_xFactory );
307 		uno::Reference< XSingleServiceFactory > xPackageAsFactory( static_cast< XSingleServiceFactory* >( pPackage ) );
308 		if ( !xPackageAsFactory.is() )
309 			throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
310 
311 		Sequence< Any > aArgs( 1 );
312 		aArgs[0] <<= xTempStream;
313 		pPackage->initialize( aArgs );
314 
315 		// create a new package stream
316 		uno::Reference< XDataSinkEncrSupport > xNewPackStream( xPackageAsFactory->createInstance(), UNO_QUERY );
317 		if ( !xNewPackStream.is() )
318 			throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
319 
320 		xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
321 													new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() ) ) );
322 
323 		uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
324 		if ( !xNewPSProps.is() )
325 			throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
326 
327 		// copy all the properties of this stream to the new stream
328 		xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ), makeAny( sMediaType ) );
329 		xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Compressed" ) ), makeAny( bToBeCompressed ) );
330 		if ( bToBeEncrypted )
331 		{
332 			xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ), makeAny( aKey ) );
333 			xNewPSProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Encrypted" ) ), makeAny( sal_True ) );
334 		}
335 
336 		// insert a new stream in the package
337 		uno::Reference< XUnoTunnel > xTunnel;
338 		Any aRoot = pPackage->getByHierarchicalName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) );
339 		aRoot >>= xTunnel;
340 		uno::Reference< container::XNameContainer > xRootNameContainer( xTunnel, UNO_QUERY );
341 		if ( !xRootNameContainer.is() )
342 			throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
343 
344 		uno::Reference< XUnoTunnel > xNPSTunnel( xNewPackStream, UNO_QUERY );
345 		xRootNameContainer->insertByName( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "dummy" ) ), makeAny( xNPSTunnel ) );
346 
347 		// commit the temporary package
348 		pPackage->commitChanges();
349 
350 		// get raw stream from the temporary package
351 		uno::Reference< io::XInputStream > xInRaw;
352 		if ( bAddHeaderForEncr )
353 			xInRaw = xNewPackStream->getRawStream();
354 		else
355 			xInRaw = xNewPackStream->getPlainRawStream();
356 
357 		// create another temporary file
358 		uno::Reference < io::XOutputStream > xTempOut(
359 							m_xFactory->createInstance ( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.TempFile" ) ) ),
360 							uno::UNO_QUERY );
361 		uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY );
362 		uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY );
363 		if ( !xTempOut.is() || !xTempIn.is() || !xTempSeek.is() )
364 			throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
365 
366 		// copy the raw stream to the temporary file
367 		::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
368 		xTempOut->closeOutput();
369 		xTempSeek->seek( 0 );
370 
371 		// close raw stream, package stream and folder
372 		xInRaw = uno::Reference< io::XInputStream >();
373 		xNewPSProps = uno::Reference< XPropertySet >();
374 		xNPSTunnel = uno::Reference< XUnoTunnel >();
375 		xNewPackStream = uno::Reference< XDataSinkEncrSupport >();
376 		xTunnel = uno::Reference< XUnoTunnel >();
377 		xRootNameContainer = uno::Reference< container::XNameContainer >();
378 
379 		// return the stream representing the first temporary file
380 		return xTempIn;
381 	}
382 	catch ( RuntimeException& )
383 	{
384 		throw;
385 	}
386 	catch ( Exception& )
387 	{
388 	}
389 
390 	throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
391 }
392 
393 //--------------------------------------------------------------------------
394 sal_Bool ZipPackageStream::ParsePackageRawStream()
395 {
396 	OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
397 
398 	if ( !GetOwnSeekStream().is() )
399 		return sal_False;
400 
401 	sal_Bool bOk = sal_False;
402 
403 	::rtl::Reference< BaseEncryptionData > xTempEncrData;
404 	sal_Int32 nMagHackSize = 0;
405 	Sequence < sal_Int8 > aHeader ( 4 );
406 
407 	try
408 	{
409 		if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
410 		{
411 			const sal_Int8 *pHeader = aHeader.getConstArray();
412 			sal_uInt32 nHeader = ( pHeader [0] & 0xFF )       |
413 							 	( pHeader [1] & 0xFF ) << 8  |
414 							 	( pHeader [2] & 0xFF ) << 16 |
415 							 	( pHeader [3] & 0xFF ) << 24;
416 			if ( nHeader == n_ConstHeader )
417 			{
418 				// this is one of our god-awful, but extremely devious hacks, everyone cheer
419 				xTempEncrData = new BaseEncryptionData;
420 
421 				::rtl::OUString aMediaType;
422                 sal_Int32 nEncAlgorithm = 0;
423                 sal_Int32 nChecksumAlgorithm = 0;
424                 sal_Int32 nDerivedKeySize = 0;
425                 sal_Int32 nStartKeyGenID = 0;
426 				if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
427 				{
428 					// We'll want to skip the data we've just read, so calculate how much we just read
429 					// and remember it
430 					m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength()
431 														+ xTempEncrData->m_aInitVector.getLength()
432 														+ xTempEncrData->m_aDigest.getLength()
433 														+ aMediaType.getLength() * sizeof( sal_Unicode );
434                     m_nImportedEncryptionAlgorithm = nEncAlgorithm;
435                     m_nImportedChecksumAlgorithm = nChecksumAlgorithm;
436                     m_nImportedDerivedKeySize = nDerivedKeySize;
437                     m_nImportedStartKeyAlgorithm = nStartKeyGenID;
438 					m_nMagicalHackSize = nMagHackSize;
439 					sMediaType = aMediaType;
440 
441 					bOk = sal_True;
442 				}
443 			}
444 		}
445 	}
446 	catch( Exception& )
447 	{
448 	}
449 
450 	if ( !bOk )
451 	{
452 		// the provided stream is not a raw stream
453 		return sal_False;
454 	}
455 
456 	m_xBaseEncryptionData = xTempEncrData;
457 	SetIsEncrypted ( sal_True );
458 	// it's already compressed and encrypted
459 	bToBeEncrypted = bToBeCompressed = sal_False;
460 
461 	return sal_True;
462 }
463 
464 void ZipPackageStream::SetPackageMember( sal_Bool bNewValue )
465 {
466 	if ( bNewValue )
467 	{
468 		m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
469 		m_nMagicalHackPos = 0;
470 		m_nMagicalHackSize = 0;
471 	}
472 	else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
473 		m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
474 }
475 
476 // XActiveDataSink
477 //--------------------------------------------------------------------------
478 void SAL_CALL ZipPackageStream::setInputStream( const uno::Reference< io::XInputStream >& aStream )
479 		throw( RuntimeException )
480 {
481 	// if seekable access is required the wrapping will be done on demand
482 	xStream = aStream;
483     m_nImportedEncryptionAlgorithm = 0;
484 	m_bHasSeekable = sal_False;
485 	SetPackageMember ( sal_False );
486 	aEntry.nTime = -1;
487 	m_nStreamMode = PACKAGE_STREAM_DETECT;
488 }
489 
490 //--------------------------------------------------------------------------
491 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
492 		throw( RuntimeException )
493 {
494 	try
495 	{
496 		if ( IsPackageMember() )
497 		{
498 			return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
499 		}
500 		else if ( GetOwnSeekStream().is() )
501 		{
502 			return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
503 		}
504 		else
505 			return uno::Reference < io::XInputStream > ();
506 	}
507 	catch ( ZipException & )//rException )
508 	{
509 		VOS_ENSURE( 0, "ZipException thrown" );//rException.Message );
510 		return uno::Reference < io::XInputStream > ();
511 	}
512 	catch ( Exception & )
513 	{
514 		VOS_ENSURE( 0, "Exception is thrown during stream wrapping!\n" );
515 		return uno::Reference < io::XInputStream > ();
516 	}
517 }
518 
519 //--------------------------------------------------------------------------
520 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
521 		throw( RuntimeException )
522 {
523 	try
524 	{
525 		if ( IsPackageMember() )
526 		{
527 			return rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
528 		}
529 		else if ( GetOwnSeekStream().is() )
530 		{
531 			return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
532 		}
533 		else
534 			return uno::Reference < io::XInputStream > ();
535 	}
536 	catch ( ZipException & )//rException )
537 	{
538 		VOS_ENSURE( 0,"ZipException thrown" );//rException.Message );
539 		return uno::Reference < io::XInputStream > ();
540 	}
541 	catch ( Exception & )
542 	{
543 		VOS_ENSURE( 0, "Exception is thrown during stream wrapping!\n" );
544 		return uno::Reference < io::XInputStream > ();
545 	}
546 }
547 
548 // XDataSinkEncrSupport
549 //--------------------------------------------------------------------------
550 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
551 		throw ( packages::WrongPasswordException,
552 				io::IOException,
553 				RuntimeException )
554 {
555 	// There is no stream attached to this object
556 	if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
557 		return uno::Reference< io::XInputStream >();
558 
559 	// this method can not be used together with old approach
560 	if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
561 		throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
562 
563 	if ( IsPackageMember() )
564 	{
565         uno::Reference< io::XInputStream > xResult;
566         try
567         {
568 		    xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
569         }
570         catch( packages::WrongPasswordException& )
571         {
572             // workaround for the encrypted documents generated with the old OOo1.x bug.
573             if ( rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 && !m_bUseWinEncoding )
574             {
575                 xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
576                 m_bUseWinEncoding = true;
577             }
578             else
579                 throw;
580         }
581         return xResult;
582 	}
583 	else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
584 		return ZipFile::StaticGetDataFromRawStream( m_xFactory, GetOwnSeekStream(), GetEncryptionData() );
585 	else if ( GetOwnSeekStream().is() )
586 	{
587 		return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
588 	}
589 	else
590 		return uno::Reference< io::XInputStream >();
591 }
592 
593 //--------------------------------------------------------------------------
594 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
595 		throw ( packages::NoEncryptionException,
596 				io::IOException,
597 				uno::RuntimeException )
598 {
599 	// There is no stream attached to this object
600 	if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
601 		return uno::Reference< io::XInputStream >();
602 
603 	// this method can not be used together with old approach
604 	if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
605 		throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
606 
607 	if ( IsPackageMember() )
608 	{
609 		if ( !bIsEncrypted || !GetEncryptionData().is() )
610 			throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
611 
612 		return rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), sMediaType, rZipPackage.GetSharedMutexRef() );
613 	}
614 	else if ( GetOwnSeekStream().is() )
615 	{
616 		if ( m_nStreamMode == PACKAGE_STREAM_RAW )
617 		{
618 			return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
619 		}
620 		else if ( m_nStreamMode == PACKAGE_STREAM_DATA && bToBeEncrypted )
621 			return TryToGetRawFromDataStream( sal_True );
622 	}
623 
624 	throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
625 }
626 
627 
628 //--------------------------------------------------------------------------
629 void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
630 		throw ( io::IOException,
631 				RuntimeException )
632 {
633 	setInputStream( aStream );
634 	m_nStreamMode = PACKAGE_STREAM_DATA;
635 }
636 
637 //--------------------------------------------------------------------------
638 void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
639 		throw ( packages::EncryptionNotAllowedException,
640 				packages::NoRawFormatException,
641 				io::IOException,
642 				RuntimeException )
643 {
644 	// wrap the stream in case it is not seekable
645 	uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xFactory );
646 	uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
647 	if ( !xSeek.is() )
648 		throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must support XSeekable!" ) ),
649 									uno::Reference< XInterface >() );
650 
651 	xSeek->seek( 0 );
652 	uno::Reference< io::XInputStream > xOldStream = xStream;
653 	xStream = xNewStream;
654 	if ( !ParsePackageRawStream() )
655 	{
656 		xStream = xOldStream;
657 		throw packages::NoRawFormatException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
658 	}
659 
660 	// the raw stream MUST have seekable access
661 	m_bHasSeekable = sal_True;
662 
663 	SetPackageMember ( sal_False );
664 	aEntry.nTime = -1;
665 	m_nStreamMode = PACKAGE_STREAM_RAW;
666 }
667 
668 //--------------------------------------------------------------------------
669 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
670 		throw ( io::IOException,
671 				uno::RuntimeException )
672 {
673 	// There is no stream attached to this object
674 	if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
675 		return uno::Reference< io::XInputStream >();
676 
677 	// this method can not be used together with old approach
678 	if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
679 		throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
680 
681 	if ( IsPackageMember() )
682 	{
683 		return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
684 	}
685 	else if ( GetOwnSeekStream().is() )
686 	{
687 		if ( m_nStreamMode == PACKAGE_STREAM_RAW )
688 		{
689 			// the header should not be returned here
690 			return GetRawEncrStreamNoHeaderCopy();
691 		}
692 		else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
693 			return TryToGetRawFromDataStream( sal_False );
694 	}
695 
696 	return uno::Reference< io::XInputStream >();
697 }
698 
699 // XUnoTunnel
700 
701 //--------------------------------------------------------------------------
702 sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
703 	throw( RuntimeException )
704 {
705 	sal_Int64 nMe = 0;
706 	if ( aIdentifier.getLength() == 16 &&
707 		 0 == rtl_compareMemory( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
708 		nMe = reinterpret_cast < sal_Int64 > ( this );
709 	return nMe;
710 }
711 
712 // XPropertySet
713 //--------------------------------------------------------------------------
714 void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
715 		throw( beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
716 {
717 	if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" )) )
718 	{
719 		if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
720 			throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
721 
722 		if ( aValue >>= sMediaType )
723 		{
724 			if ( sMediaType.getLength() > 0 )
725 			{
726 				if ( sMediaType.indexOf ( OUString( RTL_CONSTASCII_USTRINGPARAM ( "text" ) ) ) != -1
727 			 	|| sMediaType.equals( OUString( RTL_CONSTASCII_USTRINGPARAM ( "application/vnd.sun.star.oleobject" ) ) ) )
728 					bToBeCompressed = sal_True;
729 				else if ( !m_bCompressedIsSetFromOutside )
730 					bToBeCompressed = sal_False;
731 			}
732 		}
733 		else
734 			throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "MediaType must be a string!\n" ) ),
735 											uno::Reference< XInterface >(),
736 											2 );
737 
738 	}
739 	else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
740 	{
741 		if ( !( aValue >>= aEntry.nSize ) )
742 			throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Size property!\n" ) ),
743 											uno::Reference< XInterface >(),
744 											2 );
745 	}
746 	else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) )
747 	{
748 		if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
749 			throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
750 
751 		sal_Bool bEnc = sal_False;
752 		if ( aValue >>= bEnc )
753 		{
754 			// In case of new raw stream, the stream must not be encrypted on storing
755 			if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
756 				throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Raw stream can not be encrypted on storing" ) ),
757 												uno::Reference< XInterface >(),
758 												2 );
759 
760 			bToBeEncrypted = bEnc;
761 			if ( bToBeEncrypted && !m_xBaseEncryptionData.is() )
762 				m_xBaseEncryptionData = new BaseEncryptionData;
763 		}
764 		else
765 			throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Encrypted property!\n" ) ),
766 											uno::Reference< XInterface >(),
767 											2 );
768 
769 	}
770 	else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) )
771 	{
772 		if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
773 			throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
774 
775 		uno::Sequence< sal_Int8 > aNewKey;
776 
777 		if ( !( aValue >>= aNewKey ) )
778 		{
779 			OUString sTempString;
780 			if ( ( aValue >>= sTempString ) )
781 			{
782 				sal_Int32 nPathLength = sTempString.getLength();
783 				Sequence < sal_Int8 > aSequence ( nPathLength );
784 				sal_Int8 *pArray = aSequence.getArray();
785 				const sal_Unicode *pChar = sTempString.getStr();
786 				for ( sal_Int16 i = 0; i < nPathLength; i++ )
787 					pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
788 				aNewKey = aSequence;
789 			}
790 			else
791 				throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for EncryptionKey property!\n" ) ),
792 												uno::Reference< XInterface >(),
793 												2 );
794 		}
795 
796 		if ( aNewKey.getLength() )
797 		{
798 			if ( !m_xBaseEncryptionData.is() )
799 				m_xBaseEncryptionData = new BaseEncryptionData;
800 
801 			m_aEncryptionKey = aNewKey;
802 			// In case of new raw stream, the stream must not be encrypted on storing
803 			bHaveOwnKey = sal_True;
804 			if ( m_nStreamMode != PACKAGE_STREAM_RAW )
805 				bToBeEncrypted = sal_True;
806 		}
807 		else
808         {
809 			bHaveOwnKey = sal_False;
810             m_aEncryptionKey.realloc( 0 );
811         }
812 
813         m_aStorageEncryptionKeys.realloc( 0 );
814 	}
815 	else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) )
816 	{
817 		if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
818 			throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
819 
820 		uno::Sequence< beans::NamedValue > aKeys;
821 		if ( !( aValue >>= aKeys ) )
822 		{
823 				throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for StorageEncryptionKeys property!\n" ) ),
824 												uno::Reference< XInterface >(),
825 												2 );
826 		}
827 
828 		if ( aKeys.getLength() )
829 		{
830 			if ( !m_xBaseEncryptionData.is() )
831 				m_xBaseEncryptionData = new BaseEncryptionData;
832 
833 			m_aStorageEncryptionKeys = aKeys;
834 
835 			// In case of new raw stream, the stream must not be encrypted on storing
836 			bHaveOwnKey = sal_True;
837 			if ( m_nStreamMode != PACKAGE_STREAM_RAW )
838 				bToBeEncrypted = sal_True;
839 		}
840 		else
841         {
842 			bHaveOwnKey = sal_False;
843             m_aStorageEncryptionKeys.realloc( 0 );
844         }
845 
846         m_aEncryptionKey.realloc( 0 );
847 	}
848 	else if ( aPropertyName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) )
849 	{
850 		sal_Bool bCompr = sal_False;
851 
852 		if ( aValue >>= bCompr )
853 		{
854 			// In case of new raw stream, the stream must not be encrypted on storing
855 			if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
856 				throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Raw stream can not be encrypted on storing" ) ),
857 												uno::Reference< XInterface >(),
858 												2 );
859 
860 			bToBeCompressed = bCompr;
861 			m_bCompressedIsSetFromOutside = sal_True;
862 		}
863 		else
864 			throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Compressed property!\n" ) ),
865 											uno::Reference< XInterface >(),
866 											2 );
867 	}
868 	else
869 		throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
870 }
871 
872 //--------------------------------------------------------------------------
873 Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
874 		throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException )
875 {
876 	Any aAny;
877 	if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
878 	{
879 		aAny <<= sMediaType;
880 		return aAny;
881 	}
882 	else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Size" ) ) )
883 	{
884 		aAny <<= aEntry.nSize;
885 		return aAny;
886 	}
887 	else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Encrypted" ) ) )
888 	{
889 		aAny <<= ( m_nStreamMode == PACKAGE_STREAM_RAW ) ? sal_True : bToBeEncrypted;
890 		return aAny;
891 	}
892 	else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "WasEncrypted" ) ) )
893 	{
894 		aAny <<= bIsEncrypted;
895 		return aAny;
896 	}
897 	else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) )
898 	{
899 		aAny <<= bToBeCompressed;
900 		return aAny;
901 	}
902 	else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) )
903 	{
904 		aAny <<= m_aEncryptionKey;
905 		return aAny;
906 	}
907 	else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) )
908 	{
909 		aAny <<= m_aStorageEncryptionKeys;
910 		return aAny;
911 	}
912 	else
913 		throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
914 }
915 
916 //--------------------------------------------------------------------------
917 void ZipPackageStream::setSize ( const sal_Int32 nNewSize )
918 {
919 	if ( aEntry.nCompressedSize != nNewSize )
920 		aEntry.nMethod = DEFLATED;
921 	aEntry.nSize = nNewSize;
922 }
923 //--------------------------------------------------------------------------
924 OUString ZipPackageStream::getImplementationName()
925 	throw ( RuntimeException )
926 {
927 	return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageStream" ) );
928 }
929 
930 //--------------------------------------------------------------------------
931 Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
932 	throw ( RuntimeException )
933 {
934 	Sequence< OUString > aNames( 1 );
935 	aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageStream" ) );
936 	return aNames;
937 }
938 //--------------------------------------------------------------------------
939 sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
940 	throw ( RuntimeException )
941 {
942 	return rServiceName == getSupportedServiceNames()[0];
943 }
944 
945