[Libreoffice-commits] core.git: sd/source

Vasily Melenchuk (via logerrit) logerrit at kemper.freedesktop.org
Mon May 25 08:08:07 UTC 2020


 sd/source/filter/sdpptwrp.cxx |  107 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 106 insertions(+), 1 deletion(-)

New commits:
commit 1e18f22c6f497f269fe3226bc00afc3c8874049d
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Fri Nov 8 21:00:12 2019 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon May 25 10:07:26 2020 +0200

    sd: add XPackageEncryption support for binary ppt
    
    This adds read support for API-based MS-CRYPTO algos.
    
    DRM encryption is implemented as a service and description
    will be called if we found corresponding streams inside
    binary OLE package.
    
    Change-Id: Ib91538d53ee1f53a3cd14a44d47fd6f6136c0472
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/84441
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sd/source/filter/sdpptwrp.cxx b/sd/source/filter/sdpptwrp.cxx
index edc21c482d45..08d897f6acfd 100644
--- a/sd/source/filter/sdpptwrp.cxx
+++ b/sd/source/filter/sdpptwrp.cxx
@@ -19,14 +19,21 @@
 
 #include <sfx2/docfile.hxx>
 #include <sfx2/docfilt.hxx>
+#include <sfx2/sfxsids.hrc>
 #include <filter/msfilter/msoleexp.hxx>
 #include <svx/svxerr.hxx>
 #include <unotools/fltrcfg.hxx>
+#include <unotools/streamwrap.hxx>
 #include <sot/storage.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/packages/XPackageEncryption.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
 
 #include <sdpptwrp.hxx>
 #include <DrawDocShell.hxx>
-
+#include <sfx2/frame.hxx>
 
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::beans;
@@ -67,9 +74,101 @@ SdPPTFilter::~SdPPTFilter()
     delete pBas;    // deleting the compressed basic storage
 }
 
+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();
+                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
+    Sequence< Any > aArguments;
+    Reference<XComponentContext> xComponentContext(comphelper::getProcessComponentContext());
+    Reference< css::packages::XPackageEncryption > xPackageEncryption(
+        xComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+            "com.sun.star.comp.oox.crypto.DRMDataSpace", aArguments, xComponentContext), UNO_QUERY);
+
+    if (!xPackageEncryption.is())
+    {
+        // We do not know how to decrypt this
+        return aNewStorage;
+    }
+
+    comphelper::SequenceAsHashMap aStreamsData;
+    lcl_getListOfStreams(rStorage.get(), aStreamsData, "");
+
+    try {
+        Sequence<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>();
+
+        Reference<css::io::XInputStream > xInputStream(new utl::OSeekableInputStreamWrapper(rContentStream.get(), false));
+        Reference<css::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
+        Sequence<NamedValue> aEncryptionData = xPackageEncryption->createEncryptionData("");
+        rMedium.GetItemSet()->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA, makeAny(aEncryptionData)));
+    }
+    catch (const std::exception&)
+    {
+        return aNewStorage;
+    }
+
+    return aNewStorage;
+}
+
 bool SdPPTFilter::Import()
 {
     bool bRet = false;
+    std::shared_ptr<SvStream> aDecryptedStorageStrm;
     tools::SvRef<SotStorage> pStorage = new SotStorage( mrMedium.GetInStream(), false );
     if( !pStorage->GetError() )
     {
@@ -82,6 +181,12 @@ bool SdPPTFilter::Import()
             xDualStorage = pStorage->OpenSotStorage( sDualStorage, StreamMode::STD_READ );
             pStorage = xDualStorage;
         }
+        OUString sDRMContent("\011DRMContent");
+        if (pStorage->IsContained(sDRMContent))
+        {
+            // Document is DRM encrypted
+            pStorage = lcl_DRMDecrypt(mrMedium, pStorage, aDecryptedStorageStrm);
+        }
         std::unique_ptr<SvStream> pDocStream(pStorage->OpenSotStream( "PowerPoint Document" , StreamMode::STD_READ ));
         if( pDocStream )
         {


More information about the Libreoffice-commits mailing list