summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2019-11-08 18:28:41 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2020-05-25 10:06:46 +0200
commitaddb6099b85e1d15d8699856a626d48a8cf59f0a (patch)
tree9c290b9561f54f0eebda1c5796d644f266001ddf /sc
parentaef6106e4c2d956ee89be2a67372de0774d6087f (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.cxx92
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;
}