diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /xmloff/source/core/xmlimp.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmloff/source/core/xmlimp.cxx')
-rw-r--r-- | xmloff/source/core/xmlimp.cxx | 2325 |
1 files changed, 2325 insertions, 0 deletions
diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx new file mode 100644 index 000000000..0c9e9d06c --- /dev/null +++ b/xmloff/source/core/xmlimp.cxx @@ -0,0 +1,2325 @@ +/* -*- 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 <memory> + +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> +#include <com/sun/star/beans/XPropertySetInfo.hpp> +#include <tools/urlobj.hxx> +#include <vcl/embeddedfontshelper.hxx> +#include <vcl/graph.hxx> +#include <xmloff/unointerfacetouniqueidentifiermapper.hxx> +#include <xmloff/nmspmap.hxx> +#include <xmloff/xmluconv.hxx> +#include <xmloff/xmlnmspe.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/XMLFontStylesContext.hxx> +#include <xmloff/xmlictxt.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/xmlnumfi.hxx> +#include <XMLEventImportHelper.hxx> +#include <XMLStarBasicContextFactory.hxx> +#include <XMLScriptContextFactory.hxx> +#include <StyleMap.hxx> +#include <xmloff/ProgressBarHelper.hxx> +#include <xmloff/xmlerror.hxx> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/document/XBinaryStreamResolver.hpp> +#include <com/sun/star/document/XStorageBasedDocument.hpp> +#include <com/sun/star/document/XGraphicStorageHandler.hpp> +#include <com/sun/star/document/XEmbeddedObjectResolver.hpp> +#include <com/sun/star/xml/sax/XLocator.hpp> +#include <com/sun/star/xml/sax/FastParser.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> +#include <comphelper/fileformat.h> +#include <comphelper/namecontainer.hxx> +#include <comphelper/servicehelper.hxx> +#include <cppuhelper/implbase.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <comphelper/extract.hxx> +#include <comphelper/documentconstants.hxx> +#include <comphelper/documentinfo.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/attributelist.hxx> +#include <unotools/fontcvt.hxx> +#include <fasttokenhandler.hxx> +#include <vcl/GraphicExternalLink.hxx> + +#include <com/sun/star/rdf/XMetadatable.hpp> +#include <com/sun/star/rdf/XRepositorySupplier.hpp> +#include <RDFaImportHelper.hxx> + +using ::com::sun::star::beans::XPropertySetInfo; + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::document; +using namespace ::xmloff::token; + +rtl::Reference< FastTokenHandler > SvXMLImport::xTokenHandler( new FastTokenHandler() ); +std::unordered_map< sal_Int32, std::pair< OUString, OUString > > SvXMLImport::aNamespaceMap; +std::unordered_map< OUString, OUString > SvXMLImport::aNamespaceURIPrefixMap; +const OUString SvXMLImport::aDefaultNamespace = OUString(""); +const OUString SvXMLImport::aNamespaceSeparator = OUString(":"); +bool SvXMLImport::bIsNSMapsInitialized = false; + +namespace { + +class SvXMLImportEventListener : public cppu::WeakImplHelper< css::lang::XEventListener > +{ +private: + SvXMLImport* pImport; + +public: + explicit SvXMLImportEventListener(SvXMLImport* pImport); + + // XEventListener + virtual void SAL_CALL disposing(const lang::EventObject& rEventObject) override; +}; + +} + +SvXMLImportEventListener::SvXMLImportEventListener(SvXMLImport* pTempImport) + : pImport(pTempImport) +{ +} + +// XEventListener +void SAL_CALL SvXMLImportEventListener::disposing( const lang::EventObject& ) +{ + if (pImport) + { + pImport->DisposingModel(); + pImport = nullptr; + } +} + +namespace +{ + +OUString +getBuildIdsProperty(uno::Reference<beans::XPropertySet> const& xImportInfo) +{ + if (xImportInfo.is()) + { + try + { + Reference< XPropertySetInfo > const xSetInfo( + xImportInfo->getPropertySetInfo()); + if (xSetInfo.is() && xSetInfo->hasPropertyByName("BuildId")) + { + OUString aBuildId; + xImportInfo->getPropertyValue("BuildId") >>= aBuildId; + return aBuildId; + } + } + catch (Exception const&) + { + DBG_UNHANDLED_EXCEPTION("xmloff.core", "exception getting BuildId"); + } + } + return OUString(); +} + +class DocumentInfo +{ +private: + sal_uInt16 mnGeneratorVersion; + +public: + explicit DocumentInfo( const SvXMLImport& rImport ) + : mnGeneratorVersion( SvXMLImport::ProductVersionUnknown ) + { + OUString const buildIds( + getBuildIdsProperty(rImport.getImportInfo())); + if (!buildIds.isEmpty()) + { + sal_Int32 const ix = buildIds.indexOf(';'); + if (-1 != ix) + { + OUString const loVersion(buildIds.copy(ix + 1)); + if (!loVersion.isEmpty()) + { + if ('3' == loVersion[0]) + { + mnGeneratorVersion = SvXMLImport::LO_3x; + } + else if ('4' == loVersion[0]) + { + if (loVersion.getLength() > 1 + && (loVersion[1] == '0' || loVersion[1] == '1')) + { + mnGeneratorVersion = SvXMLImport::LO_41x; // 4.0/4.1 + } + else if (loVersion.getLength() > 1 && '2' == loVersion[1]) + { + mnGeneratorVersion = SvXMLImport::LO_42x; // 4.2 + } + else if (loVersion.getLength() > 1 && '3' == loVersion[1]) + { + mnGeneratorVersion = SvXMLImport::LO_43x; // 4.3 + } + else if (loVersion.getLength() > 1 && '4' == loVersion[1]) + { + mnGeneratorVersion = SvXMLImport::LO_44x; // 4.4 + } + } + else if ('5' == loVersion[0]) + { + mnGeneratorVersion = SvXMLImport::LO_5x; + } + else if ('6' == loVersion[0]) + { + mnGeneratorVersion = SvXMLImport::LO_6x; + } + else if ('7' == loVersion[0]) + { + mnGeneratorVersion = SvXMLImport::LO_7x; + } + else + { + SAL_INFO("xmloff.core", "unknown LO version: " << loVersion); + } + return; // ignore buildIds + } + } + } + sal_Int32 nUPD, nBuild; + if ( rImport.getBuildIds( nUPD, nBuild ) ) + { + if ( nUPD >= 640 && nUPD <= 645 ) + { + mnGeneratorVersion = SvXMLImport::OOo_1x; + } + else if ( nUPD == 680 ) + { + mnGeneratorVersion = SvXMLImport::OOo_2x; + } + else if ( nUPD == 300 && nBuild <= 9379 ) + { + mnGeneratorVersion = SvXMLImport::OOo_30x; + } + else if ( nUPD == 310 ) + { + mnGeneratorVersion = SvXMLImport::OOo_31x; + } + else if ( nUPD == 320 ) + { + mnGeneratorVersion = SvXMLImport::OOo_32x; + } + else if ( nUPD == 330 ) + { + mnGeneratorVersion = SvXMLImport::OOo_33x; + } + else if ( nUPD == 340 ) + { + mnGeneratorVersion = SvXMLImport::OOo_34x; + } + else if (nUPD == 400 || nUPD == 401) + { + mnGeneratorVersion = SvXMLImport::AOO_40x; + } + else if (nUPD >= 410) + { + // effectively this means "latest", see use + // in XMLGraphicsDefaultStyle::SetDefaults()! + mnGeneratorVersion = SvXMLImport::AOO_4x; + } + } + } + + sal_uInt16 getGeneratorVersion() const + { + return mnGeneratorVersion; + } +}; + +} + +class SvXMLImport_Impl +{ +public: + FontToSubsFontConverter hBatsFontConv; + FontToSubsFontConverter hMathFontConv; + + bool mbOwnGraphicResolver; + bool mbOwnEmbeddedResolver; + INetURLObject aBaseURL; + INetURLObject aDocBase; + + /// name of stream in package, e.g., "content.xml" + OUString mStreamName; + + OUString aODFVersion; + + bool mbIsOOoXML; + + // Boolean, indicating that position attributes + // of shapes are given in horizontal left-to-right layout. This is the case + // for the OpenOffice.org file format. (#i28749#) + bool mbShapePositionInHoriL2R; + bool mbTextDocInOOoFileFormat; + + const uno::Reference< uno::XComponentContext > mxComponentContext; + OUString implementationName; + + uno::Reference< embed::XStorage > mxSourceStorage; + + std::unique_ptr< xmloff::RDFaImportHelper > mpRDFaHelper; + + std::unique_ptr< DocumentInfo > mpDocumentInfo; + + SvXMLImport_Impl( const uno::Reference< uno::XComponentContext >& rxContext, + OUString const & theImplementationName) + : hBatsFontConv( nullptr ) + , hMathFontConv( nullptr ) + , mbOwnGraphicResolver( false ) + , mbOwnEmbeddedResolver( false ) + , mbIsOOoXML(false) + // Convert drawing object positions from OOo file format to OASIS (#i28749#) + , mbShapePositionInHoriL2R( false ) + , mbTextDocInOOoFileFormat( false ) + , mxComponentContext( rxContext ) + , implementationName(theImplementationName) + , mpRDFaHelper() // lazy + , mpDocumentInfo() // lazy + { + SAL_WARN_IF(!mxComponentContext.is(), "xmloff.core", "SvXMLImport: no ComponentContext"); + if (!mxComponentContext.is()) throw uno::RuntimeException(); + } + + sal_uInt16 getGeneratorVersion( const SvXMLImport& rImport ) + { + if (!mpDocumentInfo) + { + mpDocumentInfo.reset( new DocumentInfo( rImport ) ); + } + + return mpDocumentInfo->getGeneratorVersion(); + } + + ::comphelper::UnoInterfaceToUniqueIdentifierMapper maInterfaceToIdentifierMapper; +}; + +SvXMLImportContext *SvXMLImport::CreateFastContext( sal_Int32 nElement, + const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ ) +{ + SAL_WARN( "xmloff.core", "CreateFastContext should be overridden, for element " << nElement); + return new SvXMLImportContext( *this ); +} + +void SvXMLImport::InitCtor_() +{ + if( mnImportFlags != SvXMLImportFlags::NONE ) + { + // implicit "xml" namespace prefix + mpNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML ); + mpNamespaceMap->Add( "_office", GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE ); + mpNamespaceMap->Add( "_office_ooo", GetXMLToken(XML_N_OFFICE_EXT), XML_NAMESPACE_OFFICE_EXT ); + mpNamespaceMap->Add( "_ooo", GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO ); + mpNamespaceMap->Add( "_style", GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE ); + mpNamespaceMap->Add( "_text", GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT ); + mpNamespaceMap->Add( "_table", GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE ); + mpNamespaceMap->Add( "_table_ooo", GetXMLToken(XML_N_TABLE_EXT), XML_NAMESPACE_TABLE_EXT ); + mpNamespaceMap->Add( "_draw", GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW ); + mpNamespaceMap->Add( "_draw_ooo", GetXMLToken(XML_N_DRAW_EXT), XML_NAMESPACE_DRAW_EXT ); + mpNamespaceMap->Add( "_dr3d", GetXMLToken(XML_N_DR3D), XML_NAMESPACE_DR3D ); + mpNamespaceMap->Add( "_fo", GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO ); + mpNamespaceMap->Add( "_xlink", GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK ); + mpNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC ); + mpNamespaceMap->Add( "_dom", GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM ); + mpNamespaceMap->Add( "_meta", GetXMLToken(XML_N_META), XML_NAMESPACE_META ); + mpNamespaceMap->Add( "_number", GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER ); + mpNamespaceMap->Add( "_svg", GetXMLToken(XML_N_SVG_COMPAT), XML_NAMESPACE_SVG ); + mpNamespaceMap->Add( "_chart", GetXMLToken(XML_N_CHART), XML_NAMESPACE_CHART ); + mpNamespaceMap->Add( "_math", GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH ); + mpNamespaceMap->Add( "_form", GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM ); + mpNamespaceMap->Add( "_script", GetXMLToken(XML_N_SCRIPT), XML_NAMESPACE_SCRIPT ); + mpNamespaceMap->Add( "_config", GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG ); + mpNamespaceMap->Add( "_xforms", GetXMLToken(XML_N_XFORMS_1_0), XML_NAMESPACE_XFORMS ); + mpNamespaceMap->Add( "_formx", GetXMLToken( XML_N_FORMX ), XML_NAMESPACE_FORMX ); + mpNamespaceMap->Add( "_xsd", GetXMLToken(XML_N_XSD), XML_NAMESPACE_XSD ); + mpNamespaceMap->Add( "_xsi", GetXMLToken(XML_N_XSI), XML_NAMESPACE_XFORMS ); + mpNamespaceMap->Add( "_ooow", GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW ); + mpNamespaceMap->Add( "_oooc", GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC ); + mpNamespaceMap->Add( "_field", GetXMLToken(XML_N_FIELD), XML_NAMESPACE_FIELD ); + mpNamespaceMap->Add( "_of", GetXMLToken(XML_N_OF), XML_NAMESPACE_OF ); + mpNamespaceMap->Add( "_xhtml", GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML ); + mpNamespaceMap->Add( "_css3text", GetXMLToken(XML_N_CSS3TEXT), XML_NAMESPACE_CSS3TEXT ); + + mpNamespaceMap->Add( "_calc_libo", GetXMLToken(XML_N_CALC_EXT), XML_NAMESPACE_CALC_EXT); + mpNamespaceMap->Add( "_office_libo", + GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT); + } + + if (mxNumberFormatsSupplier.is()) + mpNumImport = std::make_unique<SvXMLNumFmtHelper>(mxNumberFormatsSupplier, GetComponentContext()); + + if (mxModel.is() && !mxEventListener.is()) + { + mxEventListener.set(new SvXMLImportEventListener(this)); + mxModel->addEventListener(mxEventListener); + } +} + +SvXMLImport::SvXMLImport( + const css::uno::Reference< css::uno::XComponentContext >& xContext, + OUString const & implementationName, SvXMLImportFlags nImportFlags ) +: mpImpl( new SvXMLImport_Impl(xContext, implementationName) ), + mpNamespaceMap( new SvXMLNamespaceMap ), + + mpUnitConv( new SvXMLUnitConverter( xContext, + util::MeasureUnit::MM_100TH, util::MeasureUnit::MM_100TH) ), + + mnImportFlags( nImportFlags ), + isFastContext( false ), + maNamespaceHandler( new SvXMLImportFastNamespaceHandler() ), + mbIsFormsSupported( true ), + mbIsTableShapeSupported( false ), + mbNotifyMacroEventRead( false ) +{ + SAL_WARN_IF( !xContext.is(), "xmloff.core", "got no service manager" ); + InitCtor_(); + mxParser = xml::sax::FastParser::create( xContext ); + setNamespaceHandler( maNamespaceHandler.get() ); + setTokenHandler( xTokenHandler.get() ); + if ( !bIsNSMapsInitialized ) + { + initializeNamespaceMaps(); + bIsNSMapsInitialized = true; + } + registerNamespaces(); +} + +void SvXMLImport::cleanup() throw () +{ + if (mxEventListener.is() && mxModel.is()) + mxModel->removeEventListener(mxEventListener); + // clear context stacks first in case of parse error because the context + // class dtors are full of application logic + while (!maFastContexts.empty()) + { + if (SvXMLStylesContext* pStylesContext = dynamic_cast<SvXMLStylesContext*>(maFastContexts.top().get())) + pStylesContext->Clear(); + maFastContexts.pop(); + } + while (!maContexts.empty()) + { + if (SvXMLStylesContext* pStylesContext = dynamic_cast<SvXMLStylesContext*>(maContexts.top().get())) + pStylesContext->Clear(); + maContexts.pop(); + } + mxTextImport.clear(); // XMLRedlineImportHelper needs model + DisposingModel(); +} + +SvXMLImport::~SvXMLImport() throw () +{ + cleanup(); +} + +bool SvXMLImport::addEmbeddedFont(const css::uno::Reference< css::io::XInputStream >& stream, + const OUString& fontName, const char* extra, + std::vector<unsigned char> key, bool eot) +{ + if (!mxEmbeddedFontHelper) + mxEmbeddedFontHelper.reset(new EmbeddedFontsHelper); + return mxEmbeddedFontHelper->addEmbeddedFont(stream, fontName, extra, key, eot); +} + +namespace +{ + class theSvXMLImportUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theSvXMLImportUnoTunnelId> {}; +} + +const css::uno::Sequence<sal_Int8>& SvXMLImport::getUnoTunnelId() throw() +{ + return theSvXMLImportUnoTunnelId::get().getSeq(); +} + +// XUnoTunnel +sal_Int64 SAL_CALL SvXMLImport::getSomething( const uno::Sequence< sal_Int8 >& rId ) +{ + if( isUnoTunnelId<SvXMLImport>(rId) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this)); + } + return 0; +} + +namespace +{ + class setFastDocumentHandlerGuard + { + private: + css::uno::Reference<css::xml::sax::XFastParser> mxParser; + public: + setFastDocumentHandlerGuard(const css::uno::Reference<css::xml::sax::XFastParser>& Parser, + const css::uno::Reference<css::xml::sax::XFastDocumentHandler>& Handler) + : mxParser(Parser) + { + mxParser->setFastDocumentHandler(Handler); + } + //guarantee restoration of null document handler + ~setFastDocumentHandlerGuard() + { + mxParser->setFastDocumentHandler(nullptr); + } + }; +} + +// XFastParser +void SAL_CALL SvXMLImport::parseStream( const xml::sax::InputSource& aInputSource ) +{ + setFastDocumentHandlerGuard aDocumentHandlerGuard(mxParser, mxFastDocumentHandler.is() ? mxFastDocumentHandler : this); + mxParser->parseStream(aInputSource); +} + +void SAL_CALL SvXMLImport::setFastDocumentHandler( const uno::Reference< xml::sax::XFastDocumentHandler >& Handler ) +{ + mxFastDocumentHandler = Handler; +} + +void SAL_CALL SvXMLImport::setTokenHandler( const uno::Reference< xml::sax::XFastTokenHandler >& Handler ) +{ + mxParser->setTokenHandler( Handler ); +} + +void SAL_CALL SvXMLImport::registerNamespace( const OUString& NamespaceURL, sal_Int32 NamespaceToken ) +{ + mxParser->registerNamespace( NamespaceURL, NamespaceToken ); +} + +OUString SAL_CALL SvXMLImport::getNamespaceURL( const OUString& rPrefix ) +{ + return mxParser->getNamespaceURL( rPrefix ); +} + +void SAL_CALL SvXMLImport::setErrorHandler( const uno::Reference< xml::sax::XErrorHandler >& Handler ) +{ + mxParser->setErrorHandler( Handler ); +} + +void SAL_CALL SvXMLImport::setEntityResolver( const uno::Reference< xml::sax::XEntityResolver >& Resolver ) +{ + mxParser->setEntityResolver( Resolver ); +} + +void SAL_CALL SvXMLImport::setLocale( const lang::Locale& rLocale ) +{ + mxParser->setLocale( rLocale ); +} + +void SAL_CALL SvXMLImport::setNamespaceHandler( const uno::Reference< xml::sax::XFastNamespaceHandler >& Handler) +{ + mxParser->setNamespaceHandler( Handler ); +} + + +void SAL_CALL SvXMLImport::startDocument() +{ + SAL_INFO( "xmloff.core", "{ SvXMLImport::startDocument" ); + if (!mxGraphicStorageHandler.is() || !mxEmbeddedResolver.is()) + { + Reference< lang::XMultiServiceFactory > xFactory( mxModel, UNO_QUERY ); + if( xFactory.is() ) + { + try + { + if (!mxGraphicStorageHandler.is()) + { + // #99870# Import... instead of Export... + mxGraphicStorageHandler.set( + xFactory->createInstance("com.sun.star.document.ImportGraphicStorageHandler"), + UNO_QUERY); + mpImpl->mbOwnGraphicResolver = mxGraphicStorageHandler.is(); + } + + if( !mxEmbeddedResolver.is() ) + { + // #99870# Import... instead of Export... + mxEmbeddedResolver.set( + xFactory->createInstance("com.sun.star.document.ImportEmbeddedObjectResolver"), + UNO_QUERY); + mpImpl->mbOwnEmbeddedResolver = mxEmbeddedResolver.is(); + } + } + catch( css::uno::Exception& ) + { + } + } + } +} + +void SAL_CALL SvXMLImport::endDocument() +{ + SAL_INFO( "xmloff.core", "} SvXMLImport::endDocument" ); + // #i9518# All the stuff that accesses the document has to be done here, not in the dtor, + // because the SvXMLImport dtor might not be called until after the document has been closed. + + GetTextImport()->MapCrossRefHeadingFieldsHorribly(); + + if (mpImpl->mpRDFaHelper) + { + const uno::Reference<rdf::XRepositorySupplier> xRS(mxModel, + uno::UNO_QUERY); + if (xRS.is()) + { + mpImpl->mpRDFaHelper->InsertRDFa( xRS ); + } + } + + mpNumImport.reset(); + if (mxImportInfo.is()) + { + uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxImportInfo->getPropertySetInfo(); + if (xPropertySetInfo.is()) + { + if (bool(mpProgressBarHelper)) + { + OUString sProgressMax(XML_PROGRESSMAX); + OUString sProgressCurrent(XML_PROGRESSCURRENT); + OUString sRepeat(XML_PROGRESSREPEAT); + if (xPropertySetInfo->hasPropertyByName(sProgressMax) && + xPropertySetInfo->hasPropertyByName(sProgressCurrent)) + { + sal_Int32 nProgressMax(mpProgressBarHelper->GetReference()); + sal_Int32 nProgressCurrent(mpProgressBarHelper->GetValue()); + mxImportInfo->setPropertyValue(sProgressMax, uno::Any(nProgressMax)); + mxImportInfo->setPropertyValue(sProgressCurrent, uno::Any(nProgressCurrent)); + } + if (xPropertySetInfo->hasPropertyByName(sRepeat)) + mxImportInfo->setPropertyValue(sRepeat, css::uno::makeAny(mpProgressBarHelper->GetRepeat())); + // pProgressBarHelper is deleted in dtor + } + OUString sNumberStyles(XML_NUMBERSTYLES); + if (mxNumberStyles.is() && xPropertySetInfo->hasPropertyByName(sNumberStyles)) + { + mxImportInfo->setPropertyValue(sNumberStyles, Any(mxNumberStyles)); + } + } + } + + if( mxFontDecls.is() ) + static_cast<SvXMLStylesContext *>(mxFontDecls.get())->Clear(); + if( mxStyles.is() ) + static_cast<SvXMLStylesContext *>(mxStyles.get())->Clear(); + if( mxAutoStyles.is() ) + static_cast<SvXMLStylesContext *>(mxAutoStyles.get())->Clear(); + if( mxMasterStyles.is() ) + static_cast<SvXMLStylesContext *>(mxMasterStyles.get())->Clear(); + + // possible form-layer related knittings which can only be done when + // the whole document exists + if ( mxFormImport.is() ) + mxFormImport->documentDone(); + + // The shape import helper does the z-order sorting in the dtor, + // so it must be deleted here, too. + mxShapeImport = nullptr; + + if( mpImpl->mbOwnGraphicResolver ) + { + Reference<lang::XComponent> xComp(mxGraphicStorageHandler, UNO_QUERY); + xComp->dispose(); + } + + if( mpImpl->mbOwnEmbeddedResolver ) + { + Reference< lang::XComponent > xComp( mxEmbeddedResolver, UNO_QUERY ); + xComp->dispose(); + } + mpStyleMap.clear(); + + if ( bool( mpXMLErrors ) ) + { + mpXMLErrors->ThrowErrorAsSAXException( XMLERROR_FLAG_SEVERE ); + } +} + +std::unique_ptr<SvXMLNamespaceMap> SvXMLImport::processNSAttributes( + const uno::Reference< xml::sax::XAttributeList >& xAttrList) +{ + std::unique_ptr<SvXMLNamespaceMap> pRewindMap; + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + if ( rAttrName == "office:version" ) + { + mpImpl->aODFVersion = xAttrList->getValueByIndex( i ); + + // the ODF version in content.xml and manifest.xml must be the same starting from ODF1.2 + if ( mpImpl->mStreamName == "content.xml" && !IsODFVersionConsistent( mpImpl->aODFVersion ) ) + { + throw xml::sax::SAXException("Inconsistent ODF versions in content.xml and manifest.xml!", + uno::Reference< uno::XInterface >(), + uno::makeAny( + packages::zip::ZipIOException("Inconsistent ODF versions in content.xml and manifest.xml!" ) ) ); + } + } + else if( ( rAttrName.getLength() >= 5 ) && + ( rAttrName.startsWith( GetXMLToken(XML_XMLNS) ) ) && + ( rAttrName.getLength() == 5 || ':' == rAttrName[5] ) ) + { + if( !pRewindMap ) + { + pRewindMap = std::move(mpNamespaceMap); + mpNamespaceMap.reset(new SvXMLNamespaceMap(*pRewindMap)); + } + const OUString& rAttrValue = xAttrList->getValueByIndex( i ); + + OUString aPrefix( ( rAttrName.getLength() == 5 ) + ? OUString() + : rAttrName.copy( 6 ) ); + // Add namespace, but only if it is known. + sal_uInt16 nKey = mpNamespaceMap->AddIfKnown( aPrefix, rAttrValue ); + // If namespace is unknown, try to match a name with similar + // TC Id and version + if( XML_NAMESPACE_UNKNOWN == nKey ) + { + OUString aTestName( rAttrValue ); + if( SvXMLNamespaceMap::NormalizeURI( aTestName ) ) + nKey = mpNamespaceMap->AddIfKnown( aPrefix, aTestName ); + } + // If that namespace is not known, too, add it as unknown + if( XML_NAMESPACE_UNKNOWN == nKey ) + mpNamespaceMap->Add( aPrefix, rAttrValue ); + + } + } + return pRewindMap; +} + +void SAL_CALL SvXMLImport::startElement( const OUString& rName, + const uno::Reference< xml::sax::XAttributeList >& xAttrList ) +{ + // SAL_INFO("svg", "startElement " << rName); + // Process namespace attributes. This must happen before creating the + // context, because namespace declaration apply to the element name itself. + std::unique_ptr<SvXMLNamespaceMap> pRewindMap(processNSAttributes(xAttrList)); + + // Get element's namespace and local name. + OUString aLocalName; + sal_uInt16 nPrefix = + mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); + + // If there are contexts already, call a CreateChildContext at the topmost + // context. Otherwise, create a default context. + SvXMLImportContextRef xContext; + if(!maContexts.empty()) + { + xContext = maContexts.top()->CreateChildContext(nPrefix, aLocalName, xAttrList); + SAL_WARN_IF( xContext.is() && xContext->IsPrefixFilledIn() && (xContext->GetPrefix() != nPrefix), "xmloff.core", + "SvXMLImport::startElement: created context has wrong prefix" ); + } + else + { + Reference<xml::sax::XLocator> xDummyLocator; + Sequence < OUString > aParams { rName }; + + SetError( XMLERROR_FLAG_SEVERE|XMLERROR_UNKNOWN_ROOT, + aParams, "Root element " + rName + " unknown", xDummyLocator ); + } + + if ( !xContext.is() ) + SAL_INFO_IF( !xContext.is(), "xmloff.core", "SvXMLImport::startElement: missing context for element " << rName ); + + if( !xContext.is() ) + xContext.set(new SvXMLImportContext( *this, nPrefix, aLocalName )); + + // Remember old namespace map. + if( pRewindMap ) + xContext->PutRewindMap(std::move(pRewindMap)); + + // Call a startElement at the new context. + xContext->StartElement( xAttrList ); + + // Push context on stack. + maContexts.push(xContext); +} + +void SAL_CALL SvXMLImport::endElement( const OUString& +#ifdef DBG_UTIL +rName +#endif +) +{ + if (maContexts.empty()) + { + SAL_WARN("xmloff.core", "SvXMLImport::endElement: no context left"); + return; + } + + std::unique_ptr<SvXMLNamespaceMap> pRewindMap; + + { + // Get topmost context and remove it from the stack. + SvXMLImportContextRef xContext = std::move(maContexts.top()); + maContexts.pop(); + +#ifdef DBG_UTIL + // Non product only: check if endElement call matches startELement call. + if (xContext->IsPrefixFilledIn()) // prefix+localname are only valid in the non-FastParser case + { + OUString aLocalName; + sal_uInt16 nPrefix = + mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); + SAL_WARN_IF( xContext->GetPrefix() != nPrefix, "xmloff.core", "SvXMLImport::endElement: popped context has wrong prefix" ); + SAL_WARN_IF( xContext->GetLocalName() != aLocalName, "xmloff.core", "SvXMLImport::endElement: popped context has wrong lname" ); + } +#endif + + // Call a EndElement at the current context. + xContext->EndElement(); + // Get a namespace map to rewind. + pRewindMap = xContext->TakeRewindMap(); + // note: delete xContext *before* rewinding namespace map! + } + + // Rewind a namespace map. + if (pRewindMap) + { + mpNamespaceMap.reset(); + mpNamespaceMap = std::move(pRewindMap); + } +} + +void SAL_CALL SvXMLImport::characters( const OUString& rChars ) +{ + if ( !maFastContexts.empty() ) + { + maFastContexts.top()->characters( rChars ); + } + else if( !maContexts.empty() ) + { + maContexts.top()->Characters( rChars ); + } +} + +void SvXMLImport::Characters( const OUString& rChars ) +{ + if( !maContexts.empty() ) + { + maContexts.top()->Characters( rChars ); + } +} + +void SAL_CALL SvXMLImport::ignorableWhitespace( const OUString& ) +{ +} + +void SAL_CALL SvXMLImport::processingInstruction( const OUString&, + const OUString& ) +{ +} + +void SAL_CALL SvXMLImport::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& rLocator ) +{ + mxLocator = rLocator; +} + +// XFastContextHandler +void SAL_CALL SvXMLImport::startFastElement (sal_Int32 Element, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) +{ + if ( Attribs.is() ) + { + sax_fastparser::FastAttributeList& rAttribList = + sax_fastparser::castToFastAttributeList( Attribs ); + auto aIter( rAttribList.find( XML_ELEMENT( OFFICE, XML_VERSION ) ) ); + if( aIter != rAttribList.end() ) + { + mpImpl->aODFVersion = aIter.toString(); + + // the ODF version in content.xml and manifest.xml must be the same starting from ODF1.2 + if ( mpImpl->mStreamName == "content.xml" && !IsODFVersionConsistent( mpImpl->aODFVersion ) ) + { + throw xml::sax::SAXException("Inconsistent ODF versions in content.xml and manifest.xml!", + uno::Reference< uno::XInterface >(), + uno::makeAny( + packages::zip::ZipIOException("Inconsistent ODF versions in content.xml and manifest.xml!" ) ) ); + } + } + } + + //Namespace handling is unnecessary. It is done by the fastparser itself. + uno::Reference<XFastContextHandler> xContext; + if (!maFastContexts.empty()) + { + uno::Reference<XFastContextHandler> pHandler = maFastContexts.top(); + xContext = pHandler->createFastChildContext( Element, Attribs ); + } + else + xContext.set( CreateFastContext( Element, Attribs ) ); + + SAL_INFO_IF(!xContext.is(), "xmloff.core", "No fast context for element " << getNameFromToken(Element)); + if ( !xContext.is() ) + xContext.set( new SvXMLImportContext( *this ) ); + + isFastContext = true; + + // Call a startElement at the new context. + xContext->startFastElement( Element, Attribs ); + + if ( isFastContext ) + { + if ( maNamespaceAttrList.is() ) + maNamespaceAttrList->Clear(); + else + maNamespaceAttrList = new comphelper::AttributeList; + + maNamespaceHandler->addNSDeclAttributes( maNamespaceAttrList ); + std::unique_ptr<SvXMLNamespaceMap> pRewindMap( + processNSAttributes( maNamespaceAttrList.get() )); + assert( dynamic_cast<SvXMLImportContext*>( xContext.get() ) != nullptr ); + SvXMLImportContext *pContext = static_cast<SvXMLImportContext*>( xContext.get() ); + if (pRewindMap) + pContext->PutRewindMap(std::move(pRewindMap)); + maContexts.push(pContext); + } + + // Push context on stack. + maFastContexts.push(xContext); +} + +void SAL_CALL SvXMLImport::startUnknownElement (const OUString & rPrefix, const OUString & rLocalName, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) +{ + uno::Reference<XFastContextHandler> xContext; + if (!maFastContexts.empty()) + { + uno::Reference<XFastContextHandler> pHandler = maFastContexts.top(); + xContext = pHandler->createUnknownChildContext( rPrefix, rLocalName, Attribs ); + } + else + xContext.set( CreateFastContext( -1, Attribs ) ); + + SAL_WARN_IF(!xContext.is(), "xmloff.core", "No context for unknown-element " << rLocalName); + if ( !xContext.is() ) + xContext.set( new SvXMLImportContext( *this ) ); + + xContext->startUnknownElement( rPrefix, rLocalName, Attribs ); + maFastContexts.push(xContext); +} + +void SAL_CALL SvXMLImport::endFastElement (sal_Int32 Element) +{ + if (!maFastContexts.empty()) + { + uno::Reference<XFastContextHandler> xContext = std::move(maFastContexts.top()); + maFastContexts.pop(); + isFastContext = true; + xContext->endFastElement( Element ); + if (isFastContext) + maContexts.pop(); + + xContext = nullptr; + } +} + +void SAL_CALL SvXMLImport::endUnknownElement (const OUString & rPrefix, const OUString & rLocalName) +{ + if (!maFastContexts.empty()) + { + uno::Reference<XFastContextHandler> xContext = std::move(maFastContexts.top()); + maFastContexts.pop(); + xContext->endUnknownElement( rPrefix, rLocalName ); + xContext = nullptr; + } +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL + SvXMLImport::createFastChildContext (sal_Int32, + const uno::Reference< xml::sax::XFastAttributeList > &) +{ + return this; +} + +uno::Reference< xml::sax::XFastContextHandler > SAL_CALL + SvXMLImport::createUnknownChildContext (const OUString &, const OUString &, + const uno::Reference< xml::sax::XFastAttributeList > &) +{ + return this; +} + +// XExtendedDocumentHandler +void SAL_CALL SvXMLImport::startCDATA() +{ +} + +void SAL_CALL SvXMLImport::endCDATA() +{ +} + +void SAL_CALL SvXMLImport::comment( const OUString& ) +{ +} + +void SAL_CALL SvXMLImport::allowLineBreak() +{ +} + +void SAL_CALL SvXMLImport::unknown( const OUString& ) +{ +} + +void SvXMLImport::SetStatistics(const uno::Sequence< beans::NamedValue> &) +{ + GetProgressBarHelper()->SetRepeat(false); + GetProgressBarHelper()->SetReference(0); +} + +// XImporter +void SAL_CALL SvXMLImport::setTargetDocument( const uno::Reference< lang::XComponent >& xDoc ) +{ + mxModel.set( xDoc, UNO_QUERY ); + if( !mxModel.is() ) + throw lang::IllegalArgumentException(); + + try + { + uno::Reference<document::XStorageBasedDocument> const xSBDoc(mxModel, uno::UNO_QUERY); + uno::Reference<embed::XStorage> const xStor(xSBDoc.is() ? xSBDoc->getDocumentStorage() + : nullptr); + if (xStor.is()) + { + mpImpl->mbIsOOoXML = + ::comphelper::OStorageHelper::GetXStorageFormat(xStor) + < SOFFICE_FILEFORMAT_8; + } + } + catch (uno::Exception const&) + { + DBG_UNHANDLED_EXCEPTION("xmloff.core"); + } + if (!mxEventListener.is()) + { + mxEventListener.set(new SvXMLImportEventListener(this)); + mxModel->addEventListener(mxEventListener); + } + + SAL_WARN_IF( bool(mpNumImport), "xmloff.core", "number format import already exists." ); + mpNumImport.reset(); +} + +// XFilter +sal_Bool SAL_CALL SvXMLImport::filter( const uno::Sequence< beans::PropertyValue >& ) +{ + return false; +} + +void SAL_CALL SvXMLImport::cancel( ) +{ +} + +// XInitialize +void SAL_CALL SvXMLImport::initialize( const uno::Sequence< uno::Any >& aArguments ) +{ + for( const auto& rAny : aArguments ) + { + Reference<XInterface> xValue; + rAny >>= xValue; + + uno::Reference<task::XStatusIndicator> xTmpStatusIndicator( + xValue, UNO_QUERY ); + if( xTmpStatusIndicator.is() ) + mxStatusIndicator = xTmpStatusIndicator; + + uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler(xValue, UNO_QUERY); + if (xGraphicStorageHandler.is()) + mxGraphicStorageHandler = xGraphicStorageHandler; + + uno::Reference<document::XEmbeddedObjectResolver> xTmpObjectResolver( + xValue, UNO_QUERY ); + if( xTmpObjectResolver.is() ) + mxEmbeddedResolver = xTmpObjectResolver; + + uno::Reference<beans::XPropertySet> xTmpPropSet( xValue, UNO_QUERY ); + if( xTmpPropSet.is() ) + { + mxImportInfo = xTmpPropSet; + uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxImportInfo->getPropertySetInfo(); + if (xPropertySetInfo.is()) + { + OUString sPropName(XML_NUMBERSTYLES); + if (xPropertySetInfo->hasPropertyByName(sPropName)) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= mxNumberStyles; + } + + sPropName = "PrivateData"; + if (xPropertySetInfo->hasPropertyByName(sPropName)) + { + Reference < XInterface > xIfc; + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= xIfc; + + StyleMap *pSMap = comphelper::getUnoTunnelImplementation<StyleMap>( xIfc ); + if( pSMap ) + { + mpStyleMap = pSMap; + } + } + OUString sBaseURI; + sPropName = "BaseURI"; + if (xPropertySetInfo->hasPropertyByName(sPropName)) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= sBaseURI; + mpImpl->aBaseURL.SetURL( sBaseURI ); + mpImpl->aDocBase.SetURL( sBaseURI ); + } + OUString sRelPath; + sPropName = "StreamRelPath"; + if( xPropertySetInfo->hasPropertyByName(sPropName) ) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= sRelPath; + } + OUString sName; + sPropName = "StreamName"; + if( xPropertySetInfo->hasPropertyByName(sPropName) ) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= sName; + } + if( !sBaseURI.isEmpty() && !sName.isEmpty() ) + { + if( !sRelPath.isEmpty() ) + mpImpl->aBaseURL.insertName( sRelPath ); + mpImpl->aBaseURL.insertName( sName ); + } + mpImpl->mStreamName = sName; // Note: may be empty (XSLT) + // Retrieve property <ShapePositionInHoriL2R> (#i28749#) + sPropName = "ShapePositionInHoriL2R"; + if( xPropertySetInfo->hasPropertyByName(sPropName) ) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= mpImpl->mbShapePositionInHoriL2R; + } + sPropName = "TextDocInOOoFileFormat"; + if( xPropertySetInfo->hasPropertyByName(sPropName) ) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sPropName); + aAny >>= mpImpl->mbTextDocInOOoFileFormat; + } + + sPropName = "SourceStorage"; + if( xPropertySetInfo->hasPropertyByName(sPropName) ) + mxImportInfo->getPropertyValue(sPropName) >>= mpImpl->mxSourceStorage; + } + } + } + + uno::Reference<lang::XInitialization> const xInit(mxParser, uno::UNO_QUERY_THROW); + uno::Sequence<uno::Any> args(1); + args[0] <<= OUString("IgnoreMissingNSDecl"); + xInit->initialize( args ); +} + +// XServiceInfo +OUString SAL_CALL SvXMLImport::getImplementationName() +{ + return mpImpl->implementationName; +} + +sal_Bool SAL_CALL SvXMLImport::supportsService( const OUString& rServiceName ) +{ + return cppu::supportsService(this, rServiceName); +} + +uno::Sequence< OUString > SAL_CALL SvXMLImport::getSupportedServiceNames( ) +{ + return { "com.sun.star.document.ImportFilter", "com.sun.star.xml.XMLImportFilter" }; +} + +XMLTextImportHelper* SvXMLImport::CreateTextImport() +{ + return new XMLTextImportHelper( mxModel, *this ); +} + +XMLShapeImportHelper* SvXMLImport::CreateShapeImport() +{ + return new XMLShapeImportHelper( *this, mxModel ); +} + +SchXMLImportHelper* SvXMLImport::CreateChartImport() +{ + return new SchXMLImportHelper(); +} + +::xmloff::OFormLayerXMLImport* SvXMLImport::CreateFormImport() +{ + return new ::xmloff::OFormLayerXMLImport(*this); +} + + +// Get or create fill/line/lineend-style-helper + + +const Reference< container::XNameContainer > & SvXMLImport::GetGradientHelper() +{ + if( !mxGradientHelper.is() ) + { + if( mxModel.is() ) + { + Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY); + if( xServiceFact.is() ) + { + try + { + mxGradientHelper.set( xServiceFact->createInstance( + "com.sun.star.drawing.GradientTable" ), UNO_QUERY); + } + catch( lang::ServiceNotRegisteredException& ) + {} + } + } + } + + return mxGradientHelper; +} + +const Reference< container::XNameContainer > & SvXMLImport::GetHatchHelper() +{ + if( !mxHatchHelper.is() ) + { + if( mxModel.is() ) + { + Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY); + if( xServiceFact.is() ) + { + try + { + mxHatchHelper.set( xServiceFact->createInstance( + "com.sun.star.drawing.HatchTable" ), UNO_QUERY); + } + catch( lang::ServiceNotRegisteredException& ) + {} + } + } + } + + return mxHatchHelper; +} + +const Reference< container::XNameContainer > & SvXMLImport::GetBitmapHelper() +{ + if( !mxBitmapHelper.is() ) + { + if( mxModel.is() ) + { + Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY); + if( xServiceFact.is() ) + { + try + { + mxBitmapHelper.set( xServiceFact->createInstance( + "com.sun.star.drawing.BitmapTable" ), UNO_QUERY); + } + catch( lang::ServiceNotRegisteredException& ) + {} + } + } + } + + return mxBitmapHelper; +} + +const Reference< container::XNameContainer > & SvXMLImport::GetTransGradientHelper() +{ + if( !mxTransGradientHelper.is() ) + { + if( mxModel.is() ) + { + Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY); + if( xServiceFact.is() ) + { + try + { + mxTransGradientHelper.set( xServiceFact->createInstance( + "com.sun.star.drawing.TransparencyGradientTable" ), UNO_QUERY); + } + catch( lang::ServiceNotRegisteredException& ) + {} + } + } + } + + return mxTransGradientHelper; +} + +const Reference< container::XNameContainer > & SvXMLImport::GetMarkerHelper() +{ + if( !mxMarkerHelper.is() ) + { + if( mxModel.is() ) + { + Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY); + if( xServiceFact.is() ) + { + try + { + mxMarkerHelper.set( xServiceFact->createInstance( "com.sun.star.drawing.MarkerTable" ), UNO_QUERY); + } + catch( lang::ServiceNotRegisteredException& ) + {} + } + } + } + + return mxMarkerHelper; +} + +const Reference< container::XNameContainer > & SvXMLImport::GetDashHelper() +{ + if( !mxDashHelper.is() && mxModel.is() ) + { + Reference< lang::XMultiServiceFactory > xServiceFact( mxModel, UNO_QUERY); + if( xServiceFact.is() ) + { + try + { + mxDashHelper.set( xServiceFact->createInstance( "com.sun.star.drawing.DashTable" ), UNO_QUERY); + } + catch( lang::ServiceNotRegisteredException& ) + {} + } + } + + return mxDashHelper; +} + +bool SvXMLImport::IsPackageURL( const OUString& rURL ) const +{ + + // if, and only if, only parts are imported, then we're in a package + const SvXMLImportFlags nTest = SvXMLImportFlags::META|SvXMLImportFlags::STYLES|SvXMLImportFlags::CONTENT|SvXMLImportFlags::SETTINGS; + if( (mnImportFlags & nTest) == nTest ) + return false; + + // TODO: from this point extract to own static function + + // Some quick tests: Some may rely on the package structure! + sal_Int32 nLen = rURL.getLength(); + if( nLen > 0 && '/' == rURL[0] ) + // RFC2396 net_path or abs_path + return false; + else if( nLen > 1 && '.' == rURL[0] ) + { + if( '.' == rURL[1] ) + // ../: We are never going up one level, so we know + // it's not an external URI + return false; + else if( '/' == rURL[1] ) + // we are remaining on a level, so it's a package URI + return true; + } + + // Now check for a RFC2396 schema + sal_Int32 nPos = 1; + while( nPos < nLen ) + { + switch( rURL[nPos] ) + { + case '/': + // a relative path segment + return true; + case ':': + // a schema + return false; + default: + break; + // we don't care about any other characters + } + ++nPos; + } + + return true; +} + +uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicByURL(OUString const & rURL) +{ + uno::Reference<graphic::XGraphic> xGraphic; + + if (mxGraphicStorageHandler.is()) + { + if (IsPackageURL(rURL)) + { + xGraphic = mxGraphicStorageHandler->loadGraphic(rURL); + } + else + { + OUString const & rAbsoluteURL = GetAbsoluteReference(rURL); + GraphicExternalLink aExternalLink(rAbsoluteURL); + Graphic aGraphic(aExternalLink); + xGraphic = aGraphic.GetXGraphic(); + } + } + + return xGraphic; +} + +uno::Reference<graphic::XGraphic> SvXMLImport::loadGraphicFromBase64(uno::Reference<io::XOutputStream> const & rxOutputStream) +{ + uno::Reference<graphic::XGraphic> xGraphic; + + if (mxGraphicStorageHandler.is()) + { + xGraphic = mxGraphicStorageHandler->loadGraphicFromOutputStream(rxOutputStream); + } + + return xGraphic; +} + +Reference< XOutputStream > SvXMLImport::GetStreamForGraphicObjectURLFromBase64() const +{ + Reference< XOutputStream > xOStm; + Reference< document::XBinaryStreamResolver > xStmResolver(mxGraphicStorageHandler, UNO_QUERY); + + if( xStmResolver.is() ) + xOStm = xStmResolver->createOutputStream(); + + return xOStm; +} + +OUString SvXMLImport::ResolveEmbeddedObjectURL( + const OUString& rURL, + const OUString& rClassId ) +{ + OUString sRet; + + if( IsPackageURL( rURL ) ) + { + if ( mxEmbeddedResolver.is() ) + { + OUString sURL( rURL ); + if( !rClassId.isEmpty() ) + { + sURL += "!" + rClassId; + } + sRet = mxEmbeddedResolver->resolveEmbeddedObjectURL( sURL ); + } + } + else + sRet = GetAbsoluteReference( rURL ); + + return sRet; +} + +Reference< embed::XStorage > const & SvXMLImport::GetSourceStorage() const +{ + return mpImpl->mxSourceStorage; +} + +Reference < XOutputStream > + SvXMLImport::GetStreamForEmbeddedObjectURLFromBase64() const +{ + Reference < XOutputStream > xOLEStream; + + if( mxEmbeddedResolver.is() ) + { + Reference< XNameAccess > xNA( mxEmbeddedResolver, UNO_QUERY ); + if( xNA.is() ) + { + Any aAny = xNA->getByName( "Obj12345678" ); + aAny >>= xOLEStream; + } + } + + return xOLEStream; +} + +OUString SvXMLImport::ResolveEmbeddedObjectURLFromBase64() +{ + OUString sRet; + + if( mxEmbeddedResolver.is() ) + { + sRet = mxEmbeddedResolver->resolveEmbeddedObjectURL( "Obj12345678" ); + } + + return sRet; +} + +void SvXMLImport::AddStyleDisplayName( XmlStyleFamily nFamily, + const OUString& rName, + const OUString& rDisplayName ) +{ + if( !mpStyleMap.is() ) + { + mpStyleMap = new StyleMap; + if( mxImportInfo.is() ) + { + OUString sPrivateData( "PrivateData" ); + Reference< beans::XPropertySetInfo > xPropertySetInfo = + mxImportInfo->getPropertySetInfo(); + if( xPropertySetInfo.is() && + xPropertySetInfo->hasPropertyByName(sPrivateData) ) + { + Reference < XInterface > xIfc( + static_cast< XUnoTunnel *>( mpStyleMap.get() ) ); + mxImportInfo->setPropertyValue( sPrivateData, Any(xIfc) ); + } + } + } + + StyleMap::key_type aKey( nFamily, rName ); + StyleMap::value_type aValue( aKey, rDisplayName ); + ::std::pair<StyleMap::iterator,bool> aRes( mpStyleMap->insert( aValue ) ); + SAL_WARN_IF( !aRes.second, + "xmloff.core", + "duplicate style name of family " << static_cast<int>(nFamily) << ": \"" << rName << "\""); + +} + +OUString SvXMLImport::GetStyleDisplayName( XmlStyleFamily nFamily, + const OUString& rName ) const +{ + OUString sName( rName ); + if( mpStyleMap.is() && !rName.isEmpty() ) + { + StyleMap::key_type aKey( nFamily, rName ); + StyleMap::const_iterator aIter = mpStyleMap->find( aKey ); + if( aIter != mpStyleMap->end() ) + sName = (*aIter).second; + } + return sName; +} + +void SvXMLImport::SetViewSettings(const css::uno::Sequence<css::beans::PropertyValue>&) +{ +} + +void SvXMLImport::SetConfigurationSettings(const css::uno::Sequence<css::beans::PropertyValue>&) +{ +} + +void SvXMLImport::SetDocumentSpecificSettings(const OUString&, const uno::Sequence<beans::PropertyValue>&) +{ +} + +ProgressBarHelper* SvXMLImport::GetProgressBarHelper() +{ + if (!mpProgressBarHelper) + { + mpProgressBarHelper = std::make_unique<ProgressBarHelper>(mxStatusIndicator, false); + + if (mxImportInfo.is()) + { + uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxImportInfo->getPropertySetInfo(); + if (xPropertySetInfo.is()) + { + OUString sProgressRange(XML_PROGRESSRANGE); + OUString sProgressMax(XML_PROGRESSMAX); + OUString sProgressCurrent(XML_PROGRESSCURRENT); + OUString sRepeat(XML_PROGRESSREPEAT); + if (xPropertySetInfo->hasPropertyByName(sProgressMax) && + xPropertySetInfo->hasPropertyByName(sProgressCurrent) && + xPropertySetInfo->hasPropertyByName(sProgressRange)) + { + uno::Any aAny; + sal_Int32 nProgressMax(0); + sal_Int32 nProgressCurrent(0); + sal_Int32 nProgressRange(0); + aAny = mxImportInfo->getPropertyValue(sProgressRange); + if (aAny >>= nProgressRange) + mpProgressBarHelper->SetRange(nProgressRange); + aAny = mxImportInfo->getPropertyValue(sProgressMax); + if (aAny >>= nProgressMax) + mpProgressBarHelper->SetReference(nProgressMax); + aAny = mxImportInfo->getPropertyValue(sProgressCurrent); + if (aAny >>= nProgressCurrent) + mpProgressBarHelper->SetValue(nProgressCurrent); + } + if (xPropertySetInfo->hasPropertyByName(sRepeat)) + { + uno::Any aAny = mxImportInfo->getPropertyValue(sRepeat); + if (aAny.getValueType() == cppu::UnoType<bool>::get()) + mpProgressBarHelper->SetRepeat(::cppu::any2bool(aAny)); + else { + SAL_WARN( "xmloff.core", "why is it no boolean?" ); + } + } + } + } + } + return mpProgressBarHelper.get(); +} + +void SvXMLImport::AddNumberStyle(sal_Int32 nKey, const OUString& rName) +{ + if (!mxNumberStyles.is()) + mxNumberStyles.set( comphelper::NameContainer_createInstance( ::cppu::UnoType<sal_Int32>::get()) ); + if (mxNumberStyles.is()) + { + try + { + mxNumberStyles->insertByName(rName, Any(nKey)); + } + catch ( uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION( "xmloff.core", "Numberformat could not be inserted"); + } + } + else { + SAL_WARN( "xmloff.core", "not possible to create NameContainer"); + } +} + +XMLEventImportHelper& SvXMLImport::GetEventImport() +{ + if (!mpEventImportHelper) + { + // construct event helper and register StarBasic handler and standard + // event tables + mpEventImportHelper = std::make_unique<XMLEventImportHelper>(); + const OUString& sStarBasic(GetXMLToken(XML_STARBASIC)); + mpEventImportHelper->RegisterFactory(sStarBasic, + std::make_unique<XMLStarBasicContextFactory>()); + const OUString& sScript(GetXMLToken(XML_SCRIPT)); + mpEventImportHelper->RegisterFactory(sScript, + std::make_unique<XMLScriptContextFactory>()); + mpEventImportHelper->AddTranslationTable(aStandardEventTable); + + // register StarBasic event handler with capitalized spelling + mpEventImportHelper->RegisterFactory("StarBasic", + std::make_unique<XMLStarBasicContextFactory>()); + } + + return *mpEventImportHelper; +} + +void SvXMLImport::SetFontDecls( XMLFontStylesContext *pFontDecls ) +{ + if (mxFontDecls.is()) + static_cast<SvXMLStylesContext*>(mxFontDecls.get())->Clear(); + mxFontDecls = pFontDecls; +} + +void SvXMLImport::SetStyles( SvXMLStylesContext *pStyles ) +{ + if (mxStyles.is()) + static_cast<SvXMLStylesContext*>(mxStyles.get())->Clear(); + mxStyles = pStyles; +} + +void SvXMLImport::SetAutoStyles( SvXMLStylesContext *pAutoStyles ) +{ + if (pAutoStyles && mxNumberStyles.is()) + { + uno::Reference<xml::sax::XAttributeList> xAttrList; + const uno::Sequence<OUString> aStyleNames = mxNumberStyles->getElementNames(); + for (const auto& name : aStyleNames) + { + uno::Any aAny(mxNumberStyles->getByName(name)); + sal_Int32 nKey(0); + if (aAny >>= nKey) + { + SvXMLStyleContext* pContext = new SvXMLNumFormatContext( + *this, XML_NAMESPACE_NUMBER, name, xAttrList, nKey, + GetDataStylesImport()->GetLanguageForKey(nKey), *pAutoStyles); + pAutoStyles->AddStyle(*pContext); + } + } + } + if (mxAutoStyles.is()) + static_cast<SvXMLStylesContext*>(mxAutoStyles.get())->Clear(); + mxAutoStyles = pAutoStyles; + GetTextImport()->SetAutoStyles( pAutoStyles ); + GetShapeImport()->SetAutoStylesContext( pAutoStyles ); + GetChartImport()->SetAutoStylesContext( pAutoStyles ); + GetFormImport()->setAutoStyleContext( pAutoStyles ); +} + +void SvXMLImport::SetMasterStyles( SvXMLStylesContext *pMasterStyles ) +{ + if (mxMasterStyles.is()) + static_cast<SvXMLStylesContext*>(mxMasterStyles.get())->Clear(); + mxMasterStyles = pMasterStyles; +} + +XMLFontStylesContext *SvXMLImport::GetFontDecls() +{ + return static_cast<XMLFontStylesContext *>(mxFontDecls.get()); +} + +SvXMLStylesContext *SvXMLImport::GetStyles() +{ + return static_cast<SvXMLStylesContext *>(mxStyles.get()); +} + +SvXMLStylesContext *SvXMLImport::GetAutoStyles() +{ + return static_cast<SvXMLStylesContext *>(mxAutoStyles.get()); +} + +const XMLFontStylesContext *SvXMLImport::GetFontDecls() const +{ + return static_cast<const XMLFontStylesContext *>(mxFontDecls.get()); +} + +const SvXMLStylesContext *SvXMLImport::GetStyles() const +{ + return static_cast<const SvXMLStylesContext *>(mxStyles.get()); +} + +const SvXMLStylesContext *SvXMLImport::GetAutoStyles() const +{ + return static_cast<const SvXMLStylesContext *>(mxAutoStyles.get()); +} + +OUString SvXMLImport::GetAbsoluteReference(const OUString& rValue) const +{ + if( rValue.isEmpty() || rValue[0] == '#' ) + return rValue; + + INetURLObject aAbsURL; + if( mpImpl->aBaseURL.GetNewAbsURL( rValue, &aAbsURL ) ) + return aAbsURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); + else + return rValue; +} + +bool SvXMLImport::IsODFVersionConsistent( const OUString& aODFVersion ) +{ + // the check returns sal_False only if the storage version could be retrieved + bool bResult = true; + + if ( !aODFVersion.isEmpty() && aODFVersion.compareTo( ODFVER_012_TEXT ) >= 0 ) + { + // check the consistency only for the ODF1.2 and later ( according to content.xml ) + // manifest.xml might have no version, it should be checked here and the correct version should be set + try + { // don't use getDocumentStorage(), it's temporary and latest version + uno::Reference<embed::XStorage> const xStor(GetSourceStorage()); + uno::Reference< beans::XPropertySet > xStorProps( xStor, uno::UNO_QUERY_THROW ); + + // the check should be done only for OASIS format + if (!IsOOoXML()) + { + bool bRepairPackage = false; + try + { + xStorProps->getPropertyValue( "RepairPackage" ) + >>= bRepairPackage; + } catch ( uno::Exception& ) + {} + + // check only if not in Repair mode + if ( !bRepairPackage ) + { + OUString aStorVersion; + xStorProps->getPropertyValue( "Version" ) + >>= aStorVersion; + + // if the storage version is set in manifest.xml, it must be the same as in content.xml + // if not, set it explicitly to be used further ( it will work even for readonly storage ) + // This workaround is not nice, but I see no other way to handle it, since there are + // ODF1.2 documents without version in manifest.xml + if ( !aStorVersion.isEmpty() ) + bResult = aODFVersion == aStorVersion; + else + xStorProps->setPropertyValue( "Version", + uno::makeAny( aODFVersion ) ); + + if ( bResult ) + { + bool bInconsistent = false; + xStorProps->getPropertyValue( "IsInconsistent" ) + >>= bInconsistent; + bResult = !bInconsistent; + } + } + } + } + catch( uno::Exception& ) + {} + } + + return bResult; +} + +void SvXMLImport::CreateNumberFormatsSupplier_() +{ + SAL_WARN_IF( mxNumberFormatsSupplier.is(), "xmloff.core", "number formats supplier already exists!" ); + if(mxModel.is()) + mxNumberFormatsSupplier = + uno::Reference< util::XNumberFormatsSupplier> (mxModel, uno::UNO_QUERY); +} + +void SvXMLImport::CreateDataStylesImport_() +{ + SAL_WARN_IF( bool(mpNumImport), "xmloff.core", "data styles import already exists!" ); + uno::Reference<util::XNumberFormatsSupplier> xNum = + GetNumberFormatsSupplier(); + if ( xNum.is() ) + mpNumImport = std::make_unique<SvXMLNumFmtHelper>(xNum, GetComponentContext() ); +} + +sal_Unicode SvXMLImport::ConvStarBatsCharToStarSymbol( sal_Unicode c ) +{ + sal_Unicode cNew = c; + if( !mpImpl->hBatsFontConv ) + { + mpImpl->hBatsFontConv = CreateFontToSubsFontConverter( "StarBats", + FontToSubsFontFlags::IMPORT ); + SAL_WARN_IF( !mpImpl->hBatsFontConv, "xmloff.core", "Got no symbol font converter" ); + } + if( mpImpl->hBatsFontConv ) + { + cNew = ConvertFontToSubsFontChar( mpImpl->hBatsFontConv, c ); + } + + return cNew; +} + +sal_Unicode SvXMLImport::ConvStarMathCharToStarSymbol( sal_Unicode c ) +{ + sal_Unicode cNew = c; + if( !mpImpl->hMathFontConv ) + { + mpImpl->hMathFontConv = CreateFontToSubsFontConverter( "StarMath", + FontToSubsFontFlags::IMPORT ); + SAL_WARN_IF( !mpImpl->hMathFontConv, "xmloff.core", "Got no symbol font converter" ); + } + if( mpImpl->hMathFontConv ) + { + cNew = ConvertFontToSubsFontChar( mpImpl->hMathFontConv, c ); + } + + return cNew; +} + +void SvXMLImport::SetError( + sal_Int32 nId, + const Sequence<OUString>& rMsgParams, + const OUString& rExceptionMessage, + const Reference<xml::sax::XLocator>& rLocator ) +{ + // create error list on demand + if ( !mpXMLErrors ) + mpXMLErrors = std::make_unique<XMLErrors>(); + + // save error information + // use document locator (if none supplied) + mpXMLErrors->AddRecord( nId, rMsgParams, rExceptionMessage, + rLocator.is() ? rLocator : mxLocator ); +} + +void SvXMLImport::SetError( + sal_Int32 nId, + const Sequence<OUString>& rMsgParams) +{ + SetError( nId, rMsgParams, "", nullptr ); +} + +void SvXMLImport::SetError( + sal_Int32 nId) +{ + Sequence<OUString> aSeq(0); + SetError( nId, aSeq ); +} + +void SvXMLImport::SetError( + sal_Int32 nId, + const OUString& rMsg1) +{ + Sequence<OUString> aSeq { rMsg1 }; + SetError( nId, aSeq ); +} + +void SvXMLImport::SetError( + sal_Int32 nId, + const OUString& rMsg1, + const OUString& rMsg2) +{ + Sequence<OUString> aSeq(2); + OUString* pSeq = aSeq.getArray(); + pSeq[0] = rMsg1; + pSeq[1] = rMsg2; + SetError( nId, aSeq ); +} + +void SvXMLImport::DisposingModel() +{ + if( mxFontDecls.is() ) + static_cast<SvXMLStylesContext *>(mxFontDecls.get())->Clear(); + if( mxStyles.is() ) + static_cast<SvXMLStylesContext *>(mxStyles.get())->Clear(); + if( mxAutoStyles.is() ) + static_cast<SvXMLStylesContext *>(mxAutoStyles.get())->Clear(); + if( mxMasterStyles.is() ) + static_cast<SvXMLStylesContext *>(mxMasterStyles.get())->Clear(); + + mxModel.set(nullptr); + mxEventListener.set(nullptr); +} + +::comphelper::UnoInterfaceToUniqueIdentifierMapper& SvXMLImport::getInterfaceToIdentifierMapper() +{ + return mpImpl->maInterfaceToIdentifierMapper; +} + +uno::Reference< uno::XComponentContext > const & +SvXMLImport::GetComponentContext() const +{ + return mpImpl->mxComponentContext; +} + +OUString SvXMLImport::GetBaseURL() const +{ + return mpImpl->aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); +} + +OUString SvXMLImport::GetDocumentBase() const +{ + return mpImpl->aDocBase.GetMainURL( INetURLObject::DecodeMechanism::NONE ); +} + +// Convert drawing object positions from OOo file format to OASIS (#i28749#) +bool SvXMLImport::IsShapePositionInHoriL2R() const +{ + return mpImpl->mbShapePositionInHoriL2R; +} + +bool SvXMLImport::IsTextDocInOOoFileFormat() const +{ + return mpImpl->mbTextDocInOOoFileFormat; +} + +void SvXMLImport::initXForms() +{ + // dummy method; to be implemented by derived classes supporting XForms +} + +bool SvXMLImport::getBuildIds( sal_Int32& rUPD, sal_Int32& rBuild ) const +{ + bool bRet = false; + OUString const aBuildId(getBuildIdsProperty(mxImportInfo)); + if (!aBuildId.isEmpty()) + { + sal_Int32 nIndex = aBuildId.indexOf('$'); + if (nIndex != -1) + { + rUPD = aBuildId.copy( 0, nIndex ).toInt32(); + sal_Int32 nIndexEnd = aBuildId.indexOf(';', nIndex); + rBuild = (nIndexEnd == -1) + ? aBuildId.copy(nIndex + 1).toInt32() + : aBuildId.copy(nIndex + 1, nIndexEnd - nIndex - 1).toInt32(); + bRet = true; + } + } + return bRet; +} + +sal_uInt16 SvXMLImport::getGeneratorVersion() const +{ + // --> ORW + return mpImpl->getGeneratorVersion( *this ); + // <-- +} + +bool SvXMLImport::isGeneratorVersionOlderThan( + sal_uInt16 const nOOoVersion, sal_uInt16 const nLOVersion) +{ + assert( (nLOVersion & LO_flag)); + assert(!(nOOoVersion & LO_flag)); + const sal_uInt16 nGeneratorVersion(getGeneratorVersion()); + return (nGeneratorVersion & LO_flag) + ? nGeneratorVersion < nLOVersion + : nGeneratorVersion < nOOoVersion; +} + + +OUString const & SvXMLImport::GetODFVersion() const +{ + return mpImpl->aODFVersion; +} + +bool SvXMLImport::IsOOoXML() const +{ + return mpImpl->mbIsOOoXML; +} + +// xml:id for RDF metadata +void SvXMLImport::SetXmlId(uno::Reference<uno::XInterface> const & i_xIfc, + OUString const & i_rXmlId) +{ + if (!i_rXmlId.isEmpty()) { + try { + const uno::Reference<rdf::XMetadatable> xMeta(i_xIfc, + uno::UNO_QUERY); +//FIXME: not yet + if (xMeta.is()) { + const beans::StringPair mdref( mpImpl->mStreamName, i_rXmlId ); + try { + xMeta->setMetadataReference(mdref); + } catch (lang::IllegalArgumentException &) { + // probably duplicate; ignore + SAL_INFO("xmloff.core", "SvXMLImport::SetXmlId: cannot set xml:id"); + } + } + } catch (uno::Exception &) { + TOOLS_WARN_EXCEPTION("xmloff.core","SvXMLImport::SetXmlId"); + } + } +} + +::xmloff::RDFaImportHelper & +SvXMLImport::GetRDFaImportHelper() +{ + if (!mpImpl->mpRDFaHelper) + { + mpImpl->mpRDFaHelper.reset( new ::xmloff::RDFaImportHelper(*this) ); + } + return *mpImpl->mpRDFaHelper; +} + +void +SvXMLImport::AddRDFa(const uno::Reference<rdf::XMetadatable>& i_xObject, + OUString const & i_rAbout, + OUString const & i_rProperty, + OUString const & i_rContent, + OUString const & i_rDatatype) +{ + // N.B.: we only get called if i_xObject had xhtml:about attribute + // (an empty attribute value is valid) + ::xmloff::RDFaImportHelper & rRDFaHelper( GetRDFaImportHelper() ); + rRDFaHelper.ParseAndAddRDFa(i_xObject, + i_rAbout, i_rProperty, i_rContent, i_rDatatype); +} + +bool SvXMLImport::embeddedFontAlreadyProcessed( const OUString& url ) +{ + if( embeddedFontUrlsKnown.count( url ) != 0 ) + return true; + embeddedFontUrlsKnown.insert( url ); + return false; +} + +const OUString & SvXMLImport::getNameFromToken( sal_Int32 nToken ) +{ + return xTokenHandler->getIdentifier( nToken & TOKEN_MASK ); +} + +OUString SvXMLImport::getPrefixAndNameFromToken( sal_Int32 nToken ) +{ + OUString rv; + sal_Int32 nNamespaceToken = ( nToken & NMSP_MASK ) >> NMSP_SHIFT; + auto aIter( aNamespaceMap.find( nNamespaceToken ) ); + if( aIter != aNamespaceMap.end() ) + rv = (*aIter).second.second + " " + aIter->second.first + ":"; + return rv + xTokenHandler->getIdentifier( nToken & TOKEN_MASK ); +} + +OUString SvXMLImport::getNamespacePrefixFromToken(sal_Int32 nToken, const SvXMLNamespaceMap* pMap) +{ + sal_Int32 nNamespaceToken = ( nToken & NMSP_MASK ) >> NMSP_SHIFT; + auto aIter( aNamespaceMap.find( nNamespaceToken ) ); + if( aIter != aNamespaceMap.end() ) + { + if (pMap) + { + OUString sRet = pMap->GetPrefixByKey(pMap->GetKeyByName((*aIter).second.second)); + if (!sRet.isEmpty()) + return sRet; + } + return (*aIter).second.first; + } + else + return OUString(); +} + +OUString SvXMLImport::getNamespaceURIFromToken( sal_Int32 nToken ) +{ + sal_Int32 nNamespaceToken = ( nToken & NMSP_MASK ) >> NMSP_SHIFT; + auto aIter( aNamespaceMap.find( nNamespaceToken ) ); + if( aIter != aNamespaceMap.end() ) + return (*aIter).second.second; + else + return OUString(); +} + +OUString SvXMLImport::getNamespacePrefixFromURI( const OUString& rURI ) +{ + auto aIter( aNamespaceURIPrefixMap.find(rURI) ); + if( aIter != aNamespaceURIPrefixMap.end() ) + return (*aIter).second; + else + return OUString(); +} + +void SvXMLImport::initializeNamespaceMaps() +{ + auto mapTokenToNamespace = [&]( sal_Int32 nToken, sal_Int32 nPrefix, sal_Int32 nNamespace ) + { + if ( nToken >= 0 ) + { + const OUString& sNamespace = GetXMLToken( static_cast<XMLTokenEnum>( nNamespace ) ); + const OUString& sPrefix = GetXMLToken( static_cast<XMLTokenEnum>( nPrefix ) ); + assert( aNamespaceMap.find(nToken +1) == aNamespaceMap.end() && "cannot map two namespaces to the same token here"); + aNamespaceMap[ nToken + 1 ] = std::make_pair( sPrefix, sNamespace ); + aNamespaceURIPrefixMap.emplace( sNamespace, sPrefix ); + } + }; + + mapTokenToNamespace( XML_NAMESPACE_OFFICE, XML_NP_OFFICE, XML_N_OFFICE ); + mapTokenToNamespace( XML_NAMESPACE_OFFICE_SO52, XML_NP_OFFICE, XML_N_OFFICE_OLD ); + mapTokenToNamespace( XML_NAMESPACE_OFFICE_OOO, XML_NP_OFFICE, XML_N_OFFICE_OOO ); + mapTokenToNamespace( XML_NAMESPACE_STYLE, XML_NP_STYLE, XML_N_STYLE ); + mapTokenToNamespace( XML_NAMESPACE_STYLE_SO52, XML_NP_STYLE, XML_N_STYLE_OLD ); + mapTokenToNamespace( XML_NAMESPACE_STYLE_OOO, XML_NP_STYLE, XML_N_STYLE_OOO ); + mapTokenToNamespace( XML_NAMESPACE_TEXT, XML_NP_TEXT, XML_N_TEXT ); + mapTokenToNamespace( XML_NAMESPACE_TEXT_SO52, XML_NP_TEXT, XML_N_TEXT_OLD ); + mapTokenToNamespace( XML_NAMESPACE_TEXT_OOO, XML_NP_TEXT, XML_N_TEXT_OOO ); + mapTokenToNamespace( XML_NAMESPACE_TABLE, XML_NP_TABLE, XML_N_TABLE ); + mapTokenToNamespace( XML_NAMESPACE_TABLE_SO52, XML_NP_TABLE, XML_N_TABLE_OLD ); + mapTokenToNamespace( XML_NAMESPACE_TABLE_OOO, XML_NP_TABLE, XML_N_TABLE_OOO ); + mapTokenToNamespace( XML_NAMESPACE_DRAW, XML_NP_DRAW, XML_N_DRAW ); + mapTokenToNamespace( XML_NAMESPACE_DRAW_SO52, XML_NP_DRAW, XML_N_DRAW_OLD ); + mapTokenToNamespace( XML_NAMESPACE_DRAW_OOO, XML_NP_DRAW, XML_N_DRAW_OOO ); + mapTokenToNamespace( XML_NAMESPACE_FO, XML_NP_FO, XML_N_FO ); + mapTokenToNamespace( XML_NAMESPACE_FO_SO52, XML_NP_FO, XML_N_FO_OLD ); + mapTokenToNamespace( XML_NAMESPACE_FO_COMPAT, XML_NP_FO, XML_N_FO_COMPAT ); + mapTokenToNamespace( XML_NAMESPACE_XLINK, XML_NP_XLINK, XML_N_XLINK ); + mapTokenToNamespace( XML_NAMESPACE_XLINK_SO52, XML_NP_XLINK, XML_N_XLINK_OLD ); + mapTokenToNamespace( XML_NAMESPACE_DC, XML_NP_DC, XML_N_DC ); + mapTokenToNamespace( XML_NAMESPACE_META, XML_NP_META, XML_N_META ); + mapTokenToNamespace( XML_NAMESPACE_META_SO52, XML_NP_META, XML_N_META_OLD ); + mapTokenToNamespace( XML_NAMESPACE_META_OOO, XML_NP_META, XML_N_META_OOO ); + mapTokenToNamespace( XML_NAMESPACE_NUMBER, XML_NP_NUMBER, XML_N_NUMBER ); + mapTokenToNamespace( XML_NAMESPACE_NUMBER_SO52, XML_NP_NUMBER, XML_N_NUMBER_OLD ); + mapTokenToNamespace( XML_NAMESPACE_NUMBER_OOO, XML_NP_NUMBER, XML_N_NUMBER_OOO ); + mapTokenToNamespace( XML_NAMESPACE_PRESENTATION, XML_NP_PRESENTATION, XML_N_PRESENTATION ); + mapTokenToNamespace( XML_NAMESPACE_PRESENTATION_SO52,XML_NP_PRESENTATION, XML_N_PRESENTATION_OLD ); + mapTokenToNamespace( XML_NAMESPACE_PRESENTATION_OOO, XML_NP_PRESENTATION, XML_N_PRESENTATION_OOO ); + mapTokenToNamespace( XML_NAMESPACE_PRESENTATION_OASIS, XML_NP_PRESENTATION, XML_N_PRESENTATION_OASIS ); + mapTokenToNamespace( XML_NAMESPACE_SVG, XML_NP_SVG, XML_N_SVG ); + mapTokenToNamespace( XML_NAMESPACE_SVG_COMPAT, XML_NP_SVG, XML_N_SVG_COMPAT ); + mapTokenToNamespace( XML_NAMESPACE_CHART, XML_NP_CHART, XML_N_CHART ); + mapTokenToNamespace( XML_NAMESPACE_CHART_SO52, XML_NP_CHART, XML_N_CHART_OLD ); + mapTokenToNamespace( XML_NAMESPACE_CHART_OOO, XML_NP_CHART, XML_N_CHART_OOO ); + mapTokenToNamespace( XML_NAMESPACE_DR3D, XML_NP_DR3D, XML_N_DR3D ); + mapTokenToNamespace( XML_NAMESPACE_DR3D_OOO, XML_NP_DR3D, XML_N_DR3D_OOO ); + mapTokenToNamespace( XML_NAMESPACE_MATH, XML_NP_MATH, XML_N_MATH ); + mapTokenToNamespace( XML_NAMESPACE_VERSIONS_LIST, XML_NP_VERSIONS_LIST, XML_N_VERSIONS_LIST ); + mapTokenToNamespace( XML_NAMESPACE_FORM, XML_NP_FORM, XML_N_FORM ); + mapTokenToNamespace( XML_NAMESPACE_FORM_OOO, XML_NP_FORM, XML_N_FORM_OOO ); + mapTokenToNamespace( XML_NAMESPACE_SCRIPT, XML_NP_SCRIPT, XML_N_SCRIPT ); + mapTokenToNamespace( XML_NAMESPACE_SCRIPT_OOO, XML_NP_SCRIPT, XML_N_SCRIPT_OOO ); + mapTokenToNamespace( XML_NAMESPACE_BLOCKLIST, XML_NP_BLOCK_LIST, XML_N_BLOCK_LIST ); + mapTokenToNamespace( XML_NAMESPACE_CONFIG, XML_NP_CONFIG, XML_N_CONFIG ); + mapTokenToNamespace( XML_NAMESPACE_CONFIG_OOO, XML_NP_CONFIG, XML_N_CONFIG_OOO ); + mapTokenToNamespace( XML_NAMESPACE_OOO, XML_NP_OOO, XML_N_OOO ); + mapTokenToNamespace( XML_NAMESPACE_OOOW, XML_NP_OOOW, XML_N_OOOW ); + mapTokenToNamespace( XML_NAMESPACE_OOOC, XML_NP_OOOC, XML_N_OOOC ); + mapTokenToNamespace( XML_NAMESPACE_DOM, XML_NP_DOM, XML_N_DOM ); + mapTokenToNamespace( XML_NAMESPACE_DB, XML_NP_DB, XML_N_DB ); + mapTokenToNamespace( XML_NAMESPACE_DB_OASIS, XML_NP_DB, XML_N_DB_OASIS ); + mapTokenToNamespace( XML_NAMESPACE_DLG, XML_NP_DLG, XML_N_DLG ); + mapTokenToNamespace( XML_NAMESPACE_XFORMS, XML_NP_XFORMS_1_0, XML_N_XFORMS_1_0 ); + mapTokenToNamespace( XML_NAMESPACE_XSD, XML_NP_XSD, XML_N_XSD ); + mapTokenToNamespace( XML_NAMESPACE_XSI, XML_NP_XSI, XML_N_XSI ); + mapTokenToNamespace( XML_NAMESPACE_SMIL, XML_NP_SMIL, XML_N_SMIL ); + mapTokenToNamespace( XML_NAMESPACE_SMIL_SO52, XML_NP_SMIL, XML_N_SMIL_OLD ); + mapTokenToNamespace( XML_NAMESPACE_SMIL_COMPAT, XML_NP_SMIL, XML_N_SMIL_COMPAT ); + mapTokenToNamespace( XML_NAMESPACE_ANIMATION, XML_NP_ANIMATION, XML_N_ANIMATION ); + mapTokenToNamespace( XML_NAMESPACE_ANIMATION_OOO, XML_NP_ANIMATION, XML_N_ANIMATION_OOO ); + mapTokenToNamespace( XML_NAMESPACE_REPORT, XML_NP_RPT, XML_N_RPT ); + mapTokenToNamespace( XML_NAMESPACE_REPORT_OASIS, XML_NP_RPT, XML_N_RPT_OASIS ); + mapTokenToNamespace( XML_NAMESPACE_OF, XML_NP_OF, XML_N_OF ); + mapTokenToNamespace( XML_NAMESPACE_XHTML, XML_NP_XHTML, XML_N_XHTML ); + mapTokenToNamespace( XML_NAMESPACE_GRDDL, XML_NP_GRDDL, XML_N_GRDDL ); + mapTokenToNamespace( XML_NAMESPACE_OFFICE_EXT, XML_NP_OFFICE_EXT, XML_N_OFFICE_EXT ); + mapTokenToNamespace( XML_NAMESPACE_TABLE_EXT, XML_NP_TABLE_EXT, XML_N_TABLE_EXT ); + mapTokenToNamespace( XML_NAMESPACE_CHART_EXT, XML_NP_CHART_EXT, XML_N_CHART_EXT ); + mapTokenToNamespace( XML_NAMESPACE_DRAW_EXT, XML_NP_DRAW_EXT, XML_N_DRAW_EXT ); + mapTokenToNamespace( XML_NAMESPACE_CALC_EXT, XML_NP_CALC_EXT, XML_N_CALC_EXT ); + mapTokenToNamespace( XML_NAMESPACE_LO_EXT, XML_NP_LO_EXT, XML_N_LO_EXT ); + mapTokenToNamespace( XML_NAMESPACE_CSS3TEXT, XML_NP_CSS3TEXT, XML_N_CSS3TEXT ); + mapTokenToNamespace( XML_NAMESPACE_FIELD, XML_NP_FIELD, XML_N_FIELD ); + mapTokenToNamespace( XML_NAMESPACE_FORMX, XML_NP_FORMX, XML_N_FORMX ); +} + +void SvXMLImport::registerNamespaces() +{ + for( auto const &aNamespaceEntry : aNamespaceMap ) + { + // aNamespaceMap = { Token : ( NamespacePrefix, NamespaceURI ) } + registerNamespace( aNamespaceEntry.second.second, aNamespaceEntry.first << NMSP_SHIFT ); + } +} + +void SvXMLImport::NotifyMacroEventRead() +{ + if (mbNotifyMacroEventRead) + return; + + comphelper::DocumentInfo::notifyMacroEventRead(mxModel); + + mbNotifyMacroEventRead = true; +} + +SvXMLImportFastNamespaceHandler::SvXMLImportFastNamespaceHandler() +{ +} + +void SvXMLImportFastNamespaceHandler::addNSDeclAttributes( rtl::Reference < comphelper::AttributeList > const & rAttrList ) +{ + for(const auto& aNamespaceDefine : m_aNamespaceDefines) + { + OUString& rPrefix = aNamespaceDefine->m_aPrefix; + OUString& rNamespaceURI = aNamespaceDefine->m_aNamespaceURI; + OUString sDecl; + if ( rPrefix.isEmpty() ) + sDecl = "xmlns"; + else + sDecl = "xmlns:" + rPrefix; + rAttrList->AddAttribute( sDecl, "CDATA", rNamespaceURI ); + } + m_aNamespaceDefines.clear(); +} + +void SvXMLImportFastNamespaceHandler::registerNamespace( const OUString& rNamespacePrefix, const OUString& rNamespaceURI ) +{ + // Elements with default namespace parsed by FastParser have namespace prefix. + // A default namespace needs to be registered with the prefix, to maintain the compatibility. + if ( rNamespacePrefix.isEmpty() ) + m_aNamespaceDefines.push_back( std::make_unique<NamespaceDefine>( + SvXMLImport::getNamespacePrefixFromURI( rNamespaceURI ), rNamespaceURI) ); + + m_aNamespaceDefines.push_back( std::make_unique<NamespaceDefine>( + rNamespacePrefix, rNamespaceURI) ); +} + +OUString SvXMLImportFastNamespaceHandler::getNamespaceURI( const OUString&/* rNamespacePrefix */ ) +{ + return OUString(); +} + +SvXMLLegacyToFastDocHandler::SvXMLLegacyToFastDocHandler( const rtl::Reference< SvXMLImport > & rImport ) +: mrImport( rImport ), + mxFastAttributes( new sax_fastparser::FastAttributeList( SvXMLImport::xTokenHandler.get() ) ) +{ +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::setTargetDocument( const uno::Reference< lang::XComponent >& xDoc ) +{ + mrImport->setTargetDocument( xDoc ); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::startDocument() +{ + mrImport->startDocument(); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::endDocument() +{ + mrImport->endDocument(); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::startElement( const OUString& rName, + const uno::Reference< xml::sax::XAttributeList >& xAttrList ) +{ + mrImport->processNSAttributes(xAttrList); + OUString aLocalName; + sal_uInt16 nPrefix = mrImport->mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); + Sequence< sal_Int8 > aLocalNameSeq( reinterpret_cast<sal_Int8 const *>( + OUStringToOString( aLocalName, RTL_TEXTENCODING_UTF8 ).getStr()), aLocalName.getLength() ); + sal_Int32 mnElement = NAMESPACE_TOKEN( nPrefix ) | SvXMLImport::xTokenHandler->getTokenFromUTF8( aLocalNameSeq ); + mxFastAttributes->clear(); + + sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; + for( sal_Int16 i=0; i < nAttrCount; i++ ) + { + OUString aLocalAttrName; + OUString aNamespace; + const OUString& rAttrName = xAttrList->getNameByIndex( i ); + const OUString& rAttrValue = xAttrList->getValueByIndex( i ); + sal_uInt16 const nAttrPrefix(mrImport->mpNamespaceMap->GetKeyByAttrName( + rAttrName, nullptr, &aLocalAttrName, &aNamespace)); + if( XML_NAMESPACE_XMLNS != nAttrPrefix ) + { + Sequence< sal_Int8 > aAttrSeq( reinterpret_cast<sal_Int8 const *>( + OUStringToOString( aLocalAttrName, RTL_TEXTENCODING_UTF8 ).getStr()), aLocalAttrName.getLength() ); + auto const nToken(SvXMLImport::xTokenHandler->getTokenFromUTF8(aAttrSeq)); + if (nToken == xmloff::XML_TOKEN_INVALID) + { + mxFastAttributes->addUnknown(aNamespace, + OUStringToOString(rAttrName, RTL_TEXTENCODING_UTF8), + OUStringToOString(rAttrValue, RTL_TEXTENCODING_UTF8)); + } + else + { + sal_Int32 const nAttr = NAMESPACE_TOKEN(nAttrPrefix) | nToken; + mxFastAttributes->add(nAttr, OUStringToOString(rAttrValue, RTL_TEXTENCODING_UTF8).getStr()); + } + } + } + mrImport->startFastElement( mnElement, mxFastAttributes.get() ); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::endElement( const OUString& rName ) +{ + OUString aLocalName; + sal_uInt16 nPrefix = mrImport->mpNamespaceMap->GetKeyByAttrName( rName, &aLocalName ); + Sequence< sal_Int8 > aLocalNameSeq( reinterpret_cast<sal_Int8 const *>( + OUStringToOString( aLocalName, RTL_TEXTENCODING_UTF8 ).getStr()), aLocalName.getLength() ); + sal_Int32 mnElement = NAMESPACE_TOKEN( nPrefix ) | SvXMLImport::xTokenHandler->getTokenFromUTF8( aLocalNameSeq ); + mrImport->endFastElement( mnElement ); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::characters( const OUString& aChars ) +{ + mrImport->characters( aChars ); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::ignorableWhitespace( const OUString& aWhitespaces ) +{ + mrImport->ignorableWhitespace( aWhitespaces ); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::processingInstruction( const OUString& aTarget, + const OUString& aData) +{ + mrImport->processingInstruction( aTarget, aData ); +} + +void SAL_CALL SvXMLLegacyToFastDocHandler::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& rLocator ) +{ + mrImport->setDocumentLocator( rLocator ); +} + + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |