sc/source/filter/excel/excel.cxx | 196 ++++++++++++++++++++++++++++++++++++ sd/source/filter/sdpptwrp.cxx | 207 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 398 insertions(+), 5 deletions(-)
New commits: commit 14345498e62bbff05ace081d4a00f7489cea07d4 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 21:17:10 2019 +0300 Commit: Vasily Melenchuk <vasily.melenc...@cib.de> CommitDate: Fri Nov 8 21:24:09 2019 +0300 sd: support for DRM encryption during saving to ppt Change-Id: Id82f8b3fa7ea045b00d7d81e2c9ce5e130c8060c diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx index bb42b9d4bc11..cc418fd7fc5a 100644 --- a/sd/source/filter/sdpptwrp.cxx +++ b/sd/source/filter/sdpptwrp.cxx @@ -219,8 +219,6 @@ bool SdPPTFilter::Export() if( mxModel.is() ) { - tools::SvRef<SotStorage> xStorRef = new SotStorage( mrMedium.GetOutStream(), false ); - #ifdef DISABLE_DYNLOADING ExportPPTPointer PPTExport = ExportPPT; #else @@ -228,7 +226,7 @@ bool SdPPTFilter::Export() SdFilter::GetLibrarySymbol(mrMedium.GetFilter()->GetUserData(), "ExportPPT")); #endif - if( PPTExport && xStorRef.is() ) + if( PPTExport) { sal_uInt32 nCnvrtFlags = 0; const SvtFilterOptions& rFilterOptions = SvtFilterOptions::Get(); @@ -252,8 +250,105 @@ bool SdPPTFilter::Export() aProperty.Value <<= mrMedium.GetBaseURL( true ); aProperties.push_back( aProperty ); - bRet = PPTExport( aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags ); - xStorRef->Commit(); + SvStream * pOutputStrm = mrMedium.GetOutStream(); + + Sequence< NamedValue > aEncryptionData; + Reference< css::packages::XPackageEncryption > xPackageEncryption; + const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(mrMedium.GetItemSet(), SID_ENCRYPTIONDATA, false); + std::shared_ptr<SvStream> pMediaStrm; + if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData)) + { + ::comphelper::SequenceAsHashMap aHashData(aEncryptionData); + OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString()); + + if (sCryptoType.getLength()) + { + Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + Sequence<Any> aArguments; + xPackageEncryption.set( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), UNO_QUERY); + + if (xPackageEncryption.is()) + { + // We have an encryptor. Export document into memory stream and encrypt it later + pMediaStrm.reset(new SvMemoryStream()); + pOutputStrm = pMediaStrm.get(); + + // Temp removal of EncryptionData to avoid password protection triggering + mrMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA); + } + } + } + + tools::SvRef<SotStorage> xStorRef = new SotStorage(pOutputStrm, false); + + if (xStorRef.is()) + { + bRet = PPTExport(aProperties, xStorRef, mxModel, mxStatusIndicator, pBas, nCnvrtFlags); + xStorRef->Commit(); + + if (xPackageEncryption.is()) + { + // Perform DRM encryption + pOutputStrm->Seek(0); + + xPackageEncryption->setupEncryption(aEncryptionData); + + Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pOutputStrm, false)); + Sequence<NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream); + + tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(mrMedium.GetOutStream(), false); + for (const NamedValue & aStreamData : aStreams) + { + // To avoid long paths split and open substorages recursively + // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09 + SotStorage * pStorage = xEncryptedRootStrg.get(); + OUString sFileName; + sal_Int32 idx = 0; + do + { + OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx); + if (!sPathElem.isEmpty()) + { + if (idx < 0) + { + sFileName = sPathElem; + } + else + { + pStorage = pStorage->OpenSotStorage(sPathElem); + } + } + } while (pStorage && idx >= 0); + + if (!pStorage) + { + bRet = false; + break; + } + + SotStorageStream* pStream = pStorage->OpenSotStream(sFileName); + if (!pStream) + { + bRet = false; + break; + } + Sequence<sal_Int8> aStreamContent; + aStreamData.Value >>= aStreamContent; + size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength()); + if (nBytesWritten != aStreamContent.getLength()) + { + bRet = false; + break; + } + } + xEncryptedRootStrg->Commit(); + + // Restore encryption data + mrMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData))); + } + } } } commit 9f0a53de62238edb4ee03d13bdf1e3acdcd1e5e0 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 21:00:12 2019 +0300 Commit: Vasily Melenchuk <vasily.melenc...@cib.de> CommitDate: Fri Nov 8 21:24:09 2019 +0300 sd: support of DRM encrypted ppt files reading Change-Id: Ib91538d53ee1f53a3cd14a44d47fd6f6136c0472 diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx index edc21c482d45..bb42b9d4bc11 100644 --- a/sd/source/filter/sdpptwrp.cxx +++ b/sd/source/filter/sdpptwrp.cxx @@ -23,6 +23,10 @@ #include <svx/svxerr.hxx> #include <unotools/fltrcfg.hxx> #include <sot/storage.hxx> +#include <comphelper/sequenceashashmap.hxx> + +#include <com/sun/star/packages/XPackageEncryption.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <sdpptwrp.hxx> #include <DrawDocShell.hxx> @@ -67,9 +71,101 @@ SdPPTFilter::~SdPPTFilter() delete pBas; // deleting the compressed basic storage } +static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix) +{ + SvStorageInfoList aElements; + pStorage->FillInfoList(&aElements); + for (const auto & aElement : aElements) + { + OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName(); + if (aElement.IsStorage()) + { + SotStorage * pSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL); + lcl_getListOfStreams(pSubStorage, aStreamsData, sStreamFullName); + } + else + { + // Read stream + tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL); + assert(rStream.is()); + + sal_Int32 nStreamSize = rStream->GetSize(); + Sequence< sal_Int8 > oData; + oData.realloc(nStreamSize); + sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); + assert(nStreamSize == nReadBytes); + aStreamsData[sStreamFullName] <<= oData; + } + } +} + +static tools::SvRef<SotStorage> lcl_DRMDecrypt(SfxMedium& rMedium, tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm) +{ + tools::SvRef<SotStorage> aNewStorage; + + // We have DRM encrypted storage. We should try to decrypt it first, if we can + Sequence< Any > aArguments; + Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + Reference< css::packages::XPackageEncryption > xPackageEncryption( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), UNO_QUERY); + + if (!xPackageEncryption.is()) + { + // We do not know how to decrypt this + return aNewStorage; + } + + std::vector<OUString> aStreamsList; + comphelper::SequenceAsHashMap aStreamsData; + lcl_getListOfStreams(rStorage.get(), aStreamsData, OUString("")); + + try { + Sequence<NamedValue> aStreams = aStreamsData.getAsConstNamedValueList(); + if (!xPackageEncryption->readEncryptionInfo(aStreams)) + { + // We failed with decryption + return aNewStorage; + } + + tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL); + if (!rContentStream.is()) + { + return aNewStorage; + } + + rNewStorageStrm.reset(new SvMemoryStream()); + + Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); + Reference<css::io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm.get())); + + if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream)) + { + // We failed with decryption + return aNewStorage; + } + + rNewStorageStrm->Seek(0); + + // Further reading is done from new document + aNewStorage = new SotStorage(*rNewStorageStrm); + + // Set the media descriptor data + Sequence<NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData(""); + rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData))); + } + catch (const std::exception&) + { + return aNewStorage; + } + + return aNewStorage; +} + bool SdPPTFilter::Import() { bool bRet = false; + std::shared_ptr<SvStream> aDecryptedStorageStrm; tools::SvRef<SotStorage> pStorage = new SotStorage( mrMedium.GetInStream(), false ); if( !pStorage->GetError() ) { @@ -82,6 +178,12 @@ bool SdPPTFilter::Import() xDualStorage = pStorage->OpenSotStorage( sDualStorage, StreamMode::STD_READ ); pStorage = xDualStorage; } + OUString sDRMContent("\011DRMContent"); + if (pStorage->IsContained(sDRMContent)) + { + // Document is DRM encrypted + pStorage = lcl_DRMDecrypt(mrMedium, pStorage, aDecryptedStorageStrm); + } std::unique_ptr<SvStream> pDocStream(pStorage->OpenSotStream( "PowerPoint Document" , StreamMode::STD_READ )); if( pDocStream ) { commit b18609143902b3c59ff7025c09a7dca6bae7a2a5 Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 18:28:41 2019 +0300 Commit: Vasily Melenchuk <vasily.melenc...@cib.de> CommitDate: Fri Nov 8 21:24:09 2019 +0300 calc: support for writing DRM encrypted xls files Change-Id: I5faf885cf494becca2838c6493413bcc56e91826 diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index 56adce29a061..2e4015e34569 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -24,7 +24,7 @@ #include <sot/exchange.hxx> #include <filter/msfilter/classids.hxx> #include <tools/globname.hxx> -#include <com/sun/star/packages/XPAckageEncryption.hpp> +#include <com/sun/star/packages/XPackageEncryption.hpp> #include <com/sun/star/ucb/ContentCreationException.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <unotools/streamwrap.hxx> @@ -248,6 +248,36 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument, SvStream* pMedStrm, bool bBiff8, rtl_TextEncoding eNach ) { + uno::Reference< packages::XPackageEncryption > xPackageEncryption; + uno::Sequence< beans::NamedValue > aEncryptionData; + const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(rMedium.GetItemSet(), SID_ENCRYPTIONDATA, false); + SvStream* pOriginalMediaStrm = pMedStrm; + std::shared_ptr<SvStream> pMediaStrm; + if (pEncryptionDataItem && (pEncryptionDataItem->GetValue() >>= aEncryptionData)) + { + ::comphelper::SequenceAsHashMap aHashData(aEncryptionData); + OUString sCryptoType = aHashData.getUnpackedValueOrDefault("CryptoType", OUString()); + + if (sCryptoType.getLength()) + { + uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + uno::Sequence<uno::Any> aArguments; + xPackageEncryption.set( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto." + sCryptoType, aArguments, xComponentContext), uno::UNO_QUERY); + + if (xPackageEncryption.is()) + { + // We have an encryptor. Export document into memory stream and encrypt it later + pMediaStrm.reset(new SvMemoryStream()); + pMedStrm = pMediaStrm.get(); + + // Temp removal of EncryptionData to avoid password protection triggering + rMedium.GetItemSet()->ClearItem(SID_ENCRYPTIONDATA); + } + } + } + // try to open an OLE storage tools::SvRef<SotStorage> xRootStrg = new SotStorage( pMedStrm, false ); if( xRootStrg->GetError() ) return SCERR_IMPORT_OPEN; @@ -296,6 +326,67 @@ static ErrCode lcl_ExportExcelBiff( SfxMedium& rMedium, ScDocument *pDocument, xStrgStrm->Commit(); xRootStrg->Commit(); + if (xPackageEncryption.is()) + { + // Perform DRM encryption + pMedStrm->Seek(0); + + xPackageEncryption->setupEncryption(aEncryptionData); + + uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(pMedStrm, false)); + uno::Sequence<beans::NamedValue> aStreams = xPackageEncryption->encrypt(xInputStream); + + tools::SvRef<SotStorage> xEncryptedRootStrg = new SotStorage(pOriginalMediaStrm, false); + for (const beans::NamedValue & aStreamData : aStreams) + { + // To avoid long paths split and open substorages recursively + // Splitting paths manually, since comphelper::string::split is trimming special characters like \0x01, \0x09 + SotStorage * pStorage = xEncryptedRootStrg.get(); + OUString sFileName; + sal_Int32 idx = 0; + do + { + OUString sPathElem = aStreamData.Name.getToken(0, L'/', idx); + if (!sPathElem.isEmpty()) + { + if (idx < 0) + { + sFileName = sPathElem; + } + else + { + pStorage = pStorage->OpenSotStorage(sPathElem); + } + } + } while (pStorage && idx >= 0); + + if (!pStorage) + { + eRet = ERRCODE_IO_GENERAL; + break; + } + + SotStorageStream* pStream = pStorage->OpenSotStream(sFileName); + if (!pStream) + { + eRet = ERRCODE_IO_GENERAL; + break; + } + uno::Sequence<sal_Int8> aStreamContent; + aStreamData.Value >>= aStreamContent; + size_t nBytesWritten = pStream->WriteBytes(aStreamContent.getArray(), aStreamContent.getLength()); + if (nBytesWritten != aStreamContent.getLength()) + { + eRet = ERRCODE_IO_CANTWRITE; + break; + } + } + xEncryptedRootStrg->Commit(); + + // Restore encryption data + rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData))); + } + return eRet; } commit 7bcb4fac6adebe29f6b2479f5bda91ebf4da7f0e Author: Vasily Melenchuk <vasily.melenc...@cib.de> AuthorDate: Fri Nov 8 17:53:30 2019 +0300 Commit: Vasily Melenchuk <vasily.melenc...@cib.de> CommitDate: Fri Nov 8 21:24:08 2019 +0300 calc: support for reading DRM encrypted xls files DRM encryption is implemented as an optional service, so just use it when available. Change-Id: Ie580e5c12c48ccf99f9a932b1c66eb35866b7ef4 diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index ca87efc2988c..56adce29a061 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -24,7 +24,9 @@ #include <sot/exchange.hxx> #include <filter/msfilter/classids.hxx> #include <tools/globname.hxx> +#include <com/sun/star/packages/XPAckageEncryption.hpp> #include <com/sun/star/ucb/ContentCreationException.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <unotools/streamwrap.hxx> #include <osl/diagnose.h> #include <filter.hxx> @@ -32,6 +34,8 @@ #include <xistream.hxx> #include <xltools.hxx> #include <docoptio.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <comphelper/processfactory.hxx> #include <docsh.hxx> #include <scerrors.hxx> @@ -42,6 +46,99 @@ #include <memory> +using namespace css; + +static void lcl_getListOfStreams(SotStorage * pStorage, comphelper::SequenceAsHashMap& aStreamsData, const OUString& sPrefix) +{ + SvStorageInfoList aElements; + pStorage->FillInfoList(&aElements); + for (const auto & aElement : aElements) + { + OUString sStreamFullName = sPrefix.getLength() ? sPrefix + "/" + aElement.GetName() : aElement.GetName(); + if (aElement.IsStorage()) + { + SotStorage * pSubStorage = pStorage->OpenSotStorage(aElement.GetName(), StreamMode::STD_READ | StreamMode::SHARE_DENYALL); + lcl_getListOfStreams(pSubStorage, aStreamsData, sStreamFullName); + } + else + { + // Read stream + tools::SvRef<SotStorageStream> rStream = pStorage->OpenSotStream(aElement.GetName(), StreamMode::READ | StreamMode::SHARE_DENYALL); + assert(rStream.is()); + + sal_Int32 nStreamSize = rStream->GetSize(); + uno::Sequence< sal_Int8 > oData; + oData.realloc(nStreamSize); + sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize); + assert(nStreamSize == nReadBytes); + aStreamsData[sStreamFullName] <<= oData; + } + } +} + +static tools::SvRef<SotStorage> lcl_DRMDecrypt(SfxMedium& rMedium, tools::SvRef<SotStorage>& rStorage, std::shared_ptr<SvStream>& rNewStorageStrm) +{ + tools::SvRef<SotStorage> aNewStorage; + + // We have DRM encrypted storage. We should try to decrypt it first, if we can + uno::Sequence< uno::Any > aArguments; + uno::Reference<uno::XComponentContext> xComponentContext(comphelper::getProcessComponentContext()); + uno::Reference< packages::XPackageEncryption > xPackageEncryption( + xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), uno::UNO_QUERY); + + if (!xPackageEncryption.is()) + { + // We do not know how to decrypt this + return aNewStorage; + } + + std::vector<OUString> aStreamsList; + comphelper::SequenceAsHashMap aStreamsData; + lcl_getListOfStreams(rStorage.get(), aStreamsData, OUString("")); + + try { + uno::Sequence<beans::NamedValue> aStreams = aStreamsData.getAsConstNamedValueList(); + if (!xPackageEncryption->readEncryptionInfo(aStreams)) + { + // We failed with decryption + return aNewStorage; + } + + tools::SvRef<SotStorageStream> rContentStream = rStorage->OpenSotStream("\011DRMContent", StreamMode::READ | StreamMode::SHARE_DENYALL); + if (!rContentStream.is()) + { + return aNewStorage; + } + + rNewStorageStrm.reset(new SvMemoryStream()); + + uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false)); + uno::Reference<io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm.get())); + + if (!xPackageEncryption->decrypt(xInputStream, xDecryptedStream)) + { + // We failed with decryption + return aNewStorage; + } + + rNewStorageStrm->Seek(0); + + // Further reading is done from new document + aNewStorage = new SotStorage(*rNewStorageStrm); + + // Set the media descriptor data + uno::Sequence<beans::NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData(""); + rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData))); + } + catch (const std::exception&) + { + return aNewStorage; + } + + return aNewStorage; +} + ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* pDocument, const EXCIMPFORMAT eFormat ) { // check the passed Calc document @@ -67,6 +164,7 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* // try to open an OLE storage tools::SvRef<SotStorage> xRootStrg; tools::SvRef<SotStorageStream> xStrgStrm; + std::shared_ptr<SvStream> aNewStorageStrm; if( SotStorage::IsStorageFile( pMedStrm ) ) { xRootStrg = new SotStorage( pMedStrm, false ); @@ -77,6 +175,13 @@ ErrCode ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument* // try to open "Book" or "Workbook" stream in OLE storage if( xRootStrg.is() ) { + // Check if there is DRM encryption in storage + tools::SvRef<SotStorageStream> xDRMStrm = ScfTools::OpenStorageStreamRead(xRootStrg, "\011DRMContent"); + if (xDRMStrm.is()) + { + xRootStrg = lcl_DRMDecrypt(rMedium, xRootStrg, aNewStorageStrm); + } + // try to open the "Book" stream tools::SvRef<SotStorageStream> xBookStrm = ScfTools::OpenStorageStreamRead( xRootStrg, EXC_STREAM_BOOK ); XclBiff eBookBiff = xBookStrm.is() ? XclImpStream::DetectBiffVersion( *xBookStrm ) : EXC_BIFF_UNKNOWN; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits