include/svtools/HtmlWriter.hxx       |    4 +++
 svtools/qa/unit/testHtmlWriter.cxx   |   38 +++++++++++++++++++++++++++++++++++
 svtools/source/svhtml/HtmlWriter.cxx |   30 +++++++++++++++++++++++----
 3 files changed, 67 insertions(+), 5 deletions(-)

New commits:
commit c4c7d967588b2efbb60f89d80d911c87277a347b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Jun 24 16:07:15 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Jun 27 15:04:37 2022 +0200

    sw HTML export: fix missing escaping for image links
    
    Hyperlink URLs on images are currently written to the HTML output as-is,
    without any any encoding.
    
    Image links are written using HtmlWriter from svtools, which has the
    advantage of not building the markup manually (similar to
    sax_fastparser::FastSerializerHelper for XML), but that doesn't do any
    escaping. Some other parts of the HTML export build the export markup
    manually, but use HTMLOutFuncs::Out_String() to encode problematic
    content.
    
    Fix the problem by using HTMLOutFuncs::Out_String() in HtmlWriter for
    attribute values: it seems reasonable to assume that users of HtmlWriter
    would pass in unencoded strings, similar to how the sax serializer
    works.
    
    This could lead to double-encoding in case some user of
    HtmlWriter::attribute() would encode its attribute value already, but
    inspecting existing calls, none of the clients seem to do that at the
    moment.
    
    (cherry picked from commit 167a5ce786b0561028ad42ea3fc92e55d14484a4)
    
    Change-Id: I5439e829b1b837cb9c51292b118f0b47e84197db

diff --git a/svtools/qa/unit/testHtmlWriter.cxx 
b/svtools/qa/unit/testHtmlWriter.cxx
index 70045ba8a50b..9328347f6ff4 100644
--- a/svtools/qa/unit/testHtmlWriter.cxx
+++ b/svtools/qa/unit/testHtmlWriter.cxx
@@ -200,6 +200,27 @@ CPPUNIT_TEST_FIXTURE(Test, testExactElementEnd)
     CPPUNIT_ASSERT_EQUAL(OString("<start><a/><b/></start>"), aString);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testAttributeValueEncode)
+{
+    // Given a HTML writer:
+    SvMemoryStream aStream;
+    HtmlWriter aHtml(aStream);
+    aHtml.prettyPrint(false);
+
+    // When writing an attribute with a value that needs encoding:
+    aHtml.start("element");
+    aHtml.attribute("attribute", "a&b");
+    aHtml.end();
+
+    // Then make sure that the encoding is performed:
+    OString aString = extractFromStream(aStream);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: <element attribute="a&amp;b"/>
+    // - Actual  : <element attribute="a&b"/>
+    // i.e. attribute value was not encoded in HTML, but it was in e.g. XML.
+    CPPUNIT_ASSERT_EQUAL(OString("<element attribute=\"a&amp;b\"/>"), aString);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/svhtml/HtmlWriter.cxx 
b/svtools/source/svhtml/HtmlWriter.cxx
index 875da0a724ca..9010564d986f 100644
--- a/svtools/source/svhtml/HtmlWriter.cxx
+++ b/svtools/source/svhtml/HtmlWriter.cxx
@@ -11,6 +11,7 @@
 #include <svtools/HtmlWriter.hxx>
 #include <tools/stream.hxx>
 #include <sal/log.hxx>
+#include <svtools/htmlout.hxx>
 
 HtmlWriter::HtmlWriter(SvStream& rStream, const OString& rNamespace) :
     mrStream(rStream),
@@ -127,7 +128,7 @@ void HtmlWriter::writeAttribute(SvStream& rStream, const 
OString& aAttribute, co
     rStream.WriteOString(aAttribute);
     rStream.WriteChar('=');
     rStream.WriteChar('"');
-    rStream.WriteOString(aValue);
+    HTMLOutFuncs::Out_String(rStream, OStringToOUString(aValue, 
RTL_TEXTENCODING_UTF8), RTL_TEXTENCODING_UTF8);
     rStream.WriteChar('"');
 }
 
commit 12248c17f2ec0e61a85b1b2fc1715ffb2868eba9
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon May 31 21:14:41 2021 +0900
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Mon Jun 27 14:29:07 2022 +0200

    HtmlWriter: add end tag checking and helper for attribute writing
    
    Added an input variable to end to enter the name of which variable
    is ending. This is to check that the expected end tag is actually
    written.
    
    Added writeAttribute, which is independent from HtmlWriter and just
    writes the HTML attribute format to the stream.
    
    (cherry picked from commit 685c8db519b022f879cf575ec763d00de98906a3)
    
    Conflicts:
            include/svtools/HtmlWriter.hxx
            svtools/source/svhtml/HtmlWriter.cxx
    
    Change-Id: Ib00a4a37354cd1cb1781ba729ed4046a966e1eb1

diff --git a/include/svtools/HtmlWriter.hxx b/include/svtools/HtmlWriter.hxx
index 49f2aa6c02f2..007668b6018f 100644
--- a/include/svtools/HtmlWriter.hxx
+++ b/include/svtools/HtmlWriter.hxx
@@ -39,10 +39,14 @@ public:
 
     void start(const OString& aElement);
 
+    bool end(const OString& aElement);
     void end();
 
     void flushStack();
 
+    static void writeAttribute(SvStream& rStream, const OString& aAttribute, 
sal_Int32 aValue);
+    static void writeAttribute(SvStream& rStream, const OString& aAttribute, 
const OString& aValue);
+
     void attribute(const OString& aAttribute, const char* aValue);
     void attribute(const OString& aAttribute, sal_Int32 aValue);
     void attribute(const OString& aAttribute, const OString& aValue);
diff --git a/svtools/qa/unit/testHtmlWriter.cxx 
b/svtools/qa/unit/testHtmlWriter.cxx
index 773da64c4891..70045ba8a50b 100644
--- a/svtools/qa/unit/testHtmlWriter.cxx
+++ b/svtools/qa/unit/testHtmlWriter.cxx
@@ -183,6 +183,23 @@ CPPUNIT_TEST_FIXTURE(Test, testCharacters)
     CPPUNIT_ASSERT_EQUAL(OString("<abc>hello</abc>"), aString);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testExactElementEnd)
+{
+    SvMemoryStream aStream;
+
+    HtmlWriter aHtml(aStream);
+    aHtml.prettyPrint(false);
+    aHtml.start("start");
+    aHtml.start("a");
+    CPPUNIT_ASSERT(aHtml.end("a"));
+    aHtml.start("b");
+    CPPUNIT_ASSERT(!aHtml.end("c"));
+    CPPUNIT_ASSERT(aHtml.end("start"));
+
+    OString aString = extractFromStream(aStream);
+    CPPUNIT_ASSERT_EQUAL(OString("<start><a/><b/></start>"), aString);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svtools/source/svhtml/HtmlWriter.cxx 
b/svtools/source/svhtml/HtmlWriter.cxx
index 7414b40b15b5..875da0a724ca 100644
--- a/svtools/source/svhtml/HtmlWriter.cxx
+++ b/svtools/source/svhtml/HtmlWriter.cxx
@@ -10,6 +10,7 @@
 
 #include <svtools/HtmlWriter.hxx>
 #include <tools/stream.hxx>
+#include <sal/log.hxx>
 
 HtmlWriter::HtmlWriter(SvStream& rStream, const OString& rNamespace) :
     mrStream(rStream),
@@ -80,6 +81,14 @@ void HtmlWriter::flushStack()
     }
 }
 
+bool HtmlWriter::end(const OString& aElement)
+{
+    bool bExpected = maElementStack.back() == aElement;
+    SAL_WARN_IF(!bExpected, "svtools", "HtmlWriter: end element mismatch - '" 
<< aElement << "' expected '" << maElementStack.back() << "'");
+    end();
+    return bExpected;
+}
+
 void HtmlWriter::end()
 {
     if (mbElementOpen && !mbCharactersWritten)
@@ -108,16 +117,26 @@ void HtmlWriter::end()
     mbCharactersWritten = false;
 }
 
+void HtmlWriter::writeAttribute(SvStream& rStream, const OString& aAttribute, 
sal_Int32 aValue)
+{
+    writeAttribute(rStream, aAttribute, OString::number(aValue));
+}
+
+void HtmlWriter::writeAttribute(SvStream& rStream, const OString& aAttribute, 
const OString& aValue)
+{
+    rStream.WriteOString(aAttribute);
+    rStream.WriteChar('=');
+    rStream.WriteChar('"');
+    rStream.WriteOString(aValue);
+    rStream.WriteChar('"');
+}
+
 void HtmlWriter::attribute(const OString &aAttribute, const OString& aValue)
 {
     if (mbElementOpen && !aAttribute.isEmpty() && !aValue.isEmpty())
     {
         mrStream.WriteChar(' ');
-        mrStream.WriteOString(aAttribute);
-        mrStream.WriteChar('=');
-        mrStream.WriteChar('"');
-        mrStream.WriteOString(aValue);
-        mrStream.WriteChar('"');
+        writeAttribute(mrStream, aAttribute, aValue);
     }
 }
 

Reply via email to