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