diff options
Diffstat (limited to 'package/source/zipapi/ZipFile.cxx')
-rw-r--r-- | package/source/zipapi/ZipFile.cxx | 118 |
1 files changed, 112 insertions, 6 deletions
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index da44e34aca8c..fb8fc3db3c66 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -75,6 +75,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference , xSeek(xInput, UNO_QUERY) , m_xContext ( rxContext ) , bRecoveryMode( false ) +, mbUseBufferedStream(false) { if (bInitialise) { @@ -94,6 +95,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference , xSeek(xInput, UNO_QUERY) , m_xContext ( rxContext ) , bRecoveryMode( bForceRecovery ) +, mbUseBufferedStream(false) { if (bInitialise) { @@ -114,6 +116,11 @@ ZipFile::~ZipFile() aEntries.clear(); } +void ZipFile::setUseBufferedStream( bool b ) +{ + mbUseBufferedStream = b; +} + void ZipFile::setInputStream ( const uno::Reference < XInputStream >& xNewStream ) { ::osl::MutexGuard aGuard( m_aMutex ); @@ -508,7 +515,99 @@ bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference< Encr return bRet; } -uno::Reference< XInputStream > ZipFile::createUnbufferedStream( +namespace { + +class XBufferedStream : public cppu::WeakImplHelper<css::io::XInputStream> +{ + std::vector<sal_Int8> maBytes; + size_t mnPos; + + size_t remainingSize() const + { + return maBytes.size() - mnPos; + } + + bool hasBytes() const + { + return mnPos < maBytes.size(); + } + +public: + XBufferedStream( const uno::Reference<XInputStream>& xSrcStream ) : mnPos(0) + { + const sal_Int32 nBufSize = 8192; + + sal_Int32 nRemaining = xSrcStream->available(); + maBytes.reserve(nRemaining); + uno::Sequence<sal_Int8> aBuf(nBufSize); + + auto readAndCopy = [&]( sal_Int32 nReadSize ) -> sal_Int32 + { + sal_Int32 nBytes = xSrcStream->readBytes(aBuf, nReadSize); + const sal_Int8* p = aBuf.getArray(); + const sal_Int8* pEnd = p + nBytes; + std::copy(p, pEnd, std::back_inserter(maBytes)); + return nBytes; + }; + + while (nRemaining > nBufSize) + nRemaining -= readAndCopy(nBufSize); + + if (nRemaining) + readAndCopy(nRemaining); + } + + virtual sal_Int32 SAL_CALL readBytes( uno::Sequence<sal_Int8>& rData, sal_Int32 nBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + if (!hasBytes()) + return 0; + + sal_Int32 nReadSize = std::min<sal_Int32>(nBytesToRead, remainingSize()); + rData.realloc(nReadSize); + std::vector<sal_Int8>::const_iterator it = maBytes.cbegin(); + std::advance(it, mnPos); + for (sal_Int32 i = 0; i < nReadSize; ++i, ++it) + rData[i] = *it; + + mnPos += nReadSize; + + return nReadSize; + } + + virtual sal_Int32 SAL_CALL readSomeBytes( ::css::uno::Sequence<sal_Int8>& rData, sal_Int32 nMaxBytesToRead ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + return readBytes(rData, nMaxBytesToRead); + } + + virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + if (!hasBytes()) + return; + + mnPos += nBytesToSkip; + } + + virtual sal_Int32 SAL_CALL available() + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + if (!hasBytes()) + return 0; + + return remainingSize(); + } + + virtual void SAL_CALL closeInput() + throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) override + { + } +}; + +} + +uno::Reference< XInputStream > ZipFile::createStreamForZipEntry( const rtl::Reference<SotMutexHolder>& aMutexHolder, ZipEntry & rEntry, const ::rtl::Reference< EncryptionData > &rData, @@ -518,7 +617,14 @@ uno::Reference< XInputStream > ZipFile::createUnbufferedStream( { ::osl::MutexGuard aGuard( m_aMutex ); - return new XUnbufferedStream ( m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode ); + uno::Reference<io::XInputStream> xSrcStream = new XUnbufferedStream( + m_xContext, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode); + + if (!mbUseBufferedStream) + return xSrcStream; + + uno::Reference<io::XInputStream> xBufStream(new XBufferedStream(xSrcStream)); + return xBufStream; } ZipEnumeration * SAL_CALL ZipFile::entries( ) @@ -547,7 +653,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntr if ( bIsEncrypted && rData.is() && rData->m_aDigest.getLength() ) bNeedRawStream = !hasValidPassword ( rEntry, rData ); - return createUnbufferedStream ( aMutexHolder, + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, @@ -587,7 +693,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry else bNeedRawStream = ( rEntry.nMethod == STORED ); - return createUnbufferedStream ( aMutexHolder, + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, @@ -605,7 +711,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry, if ( rEntry.nOffset <= 0 ) readLOC( rEntry ); - return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted ); + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted ); } uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream( @@ -626,7 +732,7 @@ uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream( if ( rEntry.nOffset <= 0 ) readLOC( rEntry ); - return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, true, aMediaType ); + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, true, aMediaType ); } bool ZipFile::readLOC( ZipEntry &rEntry ) |