fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / package / source / zippackage / ZipPackageStream.cxx
blob299f53c2cf9c0674a6da5f85066fa29b93d7a338
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // MARKER( update_precomp.py ): autogen include statement, do not remove
21 #include <com/sun/star/packages/zip/ZipConstants.hpp>
22 #include <com/sun/star/embed/StorageFormats.hpp>
23 #include <com/sun/star/packages/zip/ZipIOException.hpp>
24 #include <com/sun/star/io/TempFile.hpp>
25 #include <com/sun/star/io/XInputStream.hpp>
26 #include <com/sun/star/io/XOutputStream.hpp>
27 #include <com/sun/star/io/XStream.hpp>
28 #include <com/sun/star/io/XSeekable.hpp>
29 #include <com/sun/star/xml/crypto/DigestID.hpp>
30 #include <com/sun/star/xml/crypto/CipherID.hpp>
32 #include <string.h>
34 #include <ZipPackageStream.hxx>
35 #include <ZipPackage.hxx>
36 #include <ZipFile.hxx>
37 #include <EncryptedDataHeader.hxx>
38 #include <osl/diagnose.h>
39 #include "wrapstreamforshare.hxx"
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/seekableinput.hxx>
43 #include <comphelper/storagehelper.hxx>
45 #include <rtl/instance.hxx>
47 #include <PackageConstants.hxx>
49 using namespace com::sun::star::packages::zip::ZipConstants;
50 using namespace com::sun::star::packages::zip;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star;
54 using namespace cppu;
56 namespace { struct lcl_CachedImplId : public rtl::Static< Sequence < sal_Int8 >, lcl_CachedImplId > {}; }
58 const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageStream::static_getImplementationId()
60 return lcl_CachedImplId::get();
63 ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
64 const uno::Reference< XComponentContext >& xContext,
65 sal_Bool bAllowRemoveOnInsert )
66 : m_xContext( xContext )
67 , rZipPackage( rNewPackage )
68 , bToBeCompressed ( sal_True )
69 , bToBeEncrypted ( sal_False )
70 , bHaveOwnKey ( sal_False )
71 , bIsEncrypted ( sal_False )
72 , m_nImportedStartKeyAlgorithm( 0 )
73 , m_nImportedEncryptionAlgorithm( 0 )
74 , m_nImportedChecksumAlgorithm( 0 )
75 , m_nImportedDerivedKeySize( 0 )
76 , m_nStreamMode( PACKAGE_STREAM_NOTSET )
77 , m_nMagicalHackPos( 0 )
78 , m_nMagicalHackSize( 0 )
79 , m_bHasSeekable( sal_False )
80 , m_bCompressedIsSetFromOutside( sal_False )
81 , m_bFromManifest( sal_False )
82 , m_bUseWinEncoding( false )
84 OSL_ENSURE( m_xContext.is(), "No factory is provided to ZipPackageStream!\n" );
86 this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
88 SetFolder ( sal_False );
89 aEntry.nVersion = -1;
90 aEntry.nFlag = 0;
91 aEntry.nMethod = -1;
92 aEntry.nTime = -1;
93 aEntry.nCrc = -1;
94 aEntry.nCompressedSize = -1;
95 aEntry.nSize = -1;
96 aEntry.nOffset = -1;
97 aEntry.nPathLen = -1;
98 aEntry.nExtraLen = -1;
100 Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
101 if ( !rCachedImplId.getLength() )
102 rCachedImplId = getImplementationId();
105 ZipPackageStream::~ZipPackageStream( void )
109 void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
111 aEntry.nVersion = rInEntry.nVersion;
112 aEntry.nFlag = rInEntry.nFlag;
113 aEntry.nMethod = rInEntry.nMethod;
114 aEntry.nTime = rInEntry.nTime;
115 aEntry.nCrc = rInEntry.nCrc;
116 aEntry.nCompressedSize = rInEntry.nCompressedSize;
117 aEntry.nSize = rInEntry.nSize;
118 aEntry.nOffset = rInEntry.nOffset;
119 aEntry.sPath = rInEntry.sPath;
120 aEntry.nPathLen = rInEntry.nPathLen;
121 aEntry.nExtraLen = rInEntry.nExtraLen;
123 if ( aEntry.nMethod == STORED )
124 bToBeCompressed = sal_False;
127 //--------------------------------------------------------------------------
128 void ZipPackageStream::CloseOwnStreamIfAny()
130 if ( xStream.is() )
132 xStream->closeInput();
133 xStream = uno::Reference< io::XInputStream >();
134 m_bHasSeekable = sal_False;
138 //--------------------------------------------------------------------------
139 uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream()
141 if ( !m_bHasSeekable && xStream.is() )
143 // The package component requires that every stream either be FROM a package or it must support XSeekable!
144 // The only exception is a nonseekable stream that is provided only for storing, if such a stream
145 // is accessed before commit it MUST be wrapped.
146 // Wrap the stream in case it is not seekable
147 xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( xStream, m_xContext );
148 uno::Reference< io::XSeekable > xSeek( xStream, UNO_QUERY );
149 if ( !xSeek.is() )
150 throw RuntimeException( OSL_LOG_PREFIX "The stream must support XSeekable!",
151 uno::Reference< XInterface >() );
153 m_bHasSeekable = sal_True;
156 return xStream;
159 //--------------------------------------------------------------------------
160 uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
162 if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() )
163 throw io::IOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
165 if ( m_xBaseEncryptionData.is() )
166 throw ZipIOException(OSL_LOG_PREFIX "Encrypted stream without encryption data!\n",
167 uno::Reference< XInterface >() );
169 uno::Reference< io::XSeekable > xSeek( GetOwnSeekStream(), UNO_QUERY );
170 if ( !xSeek.is() )
171 throw ZipIOException(OSL_LOG_PREFIX "The stream must be seekable!\n",
172 uno::Reference< XInterface >() );
174 // skip header
175 xSeek->seek( n_ConstHeaderSize + getInitialisationVector().getLength() +
176 getSalt().getLength() + getDigest().getLength() );
178 // create temporary stream
179 uno::Reference < io::XTempFile > xTempFile = io::TempFile::create(m_xContext);
180 uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
181 uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();;
182 uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
184 // copy the raw stream to the temporary file starting from the current position
185 ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
186 xTempOut->closeOutput();
187 xTempSeek->seek( 0 );
189 return xTempIn;
192 //--------------------------------------------------------------------------
193 sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
195 return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : rZipPackage.GetEncAlgID();
198 //--------------------------------------------------------------------------
199 sal_Int32 ZipPackageStream::GetBlockSize() const
201 return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
204 //--------------------------------------------------------------------------
205 ::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding )
207 ::rtl::Reference< EncryptionData > xResult;
208 if ( m_xBaseEncryptionData.is() )
209 xResult = new EncryptionData(
210 *m_xBaseEncryptionData,
211 GetEncryptionKey( bUseWinEncoding ),
212 GetEncryptionAlgorithm(),
213 m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : rZipPackage.GetChecksumAlgID(),
214 m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : rZipPackage.GetDefaultDerivedKeySize(),
215 GetStartKeyGenID() );
217 return xResult;
220 //--------------------------------------------------------------------------
221 uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding )
223 uno::Sequence< sal_Int8 > aResult;
224 sal_Int32 nKeyGenID = GetStartKeyGenID();
225 bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding );
227 if ( bHaveOwnKey && m_aStorageEncryptionKeys.getLength() )
229 OUString aNameToFind;
230 if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
231 aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
232 else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
234 aNameToFind = bUseWinEncoding ? PACKAGE_ENCRYPTIONDATA_SHA1MS1252 : PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
236 else
237 throw uno::RuntimeException(OSL_LOG_PREFIX "No expected key is provided!", uno::Reference< uno::XInterface >() );
239 for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
240 if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) )
241 m_aStorageEncryptionKeys[nInd].Value >>= aResult;
243 // empty keys are not allowed here
244 // so it is not important whether there is no key, or the key is empty, it is an error
245 if ( !aResult.getLength() )
246 throw uno::RuntimeException(OSL_LOG_PREFIX "No expected key is provided!", uno::Reference< uno::XInterface >() );
248 else
249 aResult = m_aEncryptionKey;
251 if ( !aResult.getLength() || !bHaveOwnKey )
252 aResult = rZipPackage.GetEncryptionKey();
254 return aResult;
257 //--------------------------------------------------------------------------
258 sal_Int32 ZipPackageStream::GetStartKeyGenID()
260 // generally should all the streams use the same Start Key
261 // but if raw copy without password takes place, we should preserve the imported algorithm
262 return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : rZipPackage.GetStartKeyGenID();
265 //--------------------------------------------------------------------------
266 uno::Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( sal_Bool bAddHeaderForEncr )
268 if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || ( bAddHeaderForEncr && !bToBeEncrypted ) )
269 throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
271 Sequence< sal_Int8 > aKey;
273 if ( bToBeEncrypted )
275 aKey = GetEncryptionKey();
276 if ( !aKey.getLength() )
277 throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
282 // create temporary file
283 uno::Reference < io::XStream > xTempStream(
284 io::TempFile::create(m_xContext),
285 uno::UNO_QUERY_THROW );
287 // create a package based on it
288 ZipPackage* pPackage = new ZipPackage( m_xContext );
289 uno::Reference< XSingleServiceFactory > xPackageAsFactory( static_cast< XSingleServiceFactory* >( pPackage ) );
290 if ( !xPackageAsFactory.is() )
291 throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
293 Sequence< Any > aArgs( 1 );
294 aArgs[0] <<= xTempStream;
295 pPackage->initialize( aArgs );
297 // create a new package stream
298 uno::Reference< XDataSinkEncrSupport > xNewPackStream( xPackageAsFactory->createInstance(), UNO_QUERY );
299 if ( !xNewPackStream.is() )
300 throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
302 xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
303 new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() ) ) );
305 uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
306 if ( !xNewPSProps.is() )
307 throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
309 // copy all the properties of this stream to the new stream
310 xNewPSProps->setPropertyValue("MediaType", makeAny( sMediaType ) );
311 xNewPSProps->setPropertyValue("Compressed", makeAny( bToBeCompressed ) );
312 if ( bToBeEncrypted )
314 xNewPSProps->setPropertyValue(ENCRYPTION_KEY_PROPERTY, makeAny( aKey ) );
315 xNewPSProps->setPropertyValue("Encrypted", makeAny( sal_True ) );
318 // insert a new stream in the package
319 uno::Reference< XUnoTunnel > xTunnel;
320 Any aRoot = pPackage->getByHierarchicalName("/");
321 aRoot >>= xTunnel;
322 uno::Reference< container::XNameContainer > xRootNameContainer( xTunnel, UNO_QUERY );
323 if ( !xRootNameContainer.is() )
324 throw RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
326 uno::Reference< XUnoTunnel > xNPSTunnel( xNewPackStream, UNO_QUERY );
327 xRootNameContainer->insertByName("dummy", makeAny( xNPSTunnel ) );
329 // commit the temporary package
330 pPackage->commitChanges();
332 // get raw stream from the temporary package
333 uno::Reference< io::XInputStream > xInRaw;
334 if ( bAddHeaderForEncr )
335 xInRaw = xNewPackStream->getRawStream();
336 else
337 xInRaw = xNewPackStream->getPlainRawStream();
339 // create another temporary file
340 uno::Reference < io::XOutputStream > xTempOut(
341 io::TempFile::create(m_xContext),
342 uno::UNO_QUERY_THROW );
343 uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY_THROW );
344 uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
346 // copy the raw stream to the temporary file
347 ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
348 xTempOut->closeOutput();
349 xTempSeek->seek( 0 );
351 // close raw stream, package stream and folder
352 xInRaw = uno::Reference< io::XInputStream >();
353 xNewPSProps = uno::Reference< XPropertySet >();
354 xNPSTunnel = uno::Reference< XUnoTunnel >();
355 xNewPackStream = uno::Reference< XDataSinkEncrSupport >();
356 xTunnel = uno::Reference< XUnoTunnel >();
357 xRootNameContainer = uno::Reference< container::XNameContainer >();
359 // return the stream representing the first temporary file
360 return xTempIn;
362 catch ( RuntimeException& )
364 throw;
366 catch ( Exception& )
370 throw io::IOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
373 //--------------------------------------------------------------------------
374 sal_Bool ZipPackageStream::ParsePackageRawStream()
376 OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
378 if ( !GetOwnSeekStream().is() )
379 return sal_False;
381 sal_Bool bOk = sal_False;
383 ::rtl::Reference< BaseEncryptionData > xTempEncrData;
384 sal_Int32 nMagHackSize = 0;
385 Sequence < sal_Int8 > aHeader ( 4 );
389 if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
391 const sal_Int8 *pHeader = aHeader.getConstArray();
392 sal_uInt32 nHeader = ( pHeader [0] & 0xFF ) |
393 ( pHeader [1] & 0xFF ) << 8 |
394 ( pHeader [2] & 0xFF ) << 16 |
395 ( pHeader [3] & 0xFF ) << 24;
396 if ( nHeader == n_ConstHeader )
398 // this is one of our god-awful, but extremely devious hacks, everyone cheer
399 xTempEncrData = new BaseEncryptionData;
401 OUString aMediaType;
402 sal_Int32 nEncAlgorithm = 0;
403 sal_Int32 nChecksumAlgorithm = 0;
404 sal_Int32 nDerivedKeySize = 0;
405 sal_Int32 nStartKeyGenID = 0;
406 if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
408 // We'll want to skip the data we've just read, so calculate how much we just read
409 // and remember it
410 m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength()
411 + xTempEncrData->m_aInitVector.getLength()
412 + xTempEncrData->m_aDigest.getLength()
413 + aMediaType.getLength() * sizeof( sal_Unicode );
414 m_nImportedEncryptionAlgorithm = nEncAlgorithm;
415 m_nImportedChecksumAlgorithm = nChecksumAlgorithm;
416 m_nImportedDerivedKeySize = nDerivedKeySize;
417 m_nImportedStartKeyAlgorithm = nStartKeyGenID;
418 m_nMagicalHackSize = nMagHackSize;
419 sMediaType = aMediaType;
421 bOk = sal_True;
426 catch( Exception& )
430 if ( !bOk )
432 // the provided stream is not a raw stream
433 return sal_False;
436 m_xBaseEncryptionData = xTempEncrData;
437 SetIsEncrypted ( sal_True );
438 // it's already compressed and encrypted
439 bToBeEncrypted = bToBeCompressed = sal_False;
441 return sal_True;
444 void ZipPackageStream::SetPackageMember( sal_Bool bNewValue )
446 if ( bNewValue )
448 m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
449 m_nMagicalHackPos = 0;
450 m_nMagicalHackSize = 0;
452 else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
453 m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
456 // XActiveDataSink
457 //--------------------------------------------------------------------------
458 void SAL_CALL ZipPackageStream::setInputStream( const uno::Reference< io::XInputStream >& aStream )
459 throw( RuntimeException )
461 // if seekable access is required the wrapping will be done on demand
462 xStream = aStream;
463 m_nImportedEncryptionAlgorithm = 0;
464 m_bHasSeekable = sal_False;
465 SetPackageMember ( sal_False );
466 aEntry.nTime = -1;
467 m_nStreamMode = PACKAGE_STREAM_DETECT;
470 //--------------------------------------------------------------------------
471 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
472 throw( RuntimeException )
476 if ( IsPackageMember() )
478 return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
480 else if ( GetOwnSeekStream().is() )
482 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
484 else
485 return uno::Reference < io::XInputStream > ();
487 catch ( ZipException & )//rException )
489 OSL_FAIL( "ZipException thrown" );//rException.Message);
490 return uno::Reference < io::XInputStream > ();
492 catch ( Exception & )
494 OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
495 return uno::Reference < io::XInputStream > ();
499 //--------------------------------------------------------------------------
500 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
501 throw( RuntimeException )
505 if ( IsPackageMember() )
507 return rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
509 else if ( GetOwnSeekStream().is() )
511 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
513 else
514 return uno::Reference < io::XInputStream > ();
516 catch ( ZipException & )//rException )
518 OSL_FAIL( "ZipException thrown" );//rException.Message);
519 return uno::Reference < io::XInputStream > ();
521 catch ( Exception &ex )
523 OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
524 OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
525 (void)ex;
526 return uno::Reference < io::XInputStream > ();
530 // XDataSinkEncrSupport
531 //--------------------------------------------------------------------------
532 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
533 throw ( packages::WrongPasswordException,
534 io::IOException,
535 RuntimeException )
537 // There is no stream attached to this object
538 if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
539 return uno::Reference< io::XInputStream >();
541 // this method can not be used together with old approach
542 if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
543 throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
545 if ( IsPackageMember() )
547 uno::Reference< io::XInputStream > xResult;
550 xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
552 catch( const packages::WrongPasswordException& )
554 if ( rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 )
558 // rhbz#1013844 / fdo#47482 workaround for the encrypted
559 // OpenOffice.org 1.0 documents generated by Libreoffice <=
560 // 3.6 with the new encryption format and using SHA256, but
561 // missing a specified startkey of SHA256
563 // force SHA256 and see if that works
564 m_nImportedStartKeyAlgorithm = xml::crypto::DigestID::SHA256;
565 xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
566 return xResult;
568 catch (const packages::WrongPasswordException&)
570 // if that didn't work, restore to SHA1 and trundle through the *other* earlier
571 // bug fix
572 m_nImportedStartKeyAlgorithm = xml::crypto::DigestID::SHA1;
575 // workaround for the encrypted documents generated with the old OOo1.x bug.
576 if ( !m_bUseWinEncoding )
578 xResult = rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
579 m_bUseWinEncoding = true;
581 else
582 throw;
584 else
585 throw;
587 return xResult;
589 else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
590 return ZipFile::StaticGetDataFromRawStream( m_xContext, GetOwnSeekStream(), GetEncryptionData() );
591 else if ( GetOwnSeekStream().is() )
593 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
595 else
596 return uno::Reference< io::XInputStream >();
599 //--------------------------------------------------------------------------
600 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
601 throw ( packages::NoEncryptionException,
602 io::IOException,
603 uno::RuntimeException )
605 // There is no stream attached to this object
606 if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
607 return uno::Reference< io::XInputStream >();
609 // this method can not be used together with old approach
610 if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
611 throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
613 if ( IsPackageMember() )
615 if ( !bIsEncrypted || !GetEncryptionData().is() )
616 throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
618 return rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), sMediaType, rZipPackage.GetSharedMutexRef() );
620 else if ( GetOwnSeekStream().is() )
622 if ( m_nStreamMode == PACKAGE_STREAM_RAW )
624 return new WrapStreamForShare( GetOwnSeekStream(), rZipPackage.GetSharedMutexRef() );
626 else if ( m_nStreamMode == PACKAGE_STREAM_DATA && bToBeEncrypted )
627 return TryToGetRawFromDataStream( sal_True );
630 throw packages::NoEncryptionException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
634 //--------------------------------------------------------------------------
635 void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
636 throw ( io::IOException,
637 RuntimeException )
639 setInputStream( aStream );
640 m_nStreamMode = PACKAGE_STREAM_DATA;
643 //--------------------------------------------------------------------------
644 void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
645 throw ( packages::EncryptionNotAllowedException,
646 packages::NoRawFormatException,
647 io::IOException,
648 RuntimeException )
650 // wrap the stream in case it is not seekable
651 uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xContext );
652 uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
653 if ( !xSeek.is() )
654 throw RuntimeException(OSL_LOG_PREFIX "The stream must support XSeekable!",
655 uno::Reference< XInterface >() );
657 xSeek->seek( 0 );
658 uno::Reference< io::XInputStream > xOldStream = xStream;
659 xStream = xNewStream;
660 if ( !ParsePackageRawStream() )
662 xStream = xOldStream;
663 throw packages::NoRawFormatException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
666 // the raw stream MUST have seekable access
667 m_bHasSeekable = sal_True;
669 SetPackageMember ( sal_False );
670 aEntry.nTime = -1;
671 m_nStreamMode = PACKAGE_STREAM_RAW;
674 //--------------------------------------------------------------------------
675 uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
676 throw ( io::IOException,
677 uno::RuntimeException )
679 // There is no stream attached to this object
680 if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
681 return uno::Reference< io::XInputStream >();
683 // this method can not be used together with old approach
684 if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
685 throw packages::zip::ZipIOException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
687 if ( IsPackageMember() )
689 return rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), bIsEncrypted, rZipPackage.GetSharedMutexRef() );
691 else if ( GetOwnSeekStream().is() )
693 if ( m_nStreamMode == PACKAGE_STREAM_RAW )
695 // the header should not be returned here
696 return GetRawEncrStreamNoHeaderCopy();
698 else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
699 return TryToGetRawFromDataStream( sal_False );
702 return uno::Reference< io::XInputStream >();
705 // XUnoTunnel
707 //--------------------------------------------------------------------------
708 sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
709 throw( RuntimeException )
711 sal_Int64 nMe = 0;
712 if ( aIdentifier.getLength() == 16 &&
713 0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
714 nMe = reinterpret_cast < sal_Int64 > ( this );
715 return nMe;
718 // XPropertySet
719 //--------------------------------------------------------------------------
720 void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
721 throw( beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException )
723 if ( aPropertyName == "MediaType" )
725 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
726 throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
728 if ( aValue >>= sMediaType )
730 if ( !sMediaType.isEmpty() )
732 if ( sMediaType.indexOf ( "text" ) != -1
733 || sMediaType == "application/vnd.sun.star.oleobject" )
734 bToBeCompressed = sal_True;
735 else if ( !m_bCompressedIsSetFromOutside )
736 bToBeCompressed = sal_False;
739 else
740 throw IllegalArgumentException(OSL_LOG_PREFIX "MediaType must be a string!\n",
741 uno::Reference< XInterface >(),
742 2 );
745 else if ( aPropertyName == "Size" )
747 if ( !( aValue >>= aEntry.nSize ) )
748 throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Size property!\n",
749 uno::Reference< XInterface >(),
750 2 );
752 else if ( aPropertyName == "Encrypted" )
754 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
755 throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
757 sal_Bool bEnc = sal_False;
758 if ( aValue >>= bEnc )
760 // In case of new raw stream, the stream must not be encrypted on storing
761 if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
762 throw IllegalArgumentException(OSL_LOG_PREFIX "Raw stream can not be encrypted on storing",
763 uno::Reference< XInterface >(),
764 2 );
766 bToBeEncrypted = bEnc;
767 if ( bToBeEncrypted && !m_xBaseEncryptionData.is() )
768 m_xBaseEncryptionData = new BaseEncryptionData;
770 else
771 throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Encrypted property!\n",
772 uno::Reference< XInterface >(),
773 2 );
776 else if ( aPropertyName == ENCRYPTION_KEY_PROPERTY )
778 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
779 throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
781 uno::Sequence< sal_Int8 > aNewKey;
783 if ( !( aValue >>= aNewKey ) )
785 OUString sTempString;
786 if ( ( aValue >>= sTempString ) )
788 sal_Int32 nPathLength = sTempString.getLength();
789 Sequence < sal_Int8 > aSequence ( nPathLength );
790 sal_Int8 *pArray = aSequence.getArray();
791 const sal_Unicode *pChar = sTempString.getStr();
792 for ( sal_Int16 i = 0; i < nPathLength; i++ )
793 pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
794 aNewKey = aSequence;
796 else
797 throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for EncryptionKey property!\n",
798 uno::Reference< XInterface >(),
799 2 );
802 if ( aNewKey.getLength() )
804 if ( !m_xBaseEncryptionData.is() )
805 m_xBaseEncryptionData = new BaseEncryptionData;
807 m_aEncryptionKey = aNewKey;
808 // In case of new raw stream, the stream must not be encrypted on storing
809 bHaveOwnKey = sal_True;
810 if ( m_nStreamMode != PACKAGE_STREAM_RAW )
811 bToBeEncrypted = sal_True;
813 else
815 bHaveOwnKey = sal_False;
816 m_aEncryptionKey.realloc( 0 );
819 m_aStorageEncryptionKeys.realloc( 0 );
821 else if ( aPropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
823 if ( rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
824 throw beans::PropertyVetoException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
826 uno::Sequence< beans::NamedValue > aKeys;
827 if ( !( aValue >>= aKeys ) )
829 throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for StorageEncryptionKeys property!\n",
830 uno::Reference< XInterface >(),
831 2 );
834 if ( aKeys.getLength() )
836 if ( !m_xBaseEncryptionData.is() )
837 m_xBaseEncryptionData = new BaseEncryptionData;
839 m_aStorageEncryptionKeys = aKeys;
841 // In case of new raw stream, the stream must not be encrypted on storing
842 bHaveOwnKey = sal_True;
843 if ( m_nStreamMode != PACKAGE_STREAM_RAW )
844 bToBeEncrypted = sal_True;
846 else
848 bHaveOwnKey = sal_False;
849 m_aStorageEncryptionKeys.realloc( 0 );
852 m_aEncryptionKey.realloc( 0 );
854 else if ( aPropertyName == "Compressed" )
856 sal_Bool bCompr = sal_False;
858 if ( aValue >>= bCompr )
860 // In case of new raw stream, the stream must not be encrypted on storing
861 if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
862 throw IllegalArgumentException(OSL_LOG_PREFIX "Raw stream can not be encrypted on storing",
863 uno::Reference< XInterface >(),
864 2 );
866 bToBeCompressed = bCompr;
867 m_bCompressedIsSetFromOutside = sal_True;
869 else
870 throw IllegalArgumentException(OSL_LOG_PREFIX "Wrong type for Compressed property!\n",
871 uno::Reference< XInterface >(),
872 2 );
874 else
875 throw beans::UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
878 //--------------------------------------------------------------------------
879 Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
880 throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException )
882 Any aAny;
883 if ( PropertyName == "MediaType" )
885 aAny <<= sMediaType;
886 return aAny;
888 else if ( PropertyName == "Size" )
890 aAny <<= aEntry.nSize;
891 return aAny;
893 else if ( PropertyName == "Encrypted" )
895 aAny <<= ((m_nStreamMode == PACKAGE_STREAM_RAW) ? sal_True : bToBeEncrypted);
896 return aAny;
898 else if ( PropertyName == "WasEncrypted" )
900 aAny <<= bIsEncrypted;
901 return aAny;
903 else if ( PropertyName == "Compressed" )
905 aAny <<= bToBeCompressed;
906 return aAny;
908 else if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
910 aAny <<= m_aEncryptionKey;
911 return aAny;
913 else if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
915 aAny <<= m_aStorageEncryptionKeys;
916 return aAny;
918 else
919 throw beans::UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
922 //--------------------------------------------------------------------------
923 void ZipPackageStream::setSize ( const sal_Int64 nNewSize )
925 if ( aEntry.nCompressedSize != nNewSize )
926 aEntry.nMethod = DEFLATED;
927 aEntry.nSize = nNewSize;
929 //--------------------------------------------------------------------------
930 OUString ZipPackageStream::getImplementationName()
931 throw ( RuntimeException )
933 return OUString ("ZipPackageStream");
936 //--------------------------------------------------------------------------
937 Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
938 throw ( RuntimeException )
940 Sequence< OUString > aNames( 1 );
941 aNames[0] = "com.sun.star.packages.PackageStream";
942 return aNames;
944 //--------------------------------------------------------------------------
945 sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
946 throw ( RuntimeException )
948 return rServiceName == getSupportedServiceNames()[0];
951 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */