diff options
author | Vasily Melenchuk <vasily.melenchuk@cib.de> | 2019-11-08 18:28:41 +0300 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2019-12-04 03:55:28 +0100 |
commit | 1704e9480f2d8e0124580cfb62a1a3d8c8bdab8f (patch) | |
tree | 0f53070318d3dcfb2a9ee8cdccdc8897c3ac5a55 | |
parent | d807df8e645427fc0b719073b05f53801ff28652 (diff) |
calc: support for writing DRM encrypted xls files
Change-Id: I5faf885cf494becca2838c6493413bcc56e91826
-rw-r--r-- | sc/source/filter/excel/excel.cxx | 93 |
1 files changed, 92 insertions, 1 deletions
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; } |