diff options
author | Vasily Melenchuk <vasily.melenchuk@cib.de> | 2019-11-08 18:28:41 +0300 |
---|---|---|
committer | Thorsten Behrens <Thorsten.Behrens@CIB.de> | 2020-05-25 10:06:46 +0200 |
commit | addb6099b85e1d15d8699856a626d48a8cf59f0a (patch) | |
tree | 9c290b9561f54f0eebda1c5796d644f266001ddf /sc | |
parent | aef6106e4c2d956ee89be2a67372de0774d6087f (diff) |
calc: add XPackageEncryption write support for binary xls
This adds save support for API-based MS-CRYPTO algos. If we have
custom encryption data in media descriptor and corresponding service
is available it will be used during saving.
Change-Id: I5faf885cf494becca2838c6493413bcc56e91826
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/84440
Tested-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/source/filter/excel/excel.cxx | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index 40f320cf530e..2c3a885029d0 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -252,6 +252,37 @@ 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{ + uno::makeAny(beans::NamedValue("Binary", uno::makeAny(true))) }; + 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 = std::make_shared<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; @@ -300,6 +331,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 : std::as_const(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 != static_cast<size_t>(aStreamContent.getLength())) + { + eRet = ERRCODE_IO_CANTWRITE; + break; + } + } + xEncryptedRootStrg->Commit(); + + // Restore encryption data + rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, uno::makeAny(aEncryptionData))); + } + return eRet; } |