[Libreoffice-commits] core.git: sc/source
Vasily Melenchuk (via logerrit)
logerrit at kemper.freedesktop.org
Mon May 25 08:07:00 UTC 2020
sc/source/filter/excel/excel.cxx | 105 +++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
New commits:
commit aef6106e4c2d956ee89be2a67372de0774d6087f
Author: Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 8 17:53:30 2019 +0300
Commit: Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 25 10:06:12 2020 +0200
calc: add XPackageEncryption support for binary xls
This adds read support for API-based MS-CRYPTO algos.
DRM encryption is implemented as a service and desrption
will be called if we found corresponding streams inside
binary OLE package.
Change-Id: Ie580e5c12c48ccf99f9a932b1c66eb35866b7ef4
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/84439
Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx
index 386342988060..40f320cf530e 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 <unotools/defaultencoding.hxx>
#include <unotools/wincodepage.hxx>
@@ -34,6 +36,8 @@
#include <xistream.hxx>
#include <xltools.hxx>
#include <docoptio.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/processfactory.hxx>
#include <docsh.hxx>
#include <scerrors.hxx>
@@ -44,6 +48,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);
+ if (rStream.is())
+ {
+ sal_Int32 nStreamSize = rStream->GetSize();
+ uno::Sequence< sal_Int8 > oData;
+ oData.realloc(nStreamSize);
+ sal_Int32 nReadBytes = rStream->ReadBytes(oData.getArray(), nStreamSize);
+ if (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;
+ }
+
+ comphelper::SequenceAsHashMap aStreamsData;
+ lcl_getListOfStreams(rStorage.get(), aStreamsData, "");
+
+ 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 = std::make_shared<SvMemoryStream>();
+
+ uno::Reference<io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false));
+ uno::Reference<io::XOutputStream > xDecryptedStream(new utl::OSeekableOutputStreamWrapper(*rNewStorageStrm));
+
+ 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
@@ -69,6 +166,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 );
@@ -79,6 +177,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;
More information about the Libreoffice-commits
mailing list