20#include <com/sun/star/io/BufferSizeExceededException.hpp>
21#include <com/sun/star/io/NotConnectedException.hpp>
22#include <com/sun/star/lang/IllegalArgumentException.hpp>
23#include <com/sun/star/packages/NoEncryptionException.hpp>
24#include <com/sun/star/packages/WrongPasswordException.hpp>
25#include <com/sun/star/packages/zip/ZipConstants.hpp>
26#include <com/sun/star/packages/zip/ZipException.hpp>
27#include <com/sun/star/packages/zip/ZipIOException.hpp>
28#include <com/sun/star/xml/crypto/XCipherContext.hpp>
29#include <com/sun/star/xml/crypto/XDigestContext.hpp>
30#include <com/sun/star/xml/crypto/CipherID.hpp>
31#include <com/sun/star/xml/crypto/DigestID.hpp>
32#include <com/sun/star/xml/crypto/NSSInitializer.hpp>
37#include <rtl/digest.h>
40#include <osl/diagnose.h>
65using namespace com::sun::star::packages::zip;
66using namespace com::sun::star::packages::zip::ZipConstants;
70#if OSL_DEBUG_LEVEL > 0
71#define THROW_WHERE SAL_WHERE
79 uno::Reference < XInputStream >
const &xInput,
80 uno::Reference < XComponentContext > xContext,
82: m_aMutexHolder(
std::move( aMutexHolder ))
87, bRecoveryMode( false )
89 if (bInitialise && readCEN() == -1 )
97 uno::Reference < XInputStream >
const &xInput,
98 uno::Reference < XComponentContext > xContext,
99 bool bInitialise,
bool bForceRecovery)
100: m_aMutexHolder(
std::move( aMutexHolder ))
105, bRecoveryMode( bForceRecovery )
109 if ( bForceRecovery )
113 else if ( readCEN() == -1 )
126void ZipFile::setInputStream (
const uno::Reference < XInputStream >& xNewStream )
128 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
130 xStream = xNewStream;
134uno::Reference< xml::crypto::XDigestContext > ZipFile::StaticGetDigestContextForChecksum(
const uno::Reference< uno::XComponentContext >& xArgContext, const ::rtl::Reference< EncryptionData >& xEncryptionData )
136 uno::Reference< xml::crypto::XDigestContext > xDigestContext;
137 if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA256_1K )
139 uno::Reference< uno::XComponentContext > xContext = xArgContext;
140 if ( !xContext.is() )
143 uno::Reference< xml::crypto::XNSSInitializer > xDigestContextSupplier = xml::crypto::NSSInitializer::create( xContext );
145 xDigestContext.set( xDigestContextSupplier->getDigestContext( xEncryptionData->m_nCheckAlg, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW );
147 else if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA1_1K )
149 if (xEncryptionData->m_bTryWrongSHA1)
159 return xDigestContext;
162uno::Reference< xml::crypto::XCipherContext > ZipFile::StaticGetCipher(
const uno::Reference< uno::XComponentContext >& xArgContext, const ::rtl::Reference< EncryptionData >& xEncryptionData,
bool bEncrypt )
164 uno::Reference< xml::crypto::XCipherContext > xResult;
166 if (xEncryptionData->m_nDerivedKeySize < 0)
168 throw ZipIOException(
"Invalid derived key length!" );
171 uno::Sequence< sal_Int8 > aDerivedKey( xEncryptionData->m_nDerivedKeySize );
172 if ( !xEncryptionData->m_nIterationCount &&
173 xEncryptionData->m_nDerivedKeySize == xEncryptionData->m_aKey.getLength() )
177 aDerivedKey = xEncryptionData->m_aKey;
179 else if ( rtl_Digest_E_None != rtl_digest_PBKDF2(
reinterpret_cast< sal_uInt8*
>( aDerivedKey.getArray() ),
180 aDerivedKey.getLength(),
181 reinterpret_cast< const sal_uInt8 *
> (xEncryptionData->m_aKey.getConstArray() ),
182 xEncryptionData->m_aKey.getLength(),
183 reinterpret_cast< const sal_uInt8 *
> ( xEncryptionData->m_aSalt.getConstArray() ),
184 xEncryptionData->m_aSalt.getLength(),
185 xEncryptionData->m_nIterationCount ) )
187 throw ZipIOException(
"Can not create derived key!" );
190 if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING )
192 uno::Reference< uno::XComponentContext > xContext = xArgContext;
193 if ( !xContext.is() )
196 uno::Reference< xml::crypto::XNSSInitializer > xCipherContextSupplier = xml::crypto::NSSInitializer::create( xContext );
198 xResult = xCipherContextSupplier->getCipherContext( xEncryptionData->m_nEncAlg, aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt, uno::Sequence< beans::NamedValue >() );
200 else if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::BLOWFISH_CFB_8 )
206 throw ZipIOException(
"Unknown cipher algorithm is requested!" );
212void ZipFile::StaticFillHeader( const ::rtl::Reference< EncryptionData >& rData,
214 const OUString& aMediaType,
218 sal_Int16 nIVLength =
static_cast < sal_Int16
> ( rData->m_aInitVector.getLength() );
219 sal_Int16 nSaltLength =
static_cast < sal_Int16
> ( rData->m_aSalt.getLength() );
220 sal_Int16 nDigestLength =
static_cast < sal_Int16
> ( rData->m_aDigest.getLength() );
221 sal_Int16 nMediaTypeLength =
static_cast < sal_Int16
> ( aMediaType.getLength() *
sizeof(
sal_Unicode ) );
234 sal_Int32 nIterationCount = rData->m_nIterationCount;
235 *(pHeader++) =
static_cast< sal_Int8 >(( nIterationCount >> 0 ) & 0xFF);
236 *(pHeader++) =
static_cast< sal_Int8 >(( nIterationCount >> 8 ) & 0xFF);
237 *(pHeader++) =
static_cast< sal_Int8 >(( nIterationCount >> 16 ) & 0xFF);
238 *(pHeader++) =
static_cast< sal_Int8 >(( nIterationCount >> 24 ) & 0xFF);
242 *(pHeader++) =
static_cast< sal_Int8 >(( nSize >> 0 ) & 0xFF);
243 *(pHeader++) =
static_cast< sal_Int8 >(( nSize >> 8 ) & 0xFF);
244 *(pHeader++) =
static_cast< sal_Int8 >(( nSize >> 16 ) & 0xFF);
245 *(pHeader++) =
static_cast< sal_Int8 >(( nSize >> 24 ) & 0xFF);
248 sal_Int32 nEncAlgID = rData->m_nEncAlg;
249 *(pHeader++) =
static_cast< sal_Int8 >(( nEncAlgID >> 0 ) & 0xFF);
250 *(pHeader++) =
static_cast< sal_Int8 >(( nEncAlgID >> 8 ) & 0xFF);
251 *(pHeader++) =
static_cast< sal_Int8 >(( nEncAlgID >> 16 ) & 0xFF);
252 *(pHeader++) =
static_cast< sal_Int8 >(( nEncAlgID >> 24 ) & 0xFF);
255 sal_Int32 nChecksumAlgID = rData->m_nCheckAlg;
256 *(pHeader++) =
static_cast< sal_Int8 >(( nChecksumAlgID >> 0 ) & 0xFF);
257 *(pHeader++) =
static_cast< sal_Int8 >(( nChecksumAlgID >> 8 ) & 0xFF);
258 *(pHeader++) =
static_cast< sal_Int8 >(( nChecksumAlgID >> 16 ) & 0xFF);
259 *(pHeader++) =
static_cast< sal_Int8 >(( nChecksumAlgID >> 24 ) & 0xFF);
262 sal_Int32 nDerivedKeySize = rData->m_nDerivedKeySize;
263 *(pHeader++) =
static_cast< sal_Int8 >(( nDerivedKeySize >> 0 ) & 0xFF);
264 *(pHeader++) =
static_cast< sal_Int8 >(( nDerivedKeySize >> 8 ) & 0xFF);
265 *(pHeader++) =
static_cast< sal_Int8 >(( nDerivedKeySize >> 16 ) & 0xFF);
266 *(pHeader++) =
static_cast< sal_Int8 >(( nDerivedKeySize >> 24 ) & 0xFF);
269 sal_Int32 nKeyAlgID = rData->m_nStartKeyGenID;
270 *(pHeader++) =
static_cast< sal_Int8 >(( nKeyAlgID >> 0 ) & 0xFF);
271 *(pHeader++) =
static_cast< sal_Int8 >(( nKeyAlgID >> 8 ) & 0xFF);
272 *(pHeader++) =
static_cast< sal_Int8 >(( nKeyAlgID >> 16 ) & 0xFF);
273 *(pHeader++) =
static_cast< sal_Int8 >(( nKeyAlgID >> 24 ) & 0xFF);
276 *(pHeader++) =
static_cast< sal_Int8 >(( nSaltLength >> 0 ) & 0xFF);
277 *(pHeader++) =
static_cast< sal_Int8 >(( nSaltLength >> 8 ) & 0xFF);
280 *(pHeader++) =
static_cast< sal_Int8 >(( nIVLength >> 0 ) & 0xFF);
281 *(pHeader++) =
static_cast< sal_Int8 >(( nIVLength >> 8 ) & 0xFF);
284 *(pHeader++) =
static_cast< sal_Int8 >(( nDigestLength >> 0 ) & 0xFF);
285 *(pHeader++) =
static_cast< sal_Int8 >(( nDigestLength >> 8 ) & 0xFF);
288 *(pHeader++) =
static_cast< sal_Int8 >(( nMediaTypeLength >> 0 ) & 0xFF);
289 *(pHeader++) =
static_cast< sal_Int8 >(( nMediaTypeLength >> 8 ) & 0xFF);
292 memcpy ( pHeader, rData->m_aSalt.getConstArray(), nSaltLength );
293 pHeader += nSaltLength;
296 memcpy ( pHeader, rData->m_aInitVector.getConstArray(), nIVLength );
297 pHeader += nIVLength;
300 memcpy ( pHeader, rData->m_aDigest.getConstArray(), nDigestLength );
301 pHeader += nDigestLength;
304 memcpy ( pHeader, aMediaType.getStr(), nMediaTypeLength );
305 pHeader += nMediaTypeLength;
310 sal_Int32 &rChecksumAlg,
311 sal_Int32 &rDerivedKeySize,
312 sal_Int32 &rStartKeyGenID,
314 OUString& aMediaType,
315 const uno::Reference< XInputStream >& rStream )
320 if ( nHeaderSize == rStream->readBytes ( aBuffer, nHeaderSize ) )
332 rData->m_nIterationCount =
nCount;
334 rSize = pBuffer[
nPos++] & 0xFF;
335 rSize |= ( pBuffer[
nPos++] & 0xFF ) << 8;
336 rSize |= ( pBuffer[
nPos++] & 0xFF ) << 16;
337 rSize |= ( pBuffer[
nPos++] & 0xFF ) << 24;
339 rEncAlg = pBuffer[
nPos++] & 0xFF;
340 rEncAlg |= ( pBuffer[
nPos++] & 0xFF ) << 8;
341 rEncAlg |= ( pBuffer[
nPos++] & 0xFF ) << 16;
342 rEncAlg |= ( pBuffer[
nPos++] & 0xFF ) << 24;
344 rChecksumAlg = pBuffer[
nPos++] & 0xFF;
345 rChecksumAlg |= ( pBuffer[
nPos++] & 0xFF ) << 8;
346 rChecksumAlg |= ( pBuffer[
nPos++] & 0xFF ) << 16;
347 rChecksumAlg |= ( pBuffer[
nPos++] & 0xFF ) << 24;
349 rDerivedKeySize = pBuffer[
nPos++] & 0xFF;
350 rDerivedKeySize |= ( pBuffer[
nPos++] & 0xFF ) << 8;
351 rDerivedKeySize |= ( pBuffer[
nPos++] & 0xFF ) << 16;
352 rDerivedKeySize |= ( pBuffer[
nPos++] & 0xFF ) << 24;
354 rStartKeyGenID = pBuffer[
nPos++] & 0xFF;
355 rStartKeyGenID |= ( pBuffer[
nPos++] & 0xFF ) << 8;
356 rStartKeyGenID |= ( pBuffer[
nPos++] & 0xFF ) << 16;
357 rStartKeyGenID |= ( pBuffer[
nPos++] & 0xFF ) << 24;
359 sal_Int16 nSaltLength = pBuffer[
nPos++] & 0xFF;
360 nSaltLength |= ( pBuffer[
nPos++] & 0xFF ) << 8;
361 sal_Int16 nIVLength = ( pBuffer[
nPos++] & 0xFF );
362 nIVLength |= ( pBuffer[
nPos++] & 0xFF ) << 8;
363 sal_Int16 nDigestLength = pBuffer[
nPos++] & 0xFF;
364 nDigestLength |= ( pBuffer[
nPos++] & 0xFF ) << 8;
366 sal_Int16 nMediaTypeLength = pBuffer[
nPos++] & 0xFF;
367 nMediaTypeLength |= ( pBuffer[
nPos++] & 0xFF ) << 8;
369 if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) )
371 rData->m_aSalt.realloc ( nSaltLength );
372 memcpy ( rData->m_aSalt.getArray(),
aBuffer.getConstArray(), nSaltLength );
373 if ( nIVLength == rStream->readBytes ( aBuffer, nIVLength ) )
375 rData->m_aInitVector.realloc ( nIVLength );
376 memcpy ( rData->m_aInitVector.getArray(),
aBuffer.getConstArray(), nIVLength );
377 if ( nDigestLength == rStream->readBytes ( aBuffer, nDigestLength ) )
379 rData->m_aDigest.realloc ( nDigestLength );
380 memcpy ( rData->m_aDigest.getArray(),
aBuffer.getConstArray(), nDigestLength );
382 if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) )
384 aMediaType = OUString(
reinterpret_cast<sal_Unicode const *
>(
aBuffer.getConstArray()),
397 const uno::Reference< uno::XComponentContext >& rxContext,
398 const uno::Reference< XInputStream >& xStream,
399 const ::rtl::Reference< EncryptionData > &rData )
402 throw ZipIOException(
"Encrypted stream without encryption data!" );
404 if ( !rData->m_aKey.hasElements() )
405 throw packages::WrongPasswordException(
THROW_WHERE );
407 uno::Reference< XSeekable > xSeek( xStream, UNO_QUERY );
409 throw ZipIOException(
"The stream must be seekable!" );
413 OSL_ENSURE( rData->m_aDigest.hasElements(),
"Can't detect password correctness without digest!" );
414 if ( rData->m_aDigest.hasElements() )
416 sal_Int32 nSize = sal::static_int_cast< sal_Int32 >( xSeek->getLength() );
422 rData->m_aSalt.getLength() + rData->m_aDigest.getLength() );
427 xStream->readBytes( aReadBuffer, nSize );
429 if ( !StaticHasValidPassword( rxContext, aReadBuffer, rData ) )
430 throw packages::WrongPasswordException(
THROW_WHERE );
438void CheckSequence(
const uno::Sequence< sal_Int8 >& aSequence )
440 if ( aSequence.getLength() )
442 sal_Int32* pPointer = *( (sal_Int32**)&aSequence );
443 sal_Int32 nSize = *( pPointer + 1 );
444 sal_Int32 nMemSize = *( pPointer - 2 );
445 sal_Int32 nUsedMemSize = ( nSize + 4 *
sizeof( sal_Int32 ) );
446 OSL_ENSURE( nSize == aSequence.getLength() && nUsedMemSize + 7 - ( nUsedMemSize - 1 ) % 8 == nMemSize,
"Broken Sequence!" );
451bool ZipFile::StaticHasValidPassword(
const uno::Reference< uno::XComponentContext >& rxContext,
const Sequence< sal_Int8 > &aReadBuffer, const ::rtl::Reference< EncryptionData > &rData )
453 if ( !rData.is() || !rData->m_aKey.hasElements() )
458 uno::Reference< xml::crypto::XCipherContext > xCipher( StaticGetCipher( rxContext, rData,
false ), uno::UNO_SET_THROW );
460 uno::Sequence< sal_Int8 > aDecryptBuffer;
461 uno::Sequence< sal_Int8 > aDecryptBuffer2;
464 aDecryptBuffer = xCipher->convertWithCipherContext( aReadBuffer );
465 aDecryptBuffer2 = xCipher->finalizeCipherContextAndDispose();
467 catch( uno::Exception& )
473 if ( aDecryptBuffer2.hasElements() )
475 sal_Int32 nOldLen = aDecryptBuffer.getLength();
476 aDecryptBuffer.realloc( nOldLen + aDecryptBuffer2.getLength() );
477 memcpy( aDecryptBuffer.getArray() + nOldLen, aDecryptBuffer2.getConstArray(), aDecryptBuffer2.getLength() );
483 uno::Sequence< sal_Int8 > aDigestSeq;
484 uno::Reference< xml::crypto::XDigestContext > xDigestContext( StaticGetDigestContextForChecksum( rxContext, rData ), uno::UNO_SET_THROW );
486 xDigestContext->updateDigest( aDecryptBuffer );
487 aDigestSeq = xDigestContext->finalizeDigestAndDispose();
490 if ( rData->m_aDigest.hasElements() &&
491 ( aDigestSeq.getLength() != rData->m_aDigest.getLength() ||
492 0 != memcmp ( aDigestSeq.getConstArray(),
493 rData->m_aDigest.getConstArray(),
494 aDigestSeq.getLength() ) ) )
504bool ZipFile::hasValidPassword (
ZipEntry const & rEntry, const ::rtl::Reference< EncryptionData >& rData )
506 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
509 if ( rData.is() && rData->m_aKey.hasElements() )
511 css::uno::Reference < css::io::XSeekable > xSeek(xStream, UNO_QUERY_THROW);
521 xStream->readBytes( aReadBuffer, nSize );
523 bRet = StaticHasValidPassword( m_xContext, aReadBuffer, rData );
531class XBufferedStream :
public cppu::WeakImplHelper<css::io::XInputStream, css::io::XSeekable>
533 std::vector<sal_Int8> maBytes;
536 size_t remainingSize()
const
538 return maBytes.size() - mnPos;
541 bool hasBytes()
const
543 return mnPos < maBytes.size();
547 XBufferedStream(
const uno::Reference<XInputStream>& xSrcStream ) : mnPos(0)
549 sal_Int32 nRemaining = xSrcStream->available();
550 maBytes.reserve(nRemaining);
552 if (
auto pByteReader =
dynamic_cast< comphelper::ByteReader*
>( xSrcStream.get() ))
554 maBytes.resize(nRemaining);
557 while (nRemaining > 0)
559 sal_Int32 nRead = pByteReader->readSomeBytes(pData, nRemaining);
566 const sal_Int32 nBufSize = 8192;
567 uno::Sequence<sal_Int8>
aBuf(nBufSize);
568 while (nRemaining > 0)
570 const sal_Int32 nBytes = xSrcStream->readBytes(aBuf, std::min(nBufSize, nRemaining));
573 maBytes.insert(maBytes.end(),
aBuf.begin(),
aBuf.begin() + nBytes);
574 nRemaining -= nBytes;
578 virtual sal_Int32 SAL_CALL readBytes( uno::Sequence<sal_Int8>& rData, sal_Int32 nBytesToRead )
override
583 sal_Int32 nReadSize = std::min<sal_Int32>(nBytesToRead, remainingSize());
584 rData.realloc(nReadSize);
585 auto pData = rData.getArray();
586 std::vector<sal_Int8>::const_iterator it = maBytes.cbegin();
587 std::advance(it, mnPos);
588 for (sal_Int32 i = 0;
i < nReadSize; ++
i, ++it)
596 virtual sal_Int32 SAL_CALL readSomeBytes( ::css::uno::Sequence<sal_Int8>& rData, sal_Int32 nMaxBytesToRead )
override
598 return readBytes(rData, nMaxBytesToRead);
601 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
override
606 mnPos += nBytesToSkip;
609 virtual sal_Int32 SAL_CALL available()
override
614 return remainingSize();
617 virtual void SAL_CALL closeInput()
override
621 virtual void SAL_CALL seek( sal_Int64 location )
override
624 throw IllegalArgumentException(
THROW_WHERE, uno::Reference< uno::XInterface >(), 1 );
627 virtual sal_Int64 SAL_CALL getPosition()
override
631 virtual sal_Int64 SAL_CALL
getLength()
override
633 return maBytes.size();
639uno::Reference< XInputStream > ZipFile::createStreamForZipEntry(
642 const ::rtl::Reference< EncryptionData > &rData,
645 const bool bUseBufferedStream,
646 const OUString& aMediaType )
648 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
651 m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode);
653 if (!bUseBufferedStream)
656 uno::Reference<io::XInputStream> xBufStream;
658 static const sal_Int32 nThreadingThreshold = 10000;
660 if( xSrcStream->available() > nThreadingThreshold )
664 xBufStream =
new XBufferedStream(xSrcStream);
674uno::Reference< XInputStream > ZipFile::getInputStream(
ZipEntry& rEntry,
675 const ::rtl::Reference< EncryptionData > &rData,
679 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
687 bool bNeedRawStream = rEntry.
nMethod == STORED;
691 if ( bIsEncrypted && rData.is() && rData->m_aDigest.hasElements() )
692 bNeedRawStream = !hasValidPassword ( rEntry, rData );
694 return createStreamForZipEntry ( aMutexHolder,
701uno::Reference< XInputStream > ZipFile::getDataStream(
ZipEntry& rEntry,
702 const ::rtl::Reference< EncryptionData > &rData,
706 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
713 bool bNeedRawStream =
false;
719 throw ZipException(
"Encrypted stream without encryption data!" );
723 OSL_ENSURE( rData->m_aDigest.hasElements(),
"Can't detect password correctness without digest!" );
724 if ( rData->m_aDigest.hasElements() && !hasValidPassword ( rEntry, rData ) )
725 throw packages::WrongPasswordException(
THROW_WHERE );
728 bNeedRawStream = ( rEntry.
nMethod == STORED );
730 return createStreamForZipEntry ( aMutexHolder,
737uno::Reference< XInputStream > ZipFile::getRawData(
ZipEntry& rEntry,
738 const ::rtl::Reference< EncryptionData >& rData,
741 const bool bUseBufferedStream )
743 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
748 return createStreamForZipEntry ( aMutexHolder, rEntry, rData,
UNBUFF_STREAM_RAW, bIsEncrypted, bUseBufferedStream );
751uno::Reference< XInputStream > ZipFile::getWrappedRawStream(
753 const ::rtl::Reference< EncryptionData >& rData,
754 const OUString& aMediaType,
757 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
760 throw packages::NoEncryptionException(
THROW_WHERE );
768void ZipFile::readLOC(
ZipEntry &rEntry )
770 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
775 sal_Int32 nTestSig = aGrabber.
ReadInt32();
776 if (nTestSig != LOCSIG)
777 throw ZipIOException(
"Invalid LOC header (bad signature)" );
791 sal_Int16 nPathLen = aGrabber.
ReadInt16();
792 sal_Int16 nExtraLen = aGrabber.
ReadInt16();
796 SAL_WARN(
"package",
"bogus path len of: " << nPathLen);
802 bool bBroken =
false;
808 uno::Sequence<sal_Int8> aNameBuffer(nPathLen);
809 sal_Int32 nRead = aGrabber.
readBytes(aNameBuffer, nPathLen);
810 if (nRead < aNameBuffer.getLength())
811 aNameBuffer.realloc(nRead);
813 OUString sLOCPath(
reinterpret_cast<const char *
>(aNameBuffer.getConstArray()),
814 aNameBuffer.getLength(),
815 RTL_TEXTENCODING_UTF8 );
820 rEntry.
sPath = sLOCPath;
823 bBroken = rEntry.
nPathLen != nPathLen
824 || rEntry.
sPath != sLOCPath;
831 if ( bBroken && !bRecoveryMode )
832 throw ZipIOException(
"The stream seems to be broken!" );
835sal_Int32 ZipFile::findEND()
838 sal_Int32
nPos, nEnd;
843 if (nLength < ENDHDR)
848 aGrabber.
seek( nEnd );
851 if (nSize != aGrabber.
readBytes(aBuffer, nSize))
856 nPos = nSize - ENDHDR;
859 if (pBuffer[nPos] ==
'P' && pBuffer[nPos+1] ==
'K' && pBuffer[nPos+2] == 5 && pBuffer[nPos+3] == 6 )
864 catch ( IllegalArgumentException& )
868 catch ( NotConnectedException& )
872 catch ( BufferSizeExceededException& )
879sal_Int32 ZipFile::readCEN()
882 sal_Int32 nCenPos = -1, nLocPos;
887 sal_Int32 nEndPos = findEND();
890 aGrabber.
seek(nEndPos + ENDTOT);
892 sal_Int32 nCenLen = aGrabber.
ReadInt32();
893 sal_Int32 nCenOff = aGrabber.
ReadInt32();
895 if ( nTotal * CENHDR > nCenLen )
896 throw ZipException(
"invalid END header (bad entry count)" );
901 if ( nCenLen < 0 || nCenLen > nEndPos )
902 throw ZipException(
"Invalid END header (bad central directory size)" );
904 nCenPos = nEndPos - nCenLen;
906 if ( nCenOff < 0 || nCenOff > nCenPos )
907 throw ZipException(
"Invalid END header (bad central directory size)" );
909 nLocPos = nCenPos - nCenOff;
910 aGrabber.
seek( nCenPos );
912 sal_Int64 nRead = aGrabber.
readBytes ( aCENBuffer, nCenLen );
913 if (
static_cast < sal_Int64
> ( nCenLen ) != nRead )
914 throw ZipException (
"Error reading CEN into memory buffer!" );
919 sal_Int16 nCommentLen;
921 aEntries.reserve(nTotal);
924 sal_Int32 nTestSig = aMemGrabber.ReadInt32();
925 if ( nTestSig != CENSIG )
926 throw ZipException(
"Invalid CEN header (bad signature)" );
928 aMemGrabber.skipBytes ( 2 );
929 aEntry.
nVersion = aMemGrabber.ReadInt16();
930 aEntry.
nFlag = aMemGrabber.ReadInt16();
932 if ( ( aEntry.
nFlag & 1 ) == 1 )
933 throw ZipException(
"Invalid CEN header (encrypted entry)" );
935 aEntry.
nMethod = aMemGrabber.ReadInt16();
938 throw ZipException(
"Invalid CEN header (bad compression method)" );
940 aEntry.
nTime = aMemGrabber.ReadInt32();
941 aEntry.
nCrc = aMemGrabber.ReadInt32();
943 sal_uInt64 nCompressedSize = aMemGrabber.ReadUInt32();
944 sal_uInt64 nSize = aMemGrabber.ReadUInt32();
945 aEntry.
nPathLen = aMemGrabber.ReadInt16();
946 aEntry.
nExtraLen = aMemGrabber.ReadInt16();
947 nCommentLen = aMemGrabber.ReadInt16();
948 aMemGrabber.skipBytes ( 8 );
949 sal_uInt64 nOffset = aMemGrabber.ReadUInt32();
954 if ( nCommentLen < 0 )
958 throw ZipException(
"unexpected extra header info length" );
960 if (aEntry.
nPathLen > aMemGrabber.remainingSize())
964 aEntry.
sPath = OUString(
reinterpret_cast<char const *
>(aMemGrabber.getCurrentPos()),
966 RTL_TEXTENCODING_UTF8 );
971 aMemGrabber.skipBytes(aEntry.
nPathLen);
975 readExtraFields(aMemGrabber, aEntry.
nExtraLen, nSize, nCompressedSize, &nOffset);
978 aEntry.
nSize = nSize;
984 aMemGrabber.skipBytes(nCommentLen);
985 aEntries[aEntry.
sPath] = aEntry;
988 if (nCount != nTotal)
991 catch ( IllegalArgumentException & )
999void ZipFile::readExtraFields(
MemoryByteGrabber& aMemGrabber, sal_Int16 nExtraLen,
1000 sal_uInt64& nSize, sal_uInt64& nCompressedSize, sal_uInt64* nOffset)
1002 while (nExtraLen > 0)
1004 sal_Int16 nheaderID = aMemGrabber.
ReadInt16();
1005 sal_uInt16 dataSize = aMemGrabber.
ReadUInt16();
1010 sal_uInt16 nReadSize = 8;
1015 if (dataSize >= 24 && nOffset)
1022 if (dataSize > nReadSize)
1023 aMemGrabber.
skipBytes(dataSize - nReadSize);
1029 nExtraLen -= dataSize + 4;
1033void ZipFile::recover()
1035 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
1043 if (nLength < ENDHDR)
1048 const sal_Int64 nToRead = 32000;
1049 for( sal_Int64 nGenPos = 0; aGrabber.
readBytes( aBuffer, nToRead ) &&
aBuffer.getLength() > 16; )
1052 sal_Int32 nBufSize =
aBuffer.getLength();
1057 while( nPos < nBufSize - 30
1058 || ( nBufSize < nToRead && nPos < nBufSize - 16 ) )
1061 if ( nPos < nBufSize - 30 && pBuffer[nPos] ==
'P' && pBuffer[nPos+1] ==
'K' && pBuffer[nPos+2] == 3 && pBuffer[nPos+3] == 4 )
1071 if ( ( aEntry.
nFlag & 1 ) != 1 )
1079 sal_uInt64 nCompressedSize = aMemGrabber.
ReadUInt32();
1084 sal_Int32 nDescrLength =
1085 ( aEntry.
nMethod == DEFLATED && ( aEntry.
nFlag & 8 ) ) ? 16 : 0;
1087 sal_Int64 nBlockHeaderLength = aEntry.
nPathLen + aEntry.
nExtraLen + 30 + nDescrLength;
1089 && ( nGenPos + nPos + nBlockHeaderLength ) <=
nLength )
1092 if( nPos + 30 + aEntry.
nPathLen <= nBufSize )
1093 aEntry.
sPath = OUString (
reinterpret_cast<char const *
>(&pBuffer[nPos + 30]),
1095 RTL_TEXTENCODING_UTF8 );
1099 aGrabber.
seek( nGenPos + nPos + 30 );
1101 aEntry.
sPath = OUString (
reinterpret_cast<const char *
>(aFileName.getConstArray()),
1102 aFileName.getLength(),
1103 RTL_TEXTENCODING_UTF8 );
1104 aEntry.
nPathLen =
static_cast< sal_Int16
>(aFileName.getLength());
1114 &(pBuffer[nPos + 30 + aEntry.
nPathLen]),
1125 readExtraFields(aMemGrabberExtra, aEntry.
nExtraLen, nSize,
1126 nCompressedSize,
nullptr);
1130 sal_Int64 nDataSize = ( aEntry.
nMethod == DEFLATED ) ? nCompressedSize : nSize;
1131 sal_Int64 nBlockLength = nDataSize + nBlockHeaderLength;
1133 if (( nGenPos + nPos + nBlockLength ) <=
nLength )
1136 aEntry.
nSize = nSize;
1147 aEntries.emplace( aEntry.
sPath, aEntry );
1155 else if (pBuffer[nPos] ==
'P' && pBuffer[nPos+1] ==
'K' && pBuffer[nPos+2] == 7 && pBuffer[nPos+3] == 8 )
1158 sal_Int64 nCompressedSize, nSize;
1161 sal_Int32 nCRC32 = aMemGrabber.
ReadInt32();
1171 if ((pBuffer[nPos + 16] ==
'P' && pBuffer[nPos + 17] ==
'K'
1172 && pBuffer[nPos + 19] == pBuffer[nPos + 18] + 1
1173 && (pBuffer[nPos + 18] == 3 || pBuffer[nPos + 18] == 1))
1174 || !(pBuffer[nPos + 24] ==
'P' && pBuffer[nPos + 25] ==
'K'
1175 && pBuffer[nPos + 27] == pBuffer[nPos + 26] + 1
1176 && (pBuffer[nPos + 26] == 3 || pBuffer[nPos + 26] == 1)))
1187 for(
auto& rEntry : aEntries )
1190 if( rEntry.second.
nFlag & 8 )
1192 sal_Int64 nStreamOffset = nGenPos +
nPos - nCompressedSize;
1196 bool bAcceptBlock = ( rEntry.second.
nMethod == STORED && nCompressedSize == nSize );
1198 if ( !bAcceptBlock )
1200 sal_Int64 nRealSize = 0;
1201 sal_Int32 nRealCRC = 0;
1202 getSizeAndCRC( nStreamOffset, nCompressedSize, &nRealSize, &nRealCRC );
1203 bAcceptBlock = ( nRealSize == nSize && nRealCRC == nCRC32 );
1208 rEntry.second.
nCrc = nCRC32;
1210 rEntry.second.
nSize = nSize;
1217 rEntry.second.
nCrc = nCRC32;
1218 sal_Int32 nRealStreamSize = nGenPos +
nPos - rEntry.second.
nOffset;
1220 rEntry.second.
nSize = nSize;
1233 aGrabber.
seek( nGenPos );
1236 catch ( IllegalArgumentException& )
1240 catch ( NotConnectedException& )
1244 catch ( BufferSizeExceededException& )
1250bool ZipFile::checkSizeAndCRC(
const ZipEntry& aEntry )
1252 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
1255 sal_Int64 nSize = 0;
1257 if( aEntry.
nMethod == STORED )
1267 return ( aEntry.
nSize == nSize && aEntry.
nCrc == nCRC );
1270sal_Int32 ZipFile::getCRC( sal_Int64 nOffset, sal_Int64 nSize )
1272 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
1276 sal_Int64 nBlockSize = ::std::min(nSize,
static_cast< sal_Int64
>(32000));
1278 aGrabber.
seek( nOffset );
1279 for (sal_Int64 ind = 0;
1280 aGrabber.
readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize;
1283 sal_Int64 nLen = ::std::min(nBlockSize, nSize - ind * nBlockSize);
1290void ZipFile::getSizeAndCRC( sal_Int64 nOffset, sal_Int64 nCompressedSize, sal_Int64 *nSize, sal_Int32 *nCRC )
1292 ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() );
1296 sal_Int64 nRealSize = 0;
1298 sal_Int32 nBlockSize =
static_cast< sal_Int32
> (::std::min( nCompressedSize,
static_cast< sal_Int64
>( 32000 ) ) );
1300 aGrabber.
seek( nOffset );
1301 for ( sal_Int64 ind = 0;
1302 !aInflaterLocal.finished() && aGrabber.
readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize;
1306 sal_Int32 nLastInflated = 0;
1307 sal_Int64 nInBlock = 0;
1309 aInflaterLocal.setInput( aBuffer );
1312 nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize );
1314 nInBlock += nLastInflated;
1315 }
while( !aInflater.
finished() && nLastInflated );
1317 nRealSize += nInBlock;
Reference< XComponentContext > m_xContext
const sal_Int32 n_ConstDigestDecrypt
const sal_Int32 n_ConstDigestLength
#define UNBUFF_STREAM_RAW
#define UNBUFF_STREAM_DATA
#define UNBUFF_STREAM_WRAPPEDRAW
static css::uno::Reference< css::xml::crypto::XCipherContext > Create(const css::uno::Sequence< sal_Int8 > &aDerivedKey, const css::uno::Sequence< sal_Int8 > &aInitVector, bool bEncrypt)
void seek(sal_Int64 location)
void setInputStream(const css::uno::Reference< css::io::XInputStream > &xNewStream)
sal_Int32 readBytes(css::uno::Sequence< sal_Int8 > &aData, sal_Int32 nBytesToRead)
sal_Int32 getValue() const
void updateSegment(const css::uno::Sequence< sal_Int8 > &b, sal_Int32 len)
Update CRC32 with specified sequence of bytes.
static css::uno::Reference< css::xml::crypto::XDigestContext > Create()
void skipBytes(sal_Int32 nBytesToSkip)
static css::uno::Reference< css::xml::crypto::XDigestContext > Create()
ZipFile(const Filepath_t &FileName)
static bool IsValidZipEntryFileName(std::u16string_view aName, bool bSlashAllowed)
ScXMLEditAttributeMap::Entry const aEntries[]
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
double getLength(const B2DPolygon &rCandidate)
Reference< XComponentContext > getProcessComponentContext()
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
sal_Int64 nCompressedSize
std::unique_ptr< char[]> aBuffer