summaryrefslogtreecommitdiff
path: root/package
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2017-01-13 20:47:46 -0500
committerMichael Meeks <michael.meeks@collabora.com>2017-01-16 20:42:09 +0000
commit6e55e41632aabbca25ec263cd26a631ca105d0ab (patch)
treef659efc265d8a6b393edbad403f7e6bda99b4091 /package
parent0c39bdd960aaa363fd1fcf6608809d3a6068a3d4 (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.hxx5
-rw-r--r--package/source/xstor/xfactory.cxx4
-rw-r--r--package/source/xstor/xstorage.cxx3
-rw-r--r--package/source/zipapi/ZipFile.cxx118
-rw-r--r--package/source/zippackage/ZipPackage.cxx6
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 )