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