summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasily Melenchuk <vasily.melenchuk@cib.de>2019-11-08 18:28:41 +0300
committerThorsten Behrens <Thorsten.Behrens@CIB.de>2019-12-04 03:55:28 +0100
commit1704e9480f2d8e0124580cfb62a1a3d8c8bdab8f (patch)
tree0f53070318d3dcfb2a9ee8cdccdc8897c3ac5a55
parentd807df8e645427fc0b719073b05f53801ff28652 (diff)
calc: support for writing DRM encrypted xls files
Change-Id: I5faf885cf494becca2838c6493413bcc56e91826
-rw-r--r--sc/source/filter/excel/excel.cxx93
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;
}