summaryrefslogtreecommitdiffstats
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
parentResolves: tdf#101187 colossal page width wraps around if doubled (diff)
downloadcore-6e55e41632aabbca25ec263cd26a631ca105d0ab.tar.gz
core-6e55e41632aabbca25ec263cd26a631ca105d0ab.zip
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>
-rw-r--r--comphelper/source/misc/storagehelper.cxx46
-rw-r--r--include/comphelper/storagehelper.hxx6
-rw-r--r--oox/source/helper/zipstorage.cxx4
-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
8 files changed, 166 insertions, 26 deletions
diff --git a/comphelper/source/misc/storagehelper.cxx b/comphelper/source/misc/storagehelper.cxx
index 4730794de6e1..394a0aab578f 100644
--- a/comphelper/source/misc/storagehelper.cxx
+++ b/comphelper/source/misc/storagehelper.cxx
@@ -317,17 +317,28 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromInputStr
const OUString& aFormat,
const uno::Reference < io::XInputStream >& xStream,
const uno::Reference< uno::XComponentContext >& rxContext,
- bool bRepairStorage )
+ bool bRepairStorage, bool bUseBufferedStream )
throw ( uno::Exception )
{
uno::Sequence< beans::PropertyValue > aProps( 1 );
- aProps[0].Name = "StorageFormat";
- aProps[0].Value <<= aFormat;
+ sal_Int32 nPos = 0;
+ aProps[nPos].Name = "StorageFormat";
+ aProps[nPos].Value <<= aFormat;
+ ++nPos;
if ( bRepairStorage )
{
- aProps.realloc( 2 );
- aProps[1].Name = "RepairPackage";
- aProps[1].Value <<= bRepairStorage;
+ aProps.realloc(nPos+1);
+ aProps[nPos].Name = "RepairPackage";
+ aProps[nPos].Value <<= bRepairStorage;
+ ++nPos;
+ }
+
+ if (bUseBufferedStream)
+ {
+ aProps.realloc(nPos+1);
+ aProps[nPos].Name = "UseBufferedStream";
+ aProps[nPos].Value <<= bUseBufferedStream;
+ ++nPos;
}
uno::Sequence< uno::Any > aArgs( 3 );
@@ -349,17 +360,28 @@ uno::Reference< embed::XStorage > OStorageHelper::GetStorageOfFormatFromStream(
const uno::Reference < io::XStream >& xStream,
sal_Int32 nStorageMode,
const uno::Reference< uno::XComponentContext >& rxContext,
- bool bRepairStorage )
+ bool bRepairStorage, bool bUseBufferedStream )
throw ( uno::Exception )
{
uno::Sequence< beans::PropertyValue > aProps( 1 );
- aProps[0].Name = "StorageFormat";
- aProps[0].Value <<= aFormat;
+ sal_Int32 nPos = 0;
+ aProps[nPos].Name = "StorageFormat";
+ aProps[nPos].Value <<= aFormat;
+ ++nPos;
if ( bRepairStorage )
{
- aProps.realloc( 2 );
- aProps[1].Name = "RepairPackage";
- aProps[1].Value <<= bRepairStorage;
+ aProps.realloc(nPos+1);
+ aProps[nPos].Name = "RepairPackage";
+ aProps[nPos].Value <<= bRepairStorage;
+ ++nPos;
+ }
+
+ if (bUseBufferedStream)
+ {
+ aProps.realloc(nPos+1);
+ aProps[nPos].Name = "UseBufferedStream";
+ aProps[nPos].Value <<= bUseBufferedStream;
+ ++nPos;
}
uno::Sequence< uno::Any > aArgs( 3 );
diff --git a/include/comphelper/storagehelper.hxx b/include/comphelper/storagehelper.hxx
index d5655d492f75..67481985d00e 100644
--- a/include/comphelper/storagehelper.hxx
+++ b/include/comphelper/storagehelper.hxx
@@ -154,7 +154,8 @@ public:
const css::uno::Reference < css::io::XInputStream >& xStream,
const css::uno::Reference< css::uno::XComponentContext >& rxContext
= css::uno::Reference< css::uno::XComponentContext >(),
- bool bRepairStorage = false )
+ bool bRepairStorage = false,
+ bool bUseBufferedStream = false )
throw ( css::uno::Exception );
static css::uno::Reference< css::embed::XStorage >
@@ -164,7 +165,8 @@ public:
sal_Int32 nStorageMode = css::embed::ElementModes::READWRITE,
const css::uno::Reference< css::uno::XComponentContext >& rxContext
= css::uno::Reference< css::uno::XComponentContext >(),
- bool bRepairStorage = false )
+ bool bRepairStorage = false,
+ bool bUseBufferedStream = false )
throw ( css::uno::Exception );
static css::uno::Sequence< css::beans::NamedValue >
diff --git a/oox/source/helper/zipstorage.cxx b/oox/source/helper/zipstorage.cxx
index 067365199575..c0d454d14e19 100644
--- a/oox/source/helper/zipstorage.cxx
+++ b/oox/source/helper/zipstorage.cxx
@@ -58,7 +58,7 @@ ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const R
implementation of relations handling.
*/
mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
- ZIP_STORAGE_FORMAT_STRING, rxInStream, rxContext );
+ ZIP_STORAGE_FORMAT_STRING, rxInStream, rxContext, false, true);
}
catch (Exception const& e)
{
@@ -76,7 +76,7 @@ ZipStorage::ZipStorage( const Reference< XComponentContext >& rxContext, const R
{
const sal_Int32 nOpenMode = ElementModes::READWRITE | ElementModes::TRUNCATE;
mxStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream(
- OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, rxContext, true );
+ OFOPXML_STORAGE_FORMAT_STRING, rxStream, nOpenMode, rxContext, true, true);
}
catch (Exception const& e)
{
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 )