summaryrefslogtreecommitdiffstats
path: root/xmlsecurity/source/xmlsec/saxhelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmlsecurity/source/xmlsec/saxhelper.cxx')
-rw-r--r--xmlsecurity/source/xmlsec/saxhelper.cxx364
1 files changed, 364 insertions, 0 deletions
diff --git a/xmlsecurity/source/xmlsec/saxhelper.cxx b/xmlsecurity/source/xmlsec/saxhelper.cxx
new file mode 100644
index 000000000..ff576db49
--- /dev/null
+++ b/xmlsecurity/source/xmlsec/saxhelper.cxx
@@ -0,0 +1,364 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <rtl/ustring.hxx>
+
+#include <xmlsec/saxhelper.hxx>
+#include <libxml/parserInternals.h>
+
+#include <com/sun/star/xml/csax/XMLAttribute.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
+
+#ifndef XMLSEC_NO_XSLT
+#include "libxslt/xslt.h"
+#endif
+
+/**
+ * The return value is NULL terminated. The application has the responsibility to
+ * deallocate the return value.
+ */
+static xmlChar* ous_to_xmlstr( std::u16string_view oustr )
+{
+ OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
+ return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), static_cast<int>(ostr.getLength()) ) ;
+}
+
+/**
+ * The return value is NULL terminated. The application has the responsibility to
+ * deallocate the return value.
+ */
+static xmlChar* ous_to_nxmlstr( std::u16string_view oustr, int& length )
+{
+ OString ostr = OUStringToOString( oustr , RTL_TEXTENCODING_UTF8 ) ;
+ length = ostr.getLength();
+
+ return xmlStrndup( reinterpret_cast<xmlChar const *>(ostr.getStr()), length ) ;
+}
+
+/**
+ * The return value and the referenced value must be NULL terminated.
+ * The application has the responsibility to deallocate the return value.
+ */
+static const xmlChar** attrlist_to_nxmlstr( const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes )
+{
+ xmlChar* attname = nullptr ;
+ xmlChar* attvalue = nullptr ;
+ const xmlChar** attrs = nullptr ;
+
+ sal_Int32 nLength = aAttributes.getLength();
+
+ if( nLength != 0 )
+ {
+ attrs = static_cast<const xmlChar**>(xmlMalloc( ( nLength * 2 + 2 ) * sizeof( xmlChar* ) ));
+ }
+ else
+ {
+ return nullptr ;
+ }
+
+ int i = 0;
+ for( const auto& rAttr : aAttributes )
+ {
+ attname = ous_to_xmlstr( rAttr.sName ) ;
+ attvalue = ous_to_xmlstr( rAttr.sValue ) ;
+
+ if( attname != nullptr && attvalue != nullptr )
+ {
+ attrs[i++] = attname ;
+ attrs[i++] = attvalue ;
+ attrs[i] = nullptr ;
+ attrs[i+1] = nullptr ;
+ }
+ else
+ {
+ if( attname != nullptr )
+ xmlFree( attname ) ;
+ if( attvalue != nullptr )
+ xmlFree( attvalue ) ;
+ }
+ }
+
+ return attrs ;
+}
+
+/**
+ * Constructor
+ *
+ * In this constructor, a libxml sax parser context is initialized. a libxml
+ * default sax handler is initialized with the context.
+ */
+SAXHelper::SAXHelper( )
+ : m_pParserCtxt( nullptr ),
+ m_pSaxHandler( nullptr )
+{
+ xmlInitParser() ;
+ LIBXML_TEST_VERSION ;
+
+ /*
+ * compile error:
+ * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS ;
+ */
+ xmlSubstituteEntitiesDefault(0) ;
+
+#ifndef XMLSEC_NO_XSLT
+ xmlIndentTreeOutput = 1 ;
+#endif /* XMLSEC_NO_XSLT */
+
+ m_pParserCtxt = xmlNewParserCtxt() ;
+
+ if( m_pParserCtxt == nullptr )
+ {
+// see issue i74334, we cannot call xmlCleanupParser when libxml is still used
+// in other parts of the office.
+// xmlCleanupParser() ;
+// and neither can we call xsltCleanupGlobals()
+ throw css::uno::RuntimeException() ;
+ }
+
+ xmlSAXVersion(m_pParserCtxt->sax, 1);
+
+ if (m_pParserCtxt->inputTab != nullptr)
+ {
+ m_pParserCtxt->inputTab[0] = nullptr ;
+ }
+
+ if( m_pParserCtxt->sax == nullptr )
+ {
+ xmlFreeParserCtxt( m_pParserCtxt ) ;
+
+// see issue i74334, we cannot call xmlCleanupParser when libxml is still used
+// in other parts of the office.
+// xmlCleanupParser() ;
+// and neither can we call xsltCleanupGlobals()
+ m_pParserCtxt = nullptr ;
+ throw css::uno::RuntimeException() ;
+ }
+ else
+ {
+ m_pSaxHandler = m_pParserCtxt->sax ;
+
+ //Adjust the context
+ m_pParserCtxt->recovery = 1 ;
+ }
+}
+
+/**
+ * Destructor
+ *
+ * In this destructor, a libxml sax parser context is destructed. The XML tree
+ * in the context is not deallocated because the tree is bind with a document
+ * model by the setTargetDocument method, which delegate the target document to
+ * destruct the xml tree.
+ */
+SAXHelper::~SAXHelper() {
+ if( m_pParserCtxt != nullptr )
+ {
+ /*
+ * In the situation that no object refer the Document, this destructor
+ * must deallocate the Document memory
+ */
+ if( m_pSaxHandler == m_pParserCtxt->sax )
+ {
+ m_pSaxHandler = nullptr ;
+ }
+
+ xmlFreeParserCtxt( m_pParserCtxt ) ;
+ m_pParserCtxt = nullptr ;
+ }
+
+ if( m_pSaxHandler != nullptr )
+ {
+ xmlFree( m_pSaxHandler ) ;
+ m_pSaxHandler = nullptr ;
+ }
+// see issue i74334, we cannot call xmlCleanupParser when libxml is still used
+// in other parts of the office.
+// xmlCleanupParser() ;
+}
+
+
+void SAXHelper::setCurrentNode(const xmlNodePtr pNode)
+{
+ /*
+ * This is really a black trick.
+ * When the current node is replaced, the nodeTab
+ * stack's top has to been replaced with the same
+ * node, in order to make compatibility.
+ */
+ m_pParserCtxt->nodeTab[m_pParserCtxt->nodeNr - 1]
+ = m_pParserCtxt->node
+ = pNode;
+}
+
+
+/**
+ * XDocumentHandler -- start an xml document
+ */
+void SAXHelper::startDocument()
+{
+ if( m_pParserCtxt == nullptr)
+ {
+ throw css::uno::RuntimeException() ;
+ }
+ /*
+ * Adjust inputTab
+ */
+ xmlParserInputPtr pInput = xmlNewInputStream( m_pParserCtxt ) ;
+
+ if( m_pParserCtxt->inputTab != nullptr && m_pParserCtxt->inputMax != 0 )
+ {
+ m_pParserCtxt->inputTab[0] = pInput ;
+ m_pParserCtxt->input = pInput ;
+ }
+
+ m_pSaxHandler->startDocument( m_pParserCtxt ) ;
+
+ if( m_pParserCtxt->myDoc == nullptr )
+ {
+ throw css::uno::RuntimeException() ;
+ }
+}
+
+/**
+ * XDocumentHandler -- end an xml document
+ */
+void SAXHelper::endDocument()
+{
+ m_pSaxHandler->endDocument( m_pParserCtxt ) ;
+}
+
+/**
+ * XDocumentHandler -- start an xml element
+ */
+void SAXHelper::startElement(
+ std::u16string_view aName,
+ const css::uno::Sequence< css::xml::csax::XMLAttribute >& aAttributes )
+{
+ const xmlChar* fullName = nullptr ;
+ const xmlChar** attrs = nullptr ;
+
+ fullName = ous_to_xmlstr( aName ) ;
+ attrs = attrlist_to_nxmlstr( aAttributes ) ;
+
+ if( fullName != nullptr || attrs != nullptr )
+ {
+ m_pSaxHandler->startElement( m_pParserCtxt , fullName , attrs ) ;
+ }
+
+ if( fullName != nullptr )
+ {
+ xmlFree( const_cast<xmlChar*>(fullName) ) ;
+ fullName = nullptr ;
+ }
+
+ if( attrs != nullptr )
+ {
+ for( int i = 0 ; attrs[i] != nullptr ; ++i )
+ {
+ xmlFree( const_cast<xmlChar*>(attrs[i]) ) ;
+ attrs[i] = nullptr ;
+ }
+
+ xmlFree( static_cast<void*>(attrs) ) ;
+ attrs = nullptr ;
+ }
+}
+
+/**
+ * XDocumentHandler -- end an xml element
+ */
+void SAXHelper::endElement( std::u16string_view aName )
+{
+ xmlChar* fullname = ous_to_xmlstr( aName ) ;
+ m_pSaxHandler->endElement( m_pParserCtxt , fullname ) ;
+
+ if( fullname != nullptr )
+ {
+ xmlFree( fullname ) ;
+ fullname = nullptr ;
+ }
+}
+
+/**
+ * XDocumentHandler -- an xml element or cdata characters
+ */
+void SAXHelper::characters( std::u16string_view aChars )
+{
+ const xmlChar* chars = nullptr ;
+ int length = 0 ;
+
+ chars = ous_to_nxmlstr( aChars, length ) ;
+ m_pSaxHandler->characters( m_pParserCtxt , chars , length ) ;
+
+ if( chars != nullptr )
+ {
+ xmlFree( const_cast<xmlChar*>(chars) ) ;
+ }
+}
+
+/**
+ * XDocumentHandler -- ignorable xml white space
+ */
+void SAXHelper::ignorableWhitespace( std::u16string_view aWhitespaces )
+{
+ const xmlChar* chars = nullptr ;
+ int length = 0 ;
+
+ chars = ous_to_nxmlstr( aWhitespaces, length ) ;
+ m_pSaxHandler->ignorableWhitespace( m_pParserCtxt , chars , length ) ;
+
+ if( chars != nullptr )
+ {
+ xmlFree( const_cast<xmlChar*>(chars) ) ;
+ }
+}
+
+/**
+ * XDocumentHandler -- preprocessing instruction
+ */
+void SAXHelper::processingInstruction(
+ std::u16string_view aTarget,
+ std::u16string_view aData )
+{
+ xmlChar* target = nullptr ;
+ xmlChar* data = nullptr ;
+
+ target = ous_to_xmlstr( aTarget ) ;
+ data = ous_to_xmlstr( aData ) ;
+
+ m_pSaxHandler->processingInstruction( m_pParserCtxt , target , data ) ;
+
+ if( target != nullptr )
+ {
+ xmlFree( target ) ;
+ target = nullptr ;
+ }
+
+ if( data != nullptr )
+ {
+ xmlFree( data ) ;
+ data = nullptr ;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */