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 27 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 28 #include <com/sun/star/ucb/XProgressHandler.hpp> 29 #include <com/sun/star/packages/zip/ZipConstants.hpp> 30 #include <com/sun/star/xml/crypto/XCipherContext.hpp> 31 #include <com/sun/star/xml/crypto/XDigestContext.hpp> 32 #include <com/sun/star/xml/crypto/XCipherContextSupplier.hpp> 33 #include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp> 34 #include <com/sun/star/xml/crypto/CipherID.hpp> 35 #include <com/sun/star/xml/crypto/DigestID.hpp> 36 37 #include <comphelper/storagehelper.hxx> 38 #include <comphelper/processfactory.hxx> 39 #include <rtl/digest.h> 40 41 #include <vector> 42 43 #include "blowfishcontext.hxx" 44 #include "sha1context.hxx" 45 #include <ZipFile.hxx> 46 #include <ZipEnumeration.hxx> 47 #include <XUnbufferedStream.hxx> 48 #include <PackageConstants.hxx> 49 #include <EncryptedDataHeader.hxx> 50 #include <EncryptionData.hxx> 51 #include <MemoryByteGrabber.hxx> 52 53 #include <CRC32.hxx> 54 55 #define AES_CBC_BLOCK_SIZE 16 56 57 using namespace vos; 58 using namespace rtl; 59 using namespace com::sun::star; 60 using namespace com::sun::star::io; 61 using namespace com::sun::star::uno; 62 using namespace com::sun::star::ucb; 63 using namespace com::sun::star::lang; 64 using namespace com::sun::star::packages; 65 using namespace com::sun::star::packages::zip; 66 using namespace com::sun::star::packages::zip::ZipConstants; 67 68 69 /** This class is used to read entries from a zip file 70 */ 71 ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference < XMultiServiceFactory > &xNewFactory, sal_Bool bInitialise ) 72 throw(IOException, ZipException, RuntimeException) 73 : aGrabber(xInput) 74 , aInflater (sal_True) 75 , xStream(xInput) 76 , xSeek(xInput, UNO_QUERY) 77 , m_xFactory ( xNewFactory ) 78 , bRecoveryMode( sal_False ) 79 { 80 if (bInitialise) 81 { 82 if ( readCEN() == -1 ) 83 { 84 aEntries.clear(); 85 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), uno::Reference < XInterface > () ); 86 } 87 } 88 } 89 90 91 92 ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference < XMultiServiceFactory > &xNewFactory, sal_Bool bInitialise, sal_Bool bForceRecovery, uno::Reference < XProgressHandler > xProgress ) 93 throw(IOException, ZipException, RuntimeException) 94 : aGrabber(xInput) 95 , aInflater (sal_True) 96 , xStream(xInput) 97 , xSeek(xInput, UNO_QUERY) 98 , m_xFactory ( xNewFactory ) 99 , xProgressHandler( xProgress ) 100 , bRecoveryMode( bForceRecovery ) 101 { 102 if (bInitialise) 103 { 104 if ( bForceRecovery ) 105 { 106 recover(); 107 } 108 else if ( readCEN() == -1 ) 109 { 110 aEntries.clear(); 111 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), uno::Reference < XInterface > () ); 112 } 113 } 114 } 115 116 ZipFile::~ZipFile() 117 { 118 aEntries.clear(); 119 } 120 121 void ZipFile::setInputStream ( uno::Reference < XInputStream > xNewStream ) 122 { 123 ::osl::MutexGuard aGuard( m_aMutex ); 124 125 xStream = xNewStream; 126 xSeek = uno::Reference < XSeekable > ( xStream, UNO_QUERY ); 127 aGrabber.setInputStream ( xStream ); 128 } 129 130 uno::Reference< xml::crypto::XDigestContext > ZipFile::StaticGetDigestContextForChecksum( const uno::Reference< lang::XMultiServiceFactory >& xArgFactory, const ::rtl::Reference< EncryptionData >& xEncryptionData ) 131 { 132 uno::Reference< xml::crypto::XDigestContext > xDigestContext; 133 if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA256_1K ) 134 { 135 uno::Reference< lang::XMultiServiceFactory > xFactory = xArgFactory; 136 if ( !xFactory.is() ) 137 xFactory.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW ); 138 139 uno::Reference< xml::crypto::XDigestContextSupplier > xDigestContextSupplier( 140 xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ), 141 uno::UNO_QUERY_THROW ); 142 143 xDigestContext.set( xDigestContextSupplier->getDigestContext( xEncryptionData->m_nCheckAlg, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW ); 144 } 145 else if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA1_1K ) 146 xDigestContext.set( SHA1DigestContext::Create(), uno::UNO_SET_THROW ); 147 148 return xDigestContext; 149 } 150 151 uno::Reference< xml::crypto::XCipherContext > ZipFile::StaticGetCipher( const uno::Reference< lang::XMultiServiceFactory >& xArgFactory, const ::rtl::Reference< EncryptionData >& xEncryptionData, bool bEncrypt ) 152 { 153 uno::Reference< xml::crypto::XCipherContext > xResult; 154 155 try 156 { 157 uno::Sequence< sal_Int8 > aDerivedKey( xEncryptionData->m_nDerivedKeySize ); 158 if ( rtl_Digest_E_None != rtl_digest_PBKDF2( reinterpret_cast< sal_uInt8* >( aDerivedKey.getArray() ), 159 aDerivedKey.getLength(), 160 reinterpret_cast< const sal_uInt8 * > (xEncryptionData->m_aKey.getConstArray() ), 161 xEncryptionData->m_aKey.getLength(), 162 reinterpret_cast< const sal_uInt8 * > ( xEncryptionData->m_aSalt.getConstArray() ), 163 xEncryptionData->m_aSalt.getLength(), 164 xEncryptionData->m_nIterationCount ) ) 165 { 166 throw ZipIOException( ::rtl::OUString::createFromAscii( "Can not create derived key!\n" ), 167 uno::Reference< XInterface >() ); 168 } 169 170 if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING ) 171 { 172 uno::Reference< lang::XMultiServiceFactory > xFactory = xArgFactory; 173 if ( !xFactory.is() ) 174 xFactory.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW ); 175 176 uno::Reference< xml::crypto::XCipherContextSupplier > xCipherContextSupplier( 177 xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ), 178 uno::UNO_QUERY_THROW ); 179 180 xResult = xCipherContextSupplier->getCipherContext( xEncryptionData->m_nEncAlg, aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt, uno::Sequence< beans::NamedValue >() ); 181 } 182 else if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::BLOWFISH_CFB_8 ) 183 { 184 xResult = BlowfishCFB8CipherContext::Create( aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt ); 185 } 186 else 187 { 188 throw ZipIOException( ::rtl::OUString::createFromAscii( "Unknown cipher algorithm is requested!\n" ), 189 uno::Reference< XInterface >() ); 190 } 191 } 192 catch( uno::Exception& ) 193 { 194 OSL_ENSURE( sal_False, "Can not create cipher context!" ); 195 } 196 197 return xResult; 198 } 199 200 void ZipFile::StaticFillHeader( const ::rtl::Reference< EncryptionData >& rData, 201 sal_Int32 nSize, 202 const ::rtl::OUString& aMediaType, 203 sal_Int8 * & pHeader ) 204 { 205 // I think it's safe to restrict vector and salt length to 2 bytes ! 206 sal_Int16 nIVLength = static_cast < sal_Int16 > ( rData->m_aInitVector.getLength() ); 207 sal_Int16 nSaltLength = static_cast < sal_Int16 > ( rData->m_aSalt.getLength() ); 208 sal_Int16 nDigestLength = static_cast < sal_Int16 > ( rData->m_aDigest.getLength() ); 209 sal_Int16 nMediaTypeLength = static_cast < sal_Int16 > ( aMediaType.getLength() * sizeof( sal_Unicode ) ); 210 211 // First the header 212 *(pHeader++) = ( n_ConstHeader >> 0 ) & 0xFF; 213 *(pHeader++) = ( n_ConstHeader >> 8 ) & 0xFF; 214 *(pHeader++) = ( n_ConstHeader >> 16 ) & 0xFF; 215 *(pHeader++) = ( n_ConstHeader >> 24 ) & 0xFF; 216 217 // Then the version 218 *(pHeader++) = ( n_ConstCurrentVersion >> 0 ) & 0xFF; 219 *(pHeader++) = ( n_ConstCurrentVersion >> 8 ) & 0xFF; 220 221 // Then the iteration Count 222 sal_Int32 nIterationCount = rData->m_nIterationCount; 223 *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 0 ) & 0xFF); 224 *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 8 ) & 0xFF); 225 *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 16 ) & 0xFF); 226 *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 24 ) & 0xFF); 227 228 // Then the size 229 *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 0 ) & 0xFF); 230 *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 8 ) & 0xFF); 231 *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 16 ) & 0xFF); 232 *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 24 ) & 0xFF); 233 234 // Then the encryption algorithm 235 sal_Int32 nEncAlgID = rData->m_nEncAlg; 236 *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 0 ) & 0xFF); 237 *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 8 ) & 0xFF); 238 *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 16 ) & 0xFF); 239 *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 24 ) & 0xFF); 240 241 // Then the checksum algorithm 242 sal_Int32 nChecksumAlgID = rData->m_nCheckAlg; 243 *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 0 ) & 0xFF); 244 *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 8 ) & 0xFF); 245 *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 16 ) & 0xFF); 246 *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 24 ) & 0xFF); 247 248 // Then the derived key size 249 sal_Int32 nDerivedKeySize = rData->m_nDerivedKeySize; 250 *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 0 ) & 0xFF); 251 *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 8 ) & 0xFF); 252 *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 16 ) & 0xFF); 253 *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 24 ) & 0xFF); 254 255 // Then the start key generation algorithm 256 sal_Int32 nKeyAlgID = rData->m_nStartKeyGenID; 257 *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 0 ) & 0xFF); 258 *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 8 ) & 0xFF); 259 *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 16 ) & 0xFF); 260 *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 24 ) & 0xFF); 261 262 // Then the salt length 263 *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 0 ) & 0xFF); 264 *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 8 ) & 0xFF); 265 266 // Then the IV length 267 *(pHeader++) = static_cast< sal_Int8 >(( nIVLength >> 0 ) & 0xFF); 268 *(pHeader++) = static_cast< sal_Int8 >(( nIVLength >> 8 ) & 0xFF); 269 270 // Then the digest length 271 *(pHeader++) = static_cast< sal_Int8 >(( nDigestLength >> 0 ) & 0xFF); 272 *(pHeader++) = static_cast< sal_Int8 >(( nDigestLength >> 8 ) & 0xFF); 273 274 // Then the mediatype length 275 *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 0 ) & 0xFF); 276 *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 8 ) & 0xFF); 277 278 // Then the salt content 279 rtl_copyMemory ( pHeader, rData->m_aSalt.getConstArray(), nSaltLength ); 280 pHeader += nSaltLength; 281 282 // Then the IV content 283 rtl_copyMemory ( pHeader, rData->m_aInitVector.getConstArray(), nIVLength ); 284 pHeader += nIVLength; 285 286 // Then the digest content 287 rtl_copyMemory ( pHeader, rData->m_aDigest.getConstArray(), nDigestLength ); 288 pHeader += nDigestLength; 289 290 // Then the mediatype itself 291 rtl_copyMemory ( pHeader, aMediaType.getStr(), nMediaTypeLength ); 292 pHeader += nMediaTypeLength; 293 } 294 295 sal_Bool ZipFile::StaticFillData ( ::rtl::Reference< BaseEncryptionData > & rData, 296 sal_Int32 &rEncAlg, 297 sal_Int32 &rChecksumAlg, 298 sal_Int32 &rDerivedKeySize, 299 sal_Int32 &rStartKeyGenID, 300 sal_Int32 &rSize, 301 ::rtl::OUString& aMediaType, 302 const uno::Reference< XInputStream >& rStream ) 303 { 304 sal_Bool bOk = sal_False; 305 const sal_Int32 nHeaderSize = n_ConstHeaderSize - 4; 306 Sequence < sal_Int8 > aBuffer ( nHeaderSize ); 307 if ( nHeaderSize == rStream->readBytes ( aBuffer, nHeaderSize ) ) 308 { 309 sal_Int16 nPos = 0; 310 sal_Int8 *pBuffer = aBuffer.getArray(); 311 sal_Int16 nVersion = pBuffer[nPos++] & 0xFF; 312 nVersion |= ( pBuffer[nPos++] & 0xFF ) << 8; 313 if ( nVersion == n_ConstCurrentVersion ) 314 { 315 sal_Int32 nCount = pBuffer[nPos++] & 0xFF; 316 nCount |= ( pBuffer[nPos++] & 0xFF ) << 8; 317 nCount |= ( pBuffer[nPos++] & 0xFF ) << 16; 318 nCount |= ( pBuffer[nPos++] & 0xFF ) << 24; 319 rData->m_nIterationCount = nCount; 320 321 rSize = pBuffer[nPos++] & 0xFF; 322 rSize |= ( pBuffer[nPos++] & 0xFF ) << 8; 323 rSize |= ( pBuffer[nPos++] & 0xFF ) << 16; 324 rSize |= ( pBuffer[nPos++] & 0xFF ) << 24; 325 326 rEncAlg = pBuffer[nPos++] & 0xFF; 327 rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 8; 328 rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 16; 329 rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 24; 330 331 rChecksumAlg = pBuffer[nPos++] & 0xFF; 332 rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 8; 333 rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 16; 334 rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 24; 335 336 rDerivedKeySize = pBuffer[nPos++] & 0xFF; 337 rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 8; 338 rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 16; 339 rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 24; 340 341 rStartKeyGenID = pBuffer[nPos++] & 0xFF; 342 rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 8; 343 rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 16; 344 rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 24; 345 346 sal_Int16 nSaltLength = pBuffer[nPos++] & 0xFF; 347 nSaltLength |= ( pBuffer[nPos++] & 0xFF ) << 8; 348 sal_Int16 nIVLength = ( pBuffer[nPos++] & 0xFF ); 349 nIVLength |= ( pBuffer[nPos++] & 0xFF ) << 8; 350 sal_Int16 nDigestLength = pBuffer[nPos++] & 0xFF; 351 nDigestLength |= ( pBuffer[nPos++] & 0xFF ) << 8; 352 353 sal_Int16 nMediaTypeLength = pBuffer[nPos++] & 0xFF; 354 nMediaTypeLength |= ( pBuffer[nPos++] & 0xFF ) << 8; 355 356 if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) ) 357 { 358 rData->m_aSalt.realloc ( nSaltLength ); 359 rtl_copyMemory ( rData->m_aSalt.getArray(), aBuffer.getConstArray(), nSaltLength ); 360 if ( nIVLength == rStream->readBytes ( aBuffer, nIVLength ) ) 361 { 362 rData->m_aInitVector.realloc ( nIVLength ); 363 rtl_copyMemory ( rData->m_aInitVector.getArray(), aBuffer.getConstArray(), nIVLength ); 364 if ( nDigestLength == rStream->readBytes ( aBuffer, nDigestLength ) ) 365 { 366 rData->m_aDigest.realloc ( nDigestLength ); 367 rtl_copyMemory ( rData->m_aDigest.getArray(), aBuffer.getConstArray(), nDigestLength ); 368 369 if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) ) 370 { 371 aMediaType = ::rtl::OUString( (sal_Unicode*)aBuffer.getConstArray(), 372 nMediaTypeLength / sizeof( sal_Unicode ) ); 373 bOk = sal_True; 374 } 375 } 376 } 377 } 378 } 379 } 380 return bOk; 381 } 382 383 uno::Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory, 384 const uno::Reference< XInputStream >& xStream, 385 const ::rtl::Reference< EncryptionData > &rData ) 386 throw ( packages::WrongPasswordException, ZipIOException, RuntimeException ) 387 { 388 if ( !rData.is() ) 389 throw ZipIOException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ), 390 uno::Reference< XInterface >() ); 391 392 if ( !rData->m_aKey.getLength() ) 393 throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 394 395 uno::Reference< XSeekable > xSeek( xStream, UNO_QUERY ); 396 if ( !xSeek.is() ) 397 throw ZipIOException( OUString::createFromAscii( "The stream must be seekable!\n" ), 398 uno::Reference< XInterface >() ); 399 400 401 // if we have a digest, then this file is an encrypted one and we should 402 // check if we can decrypt it or not 403 OSL_ENSURE( rData->m_aDigest.getLength(), "Can't detect password correctness without digest!\n" ); 404 if ( rData->m_aDigest.getLength() ) 405 { 406 sal_Int32 nSize = sal::static_int_cast< sal_Int32 >( xSeek->getLength() ); 407 if ( nSize > n_ConstDigestLength + 32 ) 408 nSize = n_ConstDigestLength + 32; 409 410 // skip header 411 xSeek->seek( n_ConstHeaderSize + rData->m_aInitVector.getLength() + 412 rData->m_aSalt.getLength() + rData->m_aDigest.getLength() ); 413 414 // Only want to read enough to verify the digest 415 Sequence < sal_Int8 > aReadBuffer ( nSize ); 416 417 xStream->readBytes( aReadBuffer, nSize ); 418 419 if ( !StaticHasValidPassword( xFactory, aReadBuffer, rData ) ) 420 throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 421 } 422 423 return new XUnbufferedStream( xFactory, xStream, rData ); 424 } 425 426 #if 0 427 // for debugging purposes 428 void CheckSequence( const uno::Sequence< sal_Int8 >& aSequence ) 429 { 430 if ( aSequence.getLength() ) 431 { 432 sal_Int32* pPointer = *( (sal_Int32**)&aSequence ); 433 sal_Int32 nSize = *( pPointer + 1 ); 434 sal_Int32 nMemSize = *( pPointer - 2 ); 435 sal_Int32 nUsedMemSize = ( nSize + 4 * sizeof( sal_Int32 ) ); 436 OSL_ENSURE( nSize == aSequence.getLength() && nUsedMemSize + 7 - ( nUsedMemSize - 1 ) % 8 == nMemSize, "Broken Sequence!" ); 437 } 438 } 439 #endif 440 441 sal_Bool ZipFile::StaticHasValidPassword( const uno::Reference< lang::XMultiServiceFactory >& xFactory, const Sequence< sal_Int8 > &aReadBuffer, const ::rtl::Reference< EncryptionData > &rData ) 442 { 443 if ( !rData.is() || !rData->m_aKey.getLength() ) 444 return sal_False; 445 446 sal_Bool bRet = sal_False; 447 448 uno::Reference< xml::crypto::XCipherContext > xCipher( StaticGetCipher( xFactory, rData, false ), uno::UNO_SET_THROW ); 449 450 uno::Sequence< sal_Int8 > aDecryptBuffer; 451 uno::Sequence< sal_Int8 > aDecryptBuffer2; 452 try 453 { 454 aDecryptBuffer = xCipher->convertWithCipherContext( aReadBuffer ); 455 aDecryptBuffer2 = xCipher->finalizeCipherContextAndDispose(); 456 } 457 catch( uno::Exception& ) 458 { 459 // decryption with padding will throw the exception in finalizing if the buffer represent only part of the stream 460 // it is no problem, actually this is why we read 32 additional bytes ( two of maximal possible encryption blocks ) 461 } 462 463 if ( aDecryptBuffer2.getLength() ) 464 { 465 sal_Int32 nOldLen = aDecryptBuffer.getLength(); 466 aDecryptBuffer.realloc( nOldLen + aDecryptBuffer2.getLength() ); 467 rtl_copyMemory( aDecryptBuffer.getArray() + nOldLen, aDecryptBuffer2.getArray(), aDecryptBuffer2.getLength() ); 468 } 469 470 if ( aDecryptBuffer.getLength() > n_ConstDigestLength ) 471 aDecryptBuffer.realloc( n_ConstDigestLength ); 472 473 uno::Sequence< sal_Int8 > aDigestSeq; 474 uno::Reference< xml::crypto::XDigestContext > xDigestContext( StaticGetDigestContextForChecksum( xFactory, rData ), uno::UNO_SET_THROW ); 475 476 xDigestContext->updateDigest( aDecryptBuffer ); 477 aDigestSeq = xDigestContext->finalizeDigestAndDispose(); 478 479 // If we don't have a digest, then we have to assume that the password is correct 480 if ( rData->m_aDigest.getLength() != 0 && 481 ( aDigestSeq.getLength() != rData->m_aDigest.getLength() || 482 0 != rtl_compareMemory ( aDigestSeq.getConstArray(), 483 rData->m_aDigest.getConstArray(), 484 aDigestSeq.getLength() ) ) ) 485 { 486 // We should probably tell the user that the password they entered was wrong 487 } 488 else 489 bRet = sal_True; 490 491 return bRet; 492 } 493 494 sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference< EncryptionData >& rData ) 495 { 496 ::osl::MutexGuard aGuard( m_aMutex ); 497 498 sal_Bool bRet = sal_False; 499 if ( rData.is() && rData->m_aKey.getLength() ) 500 { 501 xSeek->seek( rEntry.nOffset ); 502 sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize; 503 504 // Only want to read enough to verify the digest 505 if ( nSize > n_ConstDigestDecrypt ) 506 nSize = n_ConstDigestDecrypt; 507 508 Sequence < sal_Int8 > aReadBuffer ( nSize ); 509 510 xStream->readBytes( aReadBuffer, nSize ); 511 512 bRet = StaticHasValidPassword( m_xFactory, aReadBuffer, rData ); 513 } 514 515 return bRet; 516 } 517 518 uno::Reference< XInputStream > ZipFile::createUnbufferedStream( 519 SotMutexHolderRef aMutexHolder, 520 ZipEntry & rEntry, 521 const ::rtl::Reference< EncryptionData > &rData, 522 sal_Int8 nStreamMode, 523 sal_Bool bIsEncrypted, 524 ::rtl::OUString aMediaType ) 525 { 526 ::osl::MutexGuard aGuard( m_aMutex ); 527 528 return new XUnbufferedStream ( m_xFactory, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode ); 529 } 530 531 532 ZipEnumeration * SAL_CALL ZipFile::entries( ) 533 { 534 return new ZipEnumeration ( aEntries ); 535 } 536 537 uno::Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry, 538 const ::rtl::Reference< EncryptionData > &rData, 539 sal_Bool bIsEncrypted, 540 SotMutexHolderRef aMutexHolder ) 541 throw(IOException, ZipException, RuntimeException) 542 { 543 ::osl::MutexGuard aGuard( m_aMutex ); 544 545 if ( rEntry.nOffset <= 0 ) 546 readLOC( rEntry ); 547 548 // We want to return a rawStream if we either don't have a key or if the 549 // key is wrong 550 551 sal_Bool bNeedRawStream = rEntry.nMethod == STORED; 552 553 // if we have a digest, then this file is an encrypted one and we should 554 // check if we can decrypt it or not 555 if ( bIsEncrypted && rData.is() && rData->m_aDigest.getLength() ) 556 bNeedRawStream = !hasValidPassword ( rEntry, rData ); 557 558 return createUnbufferedStream ( aMutexHolder, 559 rEntry, 560 rData, 561 bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, 562 bIsEncrypted ); 563 } 564 565 uno::Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry, 566 const ::rtl::Reference< EncryptionData > &rData, 567 sal_Bool bIsEncrypted, 568 SotMutexHolderRef aMutexHolder ) 569 throw ( packages::WrongPasswordException, 570 IOException, 571 ZipException, 572 RuntimeException ) 573 { 574 ::osl::MutexGuard aGuard( m_aMutex ); 575 576 if ( rEntry.nOffset <= 0 ) 577 readLOC( rEntry ); 578 579 // An exception must be thrown in case stream is encrypted and 580 // there is no key or the key is wrong 581 sal_Bool bNeedRawStream = sal_False; 582 if ( bIsEncrypted ) 583 { 584 // in case no digest is provided there is no way 585 // to detect password correctness 586 if ( !rData.is() ) 587 throw ZipException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ), 588 uno::Reference< XInterface >() ); 589 590 // if we have a digest, then this file is an encrypted one and we should 591 // check if we can decrypt it or not 592 OSL_ENSURE( rData->m_aDigest.getLength(), "Can't detect password correctness without digest!\n" ); 593 if ( rData->m_aDigest.getLength() && !hasValidPassword ( rEntry, rData ) ) 594 throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 595 } 596 else 597 bNeedRawStream = ( rEntry.nMethod == STORED ); 598 599 return createUnbufferedStream ( aMutexHolder, 600 rEntry, 601 rData, 602 bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, 603 bIsEncrypted ); 604 } 605 606 uno::Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry, 607 const ::rtl::Reference< EncryptionData >& rData, 608 sal_Bool bIsEncrypted, 609 SotMutexHolderRef aMutexHolder ) 610 throw(IOException, ZipException, RuntimeException) 611 { 612 ::osl::MutexGuard aGuard( m_aMutex ); 613 614 if ( rEntry.nOffset <= 0 ) 615 readLOC( rEntry ); 616 617 return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted ); 618 } 619 620 uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream( 621 ZipEntry& rEntry, 622 const ::rtl::Reference< EncryptionData >& rData, 623 const ::rtl::OUString& aMediaType, 624 SotMutexHolderRef aMutexHolder ) 625 throw ( packages::NoEncryptionException, 626 IOException, 627 ZipException, 628 RuntimeException ) 629 { 630 ::osl::MutexGuard aGuard( m_aMutex ); 631 632 if ( !rData.is() ) 633 throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); 634 635 if ( rEntry.nOffset <= 0 ) 636 readLOC( rEntry ); 637 638 return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, sal_True, aMediaType ); 639 } 640 641 sal_Bool ZipFile::readLOC( ZipEntry &rEntry ) 642 throw(IOException, ZipException, RuntimeException) 643 { 644 ::osl::MutexGuard aGuard( m_aMutex ); 645 646 sal_Int32 nTestSig, nTime, nCRC, nSize, nCompressedSize; 647 sal_Int16 nVersion, nFlag, nHow, nPathLen, nExtraLen; 648 sal_Int32 nPos = -rEntry.nOffset; 649 650 aGrabber.seek(nPos); 651 aGrabber >> nTestSig; 652 653 if (nTestSig != LOCSIG) 654 throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid LOC header (bad signature") ), uno::Reference < XInterface > () ); 655 aGrabber >> nVersion; 656 aGrabber >> nFlag; 657 aGrabber >> nHow; 658 aGrabber >> nTime; 659 aGrabber >> nCRC; 660 aGrabber >> nCompressedSize; 661 aGrabber >> nSize; 662 aGrabber >> nPathLen; 663 aGrabber >> nExtraLen; 664 rEntry.nOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nPathLen + nExtraLen; 665 666 // read always in UTF8, some tools seem not to set UTF8 bit 667 uno::Sequence < sal_Int8 > aNameBuffer( nPathLen ); 668 sal_Int32 nRead = aGrabber.readBytes( aNameBuffer, nPathLen ); 669 if ( nRead < aNameBuffer.getLength() ) 670 aNameBuffer.realloc( nRead ); 671 672 ::rtl::OUString sLOCPath = rtl::OUString::intern( (sal_Char *) aNameBuffer.getArray(), 673 aNameBuffer.getLength(), 674 RTL_TEXTENCODING_UTF8 ); 675 676 if ( rEntry.nPathLen == -1 ) // the file was created 677 { 678 rEntry.nPathLen = nPathLen; 679 rEntry.sPath = sLOCPath; 680 } 681 682 // the method can be reset for internal use so it is not checked 683 sal_Bool bBroken = rEntry.nVersion != nVersion 684 || rEntry.nFlag != nFlag 685 || rEntry.nTime != nTime 686 || rEntry.nPathLen != nPathLen 687 || !rEntry.sPath.equals( sLOCPath ); 688 689 if ( bBroken && !bRecoveryMode ) 690 throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ), 691 uno::Reference< XInterface >() ); 692 693 return sal_True; 694 } 695 696 sal_Int32 ZipFile::findEND( ) 697 throw(IOException, ZipException, RuntimeException) 698 { 699 // this method is called in constructor only, no need for mutex 700 sal_Int32 nLength, nPos, nEnd; 701 Sequence < sal_Int8 > aBuffer; 702 try 703 { 704 nLength = static_cast <sal_Int32 > (aGrabber.getLength()); 705 if (nLength == 0 || nLength < ENDHDR) 706 return -1; 707 nPos = nLength - ENDHDR - ZIP_MAXNAMELEN; 708 nEnd = nPos >= 0 ? nPos : 0 ; 709 710 aGrabber.seek( nEnd ); 711 aGrabber.readBytes ( aBuffer, nLength - nEnd ); 712 713 const sal_Int8 *pBuffer = aBuffer.getConstArray(); 714 715 nPos = nLength - nEnd - ENDHDR; 716 while ( nPos >= 0 ) 717 { 718 if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 5 && pBuffer[nPos+3] == 6 ) 719 return nPos + nEnd; 720 nPos--; 721 } 722 } 723 catch ( IllegalArgumentException& ) 724 { 725 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 726 } 727 catch ( NotConnectedException& ) 728 { 729 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 730 } 731 catch ( BufferSizeExceededException& ) 732 { 733 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 734 } 735 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 736 } 737 738 sal_Int32 ZipFile::readCEN() 739 throw(IOException, ZipException, RuntimeException) 740 { 741 // this method is called in constructor only, no need for mutex 742 sal_Int32 nCenLen, nCenPos = -1, nCenOff, nEndPos, nLocPos; 743 sal_uInt16 nCount, nTotal; 744 745 try 746 { 747 nEndPos = findEND(); 748 if (nEndPos == -1) 749 return -1; 750 aGrabber.seek(nEndPos + ENDTOT); 751 aGrabber >> nTotal; 752 aGrabber >> nCenLen; 753 aGrabber >> nCenOff; 754 755 if ( nTotal * CENHDR > nCenLen ) 756 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "invalid END header (bad entry count)") ), uno::Reference < XInterface > () ); 757 758 if ( nTotal > ZIP_MAXENTRIES ) 759 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "too many entries in ZIP File") ), uno::Reference < XInterface > () ); 760 761 if ( nCenLen < 0 || nCenLen > nEndPos ) 762 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference < XInterface > () ); 763 764 nCenPos = nEndPos - nCenLen; 765 766 if ( nCenOff < 0 || nCenOff > nCenPos ) 767 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference < XInterface > () ); 768 769 nLocPos = nCenPos - nCenOff; 770 aGrabber.seek( nCenPos ); 771 Sequence < sal_Int8 > aCENBuffer ( nCenLen ); 772 sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer, nCenLen ); 773 if ( static_cast < sal_Int64 > ( nCenLen ) != nRead ) 774 throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Error reading CEN into memory buffer!") ), uno::Reference < XInterface > () ); 775 776 MemoryByteGrabber aMemGrabber ( aCENBuffer ); 777 778 ZipEntry aEntry; 779 sal_Int32 nTestSig; 780 sal_Int16 nCommentLen; 781 782 for (nCount = 0 ; nCount < nTotal; nCount++) 783 { 784 aMemGrabber >> nTestSig; 785 if ( nTestSig != CENSIG ) 786 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), uno::Reference < XInterface > () ); 787 788 aMemGrabber.skipBytes ( 2 ); 789 aMemGrabber >> aEntry.nVersion; 790 791 if ( ( aEntry.nVersion & 1 ) == 1 ) 792 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), uno::Reference < XInterface > () ); 793 794 aMemGrabber >> aEntry.nFlag; 795 aMemGrabber >> aEntry.nMethod; 796 797 if ( aEntry.nMethod != STORED && aEntry.nMethod != DEFLATED) 798 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), uno::Reference < XInterface > () ); 799 800 aMemGrabber >> aEntry.nTime; 801 aMemGrabber >> aEntry.nCrc; 802 aMemGrabber >> aEntry.nCompressedSize; 803 aMemGrabber >> aEntry.nSize; 804 aMemGrabber >> aEntry.nPathLen; 805 aMemGrabber >> aEntry.nExtraLen; 806 aMemGrabber >> nCommentLen; 807 aMemGrabber.skipBytes ( 8 ); 808 aMemGrabber >> aEntry.nOffset; 809 810 aEntry.nOffset += nLocPos; 811 aEntry.nOffset *= -1; 812 813 if ( aEntry.nPathLen < 0 ) 814 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected name length" ) ), uno::Reference < XInterface > () ); 815 816 if ( nCommentLen < 0 ) 817 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected comment length" ) ), uno::Reference < XInterface > () ); 818 819 if ( aEntry.nExtraLen < 0 ) 820 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected extra header info length") ), uno::Reference < XInterface > () ); 821 822 // read always in UTF8, some tools seem not to set UTF8 bit 823 aEntry.sPath = rtl::OUString::intern ( (sal_Char *) aMemGrabber.getCurrentPos(), 824 aEntry.nPathLen, 825 RTL_TEXTENCODING_UTF8 ); 826 827 if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( aEntry.sPath, sal_True ) ) 828 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip entry has an invalid name.") ), uno::Reference < XInterface > () ); 829 830 aMemGrabber.skipBytes( aEntry.nPathLen + aEntry.nExtraLen + nCommentLen ); 831 aEntries[aEntry.sPath] = aEntry; 832 } 833 834 if (nCount != nTotal) 835 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), uno::Reference < XInterface > () ); 836 } 837 catch ( IllegalArgumentException & ) 838 { 839 // seek can throw this... 840 nCenPos = -1; // make sure we return -1 to indicate an error 841 } 842 return nCenPos; 843 } 844 845 sal_Int32 ZipFile::recover() 846 throw(IOException, ZipException, RuntimeException) 847 { 848 ::osl::MutexGuard aGuard( m_aMutex ); 849 850 sal_Int32 nLength; 851 Sequence < sal_Int8 > aBuffer; 852 Sequence < sal_Int32 > aHeaderOffsets; 853 854 try 855 { 856 nLength = static_cast <sal_Int32 > (aGrabber.getLength()); 857 if (nLength == 0 || nLength < ENDHDR) 858 return -1; 859 860 aGrabber.seek( 0 ); 861 862 const sal_Int32 nToRead = 32000; 863 for( sal_Int32 nGenPos = 0; aGrabber.readBytes( aBuffer, nToRead ) && aBuffer.getLength() > 16; ) 864 { 865 const sal_Int8 *pBuffer = aBuffer.getConstArray(); 866 sal_Int32 nBufSize = aBuffer.getLength(); 867 868 sal_Int32 nPos = 0; 869 // the buffer should contain at least one header, 870 // or if it is end of the file, at least the postheader with sizes and hash 871 while( nPos < nBufSize - 30 872 || ( aBuffer.getLength() < nToRead && nPos < nBufSize - 16 ) ) 873 874 { 875 if ( nPos < nBufSize - 30 && pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 3 && pBuffer[nPos+3] == 4 ) 876 { 877 ZipEntry aEntry; 878 MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 26 ) ); 879 880 aMemGrabber >> aEntry.nVersion; 881 if ( ( aEntry.nVersion & 1 ) != 1 ) 882 { 883 aMemGrabber >> aEntry.nFlag; 884 aMemGrabber >> aEntry.nMethod; 885 886 if ( aEntry.nMethod == STORED || aEntry.nMethod == DEFLATED ) 887 { 888 aMemGrabber >> aEntry.nTime; 889 aMemGrabber >> aEntry.nCrc; 890 aMemGrabber >> aEntry.nCompressedSize; 891 aMemGrabber >> aEntry.nSize; 892 aMemGrabber >> aEntry.nPathLen; 893 aMemGrabber >> aEntry.nExtraLen; 894 895 sal_Int32 nDescrLength = 896 ( aEntry.nMethod == DEFLATED && ( aEntry.nFlag & 8 ) ) ? 897 16 : 0; 898 899 900 // This is a quick fix for OOo1.1RC 901 // For OOo2.0 the whole package must be switched to unsigned values 902 if ( aEntry.nCompressedSize < 0 ) aEntry.nCompressedSize = 0x7FFFFFFF; 903 if ( aEntry.nSize < 0 ) aEntry.nSize = 0x7FFFFFFF; 904 if ( aEntry.nPathLen < 0 ) aEntry.nPathLen = 0x7FFF; 905 if ( aEntry.nExtraLen < 0 ) aEntry.nExtraLen = 0x7FFF; 906 // End of quick fix 907 908 sal_Int32 nDataSize = ( aEntry.nMethod == DEFLATED ) ? aEntry.nCompressedSize : aEntry.nSize; 909 sal_Int32 nBlockLength = nDataSize + aEntry.nPathLen + aEntry.nExtraLen + 30 + nDescrLength; 910 if ( aEntry.nPathLen >= 0 && aEntry.nExtraLen >= 0 911 && ( nGenPos + nPos + nBlockLength ) <= nLength ) 912 { 913 // read always in UTF8, some tools seem not to set UTF8 bit 914 if( nPos + 30 + aEntry.nPathLen <= nBufSize ) 915 aEntry.sPath = OUString ( (sal_Char *) &pBuffer[nPos + 30], 916 aEntry.nPathLen, 917 RTL_TEXTENCODING_UTF8 ); 918 else 919 { 920 Sequence < sal_Int8 > aFileName; 921 aGrabber.seek( nGenPos + nPos + 30 ); 922 aGrabber.readBytes( aFileName, aEntry.nPathLen ); 923 aEntry.sPath = OUString ( (sal_Char *) aFileName.getArray(), 924 aFileName.getLength(), 925 RTL_TEXTENCODING_UTF8 ); 926 aEntry.nPathLen = static_cast< sal_Int16 >(aFileName.getLength()); 927 } 928 929 aEntry.nOffset = nGenPos + nPos + 30 + aEntry.nPathLen + aEntry.nExtraLen; 930 931 if ( ( aEntry.nSize || aEntry.nCompressedSize ) && !checkSizeAndCRC( aEntry ) ) 932 { 933 aEntry.nCrc = 0; 934 aEntry.nCompressedSize = 0; 935 aEntry.nSize = 0; 936 } 937 938 if ( aEntries.find( aEntry.sPath ) == aEntries.end() ) 939 aEntries[aEntry.sPath] = aEntry; 940 } 941 } 942 } 943 944 nPos += 4; 945 } 946 else if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 7 && pBuffer[nPos+3] == 8 ) 947 { 948 sal_Int32 nCompressedSize, nSize, nCRC32; 949 MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 12 ) ); 950 aMemGrabber >> nCRC32; 951 aMemGrabber >> nCompressedSize; 952 aMemGrabber >> nSize; 953 954 for( EntryHash::iterator aIter = aEntries.begin(); aIter != aEntries.end(); aIter++ ) 955 { 956 ZipEntry aTmp = (*aIter).second; 957 958 // this is a broken package, accept this block not only for DEFLATED streams 959 if( (*aIter).second.nFlag & 8 ) 960 { 961 sal_Int32 nStreamOffset = nGenPos + nPos - nCompressedSize; 962 if ( nStreamOffset == (*aIter).second.nOffset && nCompressedSize > (*aIter).second.nCompressedSize ) 963 { 964 // only DEFLATED blocks need to be checked 965 sal_Bool bAcceptBlock = ( (*aIter).second.nMethod == STORED && nCompressedSize == nSize ); 966 967 if ( !bAcceptBlock ) 968 { 969 sal_Int32 nRealSize = 0, nRealCRC = 0; 970 getSizeAndCRC( nStreamOffset, nCompressedSize, &nRealSize, &nRealCRC ); 971 bAcceptBlock = ( nRealSize == nSize && nRealCRC == nCRC32 ); 972 } 973 974 if ( bAcceptBlock ) 975 { 976 (*aIter).second.nCrc = nCRC32; 977 (*aIter).second.nCompressedSize = nCompressedSize; 978 (*aIter).second.nSize = nSize; 979 } 980 } 981 #if 0 982 // for now ignore clearly broken streams 983 else if( !(*aIter).second.nCompressedSize ) 984 { 985 (*aIter).second.nCrc = nCRC32; 986 sal_Int32 nRealStreamSize = nGenPos + nPos - (*aIter).second.nOffset; 987 (*aIter).second.nCompressedSize = nGenPos + nPos - (*aIter).second.nOffset; 988 (*aIter).second.nSize = nSize; 989 } 990 #endif 991 } 992 } 993 994 nPos += 4; 995 } 996 else 997 nPos++; 998 } 999 1000 nGenPos += nPos; 1001 aGrabber.seek( nGenPos ); 1002 } 1003 1004 return 0; 1005 } 1006 catch ( IllegalArgumentException& ) 1007 { 1008 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 1009 } 1010 catch ( NotConnectedException& ) 1011 { 1012 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 1013 } 1014 catch ( BufferSizeExceededException& ) 1015 { 1016 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () ); 1017 } 1018 } 1019 1020 sal_Bool ZipFile::checkSizeAndCRC( const ZipEntry& aEntry ) 1021 { 1022 ::osl::MutexGuard aGuard( m_aMutex ); 1023 1024 sal_Int32 nSize = 0, nCRC = 0; 1025 1026 if( aEntry.nMethod == STORED ) 1027 return ( getCRC( aEntry.nOffset, aEntry.nSize ) == aEntry.nCrc ); 1028 1029 getSizeAndCRC( aEntry.nOffset, aEntry.nCompressedSize, &nSize, &nCRC ); 1030 return ( aEntry.nSize == nSize && aEntry.nCrc == nCRC ); 1031 } 1032 1033 sal_Int32 ZipFile::getCRC( sal_Int32 nOffset, sal_Int32 nSize ) 1034 { 1035 ::osl::MutexGuard aGuard( m_aMutex ); 1036 1037 Sequence < sal_Int8 > aBuffer; 1038 CRC32 aCRC; 1039 sal_Int32 nBlockSize = ::std::min( nSize, static_cast< sal_Int32 >( 32000 ) ); 1040 1041 aGrabber.seek( nOffset ); 1042 for ( int ind = 0; 1043 aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize; 1044 ind++ ) 1045 { 1046 aCRC.updateSegment( aBuffer, 0, ::std::min( nBlockSize, nSize - ind * nBlockSize ) ); 1047 } 1048 1049 return aCRC.getValue(); 1050 } 1051 1052 void ZipFile::getSizeAndCRC( sal_Int32 nOffset, sal_Int32 nCompressedSize, sal_Int32 *nSize, sal_Int32 *nCRC ) 1053 { 1054 ::osl::MutexGuard aGuard( m_aMutex ); 1055 1056 Sequence < sal_Int8 > aBuffer; 1057 CRC32 aCRC; 1058 sal_Int32 nRealSize = 0; 1059 Inflater aInflaterLocal( sal_True ); 1060 sal_Int32 nBlockSize = ::std::min( nCompressedSize, static_cast< sal_Int32 >( 32000 ) ); 1061 1062 aGrabber.seek( nOffset ); 1063 for ( int ind = 0; 1064 !aInflaterLocal.finished() && aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize; 1065 ind++ ) 1066 { 1067 Sequence < sal_Int8 > aData( nBlockSize ); 1068 sal_Int32 nLastInflated = 0; 1069 sal_Int32 nInBlock = 0; 1070 1071 aInflaterLocal.setInput( aBuffer ); 1072 do 1073 { 1074 nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize ); 1075 aCRC.updateSegment( aData, 0, nLastInflated ); 1076 nInBlock += nLastInflated; 1077 } while( !aInflater.finished() && nLastInflated ); 1078 1079 nRealSize += nInBlock; 1080 } 1081 1082 *nSize = nRealSize; 1083 *nCRC = aCRC.getValue(); 1084 } 1085 1086