xref: /AOO41X/main/package/source/zippackage/ZipPackageStream.cxx (revision a38728232e8c39f9058a1a2aa8ee4e6db7b8ca34)
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