diff options
author | Kohei Yoshida <kohei.yoshida@collabora.com> | 2017-01-13 20:47:46 -0500 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2017-01-16 20:42:09 +0000 |
commit | 6e55e41632aabbca25ec263cd26a631ca105d0ab (patch) | |
tree | f659efc265d8a6b393edbad403f7e6bda99b4091 /package | |
parent | 0c39bdd960aaa363fd1fcf6608809d3a6068a3d4 (diff) |
tdf#97597: Ensure that each parsing thread has its own buffer.
(cherry picked from commit 4ae705d02df0ddf75b97d0e94add6994626f487e)
Change-Id: I93077f954a49b3922930e4fc86c80228be0f4dd2
Reviewed-on: https://gerrit.libreoffice.org/33069
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Kohei Yoshida <libreoffice@kohei.us>
Reviewed-on: https://gerrit.libreoffice.org/33176
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Diffstat (limited to 'package')
-rw-r--r-- | package/inc/ZipFile.hxx | 5 | ||||
-rw-r--r-- | package/source/xstor/xfactory.cxx | 4 | ||||
-rw-r--r-- | package/source/xstor/xstorage.cxx | 3 | ||||
-rw-r--r-- | package/source/zipapi/ZipFile.cxx | 118 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackage.cxx | 6 |
5 files changed, 126 insertions, 10 deletions
diff --git a/package/inc/ZipFile.hxx b/package/inc/ZipFile.hxx index c32d58209e0b..3d6b27b882d5 100644 --- a/package/inc/ZipFile.hxx +++ b/package/inc/ZipFile.hxx @@ -64,9 +64,10 @@ protected: const css::uno::Reference < css::uno::XComponentContext > m_xContext; bool bRecoveryMode; + bool mbUseBufferedStream; // aMediaType parameter is used only for raw stream header creation - css::uno::Reference < css::io::XInputStream > createUnbufferedStream( + css::uno::Reference < css::io::XInputStream > createStreamForZipEntry( const rtl::Reference<SotMutexHolder>& aMutexHolder, ZipEntry & rEntry, const ::rtl::Reference < EncryptionData > &rData, @@ -101,6 +102,8 @@ public: EntryHash& GetEntryHash() { return aEntries; } + void setUseBufferedStream( bool b ); + void setInputStream ( const css::uno::Reference < css::io::XInputStream >& xNewStream ); css::uno::Reference< css::io::XInputStream > SAL_CALL getRawData( ZipEntry& rEntry, diff --git a/package/source/xstor/xfactory.cxx b/package/source/xstor/xfactory.cxx index 95bb21a84622..d5031b4dbc03 100644 --- a/package/source/xstor/xfactory.cxx +++ b/package/source/xstor/xfactory.cxx @@ -193,8 +193,8 @@ uno::Reference< uno::XInterface > SAL_CALL OStorageFactory::createInstanceWithAr if ( aDescr[nInd].Name == "InteractionHandler" || aDescr[nInd].Name == "Password" || aDescr[nInd].Name == "RepairPackage" - || aDescr[nInd].Name == "StatusIndicator" ) - // || aDescr[nInd].Name == "Unpacked" ) // TODO: + || aDescr[nInd].Name == "StatusIndicator" + || aDescr[nInd].Name == "UseBufferedStream" ) { aPropsToSet.realloc( ++nNumArgs ); aPropsToSet[nNumArgs-1].Name = aDescr[nInd].Name; diff --git a/package/source/xstor/xstorage.cxx b/package/source/xstor/xstorage.cxx index 29155de03ebb..68f47a89db85 100644 --- a/package/source/xstor/xstorage.cxx +++ b/package/source/xstor/xstorage.cxx @@ -467,7 +467,8 @@ void OStorage_Impl::OpenOwnPackage() for ( sal_Int32 aInd = 0; aInd < m_xProperties.getLength(); aInd++ ) { if ( m_xProperties[aInd].Name == "RepairPackage" - || m_xProperties[aInd].Name == "ProgressHandler" ) + || m_xProperties[aInd].Name == "ProgressHandler" + || m_xProperties[aInd].Name == "UseBufferedStream" ) { beans::NamedValue aNamedValue( m_xProperties[aInd].Name, m_xProperties[aInd].Value ); 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 ) diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index d17fee0b3607..faaab714ee85 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -572,6 +572,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) if ( aArguments.getLength() ) { bool bHaveZipFile = true; + bool bUseBufferedStream = false; for( int ind = 0; ind < aArguments.getLength(); ind++ ) { @@ -699,6 +700,10 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) aNamedValue.Value >>= m_bAllowRemoveOnInsert; m_pRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert ); } + else if (aNamedValue.Name == "UseBufferedStream") + { + aNamedValue.Value >>= bUseBufferedStream; + } // for now the progress handler is not used, probably it will never be // if ( aNamedValue.Name == "ProgressHandler" ) @@ -742,6 +747,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) try { m_pZipFile = new ZipFile ( m_xContentStream, m_xContext, true, m_bForceRecovery ); + m_pZipFile->setUseBufferedStream(bUseBufferedStream); getZipFileContents(); } catch ( IOException & e ) |