diff options
-rw-r--r-- | comphelper/source/misc/storagehelper.cxx | 46 | ||||
-rw-r--r-- | include/comphelper/storagehelper.hxx | 6 | ||||
-rw-r--r-- | oox/source/helper/zipstorage.cxx | 4 | ||||
-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 |
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 9d1a6da0d2bc..e84ace2abd11 100644 --- a/package/inc/ZipFile.hxx +++ b/package/inc/ZipFile.hxx @@ -64,9 +64,10 @@ class ZipFile 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, @@ -102,6 +103,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 > 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 08d862aad637..0f436aba67a0 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -74,6 +74,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference , xStream(xInput) , m_xContext ( rxContext ) , bRecoveryMode( false ) +, mbUseBufferedStream(false) { if (bInitialise) { @@ -91,6 +92,7 @@ ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference , xStream(xInput) , m_xContext ( rxContext ) , bRecoveryMode( bForceRecovery ) +, mbUseBufferedStream(false) { if (bInitialise) { @@ -111,6 +113,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 ); @@ -504,7 +511,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, @@ -514,7 +613,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; } std::unique_ptr<ZipEnumeration> ZipFile::entries() @@ -542,7 +648,7 @@ uno::Reference< XInputStream > ZipFile::getInputStream( ZipEntry& rEntry, 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, @@ -578,7 +684,7 @@ uno::Reference< XInputStream > ZipFile::getDataStream( ZipEntry& rEntry, else bNeedRawStream = ( rEntry.nMethod == STORED ); - return createUnbufferedStream ( aMutexHolder, + return createStreamForZipEntry ( aMutexHolder, rEntry, rData, bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA, @@ -595,7 +701,7 @@ uno::Reference< XInputStream > 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 > ZipFile::getWrappedRawStream( @@ -612,7 +718,7 @@ uno::Reference< XInputStream > 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 cb2e618a62ee..83b3a82c37c1 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -563,6 +563,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++ ) { @@ -690,6 +691,10 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) aNamedValue.Value >>= m_bAllowRemoveOnInsert; m_xRootFolder->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" ) @@ -733,6 +738,7 @@ void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) try { m_pZipFile = o3tl::make_unique<ZipFile>(m_xContentStream, m_xContext, true, m_bForceRecovery); + m_pZipFile->setUseBufferedStream(bUseBufferedStream); getZipFileContents(); } catch ( IOException & e ) |