[Libreoffice-commits] core.git: Branch 'libreoffice-4-3' - include/sal sw/qa sw/source writerfilter/source

Miklos Vajna vmiklos at collabora.co.uk
Wed Aug 27 09:09:39 PDT 2014


 include/sal/log-areas.dox                                     |    1 
 sw/qa/extras/htmlexport/data/skipimage-embedded-document.docx |binary
 sw/qa/extras/htmlexport/htmlexport.cxx                        |   13 +
 sw/source/filter/html/htmlplug.cxx                            |   12 +
 sw/source/filter/html/wrthtml.cxx                             |   20 ++
 sw/source/filter/html/wrthtml.hxx                             |    2 
 writerfilter/source/dmapper/DomainMapper_Impl.cxx             |   12 +
 writerfilter/source/dmapper/OLEHandler.cxx                    |   69 +++++++++-
 writerfilter/source/dmapper/OLEHandler.hxx                    |   15 ++
 9 files changed, 134 insertions(+), 10 deletions(-)

New commits:
commit 2c7333edf0b0fef2ee4f6757012196cf99a83ca5
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.
    
    (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 at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index 0fb8193..62525e4 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -415,6 +415,7 @@ certain functionality.
 @li @c sw.uno - Writer UNO interfaces
 @li @c sw.ww8 - .doc/.docx export filter, .doc import filter (not writerfilter)
 @li @c sw.ww8.level2 - further info for sw.ww8
+ at li @c sw.html - Writer HTML import/export
 
 @section writerfilter
 
diff --git a/sw/qa/extras/htmlexport/data/skipimage-embedded-document.docx b/sw/qa/extras/htmlexport/data/skipimage-embedded-document.docx
new file mode 100644
index 0000000..f48935a
Binary files /dev/null and b/sw/qa/extras/htmlexport/data/skipimage-embedded-document.docx differ
diff --git a/sw/qa/extras/htmlexport/htmlexport.cxx b/sw/qa/extras/htmlexport/htmlexport.cxx
index fc7f6892..94fb667 100644
--- a/sw/qa/extras/htmlexport/htmlexport.cxx
+++ b/sw/qa/extras/htmlexport/htmlexport.cxx
@@ -149,6 +149,19 @@ DECLARE_HTMLEXPORT_TEST(testSkipImageEmbedded, "skipimage-embedded.doc")
     assertXPath(pDoc, "//span/table", 1);
 }
 
+DECLARE_HTMLEXPORT_TEST(testSkipImageEmbeddedDocument, "skipimage-embedded-document.docx")
+{
+    // Similar to testSkipImageEmbedded, but with an embedded Writer object,
+    // not a Calc one, and this time OOXML, not WW8.
+    htmlDocPtr pDoc = parseHtml(maTempFile);
+    CPPUNIT_ASSERT(pDoc);
+
+    // This was 2, the HTML header was in the document two times.
+    assertXPath(pDoc, "//meta[@name='generator']", 1);
+    // Text of embedded document was missing.
+    assertXPathContent(pDoc, "/html/body/p/span/p/span", "Inner.");
+}
+
 #endif
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx
index 489d28f..8f8f301 100644
--- a/sw/source/filter/html/htmlplug.cxx
+++ b/sw/source/filter/html/htmlplug.cxx
@@ -1270,14 +1270,20 @@ Writer& OutHTML_FrmFmtOLENodeGrf( Writer& rWrt, const SwFrmFmt& rFrmFmt,
         uno::Reference<text::XTextContent> xTextContent(xShape, uno::UNO_QUERY);
         uno::Reference<document::XEmbeddedObjectSupplier2> xEmbeddedObjectSupplier(xTextContent, uno::UNO_QUERY);
         uno::Reference<frame::XStorable> xStorable(xEmbeddedObjectSupplier->getEmbeddedObject(), uno::UNO_QUERY);
+        SAL_WARN_IF(!xStorable.is(), "sw.html", "OutHTML_FrmFmtOLENodeGrf: no embedded object");
 
         // Figure out what is the filter name of the embedded object.
         uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY);
         OUString aFilter;
-        if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
-            aFilter = "HTML (StarCalc)";
+        if (xServiceInfo.is())
+        {
+            if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument"))
+                aFilter = "HTML (StarCalc)";
+            else if (xServiceInfo->supportsService("com.sun.star.text.TextDocument"))
+                aFilter = "HTML (StarWriter)";
+        }
 
-        if (!aFilter.isEmpty())
+        if (xStorable.is() && !aFilter.isEmpty())
         {
             SvMemoryStream aStream;
             uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
diff --git a/sw/source/filter/html/wrthtml.cxx b/sw/source/filter/html/wrthtml.cxx
index 100518f..b9464f6 100644
--- a/sw/source/filter/html/wrthtml.cxx
+++ b/sw/source/filter/html/wrthtml.cxx
@@ -112,6 +112,7 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL )
     , bPreserveForm( false )
     , bCfgNetscape4( false )
     , mbSkipImages(false)
+    , mbSkipHeaderFooter(false)
 
 {
     SetBaseURL( rBaseURL );
@@ -150,6 +151,10 @@ void SwHTMLWriter::SetupFilterOptions(SfxMedium& rMedium)
     {
         mbSkipImages = true;
     }
+    else if (sFilterOptions == "SkipHeaderFooter")
+    {
+        mbSkipHeaderFooter = true;
+    }
 }
 
 sal_uLong SwHTMLWriter::WriteStream()
@@ -391,9 +396,12 @@ sal_uLong SwHTMLWriter::WriteStream()
 
     if( bLFPossible )
         OutNewLine();
-    HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body, false );
-    OutNewLine();
-    HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html, false );
+    if (!mbSkipHeaderFooter)
+    {
+        HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body, false );
+        OutNewLine();
+        HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html, false );
+    }
 
     // loesche die Tabelle mit den freifliegenden Rahmen
     sal_uInt16 i;
@@ -902,6 +910,8 @@ sal_uInt16 SwHTMLWriter::OutHeaderAttrs()
 const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
 {
     OStringBuffer sOut;
+    if (!mbSkipHeaderFooter)
+    {
     sOut.append(OString(OOO_STRING_SVTOOLS_HTML_doctype) + " " + OString(OOO_STRING_SVTOOLS_HTML_doctype40));
     HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.makeStringAndClear().getStr() );
 
@@ -935,6 +945,7 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
     rHeaderAttrs = OutHeaderAttrs();
 
     OutFootEndNoteInfo();
+    }
 
     const SwPageDesc *pPageDesc = 0;
 
@@ -964,6 +975,8 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
     if( !pPageDesc )
         pPageDesc = &pDoc->GetPageDesc( 0 );
 
+    if (!mbSkipHeaderFooter)
+    {
     // und nun ... das Style-Sheet!!!
     if( bCfgOutStyles )
     {
@@ -1015,6 +1028,7 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
         OutBasicBodyEvents();
 
     Strm().WriteChar( '>' );
+    }
 
     return pPageDesc;
 }
diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx
index 70b6f4a..3de8a59 100644
--- a/sw/source/filter/html/wrthtml.hxx
+++ b/sw/source/filter/html/wrthtml.hxx
@@ -399,6 +399,8 @@ public:
     bool bCfgNetscape4 : 1;         // Netscape4 Hacks
 
     bool mbSkipImages : 1;
+    /// If HTML header and footer should be written as well, or just the content itself.
+    bool mbSkipHeaderFooter : 1;
 
     // 23
 
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 34ccea8..d873892 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 a07b443..446ba57 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 9e22fc1..2937900 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;}


More information about the Libreoffice-commits mailing list