Files
libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx

724 lines
22 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2012-07-09 14:31:34 +01:00
/*
* This file is part of the LibreOffice project.
2001-02-16 13:14:51 +00:00
*
2012-07-09 14:31:34 +01:00
* 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/.
2001-02-16 13:14:51 +00:00
*
2012-07-09 14:31:34 +01:00
* This file incorporates work covered by the following license notice:
2001-02-16 13:14:51 +00:00
*
2012-07-09 14:31:34 +01:00
* 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 .
*/
2001-02-16 13:14:51 +00:00
#include <sal/config.h>
#include <unoservices.hxx>
#include <xml_import.hxx>
#include <cppuhelper/factory.hxx>
#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/xml/input/XAttributes.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <sal/log.hxx>
#include <rtl/ref.hxx>
#include <memory>
#include <unordered_map>
#include <vector>
2001-02-16 13:14:51 +00:00
using namespace ::osl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
2001-02-16 13:14:51 +00:00
namespace xmlscript
{
2001-02-16 13:14:51 +00:00
const sal_Int32 UID_UNKNOWN = -1;
2001-02-16 13:14:51 +00:00
Sequence< OUString > getSupportedServiceNames_DocumentHandlerImpl()
{
return Sequence< OUString > { "com.sun.star.xml.input.SaxDocumentHandler" };
}
2001-02-16 13:14:51 +00:00
OUString getImplementationName_DocumentHandlerImpl()
2001-02-16 13:14:51 +00:00
{
return OUString( "com.sun.star.comp.xml.input.SaxDocumentHandler" );
}
2001-02-16 13:14:51 +00:00
typedef std::unordered_map< OUString, sal_Int32 > t_OUString2LongMap;
2001-02-16 13:14:51 +00:00
struct PrefixEntry
{
::std::vector< sal_Int32 > m_Uids;
2001-02-16 13:14:51 +00:00
PrefixEntry()
{ m_Uids.reserve( 4 ); }
2001-02-16 13:14:51 +00:00
};
typedef std::unordered_map<
OUString, std::unique_ptr<PrefixEntry> > t_OUString2PrefixMap;
2001-02-16 13:14:51 +00:00
struct ElementEntry
2001-02-16 13:14:51 +00:00
{
Reference< xml::input::XElement > m_xElement;
::std::vector< OUString > m_prefixes;
2001-02-16 13:14:51 +00:00
ElementEntry()
{ m_prefixes.reserve( 2 ); }
2001-02-16 13:14:51 +00:00
};
2001-02-16 13:14:51 +00:00
class ExtendedAttributes;
class MGuard
2001-02-16 13:14:51 +00:00
{
Mutex * m_pMutex;
public:
explicit MGuard( std::unique_ptr<Mutex> const & pMutex )
: m_pMutex( pMutex.get() )
{ if (m_pMutex) m_pMutex->acquire(); }
~MGuard() throw ()
{ if (m_pMutex) m_pMutex->release(); }
2001-02-16 13:14:51 +00:00
};
class DocumentHandlerImpl :
public ::cppu::WeakImplHelper< xml::sax::XDocumentHandler,
xml::input::XNamespaceMapping,
lang::XInitialization,
css::lang::XServiceInfo >
2001-02-16 13:14:51 +00:00
{
friend class ExtendedAttributes;
Reference< xml::input::XRoot > m_xRoot;
2001-02-16 13:14:51 +00:00
t_OUString2LongMap m_URI2Uid;
sal_Int32 m_uid_count;
2001-02-16 13:14:51 +00:00
sal_Int32 m_nLastURI_lookup;
OUString m_aLastURI_lookup;
2001-02-16 13:14:51 +00:00
t_OUString2PrefixMap m_prefixes;
sal_Int32 m_nLastPrefix_lookup;
OUString m_aLastPrefix_lookup;
2001-02-16 13:14:51 +00:00
std::vector< ElementEntry > m_elements;
sal_Int32 m_nSkipElements;
2001-02-16 13:14:51 +00:00
std::unique_ptr<Mutex> m_pMutex;
2001-02-16 13:14:51 +00:00
inline Reference< xml::input::XElement > getCurrentElement() const;
inline sal_Int32 getUidByURI( OUString const & rURI );
inline sal_Int32 getUidByPrefix( OUString const & rPrefix );
2001-02-16 13:14:51 +00:00
inline void pushPrefix(
OUString const & rPrefix, OUString const & rURI );
inline void popPrefix( OUString const & rPrefix );
2001-02-16 13:14:51 +00:00
inline void getElementName(
OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName );
2001-02-16 13:14:51 +00:00
public:
DocumentHandlerImpl(
Reference< xml::input::XRoot > const & xRoot,
bool bSingleThreadedUse );
// XServiceInfo
virtual OUString SAL_CALL getImplementationName() override;
virtual sal_Bool SAL_CALL supportsService(
OUString const & servicename ) override;
virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
// XInitialization
virtual void SAL_CALL initialize(
Sequence< Any > const & arguments ) override;
2001-02-16 13:14:51 +00:00
// XDocumentHandler
virtual void SAL_CALL startDocument() override;
virtual void SAL_CALL endDocument() override;
2001-02-16 13:14:51 +00:00
virtual void SAL_CALL startElement(
OUString const & rQElementName,
Reference< xml::sax::XAttributeList > const & xAttribs ) override;
2001-02-16 13:14:51 +00:00
virtual void SAL_CALL endElement(
OUString const & rQElementName ) override;
2001-02-16 13:14:51 +00:00
virtual void SAL_CALL characters(
OUString const & rChars ) override;
2001-02-16 13:14:51 +00:00
virtual void SAL_CALL ignorableWhitespace(
OUString const & rWhitespaces ) override;
2001-02-16 13:14:51 +00:00
virtual void SAL_CALL processingInstruction(
OUString const & rTarget, OUString const & rData ) override;
2001-02-16 13:14:51 +00:00
virtual void SAL_CALL setDocumentLocator(
Reference< xml::sax::XLocator > const & xLocator ) override;
// XNamespaceMapping
virtual sal_Int32 SAL_CALL getUidByUri( OUString const & Uri ) override;
virtual OUString SAL_CALL getUriByUid( sal_Int32 Uid ) override;
2001-02-16 13:14:51 +00:00
};
static OUString const g_sXMLNS_PREFIX_UNKNOWN( "<<< unknown prefix >>>" );
static OUString const g_sXMLNS( "xmlns" );
2001-02-16 13:14:51 +00:00
DocumentHandlerImpl::DocumentHandlerImpl(
Reference< xml::input::XRoot > const & xRoot,
2001-02-16 13:14:51 +00:00
bool bSingleThreadedUse )
: m_xRoot( xRoot ),
m_uid_count( 0 ),
m_nLastURI_lookup( UID_UNKNOWN ),
m_aLastURI_lookup( "<<< unknown URI >>>" ),
m_nLastPrefix_lookup( UID_UNKNOWN ),
m_aLastPrefix_lookup( "<<< unknown URI >>>" ),
m_nSkipElements( 0 )
{
m_elements.reserve( 10 );
2001-02-16 13:14:51 +00:00
if (! bSingleThreadedUse)
m_pMutex.reset(new Mutex);
2001-02-16 13:14:51 +00:00
}
inline Reference< xml::input::XElement >
DocumentHandlerImpl::getCurrentElement() const
2001-02-16 13:14:51 +00:00
{
MGuard aGuard( m_pMutex );
if (m_elements.empty())
return Reference< xml::input::XElement >();
else
return m_elements.back().m_xElement;
2001-02-16 13:14:51 +00:00
}
inline sal_Int32 DocumentHandlerImpl::getUidByURI( OUString const & rURI )
2001-02-16 13:14:51 +00:00
{
MGuard guard( m_pMutex );
if (m_nLastURI_lookup == UID_UNKNOWN || m_aLastURI_lookup != rURI)
2001-02-16 13:14:51 +00:00
{
t_OUString2LongMap::const_iterator iFind( m_URI2Uid.find( rURI ) );
if (iFind != m_URI2Uid.end()) // id found
2001-02-16 13:14:51 +00:00
{
m_nLastURI_lookup = iFind->second;
m_aLastURI_lookup = rURI;
2001-02-16 13:14:51 +00:00
}
else
{
m_nLastURI_lookup = m_uid_count;
++m_uid_count;
m_URI2Uid[ rURI ] = m_nLastURI_lookup;
m_aLastURI_lookup = rURI;
2001-02-16 13:14:51 +00:00
}
}
return m_nLastURI_lookup;
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
inline sal_Int32 DocumentHandlerImpl::getUidByPrefix(
OUString const & rPrefix )
{
// commonly the last added prefix is used often for several tags...
// good guess
if (m_nLastPrefix_lookup == UID_UNKNOWN || m_aLastPrefix_lookup != rPrefix)
2001-02-16 13:14:51 +00:00
{
t_OUString2PrefixMap::const_iterator iFind(
m_prefixes.find( rPrefix ) );
if (iFind != m_prefixes.end())
2001-02-16 13:14:51 +00:00
{
const PrefixEntry & rPrefixEntry = *iFind->second;
SAL_WARN_IF( rPrefixEntry.m_Uids.empty(), "xmlscript.xmlhelper", "rPrefixEntry.m_Uids is empty" );
m_nLastPrefix_lookup = rPrefixEntry.m_Uids.back();
m_aLastPrefix_lookup = rPrefix;
2001-02-16 13:14:51 +00:00
}
else
{
m_nLastPrefix_lookup = UID_UNKNOWN;
m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
2001-02-16 13:14:51 +00:00
}
}
return m_nLastPrefix_lookup;
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
inline void DocumentHandlerImpl::pushPrefix(
OUString const & rPrefix, OUString const & rURI )
{
// lookup id for URI
sal_Int32 nUid = getUidByURI( rURI );
// mark prefix with id
t_OUString2PrefixMap::const_iterator iFind( m_prefixes.find( rPrefix ) );
if (iFind == m_prefixes.end()) // unused prefix
2001-02-16 13:14:51 +00:00
{
PrefixEntry * pEntry = new PrefixEntry();
pEntry->m_Uids.push_back( nUid ); // latest id for prefix
ofz: fix leak on exception #0 0x600ca0 in operator new(unsigned long) /src/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82 #1 0x4802b4b in xmlscript::DocumentHandlerImpl::pushPrefix(rtl::OUString const&, rtl::OUString const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:259:32 #2 0x47ff026 in xmlscript::DocumentHandlerImpl::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:480:17 #3 0x7665a34 in xmlscript::XMLBasicImporterBase::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xmlflat_imexp/xmlbas_import.cxx:537:25 #4 0x4c2831f in XMLBasicImportContext::StartElement(com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/script/xmlbasici.cxx:84:21 #5 0x489c29b in SvXMLImport::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:728:15 #6 0x4892ab7 in SvXMLImportContext::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlictxt.cxx:124:14 #7 0x489ec2d in SvXMLImport::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:889:15 #8 0x86871f3 in (anonymous namespace)::Entity::startElement((anonymous namespace)::Event*) /src/libreoffice/sax/source/fastparser/fastparser.cxx:445:27 #9 0x86823f1 in sax_fastparser::FastSaxParserImpl::consume((anonymous namespace)::EventList&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:960:25 #10 0x86812f8 in sax_fastparser::FastSaxParserImpl::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:784:26 #11 0x489842e in SvXMLImport::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:464:15 #12 0x837fb5d in filter::odfflatxml::OdfFlatXml::importer(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XDocumentHandler> const&, com::sun::star::uno::Sequence<rtl::OUString> const&) /src/libreoffice/filter/source/odfflatxml/OdfFlatXml.cxx:149:26 Change-Id: Ic4ba40dca088a333a1271e005a05bd3c6e7d70ac Reviewed-on: https://gerrit.libreoffice.org/42375 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2017-09-17 12:31:08 +01:00
m_prefixes[rPrefix].reset(pEntry);
2001-02-16 13:14:51 +00:00
}
else
{
ofz: fix leak on exception #0 0x600ca0 in operator new(unsigned long) /src/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82 #1 0x4802b4b in xmlscript::DocumentHandlerImpl::pushPrefix(rtl::OUString const&, rtl::OUString const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:259:32 #2 0x47ff026 in xmlscript::DocumentHandlerImpl::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:480:17 #3 0x7665a34 in xmlscript::XMLBasicImporterBase::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xmlflat_imexp/xmlbas_import.cxx:537:25 #4 0x4c2831f in XMLBasicImportContext::StartElement(com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/script/xmlbasici.cxx:84:21 #5 0x489c29b in SvXMLImport::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:728:15 #6 0x4892ab7 in SvXMLImportContext::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlictxt.cxx:124:14 #7 0x489ec2d in SvXMLImport::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:889:15 #8 0x86871f3 in (anonymous namespace)::Entity::startElement((anonymous namespace)::Event*) /src/libreoffice/sax/source/fastparser/fastparser.cxx:445:27 #9 0x86823f1 in sax_fastparser::FastSaxParserImpl::consume((anonymous namespace)::EventList&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:960:25 #10 0x86812f8 in sax_fastparser::FastSaxParserImpl::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:784:26 #11 0x489842e in SvXMLImport::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:464:15 #12 0x837fb5d in filter::odfflatxml::OdfFlatXml::importer(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XDocumentHandler> const&, com::sun::star::uno::Sequence<rtl::OUString> const&) /src/libreoffice/filter/source/odfflatxml/OdfFlatXml.cxx:149:26 Change-Id: Ic4ba40dca088a333a1271e005a05bd3c6e7d70ac Reviewed-on: https://gerrit.libreoffice.org/42375 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2017-09-17 12:31:08 +01:00
PrefixEntry& rEntry = *iFind->second;
SAL_WARN_IF(rEntry.m_Uids.empty(), "xmlscript.xmlhelper", "pEntry->m_Uids is empty");
rEntry.m_Uids.push_back(nUid);
2001-02-16 13:14:51 +00:00
}
m_aLastPrefix_lookup = rPrefix;
m_nLastPrefix_lookup = nUid;
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
inline void DocumentHandlerImpl::popPrefix(
OUString const & rPrefix )
{
t_OUString2PrefixMap::iterator iFind( m_prefixes.find( rPrefix ) );
if (iFind != m_prefixes.end()) // unused prefix
2001-02-16 13:14:51 +00:00
{
ofz: fix leak on exception #0 0x600ca0 in operator new(unsigned long) /src/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82 #1 0x4802b4b in xmlscript::DocumentHandlerImpl::pushPrefix(rtl::OUString const&, rtl::OUString const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:259:32 #2 0x47ff026 in xmlscript::DocumentHandlerImpl::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:480:17 #3 0x7665a34 in xmlscript::XMLBasicImporterBase::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xmlflat_imexp/xmlbas_import.cxx:537:25 #4 0x4c2831f in XMLBasicImportContext::StartElement(com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/script/xmlbasici.cxx:84:21 #5 0x489c29b in SvXMLImport::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:728:15 #6 0x4892ab7 in SvXMLImportContext::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlictxt.cxx:124:14 #7 0x489ec2d in SvXMLImport::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:889:15 #8 0x86871f3 in (anonymous namespace)::Entity::startElement((anonymous namespace)::Event*) /src/libreoffice/sax/source/fastparser/fastparser.cxx:445:27 #9 0x86823f1 in sax_fastparser::FastSaxParserImpl::consume((anonymous namespace)::EventList&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:960:25 #10 0x86812f8 in sax_fastparser::FastSaxParserImpl::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:784:26 #11 0x489842e in SvXMLImport::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:464:15 #12 0x837fb5d in filter::odfflatxml::OdfFlatXml::importer(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XDocumentHandler> const&, com::sun::star::uno::Sequence<rtl::OUString> const&) /src/libreoffice/filter/source/odfflatxml/OdfFlatXml.cxx:149:26 Change-Id: Ic4ba40dca088a333a1271e005a05bd3c6e7d70ac Reviewed-on: https://gerrit.libreoffice.org/42375 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2017-09-17 12:31:08 +01:00
PrefixEntry& rEntry = *iFind->second;
rEntry.m_Uids.pop_back(); // pop last id for prefix
if (rEntry.m_Uids.empty()) // erase prefix key
2001-02-16 13:14:51 +00:00
{
ofz: fix leak on exception #0 0x600ca0 in operator new(unsigned long) /src/llvm/projects/compiler-rt/lib/asan/asan_new_delete.cc:82 #1 0x4802b4b in xmlscript::DocumentHandlerImpl::pushPrefix(rtl::OUString const&, rtl::OUString const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:259:32 #2 0x47ff026 in xmlscript::DocumentHandlerImpl::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xml_helper/xml_impctx.cxx:480:17 #3 0x7665a34 in xmlscript::XMLBasicImporterBase::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmlscript/source/xmlflat_imexp/xmlbas_import.cxx:537:25 #4 0x4c2831f in XMLBasicImportContext::StartElement(com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/script/xmlbasici.cxx:84:21 #5 0x489c29b in SvXMLImport::startElement(rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:728:15 #6 0x4892ab7 in SvXMLImportContext::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlictxt.cxx:124:14 #7 0x489ec2d in SvXMLImport::startUnknownElement(rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XFastAttributeList> const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:889:15 #8 0x86871f3 in (anonymous namespace)::Entity::startElement((anonymous namespace)::Event*) /src/libreoffice/sax/source/fastparser/fastparser.cxx:445:27 #9 0x86823f1 in sax_fastparser::FastSaxParserImpl::consume((anonymous namespace)::EventList&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:960:25 #10 0x86812f8 in sax_fastparser::FastSaxParserImpl::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/sax/source/fastparser/fastparser.cxx:784:26 #11 0x489842e in SvXMLImport::parseStream(com::sun::star::xml::sax::InputSource const&) /src/libreoffice/xmloff/source/core/xmlimp.cxx:464:15 #12 0x837fb5d in filter::odfflatxml::OdfFlatXml::importer(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> const&, com::sun::star::uno::Reference<com::sun::star::xml::sax::XDocumentHandler> const&, com::sun::star::uno::Sequence<rtl::OUString> const&) /src/libreoffice/filter/source/odfflatxml/OdfFlatXml.cxx:149:26 Change-Id: Ic4ba40dca088a333a1271e005a05bd3c6e7d70ac Reviewed-on: https://gerrit.libreoffice.org/42375 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2017-09-17 12:31:08 +01:00
m_prefixes.erase(iFind);
2001-02-16 13:14:51 +00:00
}
}
m_nLastPrefix_lookup = UID_UNKNOWN;
m_aLastPrefix_lookup = g_sXMLNS_PREFIX_UNKNOWN;
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
inline void DocumentHandlerImpl::getElementName(
OUString const & rQName, sal_Int32 * pUid, OUString * pLocalName )
{
sal_Int32 nColonPos = rQName.indexOf( ':' );
2001-02-16 13:14:51 +00:00
*pLocalName = (nColonPos >= 0 ? rQName.copy( nColonPos +1 ) : rQName);
*pUid = getUidByPrefix(
nColonPos >= 0 ? rQName.copy( 0, nColonPos ) : OUString() );
2001-02-16 13:14:51 +00:00
}
class ExtendedAttributes :
public ::cppu::WeakImplHelper< xml::input::XAttributes >
2001-02-16 13:14:51 +00:00
{
sal_Int32 const m_nAttributes;
std::unique_ptr<sal_Int32[]> m_pUids;
std::unique_ptr<OUString[]> m_pLocalNames;
std::unique_ptr<OUString[]> m_pQNames;
std::unique_ptr<OUString[]> m_pValues;
2001-02-16 13:14:51 +00:00
public:
inline ExtendedAttributes(
sal_Int32 nAttributes,
std::unique_ptr<sal_Int32[]> pUids,
std::unique_ptr<OUString[]> pLocalNames,
std::unique_ptr<OUString[]> pQNames,
Reference< xml::sax::XAttributeList > const & xAttributeList );
2001-02-16 13:14:51 +00:00
// XAttributes
virtual sal_Int32 SAL_CALL getLength() override;
2001-02-16 13:14:51 +00:00
virtual sal_Int32 SAL_CALL getIndexByQName(
OUString const & rQName ) override;
virtual sal_Int32 SAL_CALL getIndexByUidName(
sal_Int32 nUid, OUString const & rLocalName ) override;
2001-02-16 13:14:51 +00:00
virtual OUString SAL_CALL getQNameByIndex(
sal_Int32 nIndex ) override;
virtual sal_Int32 SAL_CALL getUidByIndex(
sal_Int32 nIndex ) override;
virtual OUString SAL_CALL getLocalNameByIndex(
sal_Int32 nIndex ) override;
2001-02-16 13:14:51 +00:00
virtual OUString SAL_CALL getValueByIndex(
sal_Int32 nIndex ) override;
virtual OUString SAL_CALL getValueByUidName(
sal_Int32 nUid, OUString const & rLocalName ) override;
virtual OUString SAL_CALL getTypeByIndex(
sal_Int32 nIndex ) override;
2001-02-16 13:14:51 +00:00
};
2001-02-16 13:14:51 +00:00
inline ExtendedAttributes::ExtendedAttributes(
sal_Int32 nAttributes,
std::unique_ptr<sal_Int32[]> pUids,
std::unique_ptr<OUString[]> pLocalNames, std::unique_ptr<OUString[]> pQNames,
Reference< xml::sax::XAttributeList > const & xAttributeList )
: m_nAttributes( nAttributes )
, m_pUids( std::move(pUids) )
, m_pLocalNames( std::move(pLocalNames) )
, m_pQNames( std::move(pQNames) )
, m_pValues( new OUString[ nAttributes ] )
2001-02-16 13:14:51 +00:00
{
for ( sal_Int32 nPos = 0; nPos < nAttributes; ++nPos )
2001-02-16 13:14:51 +00:00
{
m_pValues[ nPos ] = xAttributeList->getValueByIndex( nPos );
2001-02-16 13:14:51 +00:00
}
}
// XServiceInfo
OUString DocumentHandlerImpl::getImplementationName()
{
return getImplementationName_DocumentHandlerImpl();
}
sal_Bool DocumentHandlerImpl::supportsService( OUString const & servicename )
{
return cppu::supportsService(this, servicename);
}
Sequence< OUString > DocumentHandlerImpl::getSupportedServiceNames()
{
return getSupportedServiceNames_DocumentHandlerImpl();
}
// XInitialization
void DocumentHandlerImpl::initialize(
Sequence< Any > const & arguments )
{
MGuard guard( m_pMutex );
Reference< xml::input::XRoot > xRoot;
if (arguments.getLength() != 1 ||
!(arguments[ 0 ] >>= xRoot) ||
!xRoot.is())
{
throw RuntimeException( "missing root instance!" );
}
m_xRoot = xRoot;
}
// XNamespaceMapping
sal_Int32 DocumentHandlerImpl::getUidByUri( OUString const & Uri )
{
sal_Int32 uid = getUidByURI( Uri );
SAL_WARN_IF( uid == UID_UNKNOWN, "xmlscript.xmlhelper", "uid UNKNOWN");
return uid;
}
OUString DocumentHandlerImpl::getUriByUid( sal_Int32 Uid )
{
MGuard guard( m_pMutex );
for (const auto& rURIUid : m_URI2Uid)
{
if (rURIUid.second == Uid)
return rURIUid.first;
}
throw container::NoSuchElementException( "no such xmlns uid!" , static_cast< OWeakObject * >(this) );
}
2001-02-16 13:14:51 +00:00
// XDocumentHandler
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::startDocument()
{
m_xRoot->startDocument( static_cast< xml::input::XNamespaceMapping * >( this ) );
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::endDocument()
{
m_xRoot->endDocument();
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::startElement(
OUString const & rQElementName,
Reference< xml::sax::XAttributeList > const & xAttribs )
2001-02-16 13:14:51 +00:00
{
Reference< xml::input::XElement > xCurrentElement;
Reference< xml::input::XAttributes > xAttributes;
2001-02-16 13:14:51 +00:00
sal_Int32 nUid;
OUString aLocalName;
ElementEntry elementEntry;
2001-02-16 13:14:51 +00:00
{ // guard start:
MGuard aGuard( m_pMutex );
// currently skipping elements and waiting for end tags?
if (m_nSkipElements > 0)
{
++m_nSkipElements; // wait for another end tag
SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
return;
}
2001-02-16 13:14:51 +00:00
sal_Int16 nAttribs = xAttribs->getLength();
2001-02-16 13:14:51 +00:00
// save all namespace ids
std::unique_ptr<sal_Int32[]> pUids(new sal_Int32[ nAttribs ]);
std::unique_ptr<OUString[]> pPrefixes(new OUString[ nAttribs ]);
std::unique_ptr<OUString[]> pLocalNames(new OUString[ nAttribs ]);
std::unique_ptr<OUString[]> pQNames(new OUString[ nAttribs ]);
2001-02-16 13:14:51 +00:00
// first recognize all xmlns attributes
sal_Int16 nPos;
for ( nPos = 0; nPos < nAttribs; ++nPos )
{
// mark attribute to be collected further
// on with attribute's uid and current prefix
pUids[ nPos ] = 0; // modified
2001-02-16 13:14:51 +00:00
pQNames[ nPos ] = xAttribs->getNameByIndex( nPos );
OUString const & rQAttributeName = pQNames[ nPos ];
if (rQAttributeName.startsWith( g_sXMLNS ))
2001-02-16 13:14:51 +00:00
{
if (rQAttributeName.getLength() == 5) // set default namespace
{
OUString aDefNamespacePrefix;
pushPrefix(
aDefNamespacePrefix,
xAttribs->getValueByIndex( nPos ) );
elementEntry.m_prefixes.push_back( aDefNamespacePrefix );
pUids[ nPos ] = UID_UNKNOWN;
pPrefixes[ nPos ] = g_sXMLNS;
2001-02-16 13:14:51 +00:00
pLocalNames[ nPos ] = aDefNamespacePrefix;
}
else if (':' == rQAttributeName[ 5 ]) // set prefix
2001-02-16 13:14:51 +00:00
{
OUString aPrefix( rQAttributeName.copy( 6 ) );
pushPrefix( aPrefix, xAttribs->getValueByIndex( nPos ) );
elementEntry.m_prefixes.push_back( aPrefix );
pUids[ nPos ] = UID_UNKNOWN;
pPrefixes[ nPos ] = g_sXMLNS;
2001-02-16 13:14:51 +00:00
pLocalNames[ nPos ] = aPrefix;
}
// else just a name starting with xmlns, but no prefix
2001-02-16 13:14:51 +00:00
}
}
// now read out attribute prefixes (all namespace prefixes have been set)
for ( nPos = 0; nPos < nAttribs; ++nPos )
{
if (pUids[ nPos ] >= 0) // no xmlns: attribute
2001-02-16 13:14:51 +00:00
{
OUString const & rQAttributeName = pQNames[ nPos ];
SAL_WARN_IF(rQAttributeName.startsWith( "xmlns:" ), "xmlscript.xmlhelper", "### unexpected xmlns!" );
2001-02-16 13:14:51 +00:00
// collect attribute's uid and current prefix
sal_Int32 nColonPos = rQAttributeName.indexOf( ':' );
2001-02-16 13:14:51 +00:00
if (nColonPos >= 0)
{
pPrefixes[ nPos ] = rQAttributeName.copy( 0, nColonPos );
pLocalNames[ nPos ] = rQAttributeName.copy( nColonPos +1 );
}
else
{
pPrefixes[ nPos ].clear();
2001-02-16 13:14:51 +00:00
pLocalNames[ nPos ] = rQAttributeName;
// leave local names unmodified
}
pUids[ nPos ] = getUidByPrefix( pPrefixes[ nPos ] );
}
}
pPrefixes.reset();
// ownership of arrays belongs to attribute list
xAttributes = static_cast< xml::input::XAttributes * >(
new ExtendedAttributes(
nAttribs, std::move(pUids), std::move(pLocalNames), std::move(pQNames),
xAttribs ) );
2001-02-16 13:14:51 +00:00
getElementName( rQElementName, &nUid, &aLocalName );
// create new child context and append to list
if (! m_elements.empty())
xCurrentElement = m_elements.back().m_xElement;
2001-02-16 13:14:51 +00:00
} // :guard end
if (xCurrentElement.is())
{
elementEntry.m_xElement =
xCurrentElement->startChildElement( nUid, aLocalName, xAttributes );
}
else
{
elementEntry.m_xElement =
m_xRoot->startRootElement( nUid, aLocalName, xAttributes );
}
2001-02-16 13:14:51 +00:00
{
MGuard aGuard( m_pMutex );
if (elementEntry.m_xElement.is())
2001-02-16 13:14:51 +00:00
{
m_elements.push_back( std::move(elementEntry) );
2001-02-16 13:14:51 +00:00
}
else
{
++m_nSkipElements;
// pop prefixes
for (sal_Int32 nPos = elementEntry.m_prefixes.size(); nPos--;)
popPrefix(elementEntry.m_prefixes[nPos]);
SAL_INFO("xmlscript.xmlhelper", " no context given on createChildElement() => ignoring element \"" << rQElementName << "\" ...");
2001-02-16 13:14:51 +00:00
}
}
}
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::endElement(
OUString const & rQElementName )
{
Reference< xml::input::XElement > xCurrentElement;
2001-02-16 13:14:51 +00:00
{
MGuard aGuard( m_pMutex );
if (m_nSkipElements)
{
--m_nSkipElements;
SAL_INFO("xmlscript.xmlhelper", "### received endElement() for \"" << rQElementName << "\".");
return;
}
2001-02-16 13:14:51 +00:00
// popping context
SAL_WARN_IF( m_elements.empty(), "xmlscript.xmlhelper", "m_elements is empty" );
ElementEntry& rEntry = m_elements.back();
xCurrentElement = rEntry.m_xElement;
2001-02-16 13:14:51 +00:00
#if OSL_DEBUG_LEVEL > 0
sal_Int32 nUid;
OUString aLocalName;
getElementName( rQElementName, &nUid, &aLocalName );
SAL_WARN_IF( xCurrentElement->getLocalName() != aLocalName, "xmlscript.xmlhelper", "xCurrentElement->getLocalName() != aLocalName" );
SAL_WARN_IF( xCurrentElement->getUid() != nUid, "xmlscript.xmlhelper", "xCurrentElement->getUid() != nUid" );
2001-02-16 13:14:51 +00:00
#endif
// pop prefixes
for ( sal_Int32 nPos = rEntry.m_prefixes.size(); nPos--; )
{
popPrefix( rEntry.m_prefixes[ nPos ] );
}
m_elements.pop_back();
2001-02-16 13:14:51 +00:00
}
xCurrentElement->endElement();
2001-02-16 13:14:51 +00:00
}
void DocumentHandlerImpl::characters( OUString const & rChars )
2001-02-16 13:14:51 +00:00
{
Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
if (xCurrentElement.is())
xCurrentElement->characters( rChars );
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::ignorableWhitespace(
OUString const & rWhitespaces )
{
Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
if (xCurrentElement.is())
xCurrentElement->ignorableWhitespace( rWhitespaces );
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::processingInstruction(
OUString const & rTarget, OUString const & rData )
{
Reference< xml::input::XElement > xCurrentElement( getCurrentElement() );
if (xCurrentElement.is())
xCurrentElement->processingInstruction( rTarget, rData );
else
m_xRoot->processingInstruction( rTarget, rData );
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
void DocumentHandlerImpl::setDocumentLocator(
Reference< xml::sax::XLocator > const & xLocator )
{
m_xRoot->setDocumentLocator( xLocator );
2001-02-16 13:14:51 +00:00
}
// XAttributes
sal_Int32 ExtendedAttributes::getIndexByQName( OUString const & rQName )
2001-02-16 13:14:51 +00:00
{
for ( sal_Int32 nPos = m_nAttributes; nPos--; )
2001-02-16 13:14:51 +00:00
{
if (m_pQNames[ nPos ] == rQName)
2001-02-16 13:14:51 +00:00
{
return nPos;
}
}
return -1;
}
2001-02-16 13:14:51 +00:00
sal_Int32 ExtendedAttributes::getLength()
{
return m_nAttributes;
2001-02-16 13:14:51 +00:00
}
OUString ExtendedAttributes::getLocalNameByIndex( sal_Int32 nIndex )
2001-02-16 13:14:51 +00:00
{
if (nIndex < m_nAttributes)
return m_pLocalNames[ nIndex ];
else
return OUString();
2001-02-16 13:14:51 +00:00
}
OUString ExtendedAttributes::getQNameByIndex( sal_Int32 nIndex )
2001-02-16 13:14:51 +00:00
{
if (nIndex < m_nAttributes)
return m_pQNames[ nIndex ];
else
return OUString();
2001-02-16 13:14:51 +00:00
}
OUString ExtendedAttributes::getTypeByIndex( sal_Int32 nIndex )
2001-02-16 13:14:51 +00:00
{
SAL_WARN_IF( nIndex >= m_nAttributes , "xmlscript.xmlhelper", "nIndex is bigger then m_nAttributes");
return OUString(); // unsupported
2001-02-16 13:14:51 +00:00
}
OUString ExtendedAttributes::getValueByIndex( sal_Int32 nIndex )
2001-02-16 13:14:51 +00:00
{
if (nIndex < m_nAttributes)
return m_pValues[ nIndex ];
else
return OUString();
2001-02-16 13:14:51 +00:00
}
sal_Int32 ExtendedAttributes::getIndexByUidName(
sal_Int32 nUid, OUString const & rLocalName )
{
for ( sal_Int32 nPos = m_nAttributes; nPos--; )
2001-02-16 13:14:51 +00:00
{
if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
2001-02-16 13:14:51 +00:00
{
return nPos;
}
}
return -1;
}
sal_Int32 ExtendedAttributes::getUidByIndex( sal_Int32 nIndex )
2001-02-16 13:14:51 +00:00
{
if (nIndex < m_nAttributes)
return m_pUids[ nIndex ];
else
return -1;
2001-02-16 13:14:51 +00:00
}
2001-02-16 13:14:51 +00:00
OUString ExtendedAttributes::getValueByUidName(
sal_Int32 nUid, OUString const & rLocalName )
{
for ( sal_Int32 nPos = m_nAttributes; nPos--; )
2001-02-16 13:14:51 +00:00
{
if (m_pUids[ nPos ] == nUid && m_pLocalNames[ nPos ] == rLocalName)
2001-02-16 13:14:51 +00:00
{
return m_pValues[ nPos ];
2001-02-16 13:14:51 +00:00
}
}
return OUString();
}
Reference< xml::sax::XDocumentHandler > createDocumentHandler(
Reference< xml::input::XRoot > const & xRoot )
2001-02-16 13:14:51 +00:00
{
SAL_WARN_IF( !xRoot.is(), "xmlscript.xmlhelper", "xRoot is NULL" );
if (xRoot.is())
2001-02-16 13:14:51 +00:00
{
return static_cast< xml::sax::XDocumentHandler * >(
new DocumentHandlerImpl( xRoot, true /* mt use */ ) );
2001-02-16 13:14:51 +00:00
}
return Reference< xml::sax::XDocumentHandler >();
}
2001-02-16 13:14:51 +00:00
Reference< XInterface > create_DocumentHandlerImpl(
SAL_UNUSED_PARAMETER Reference< XComponentContext > const & )
{
return static_cast< ::cppu::OWeakObject * >(
new DocumentHandlerImpl(
Reference< xml::input::XRoot >(), false /* mt use */ ) );
2001-02-16 13:14:51 +00:00
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */