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 {
482 // if seekable access is required the wrapping will be done on demand
483 xStream = aStream;
484 m_nImportedEncryptionAlgorithm = 0;
485 m_bHasSeekable = sal_False;
486 SetPackageMember ( sal_False );
487 aEntry.nTime = -1;
488 m_nStreamMode = PACKAGE_STREAM_DETECT;
489 }
490
491 //--------------------------------------------------------------------------
getRawData()492 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
493 {
494 try
495 {
496 if ( IsPackageMember() )
497 {
498 return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
499 }
500 else if ( GetOwnSeekStream().is() )
501 {
502 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
503 }
504 else
505 return uno::Reference < io::XInputStream > ();
506 }
507 catch ( ZipException & )//rException )
508 {
509 VOS_ENSURE( 0, "ZipException thrown" );//rException.Message );
510 return uno::Reference < io::XInputStream > ();
511 }
512 catch ( Exception & )
513 {
514 VOS_ENSURE( 0, "Exception is thrown during stream wrapping!\n" );
515 return uno::Reference < io::XInputStream > ();
516 }
517 }
518
519 //--------------------------------------------------------------------------
getInputStream()520 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
521 {
522 try
523 {
524 if ( IsPackageMember() )
525 {
526 return rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
527 }
528 else if ( GetOwnSeekStream().is() )
529 {
530 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
531 }
532 else
533 return uno::Reference < io::XInputStream > ();
534 }
535 catch ( ZipException & )//rException )
536 {
537 VOS_ENSURE( 0,"ZipException thrown" );//rException.Message );
538 return uno::Reference < io::XInputStream > ();
539 }
540 catch ( Exception & )
541 {
542 VOS_ENSURE( 0, "Exception is thrown during stream wrapping!\n" );
543 return uno::Reference < io::XInputStream > ();
544 }
545 }
546
547 // XDataSinkEncrSupport
548 //--------------------------------------------------------------------------
getDataStream()549 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
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 {
592 // There is no stream attached to this object
593 if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
594 return uno::Reference< io::XInputStream >();
595
596 // this method can not be used together with old approach
597 if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
598 throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
599
600 if ( IsPackageMember() )
601 {
602 if ( !bIsEncrypted || !GetEncryptionData().is() )
603 throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
604
605 return rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), sMediaType, rZipPackage.GetSharedMutexRef() );
606 }
607 else if ( GetOwnSeekStream().is() )
608 {
609 if ( m_nStreamMode == PACKAGE_STREAM_RAW )
610 {
611 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
612 }
613 else if ( m_nStreamMode == PACKAGE_STREAM_DATA && bToBeEncrypted )
614 return TryToGetRawFromDataStream( sal_True );
615 }
616
617 throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
618 }
619
620
621 //--------------------------------------------------------------------------
setDataStream(const uno::Reference<io::XInputStream> & aStream)622 void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
623 {
624 setInputStream( aStream );
625 m_nStreamMode = PACKAGE_STREAM_DATA;
626 }
627
628 //--------------------------------------------------------------------------
setRawStream(const uno::Reference<io::XInputStream> & aStream)629 void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
630 {
631 // wrap the stream in case it is not seekable
632 uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xFactory );
633 uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
634 if ( !xSeek.is() )
635 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "The stream must support XSeekable!" ) ),
636 uno::Reference< XInterface >() );
637
638 xSeek->seek( 0 );
639 uno::Reference< io::XInputStream > xOldStream = xStream;
640 xStream = xNewStream;
641 if ( !ParsePackageRawStream() )
642 {
643 xStream = xOldStream;
644 throw packages::NoRawFormatException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
645 }
646
647 // the raw stream MUST have seekable access
648 m_bHasSeekable = sal_True;
649
650 SetPackageMember ( sal_False );
651 aEntry.nTime = -1;
652 m_nStreamMode = PACKAGE_STREAM_RAW;
653 }
654
655 //--------------------------------------------------------------------------
getPlainRawStream()656 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
657 {
658 // There is no stream attached to this object
659 if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
660 return uno::Reference< io::XInputStream >();
661
662 // this method can not be used together with old approach
663 if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
664 throw packages::zip::ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
665
666 if ( IsPackageMember() )
667 {
668 return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
669 }
670 else if ( GetOwnSeekStream().is() )
671 {
672 if ( m_nStreamMode == PACKAGE_STREAM_RAW )
673 {
674 // the header should not be returned here
675 return GetRawEncrStreamNoHeaderCopy();
676 }
677 else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
678 return TryToGetRawFromDataStream( sal_False );
679 }
680
681 return uno::Reference< io::XInputStream >();
682 }
683
684 // XUnoTunnel
685
686 //--------------------------------------------------------------------------
getSomething(const Sequence<sal_Int8> & aIdentifier)687 sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
688 {
689 sal_Int64 nMe = 0;
690 if ( aIdentifier.getLength() == 16 &&
691 0 == rtl_compareMemory( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
692 nMe = reinterpret_cast < sal_Int64 > ( this );
693 return nMe;
694 }
695
696 // XPropertySet
697 //--------------------------------------------------------------------------
setPropertyValue(const OUString & aPropertyName,const Any & aValue)698 void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
699 {
700 if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" )) )
701 {
702 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
703 throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
704
705 if ( aValue >>= sMediaType )
706 {
707 if ( sMediaType.getLength() > 0 )
708 {
709 if ( sMediaType.indexOf ( OUString( RTL_CONSTASCII_USTRINGPARAM ( "text" ) ) ) != -1
710 || sMediaType.equals( OUString( RTL_CONSTASCII_USTRINGPARAM ( "application/vnd.sun.star.oleobject" ) ) ) )
711 bToBeCompressed = sal_True;
712 else if ( !m_bCompressedIsSetFromOutside )
713 bToBeCompressed = sal_False;
714 }
715 }
716 else
717 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "MediaType must be a string!\n" ) ),
718 uno::Reference< XInterface >(),
719 2 );
720
721 }
722 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
723 {
724 if ( !( aValue >>= aEntry.nSize ) )
725 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Size property!\n" ) ),
726 uno::Reference< XInterface >(),
727 2 );
728 }
729 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) )
730 {
731 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
732 throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
733
734 sal_Bool bEnc = sal_False;
735 if ( aValue >>= bEnc )
736 {
737 // In case of new raw stream, the stream must not be encrypted on storing
738 if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
739 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Raw stream can not be encrypted on storing" ) ),
740 uno::Reference< XInterface >(),
741 2 );
742
743 bToBeEncrypted = bEnc;
744 if ( bToBeEncrypted && !m_xBaseEncryptionData.is() )
745 m_xBaseEncryptionData = new BaseEncryptionData;
746 }
747 else
748 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Encrypted property!\n" ) ),
749 uno::Reference< XInterface >(),
750 2 );
751
752 }
753 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) )
754 {
755 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
756 throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
757
758 uno::Sequence< sal_Int8 > aNewKey;
759
760 if ( !( aValue >>= aNewKey ) )
761 {
762 OUString sTempString;
763 if ( ( aValue >>= sTempString ) )
764 {
765 sal_Int32 nPathLength = sTempString.getLength();
766 Sequence < sal_Int8 > aSequence ( nPathLength );
767 sal_Int8 *pArray = aSequence.getArray();
768 const sal_Unicode *pChar = sTempString.getStr();
769 for ( sal_Int16 i = 0; i < nPathLength; i++ )
770 pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
771 aNewKey = aSequence;
772 }
773 else
774 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for EncryptionKey property!\n" ) ),
775 uno::Reference< XInterface >(),
776 2 );
777 }
778
779 if ( aNewKey.getLength() )
780 {
781 if ( !m_xBaseEncryptionData.is() )
782 m_xBaseEncryptionData = new BaseEncryptionData;
783
784 m_aEncryptionKey = aNewKey;
785 // In case of new raw stream, the stream must not be encrypted on storing
786 bHaveOwnKey = sal_True;
787 if ( m_nStreamMode != PACKAGE_STREAM_RAW )
788 bToBeEncrypted = sal_True;
789 }
790 else
791 {
792 bHaveOwnKey = sal_False;
793 m_aEncryptionKey.realloc( 0 );
794 }
795
796 m_aStorageEncryptionKeys.realloc( 0 );
797 }
798 else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) )
799 {
800 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
801 throw beans::PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
802
803 uno::Sequence< beans::NamedValue > aKeys;
804 if ( !( aValue >>= aKeys ) )
805 {
806 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for StorageEncryptionKeys property!\n" ) ),
807 uno::Reference< XInterface >(),
808 2 );
809 }
810
811 if ( aKeys.getLength() )
812 {
813 if ( !m_xBaseEncryptionData.is() )
814 m_xBaseEncryptionData = new BaseEncryptionData;
815
816 m_aStorageEncryptionKeys = aKeys;
817
818 // In case of new raw stream, the stream must not be encrypted on storing
819 bHaveOwnKey = sal_True;
820 if ( m_nStreamMode != PACKAGE_STREAM_RAW )
821 bToBeEncrypted = sal_True;
822 }
823 else
824 {
825 bHaveOwnKey = sal_False;
826 m_aStorageEncryptionKeys.realloc( 0 );
827 }
828
829 m_aEncryptionKey.realloc( 0 );
830 }
831 else if ( aPropertyName.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) )
832 {
833 sal_Bool bCompr = sal_False;
834
835 if ( aValue >>= bCompr )
836 {
837 // In case of new raw stream, the stream must not be encrypted on storing
838 if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
839 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Raw stream can not be encrypted on storing" ) ),
840 uno::Reference< XInterface >(),
841 2 );
842
843 bToBeCompressed = bCompr;
844 m_bCompressedIsSetFromOutside = sal_True;
845 }
846 else
847 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong type for Compressed property!\n" ) ),
848 uno::Reference< XInterface >(),
849 2 );
850 }
851 else
852 throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
853 }
854
855 //--------------------------------------------------------------------------
getPropertyValue(const OUString & PropertyName)856 Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
857 {
858 Any aAny;
859 if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
860 {
861 aAny <<= sMediaType;
862 return aAny;
863 }
864 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Size" ) ) )
865 {
866 aAny <<= aEntry.nSize;
867 return aAny;
868 }
869 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Encrypted" ) ) )
870 {
871 aAny <<= ( m_nStreamMode == PACKAGE_STREAM_RAW ) ? sal_True : bToBeEncrypted;
872 return aAny;
873 }
874 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "WasEncrypted" ) ) )
875 {
876 aAny <<= bIsEncrypted;
877 return aAny;
878 }
879 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Compressed" ) ) )
880 {
881 aAny <<= bToBeCompressed;
882 return aAny;
883 }
884 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) )
885 {
886 aAny <<= m_aEncryptionKey;
887 return aAny;
888 }
889 else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) )
890 {
891 aAny <<= m_aStorageEncryptionKeys;
892 return aAny;
893 }
894 else
895 throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
896 }
897
898 //--------------------------------------------------------------------------
setSize(const sal_Int32 nNewSize)899 void ZipPackageStream::setSize ( const sal_Int32 nNewSize )
900 {
901 if ( aEntry.nCompressedSize != nNewSize )
902 aEntry.nMethod = DEFLATED;
903 aEntry.nSize = nNewSize;
904 }
905 //--------------------------------------------------------------------------
getImplementationName()906 OUString ZipPackageStream::getImplementationName()
907 {
908 return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageStream" ) );
909 }
910
911 //--------------------------------------------------------------------------
getSupportedServiceNames()912 Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
913 {
914 Sequence< OUString > aNames( 1 );
915 aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageStream" ) );
916 return aNames;
917 }
918 //--------------------------------------------------------------------------
supportsService(OUString const & rServiceName)919 sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
920 {
921 return rServiceName == getSupportedServiceNames()[0];
922 }
923