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