sw/qa/extras/ooxmlexport/data/inline-sdt-header.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport18.cxx           |    6 +++
 sw/qa/filter/ww8/ww8.cxx                             |   31 +++++++++++++++++++
 sw/source/filter/ww8/docxattributeoutput.cxx         |    7 ++++
 sw/source/filter/ww8/docxattributeoutput.hxx         |    2 +
 5 files changed, 46 insertions(+)

New commits:
commit e77b511b699feaffd14c0053c258cdfdf3042ccc
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Sep 27 14:05:10 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Sep 28 08:16:18 2022 +0200

    DOCX export: fix not-well-formed XML when hyperlink end is a textbox anchor
    
    We failed to save a document which contained anchored text and the
    anchor position was inside a hyperlink.
    
    The problem was that the hyperlink covered content which has anchored
    text, so when the text inside the shape ended its paragraph, it wanted
    to finish the hyperlink that was started outside the shape, which is not
    well-formed XML. This was a problem since
    7246e57216bb20c15af0ecf6a0183f5ffa81e780 (tdf#143591 DOCX import: handle
    anchored objects as at-char, 2021-09-20), previously we lost the
    character position of such anchor positions, so in practice this problem
    was not visible.
    
    Fix this similarly how we stash away the current state when entering a
    table cell: just save / restore the number of hyperlinks we have to
    close, that'll close the hyperlink outside the shape.
    
    Note that the source document has the hyperlink outside the shape's
    anchor, while we include the shape inside the hyperlink, but that
    doesn't cause problems in practice.
    
    (cherry picked from commit a825e23a2980fcb3d970834c4ce1f8403fb93054)
    
    Change-Id: I711fad2336fd78e2ba709c3fc0a4f75de32aae8b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140656
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/filter/ww8/ww8.cxx b/sw/qa/filter/ww8/ww8.cxx
index d537cee04188..44ef994bf412 100644
--- a/sw/qa/filter/ww8/ww8.cxx
+++ b/sw/qa/filter/ww8/ww8.cxx
@@ -83,6 +83,37 @@ CPPUNIT_TEST_FIXTURE(Test, 
testDocxComboBoxContentControlExport)
     // i.e. the combo box content control was turned into a drop-down one on 
export.
     assertXPath(pXmlDoc, "//w:sdt/w:sdtPr/w:comboBox", 1);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testDocxHyperlinkShape)
+{
+    // Given a document with a hyperlink at char positions 0 -> 6 and a shape 
with text anchored at
+    // char position 6:
+    mxComponent = loadFromDesktop("private:factory/swriter");
+    uno::Reference<lang::XMultiServiceFactory> xMSF(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xText = xTextDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor();
+    xText->insertString(xCursor, "beforeafter", /*bAbsorb=*/false);
+    xCursor->gotoStart(/*bExpand=*/false);
+    xCursor->goRight(/*nCount=*/6, /*bExpand=*/true);
+    uno::Reference<beans::XPropertySet> xCursorProps(xCursor, uno::UNO_QUERY);
+    xCursorProps->setPropertyValue("HyperLinkURL", 
uno::Any(OUString("http://www.example.com/";)));
+    xCursor->gotoStart(/*bExpand=*/false);
+    xCursor->goRight(/*nCount=*/6, /*bExpand=*/false);
+    uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<drawing::XShape> xShape(
+        xFactory->createInstance("com.sun.star.drawing.RectangleShape"), 
uno::UNO_QUERY);
+    xShape->setSize(awt::Size(5000, 5000));
+    uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
+    xShapeProps->setPropertyValue("AnchorType", 
uno::Any(text::TextContentAnchorType_AT_CHARACTER));
+    uno::Reference<text::XTextContent> xShapeContent(xShape, uno::UNO_QUERY);
+    xText->insertTextContent(xCursor, xShapeContent, /*bAbsorb=*/false);
+    xShapeProps->setPropertyValue("TextBox", uno::Any(true));
+
+    // When saving this document to DOCX, then make sure we don't crash on 
export (due to an
+    // assertion failure for not-well-formed XML output):
+    save("Office Open XML Text", maTempFile);
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index ac1882e8d20c..7862a57b8394 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -6918,6 +6918,9 @@ void 
DocxAttributeOutput::pushToTableExportContext(DocxTableExportContext& rCont
     m_aParagraphSdt.m_bStartedSdt = false;
     rContext.m_bStartedRunSdt = m_aRunSdt.m_bStartedSdt;
     m_aRunSdt.m_bStartedSdt = false;
+
+    rContext.m_nHyperLinkCount = m_nHyperLinkCount;
+    m_nHyperLinkCount = 0;
 }
 
 void DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext 
const & rContext)
@@ -6927,6 +6930,7 @@ void 
DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext const
     m_tableReference->m_nTableDepth = rContext.m_nTableDepth;
     m_aParagraphSdt.m_bStartedSdt = rContext.m_bStartedParaSdt;
     m_aRunSdt.m_bStartedSdt = rContext.m_bStartedRunSdt;
+    m_nHyperLinkCount = rContext.m_nHyperLinkCount;
 }
 
 void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index cf9a7bbe1f48..05762793a3fc 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1105,6 +1105,7 @@ struct DocxTableExportContext
     bool m_bStartedParaSdt;
     bool m_bStartedRunSdt;
     sal_uInt32 m_nTableDepth;
+    sal_Int32 m_nHyperLinkCount = 0;
     DocxTableExportContext(DocxAttributeOutput& rOutput) : m_rOutput(rOutput) 
{ m_rOutput.pushToTableExportContext(*this); }
     ~DocxTableExportContext() { m_rOutput.popFromTableExportContext(*this); }
 };
commit ff8edfbf8f43c96e4053f9d735d99917bf5cc683
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Aug 31 11:17:43 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Sep 28 08:16:06 2022 +0200

    crashtesting: fix DOCX export of forum-mso-de-102317.docx
    
    This went wrong in b2bc4ea8ddae6b01f344469d988e21fed3143c42 (DOCX
    import: handle SDT around citation field, 2014-07-16), the problem is
    that a run/inline SDT is pending, but we wrote a header stream in the
    meantime, so the invariant that Start/EndParagraph() in
    DocxAttributeOutput is called in pairs doesn't help, which results in
    not-well-formed XML, which is an assertion failure in debug build.
    
    Fix the problem similar to 5f3af56b2c0ef6c628a7cfe5ce6e86f8e1765f5f (sw:
    refactoring for docx sdt blocks output, 2021-11-16), which already did
    the same for paragraph/block SDTs.
    
    (cherry picked from commit 8431cde61432893dd5ba75d8244457306a9f177b)
    
    Change-Id: I5e7273b839bb5c1f841c0fab9b68b4ca239cca18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140655
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/data/inline-sdt-header.docx 
b/sw/qa/extras/ooxmlexport/data/inline-sdt-header.docx
new file mode 100644
index 000000000000..0a6009c2cd1b
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/inline-sdt-header.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
index 40a3a0d80c45..8d647e9cf234 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx
@@ -55,6 +55,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf150197_predefinedNumbering)
     CPPUNIT_ASSERT_EQUAL(OUString("1."), 
getProperty<OUString>(getParagraph(1), "ListLabelString"));
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testInlineSdtHeader)
+{
+    // Without the accompanying fix in place, this test would have failed with 
an assertion failure,
+    // we produced not-well-formed XML on save.
+    loadAndSave("inline-sdt-header.docx");
+}
 
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 42c5c0cdef15..ac1882e8d20c 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -6916,6 +6916,8 @@ void 
DocxAttributeOutput::pushToTableExportContext(DocxTableExportContext& rCont
 
     rContext.m_bStartedParaSdt = m_aParagraphSdt.m_bStartedSdt;
     m_aParagraphSdt.m_bStartedSdt = false;
+    rContext.m_bStartedRunSdt = m_aRunSdt.m_bStartedSdt;
+    m_aRunSdt.m_bStartedSdt = false;
 }
 
 void DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext 
const & rContext)
@@ -6924,6 +6926,7 @@ void 
DocxAttributeOutput::popFromTableExportContext(DocxTableExportContext const
     m_tableReference->m_bTableCellOpen = rContext.m_bTableCellOpen;
     m_tableReference->m_nTableDepth = rContext.m_nTableDepth;
     m_aParagraphSdt.m_bStartedSdt = rContext.m_bStartedParaSdt;
+    m_aRunSdt.m_bStartedSdt = rContext.m_bStartedRunSdt;
 }
 
 void DocxAttributeOutput::WriteTextBox(uno::Reference<drawing::XShape> xShape)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index 2fbdece0cc08..cf9a7bbe1f48 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1103,6 +1103,7 @@ struct DocxTableExportContext
     ww8::WW8TableInfo::Pointer_t m_pTableInfo;
     bool m_bTableCellOpen;
     bool m_bStartedParaSdt;
+    bool m_bStartedRunSdt;
     sal_uInt32 m_nTableDepth;
     DocxTableExportContext(DocxAttributeOutput& rOutput) : m_rOutput(rOutput) 
{ m_rOutput.pushToTableExportContext(*this); }
     ~DocxTableExportContext() { m_rOutput.popFromTableExportContext(*this); }

Reply via email to