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

Miklos Vajna vmiklos at collabora.co.uk
Wed Aug 27 06:35:23 PDT 2014


 writerfilter/source/dmapper/DomainMapper_Impl.cxx |   12 +++
 writerfilter/source/dmapper/OLEHandler.cxx        |   69 +++++++++++++++++++++-
 writerfilter/source/dmapper/OLEHandler.hxx        |   16 ++++-
 3 files changed, 93 insertions(+), 4 deletions(-)

New commits:
commit 41aa970b3120837ca9cadb12997a53ad322145a4
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Wed Aug 27 15:24:37 2014 +0200

    DOCX import: fix handling of embedded DOCX files
    
    The problem was that SwXTextEmbeddedObject::getEmbeddedObject() returned
    an empty reference for those embedded objects, so the HTML filter
    couldn't extract their content when it wanted to do so.
    
    It turns out the reason for this was that the DOCX importer only handled
    the replacement image + raw native data for the object. Fix this by
    creating the embedded object with the correct CLSID and import the
    raw data into the empty embedded document model.
    
    This is similar to what is done for XLSX-in-PPTX in
    oox::drawingml::ShapeExport::WriteOLE2Shape(), just for the import part.
    
    Change-Id: Ieb1dcb1774d2d4da00117e3a35160053066c78aa

diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 0428c87..cbb5024 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1319,8 +1319,13 @@ void DomainMapper_Impl::appendOLE( const OUString& rStreamName, OLEHandlerPtr pO
         uno::Reference< text::XTextContent > xOLE( m_xTextFactory->createInstance(sEmbeddedService), uno::UNO_QUERY_THROW );
         uno::Reference< beans::XPropertySet > xOLEProperties(xOLE, uno::UNO_QUERY_THROW);
 
-        xOLEProperties->setPropertyValue(PropertyNameSupplier::GetPropertyNameSupplier().GetName( PROP_STREAM_NAME ),
-                        uno::makeAny( rStreamName ));
+        OUString aCLSID = pOLEHandler->getCLSID();
+        if (aCLSID.isEmpty())
+            xOLEProperties->setPropertyValue(PropertyNameSupplier::GetPropertyNameSupplier().GetName( PROP_STREAM_NAME ),
+                            uno::makeAny( rStreamName ));
+        else
+            xOLEProperties->setPropertyValue("CLSID", uno::makeAny(OUString(aCLSID)));
+
         awt::Size aSize = pOLEHandler->getSize();
         if( !aSize.Width )
             aSize.Width = 1000;
@@ -1362,6 +1367,9 @@ void DomainMapper_Impl::appendOLE( const OUString& rStreamName, OLEHandlerPtr pO
 
         appendTextContent( xOLE, uno::Sequence< beans::PropertyValue >() );
 
+        if (!aCLSID.isEmpty())
+            pOLEHandler->importStream(m_xComponentContext, GetTextDocument(), xOLE);
+
     }
     catch( const uno::Exception& )
     {
diff --git a/writerfilter/source/dmapper/OLEHandler.cxx b/writerfilter/source/dmapper/OLEHandler.cxx
index a084005..a743ceb 100644
--- a/writerfilter/source/dmapper/OLEHandler.cxx
+++ b/writerfilter/source/dmapper/OLEHandler.cxx
@@ -24,9 +24,13 @@
 #include <editeng/unoprnms.hxx>
 #include <ooxml/resourceids.hxx>
 #include <rtl/ustring.hxx>
+#include <unotools/mediadescriptor.hxx>
 #include <com/sun/star/beans/PropertyValue.hpp>
 #include <com/sun/star/container/XNameAccess.hpp>
 #include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
+#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
 #include <com/sun/star/document/XStorageBasedDocument.hpp>
 #include <com/sun/star/drawing/XShape.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
@@ -34,6 +38,7 @@
 #include <com/sun/star/graphic/XGraphic.hpp>
 #include <com/sun/star/io/XStream.hpp>
 #include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
 #include <com/sun/star/uno/XComponentContext.hpp>
@@ -177,7 +182,7 @@ void OLEHandler::lcl_sprm(Sprm & rSprm)
 }
 
 
-void OLEHandler::saveInteropProperties(uno::Reference<text::XTextDocument> const& xTextDocument, const OUString& sObjectName)
+void OLEHandler::saveInteropProperties(uno::Reference<text::XTextDocument> const& xTextDocument, const OUString& sObjectName, const OUString& sOldObjectName)
 {
     const OUString sGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
     const OUString sEmbeddingsPropName = "EmbeddedObjects";
@@ -206,6 +211,17 @@ void OLEHandler::saveInteropProperties(uno::Reference<text::XTextDocument> const
 
     // save ProgID of current object
     sal_Int32 length = objectsList.getLength();
+
+    // If we got an "old name", erase that first.
+    if (!sOldObjectName.isEmpty())
+    {
+        comphelper::SequenceAsHashMap aMap(objectsList);
+        comphelper::SequenceAsHashMap::iterator it = aMap.find(sOldObjectName);
+        if (it != aMap.end())
+            aMap.erase(it);
+        objectsList = aMap.getAsConstPropertyValueList();
+    }
+
     objectsList.realloc( length + 1 );
     objectsList[length].Name = sObjectName;
     objectsList[length].Value = uno::Any( aGrabBagAttribute );
@@ -224,6 +240,56 @@ void OLEHandler::saveInteropProperties(uno::Reference<text::XTextDocument> const
     xDocProps->setPropertyValue( sGrabBagPropName, uno::Any( aGrabBag ) );
 }
 
+void OLEHandler::importStream(uno::Reference<uno::XComponentContext> xComponentContext, uno::Reference<text::XTextDocument> xTextDocument, uno::Reference<text::XTextContent> xOLE)
+{
+    OUString aFilterService, aFilterName;
+    if (m_sProgId == "Word.Document.12")
+    {
+        aFilterService = "com.sun.star.comp.Writer.WriterFilter";
+        aFilterName = "writer_MS_Word_2007";
+    }
+
+    if (!m_xInputStream.is() || aFilterService.isEmpty())
+        return;
+
+    // Create the filter service.
+    uno::Reference<uno::XInterface> xInterface = xComponentContext->getServiceManager()->createInstanceWithContext(aFilterService, xComponentContext);
+
+    // Initialize it.
+    uno::Sequence<beans::PropertyValue> aArgs(1);
+    aArgs[0].Name = "Type";
+    aArgs[0].Value <<= OUString(aFilterName);
+    uno::Sequence<uno::Any> aAnySeq(1);
+    aAnySeq[0] <<= aArgs;
+    uno::Reference<lang::XInitialization> xInitialization(xInterface, uno::UNO_QUERY);
+    xInitialization->initialize(aAnySeq);
+
+    // Set target document.
+    uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY);
+    uno::Reference<document::XEmbeddedObjectSupplier> xSupplier(xOLE, uno::UNO_QUERY);
+    uno::Reference<lang::XComponent> xEmbeddedObject(xSupplier->getEmbeddedObject(), uno::UNO_QUERY);
+    xImporter->setTargetDocument( xEmbeddedObject );
+
+    // Import the input stream.
+    utl::MediaDescriptor aMediaDescriptor;
+    aMediaDescriptor["InputStream"] <<= m_xInputStream;
+    uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY);
+    xFilter->filter(aMediaDescriptor.getAsConstPropertyValueList());
+
+    // Now that the data is imported, update the (typically) changed stream name.
+    uno::Reference<beans::XPropertySet> xPropertySet(xOLE, uno::UNO_QUERY);
+    saveInteropProperties(xTextDocument, xPropertySet->getPropertyValue("StreamName").get<OUString>(), m_aURL);
+}
+
+OUString OLEHandler::getCLSID()
+{
+    OUString aRet;
+
+    if (m_sProgId == "Word.Document.12")
+        aRet = "8BC6B165-B1B2-4EDD-aa47-dae2ee689dd6";
+
+    return aRet;
+}
 
 OUString OLEHandler::copyOLEOStream(
         uno::Reference<text::XTextDocument> const& xTextDocument)
@@ -267,6 +333,7 @@ OUString OLEHandler::copyOLEOStream(
         }
         uno::Reference< lang::XComponent > xComp( xEmbeddedResolver, uno::UNO_QUERY_THROW );
         xComp->dispose();
+        m_aURL = aURL;
     }
     catch( const uno::Exception& )
     {
diff --git a/writerfilter/source/dmapper/OLEHandler.hxx b/writerfilter/source/dmapper/OLEHandler.hxx
index 2c96955..64677bb 100644
--- a/writerfilter/source/dmapper/OLEHandler.hxx
+++ b/writerfilter/source/dmapper/OLEHandler.hxx
@@ -34,8 +34,12 @@ namespace com{ namespace sun{ namespace star{
         class XInputStream;
     }
     namespace text{
+        class XTextContent;
         class XTextDocument;
     }
+    namespace uno {
+        class XComponentContext;
+    }
 }}}
 namespace writerfilter {
 namespace dmapper
@@ -51,6 +55,8 @@ class OLEHandler : public LoggedProperties
     OUString     m_sDrawAspect;
     OUString     m_sObjectId;
     OUString     m_sr_id;
+    /// The stream URL right after the import of the raw data.
+    OUString     m_aURL;
 
     sal_Int32                   m_nDxaOrig;
     sal_Int32                   m_nDyaOrig;
@@ -72,7 +78,7 @@ class OLEHandler : public LoggedProperties
 
     // Interoperability
     virtual void saveInteropProperties( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextDocument > const& xTextDocument,
-                                        const OUString& sObjectName );
+                                        const OUString& sObjectName, const OUString& sOldObjectName = OUString() );
 
 public:
     OLEHandler(DomainMapper& rDomainMapper);
@@ -82,6 +88,14 @@ public:
 
     inline bool isOLEObject( ) { return m_xInputStream.is( ); };
 
+    /// In case of a valid CLSID, import the native data to the previously created empty OLE object.
+    void importStream(css::uno::Reference<css::uno::XComponentContext> xComponentContext,
+                      css::uno::Reference<css::text::XTextDocument> xTextDocument,
+                      css::uno::Reference<css::text::XTextContent> xOLE);
+
+    /// Get the CLSID of the OLE object, in case we can find one based on m_sProgId.
+    OUString getCLSID();
+
     OUString copyOLEOStream( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextDocument > const & xTextDocument );
 
     ::com::sun::star::awt::Size     getSize() const { return m_aShapeSize;}


More information about the Libreoffice-commits mailing list