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.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 111 ZipPackageStream::~ZipPackageStream( void ) 112 { 113 } 114 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 205 sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const 206 { 207 return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : rZipPackage.GetEncAlgID(); 208 } 209 210 //-------------------------------------------------------------------------- 211 sal_Int32 ZipPackageStream::GetBlockSize() const 212 { 213 return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8; 214 } 215 216 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 233 void ZipPackageStream::SetBaseEncryptionData( const ::rtl::Reference< BaseEncryptionData >& xData ) 234 { 235 m_xBaseEncryptionData = xData; 236 } 237 238 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 919 void ZipPackageStream::setSize ( const sal_Int32 nNewSize ) 920 { 921 if ( aEntry.nCompressedSize != nNewSize ) 922 aEntry.nMethod = DEFLATED; 923 aEntry.nSize = nNewSize; 924 } 925 //-------------------------------------------------------------------------- 926 OUString ZipPackageStream::getImplementationName() 927 throw ( RuntimeException ) 928 { 929 return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageStream" ) ); 930 } 931 932 //-------------------------------------------------------------------------- 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 //-------------------------------------------------------------------------- 941 sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName ) 942 throw ( RuntimeException ) 943 { 944 return rServiceName == getSupportedServiceNames()[0]; 945 } 946 947