writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx |   21 +++++
 writerfilter/qa/cppunittests/dmapper/data/alt-chunk.docx   |binary
 writerfilter/source/dmapper/DomainMapper.cxx               |   12 ++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx          |   54 +++++++++++++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx          |    6 +
 5 files changed, 90 insertions(+), 3 deletions(-)

New commits:
commit 4347d505e7d1c90809dd356334fcdc7936c84f73
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Oct 22 17:21:33 2020 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Oct 22 20:04:20 2020 +0200

    DOCX import: handle <w:altChunk r:id="..."/>
    
    This refers to a self-contained full DOCX file inside a DOCX file.
    
    Change-Id: Ic9451833db30231f08ff2e2493da678edbc9a4c6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104654
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
index de63ec4084d9..16b9bfa5023b 100644
--- a/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/qa/cppunittests/dmapper/DomainMapper_Impl.cxx
@@ -125,6 +125,27 @@ CPPUNIT_TEST_FIXTURE(Test, testFrameDirection)
     CPPUNIT_ASSERT_EQUAL(text::WritingMode2::TB_RL,
                          
xFrame2->getPropertyValue("WritingMode").get<sal_Int16>());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testAltChunk)
+{
+    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + 
"alt-chunk.docx";
+    getComponent() = loadFromDesktop(aURL);
+    uno::Reference<text::XTextDocument> xTextDocument(getComponent(), 
uno::UNO_QUERY);
+    uno::Reference<container::XEnumerationAccess> 
xParaEnumAccess(xTextDocument->getText(),
+                                                                  
uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xParaEnum = 
xParaEnumAccess->createEnumeration();
+    uno::Reference<text::XTextRange> xPara;
+    xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("Outer para 1"), xPara->getString());
+    xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("Outer para 2"), xPara->getString());
+
+    // Without the accompanying fix in place, this test would have failed with 
a
+    // container.NoSuchElementException, as the document had only 2 
paragraphs, all the "inner"
+    // content was lost.
+    xPara.set(xParaEnum->nextElement(), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("Inner para 1"), xPara->getString());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/qa/cppunittests/dmapper/data/alt-chunk.docx 
b/writerfilter/qa/cppunittests/dmapper/data/alt-chunk.docx
new file mode 100644
index 000000000000..3348cfd0c04c
Binary files /dev/null and 
b/writerfilter/qa/cppunittests/dmapper/data/alt-chunk.docx differ
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx 
b/writerfilter/source/dmapper/DomainMapper.cxx
index ca118c0f9c9b..938b1f41a106 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -169,8 +169,8 @@ DomainMapper::DomainMapper( const uno::Reference< 
uno::XComponentContext >& xCon
     //import document properties
     try
     {
-        uno::Reference< embed::XStorage > xDocumentStorage =
-            
comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(OFOPXML_STORAGE_FORMAT_STRING,
 xInputStream, xContext, bRepairStorage );
+        m_pImpl->m_xDocumentStorage = 
comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
+            OFOPXML_STORAGE_FORMAT_STRING, xInputStream, xContext, 
bRepairStorage);
 
         uno::Reference< uno::XInterface > xTemp = 
xContext->getServiceManager()->createInstanceWithContext(
                                 
"com.sun.star.document.OOXMLDocumentPropertiesImporter",
@@ -178,7 +178,8 @@ DomainMapper::DomainMapper( const uno::Reference< 
uno::XComponentContext >& xCon
 
         uno::Reference< document::XOOXMLDocumentPropertiesImporter > 
xImporter( xTemp, uno::UNO_QUERY_THROW );
         uno::Reference< document::XDocumentPropertiesSupplier > xPropSupplier( 
xModel, uno::UNO_QUERY_THROW);
-        xImporter->importProperties( xDocumentStorage, 
xPropSupplier->getDocumentProperties() );
+        xImporter->importProperties(m_pImpl->m_xDocumentStorage,
+                                    xPropSupplier->getDocumentProperties());
     }
     catch( const uno::Exception& ) {}
 }
@@ -1230,6 +1231,11 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
             }
         }
         break;
+        case NS_ooxml::LN_CT_AltChunk:
+        {
+            m_pImpl->HandleAltChunk(sStringValue);
+        }
+        break;
         default:
             SAL_WARN("writerfilter", "DomainMapper::lcl_attribute: unhandled 
token: " << nName);
     }
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index f6ede7c143b4..fe1ab5c99b91 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -73,12 +73,19 @@
 #include <com/sun/star/text/XTextColumns.hpp>
 #include <com/sun/star/awt/CharSet.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/embed/XHierarchicalStorageAccess.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
 #include <editeng/flditem.hxx>
 #include <editeng/unotext.hxx>
 #include <o3tl/temporary.hxx>
 #include <oox/mathml/import.hxx>
 #include <xmloff/odffields.hxx>
 #include <rtl/uri.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/streamwrap.hxx>
+
 #include <dmapper/GraphicZOrderHelper.hxx>
 
 #include <oox/token/tokens.hxx>
@@ -3239,6 +3246,53 @@ void DomainMapper_Impl::ClearPreviousParagraph()
     m_bFirstParagraphInCell = true;
 }
 
+void DomainMapper_Impl::HandleAltChunk(const OUString& rStreamName)
+{
+    try
+    {
+        // Create the import filter.
+        uno::Reference<lang::XMultiServiceFactory> xMultiServiceFactory(
+            comphelper::getProcessServiceFactory());
+        uno::Reference<uno::XInterface> xDocxFilter
+            = 
xMultiServiceFactory->createInstance("com.sun.star.comp.Writer.WriterFilter");
+
+        // Set the target document.
+        uno::Reference<document::XImporter> xImporter(xDocxFilter, 
uno::UNO_QUERY);
+        xImporter->setTargetDocument(m_xTextDocument);
+
+        // Set the import parameters.
+        uno::Reference<embed::XHierarchicalStorageAccess> 
xStorageAccess(m_xDocumentStorage,
+                                                                         
uno::UNO_QUERY);
+        if (!xStorageAccess.is())
+        {
+            return;
+        }
+        // Turn the ZIP stream into a seekable one, as the importer only works 
with such streams.
+        uno::Reference<io::XStream> xStream = 
xStorageAccess->openStreamElementByHierarchicalName(
+            rStreamName, embed::ElementModes::READ);
+        std::unique_ptr<SvStream> pStream = 
utl::UcbStreamHelper::CreateStream(xStream, true);
+        SvMemoryStream aMemory;
+        aMemory.WriteStream(*pStream);
+        uno::Reference<io::XStream> xInputStream = new 
utl::OStreamWrapper(aMemory);
+        // Not handling AltChunk during paste for now.
+        uno::Reference<text::XTextRange> xInsertTextRange = 
GetCurrentXText()->getEnd();
+        uno::Sequence<beans::PropertyValue> 
aDescriptor(comphelper::InitPropertySequence({
+            { "InputStream", uno::Any(xInputStream) },
+            { "InsertMode", uno::Any(true) },
+            { "TextInsertModeRange", uno::Any(xInsertTextRange) },
+        }));
+
+        // Do the actual import.
+        uno::Reference<document::XFilter> xFilter(xDocxFilter, uno::UNO_QUERY);
+        xFilter->filter(aDescriptor);
+    }
+    catch (const uno::Exception& rException)
+    {
+        SAL_WARN("writerfilter", "DomainMapper_Impl::HandleAltChunk: failed to 
handle alt chunk: "
+                                     << rException.Message);
+    }
+}
+
 static sal_Int16 lcl_ParseNumberingType( const OUString& rCommand )
 {
     sal_Int16 nRet = style::NumberingType::PAGE_DESCRIPTOR;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index 4a45bc3f1fd2..50b5561076ef 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -24,6 +24,7 @@
 #include <com/sun/star/text/XTextAppend.hpp>
 #include <com/sun/star/style/TabStop.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
 #include <queue>
 #include <stack>
 #include <set>
@@ -1087,6 +1088,11 @@ public:
 
     bool IsParaWithInlineObject() const { return m_bParaWithInlineObject; }
 
+    css::uno::Reference< css::embed::XStorage > m_xDocumentStorage;
+
+    /// Handles <w:altChunk>.
+    void HandleAltChunk(const OUString& rStreamName);
+
 private:
     void PushPageHeaderFooter(bool bHeader, SectionPropertyMap::PageType 
eType);
     // Start a new index section; if needed, finish current paragraph
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to