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