summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2014-08-27 15:24:37 +0200
committerTomaž Vajngerl <quikee@gmail.com>2014-08-27 11:09:16 -0500
commit2c7333edf0b0fef2ee4f6757012196cf99a83ca5 (patch)
treeb8f1e36db57962b367db29584e2de9de3a82468f /writerfilter
parentf29c5f742e8be13b5ee7d03ebf1bcaf2a4adfef9 (diff)
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. (cherry picked from commit 41aa970b3120837ca9cadb12997a53ad322145a4) Conflicts: writerfilter/source/dmapper/OLEHandler.cxx writerfilter/source/dmapper/OLEHandler.hxx Also squash in 3 fixes on top of that in the HTML filter which are relevant only after the embedded DOCX import is fixed: 1) sw HTML export: don't crash on embedded object without native data (cherry picked from commit 35e954149d976e0e69a9f8b382fc67f5abc5eaa7) 2) sw HTML export: handle embedded text documents (cherry picked from commit 8d670c9452e930460be600212d73e22acd61cc0f) 3) sw HTML export: avoid invalid output for embedded documents When an sw document is embedded inside an sw one, then the inner sw HTML export should just write what's inside the <body>. Add a filter option for that in sw, similar to the one already existing in sc. (cherry picked from commit 8760b2b05c23e5fdf8ad7ad3f447a7489c2ddeac) Conflicts: sw/source/filter/html/wrthtml.cxx Change-Id: Id2cef966c1022ba45a3540bff234029c1d396778 Reviewed-on: https://gerrit.libreoffice.org/11151 Reviewed-by: Tomaž Vajngerl <quikee@gmail.com> Tested-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx12
-rw-r--r--writerfilter/source/dmapper/OLEHandler.cxx69
-rw-r--r--writerfilter/source/dmapper/OLEHandler.hxx15
3 files changed, 92 insertions, 4 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 34ccea8d2a11..d87389250fe6 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1354,8 +1354,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;
@@ -1397,6 +1402,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 a07b443d83d0..446ba577e527 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 > xTextDocument, const OUString& sObjectName )
+void OLEHandler::saveInteropProperties( uno::Reference< text::XTextDocument > xTextDocument, const OUString& sObjectName, const OUString& sOldObjectName )
{
const OUString sGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
const OUString sEmbeddingsPropName = "EmbeddedObjects";
@@ -200,6 +205,17 @@ void OLEHandler::saveInteropProperties( uno::Reference< text::XTextDocument > xT
// 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( m_sProgId );
@@ -218,6 +234,56 @@ void OLEHandler::saveInteropProperties( uno::Reference< text::XTextDocument > xT
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 > xTextDocument )
{
@@ -260,6 +326,7 @@ OUString OLEHandler::copyOLEOStream( uno::Reference< text::XTextDocument > xText
}
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 9e22fc1d316b..29379008631f 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 > xTextDocument,
- const OUString& sObjectName );
+ const OUString& sObjectName, const OUString& sOldObjectName = OUString() );
public:
OLEHandler(DomainMapper& rDomainMapper);
@@ -83,6 +89,13 @@ public:
inline bool isOLEObject( ) { return m_xInputStream.is( ); };
OUString copyOLEOStream( ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextDocument > xTextDocument );
+ /// 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();
::com::sun::star::awt::Size getSize() const { return m_aShapeSize;}
::com::sun::star::awt::Point getPosition() const { return m_aShapePosition;}