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