office-gobmx/xmloff/source/core/xmlimp.cxx
Michael Stahl 7cf5faec6f tdf#156146 xmloff: ODF import: add backward compatibility hack
As a follow-up to ade0a153f4 "tdf#114287
xmloff: ODF import: fix text:list override of list style", add some ugly
compatibility hack to preserve the visual layout of documents produced
by LO versions before 7.6.

Override the left/first-line margin of the applied numbering rules with
what is in the paragraph or paragraph style, and try to do this only in
the specific situation where the list style is the same.

Change-Id: I1f4520c9bf9d2257d2e3864e4ddb2d28451bbd2f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157284
Tested-by: Jenkins
Tested-by: Gabor Kelemen <kelemeng@ubuntu.com>
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
2023-09-28 22:52:50 +02:00

2298 lines
83 KiB
C++

/* -*- 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 <config_wasm_strip.h>
#include <memory>
#include <optional>
#include <comphelper/diagnose_ex.hxx>
#include <sal/log.hxx>
#include <com/sun/star/beans/XPropertySetInfo.hpp>
#include <tools/urlobj.hxx>
#include <utility>
#include <vcl/embeddedfontshelper.hxx>
#include <vcl/graph.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <xmloff/namespacemap.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmlnamespace.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/XUnoTunnel.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 <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <comphelper/fileformat.h>
#include <comphelper/namecontainer.hxx>
#include <comphelper/servicehelper.hxx>
#include <comphelper/string.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 <o3tl/string_view.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;
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())
{
auto const firstDot(loVersion.indexOf('.'));
if (firstDot == 1)
{ // old version scheme 3.3 ... 7.6
if ('3' == loVersion[0])
{
mnGeneratorVersion = SvXMLImport::LO_3x;
}
else if ('4' == loVersion[0])
{
if (loVersion.getLength() > 2
&& (loVersion[2] == '0' || loVersion[2] == '1'))
{
mnGeneratorVersion = SvXMLImport::LO_41x; // 4.0/4.1
}
else if (loVersion.getLength() > 2 && '2' == loVersion[2])
{
mnGeneratorVersion = SvXMLImport::LO_42x; // 4.2
}
else if (loVersion.getLength() > 2 && '3' == loVersion[2])
{
mnGeneratorVersion = SvXMLImport::LO_43x; // 4.3
}
else if (loVersion.getLength() > 2 && '4' == loVersion[2])
{
mnGeneratorVersion = SvXMLImport::LO_44x; // 4.4
}
}
else if ('5' == loVersion[0])
{
mnGeneratorVersion = SvXMLImport::LO_5x;
}
else if ('6' == loVersion[0])
{
if (loVersion.getLength() > 2
&& (loVersion[2] == '0' || loVersion[2] == '1'
|| loVersion[2] == '2'))
{
mnGeneratorVersion = SvXMLImport::LO_6x; // 6.0/6.1/6.2
}
else
{
mnGeneratorVersion = SvXMLImport::LO_63x; // 6.3/6.4
}
}
else if ('7' == loVersion[0])
{
if (loVersion.getLength() > 2 && loVersion[2] == '6')
{
mnGeneratorVersion = SvXMLImport::LO_76; // 7.6
}
else
{
mnGeneratorVersion = SvXMLImport::LO_7x;
}
}
else
{
SAL_INFO("xmloff.core", "unknown LO version: " << loVersion);
}
}
else if (1 < firstDot) // new version scheme 24.2 ...
{
OUString const nMajor(loVersion.subView(0, firstDot));
auto const year(nMajor.toInt32());
//auto const month(loVersion.copy(firstDot+1).toInt32());
if (0 < year)
{
mnGeneratorVersion = SvXMLImport::LO_New;
}
else
{
SAL_INFO("xmloff.core", "unknown LO version: " << loVersion);
}
}
else
{
SAL_INFO("xmloff.core", "unknown LO version: " << loVersion);
}
return; // ignore buildIds
}
}
}
sal_Int32 nUPD, nBuild;
if ( !rImport.getBuildIds( nUPD, nBuild ) )
return;
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;
std::optional<OUString> mxODFVersion;
bool mbIsOOoXML;
std::optional<bool> mbIsMSO;
// 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;
css::uno::Sequence< OUString > maSupportedServiceNames;
uno::Reference< embed::XStorage > mxSourceStorage;
std::unique_ptr< xmloff::RDFaImportHelper > mpRDFaHelper;
std::optional< DocumentInfo > moDocumentInfo;
SvXMLImport_Impl( uno::Reference< uno::XComponentContext > xContext,
OUString theImplementationName,
const css::uno::Sequence< OUString > & sSupportedServiceNames = {})
: 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(std::move( xContext ))
, implementationName(std::move(theImplementationName))
, maSupportedServiceNames(sSupportedServiceNames)
{
SAL_WARN_IF(!mxComponentContext.is(), "xmloff.core", "SvXMLImport: no ComponentContext");
if (!mxComponentContext.is()) throw uno::RuntimeException();
if (!maSupportedServiceNames.hasElements())
maSupportedServiceNames = { "com.sun.star.document.ImportFilter", "com.sun.star.xml.XMLImportFilter" };
}
sal_uInt16 getGeneratorVersion( const SvXMLImport& rImport )
{
if (!moDocumentInfo)
{
moDocumentInfo.emplace( rImport );
}
return moDocumentInfo->getGeneratorVersion();
}
::comphelper::UnoInterfaceToUniqueIdentifierMapper maInterfaceToIdentifierMapper;
};
SvXMLImportContext *SvXMLImport::CreateFastContext( sal_Int32 nElement,
const uno::Reference< xml::sax::XFastAttributeList >& /*xAttrList*/ )
{
assert(false);
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
mxNamespaceMap->Add( GetXMLToken(XML_XML), GetXMLToken(XML_N_XML), XML_NAMESPACE_XML );
mxNamespaceMap->Add( "_office", GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
mxNamespaceMap->Add( "_office_ooo", GetXMLToken(XML_N_OFFICE_EXT), XML_NAMESPACE_OFFICE_EXT );
mxNamespaceMap->Add( "_ooo", GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
mxNamespaceMap->Add( "_style", GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
mxNamespaceMap->Add( "_text", GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT );
mxNamespaceMap->Add( "_table", GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE );
mxNamespaceMap->Add( "_table_ooo", GetXMLToken(XML_N_TABLE_EXT), XML_NAMESPACE_TABLE_EXT );
mxNamespaceMap->Add( "_draw", GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
mxNamespaceMap->Add( "_draw_ooo", GetXMLToken(XML_N_DRAW_EXT), XML_NAMESPACE_DRAW_EXT );
mxNamespaceMap->Add( "_dr3d", GetXMLToken(XML_N_DR3D), XML_NAMESPACE_DR3D );
mxNamespaceMap->Add( "_fo", GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
mxNamespaceMap->Add( "_xlink", GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
mxNamespaceMap->Add( "_dc", GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
mxNamespaceMap->Add( "_dom", GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM );
mxNamespaceMap->Add( "_meta", GetXMLToken(XML_N_META), XML_NAMESPACE_META );
mxNamespaceMap->Add( "_number", GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER );
mxNamespaceMap->Add( "_svg", GetXMLToken(XML_N_SVG_COMPAT), XML_NAMESPACE_SVG );
mxNamespaceMap->Add( "_chart", GetXMLToken(XML_N_CHART), XML_NAMESPACE_CHART );
mxNamespaceMap->Add( "_math", GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
mxNamespaceMap->Add( "_form", GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM );
mxNamespaceMap->Add( "_script", GetXMLToken(XML_N_SCRIPT), XML_NAMESPACE_SCRIPT );
mxNamespaceMap->Add( "_config", GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
mxNamespaceMap->Add( "_xforms", GetXMLToken(XML_N_XFORMS_1_0), XML_NAMESPACE_XFORMS );
mxNamespaceMap->Add( "_formx", GetXMLToken( XML_N_FORMX ), XML_NAMESPACE_FORMX );
mxNamespaceMap->Add( "_xsd", GetXMLToken(XML_N_XSD), XML_NAMESPACE_XSD );
mxNamespaceMap->Add( "_xsi", GetXMLToken(XML_N_XSI), XML_NAMESPACE_XFORMS );
mxNamespaceMap->Add( "_ooow", GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW );
mxNamespaceMap->Add( "_oooc", GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC );
mxNamespaceMap->Add( "_field", GetXMLToken(XML_N_FIELD), XML_NAMESPACE_FIELD );
mxNamespaceMap->Add( "_of", GetXMLToken(XML_N_OF), XML_NAMESPACE_OF );
mxNamespaceMap->Add( "_xhtml", GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
mxNamespaceMap->Add( "_css3text", GetXMLToken(XML_N_CSS3TEXT), XML_NAMESPACE_CSS3TEXT );
mxNamespaceMap->Add( "_calc_libo", GetXMLToken(XML_N_CALC_EXT), XML_NAMESPACE_CALC_EXT);
mxNamespaceMap->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,
const css::uno::Sequence< OUString > & sSupportedServiceNames )
: mpImpl( new SvXMLImport_Impl(xContext, implementationName, sSupportedServiceNames) ),
mxNamespaceMap( SvXMLNamespaceMap() ),
mpUnitConv( new SvXMLUnitConverter( xContext,
util::MeasureUnit::MM_100TH, util::MeasureUnit::MM_100TH,
SvtSaveOptions::ODFSVER_LATEST_EXTENDED) ),
mnImportFlags( nImportFlags ),
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 );
setTokenHandler( xTokenHandler );
if ( !bIsNSMapsInitialized )
{
initializeNamespaceMaps();
bIsNSMapsInitialized = true;
}
registerNamespaces();
maNamespaceAttrList = new comphelper::AttributeList;
}
void SvXMLImport::cleanup() noexcept
{
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 (!maContexts.empty())
{
if (SvXMLStylesContext* pStylesContext = dynamic_cast<SvXMLStylesContext*>(maContexts.top().get()))
pStylesContext->dispose();
maContexts.pop();
}
if( mxTextImport )
mxTextImport->dispose();
mxTextImport.clear(); // XMLRedlineImportHelper needs model
DisposingModel();
}
SvXMLImport::~SvXMLImport() noexcept
{
cleanup();
}
bool SvXMLImport::addEmbeddedFont(const css::uno::Reference< css::io::XInputStream >& stream,
const OUString& fontName, std::u16string_view extra,
std::vector<unsigned char> const & key, bool eot)
{
if (!mxEmbeddedFontHelper)
mxEmbeddedFontHelper.reset(new EmbeddedFontsHelper);
return mxEmbeddedFontHelper->addEmbeddedFont(stream, fontName, extra, key, eot);
}
namespace
{
class setFastDocumentHandlerGuard
{
private:
css::uno::Reference<css::xml::sax::XFastParser> mxParser;
public:
setFastDocumentHandlerGuard(css::uno::Reference<css::xml::sax::XFastParser> Parser,
const css::uno::Reference<css::xml::sax::XFastDocumentHandler>& Handler)
: mxParser(std::move(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::setCustomEntityNames( const ::css::uno::Sequence< ::css::beans::Pair<::rtl::OUString, ::rtl::OUString> >& replacements )
{
mxParser->setCustomEntityNames( replacements );
}
void SAL_CALL SvXMLImport::startDocument()
{
SAL_INFO( "xmloff.core", "{ SvXMLImport::startDocument" );
if (mxGraphicStorageHandler.is() && mxEmbeddedResolver.is())
return;
Reference< lang::XMultiServiceFactory > xFactory( mxModel, UNO_QUERY );
if( !xFactory.is() )
return;
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.
if (mxTextImport)
mxTextImport->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::Any(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() )
mxFontDecls->dispose();
if( mxStyles.is() )
mxStyles->dispose();
if( mxAutoStyles.is() )
mxAutoStyles->dispose();
if( mxMasterStyles.is() )
mxMasterStyles->dispose();
// 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::optional<SvXMLNamespaceMap> SvXMLImport::processNSAttributes(
std::optional<SvXMLNamespaceMap> & rpNamespaceMap,
SvXMLImport *const pImport, // TODO???
const uno::Reference< xml::sax::XAttributeList >& xAttrList)
{
std::optional<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 (pImport && rAttrName == "office:version" && !pImport->mpImpl->mxODFVersion)
{
pImport->mpImpl->mxODFVersion = xAttrList->getValueByIndex( i );
// the ODF version in content.xml and manifest.xml must be the same starting from ODF1.2
if (pImport->mpImpl->mStreamName == "content.xml"
&& !pImport->IsODFVersionConsistent(*pImport->mpImpl->mxODFVersion))
{
throw xml::sax::SAXException("Inconsistent ODF versions in content.xml and manifest.xml!",
uno::Reference< uno::XInterface >(),
uno::Any(
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(rpNamespaceMap);
rpNamespaceMap.emplace(*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 = rpNamespaceMap->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 = rpNamespaceMap->AddIfKnown( aPrefix, aTestName );
}
// If that namespace is not known, too, add it as unknown
if( XML_NAMESPACE_UNKNOWN == nKey )
rpNamespaceMap->Add( aPrefix, rAttrValue );
}
}
return pRewindMap;
}
void SAL_CALL SvXMLImport::characters( const OUString& rChars )
{
maContexts.top()->characters( rChars );
}
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)
{
SAL_INFO("xmloff.core", "startFastElement " << SvXMLImport::getNameFromToken( Element ));
if ( Attribs.is() && !mpImpl->mxODFVersion)
{
sax_fastparser::FastAttributeList& rAttribList =
sax_fastparser::castToFastAttributeList( Attribs );
auto aIter( rAttribList.find( XML_ELEMENT( OFFICE, XML_VERSION ) ) );
if( aIter != rAttribList.end() )
{
mpImpl->mxODFVersion = 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->mxODFVersion ) )
{
throw xml::sax::SAXException("Inconsistent ODF versions in content.xml and manifest.xml!",
uno::Reference< uno::XInterface >(),
uno::Any(
packages::zip::ZipIOException("Inconsistent ODF versions in content.xml and manifest.xml!" ) ) );
}
}
}
maNamespaceAttrList->Clear();
maNamespaceHandler->addNSDeclAttributes( maNamespaceAttrList );
std::optional<SvXMLNamespaceMap> pRewindMap = processNSAttributes(mxNamespaceMap, this, maNamespaceAttrList);
SvXMLImportContextRef xContext;
const bool bRootContext = maContexts.empty();
if (!maContexts.empty())
{
const SvXMLImportContextRef & pHandler = maContexts.top();
SAL_INFO("xmloff.core", "calling createFastChildContext on " << typeid(*pHandler.get()).name());
auto tmp = pHandler->createFastChildContext( Element, Attribs );
xContext = static_cast<SvXMLImportContext*>(tmp.get());
assert((tmp && xContext) || (!tmp && !xContext));
}
else
xContext.set( CreateFastContext( Element, Attribs ) );
SAL_INFO_IF(!xContext.is(), "xmloff.core", "No fast context for element " << getNameFromToken(Element));
if (bRootContext && !xContext)
{
OUString aName = getNameFromToken(Element);
SetError( XMLERROR_FLAG_SEVERE | XMLERROR_UNKNOWN_ROOT,
{ aName }, "Root element " + aName + " unknown", Reference<xml::sax::XLocator>() );
}
if ( !xContext )
xContext.set( new SvXMLImportContext( *this ) );
// Remember old namespace map.
if( pRewindMap )
xContext->PutRewindMap(std::move(pRewindMap));
// Call a startElement at the new context.
xContext->startFastElement( Element, Attribs );
// Push context on stack.
maContexts.push(xContext);
}
void SAL_CALL SvXMLImport::startUnknownElement (const OUString & rNamespace, const OUString & rName,
const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
{
SAL_INFO("xmloff.core", "startUnknownElement " << rNamespace << " " << rName);
SvXMLImportContextRef xContext;
const bool bRootContext = maContexts.empty();
if (!maContexts.empty())
{
const SvXMLImportContextRef & pHandler = maContexts.top();
SAL_INFO("xmloff.core", "calling createUnknownChildContext on " << typeid(*pHandler.get()).name());
auto tmp = pHandler->createUnknownChildContext( rNamespace, rName, Attribs );
xContext = static_cast<SvXMLImportContext*>(tmp.get());
assert((tmp && xContext) || (!tmp && !xContext));
}
else
xContext.set( CreateFastContext( -1, Attribs ) );
SAL_WARN_IF(!xContext.is(), "xmloff.core", "No context for unknown-element " << rNamespace << " " << rName);
if (bRootContext && !xContext)
{
SetError( XMLERROR_FLAG_SEVERE | XMLERROR_UNKNOWN_ROOT,
{ rName }, "Root element " + rName + " unknown", Reference<xml::sax::XLocator>() );
}
if (!xContext)
{
if (!maContexts.empty())
// This is pretty weird, but it's what the code did before I simplified it, and some parts of the
// code rely on this behaviour e.g. DocumentBuilderContext
xContext = maContexts.top();
else
xContext = new SvXMLImportContext( *this );
}
xContext->startUnknownElement( rNamespace, rName, Attribs );
maContexts.push(xContext);
}
void SAL_CALL SvXMLImport::endFastElement (sal_Int32 Element)
{
SAL_INFO("xmloff.core", "endFastElement " << SvXMLImport::getNameFromToken( Element ));
if (maContexts.empty())
{
SAL_WARN("xmloff.core", "SvXMLImport::endFastElement: no context left");
assert(false);
return;
}
SvXMLImportContextRef xContext = std::move(maContexts.top());
// Get a namespace map to rewind.
std::optional<SvXMLNamespaceMap> pRewindMap = xContext->TakeRewindMap();
maContexts.pop();
xContext->endFastElement( Element );
// Rewind a namespace map.
if (pRewindMap)
mxNamespaceMap = std::move(pRewindMap);
}
void SAL_CALL SvXMLImport::endUnknownElement (const OUString & rPrefix, const OUString & rLocalName)
{
SAL_INFO("xmloff.core", "endUnknownElement " << rPrefix << " " << rLocalName);
if (maContexts.empty())
{
SAL_WARN("xmloff.core", "SvXMLImport::endUnknownElement: no context left");
assert(false);
return;
}
SvXMLImportContextRef xContext = std::move(maContexts.top());
maContexts.pop();
xContext->endUnknownElement( rPrefix, rLocalName );
}
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;
}
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 = dynamic_cast<StyleMap*>( xIfc.get() );
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);
xInit->initialize( { Any(OUString("IgnoreMissingNSDecl")) });
}
// 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 mpImpl->maSupportedServiceNames;
}
XMLTextImportHelper* SvXMLImport::CreateTextImport()
{
return new XMLTextImportHelper( mxModel, *this );
}
XMLShapeImportHelper* SvXMLImport::CreateShapeImport()
{
return new XMLShapeImportHelper( *this, mxModel );
}
SchXMLImportHelper* SvXMLImport::CreateChartImport()
{
// WASM_CHART change
// TODO: Instead of importing the ChartModel an alternative may be
// added to convert not to Chart/OLE SdrObejct, but to GraphicObject
// with the Chart visualization. There should be a preview available
// in the imported chart data
#if !ENABLE_WASM_STRIP_CHART
return new SchXMLImportHelper();
#else
return nullptr;
#endif
}
::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( std::u16string_view 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!
size_t nLen = rURL.size();
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
size_t 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,
std::u16string_view rClassId )
{
OUString sRet;
if( IsPackageURL( rURL ) )
{
if ( mxEmbeddedResolver.is() )
{
OUString sURL( rURL );
if( !rClassId.empty() )
{
sURL += OUString::Concat("!") + 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< css::lang::XTypeProvider *>( 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())
mxFontDecls->dispose();
mxFontDecls = pFontDecls;
}
void SvXMLImport::SetStyles( SvXMLStylesContext *pStyles )
{
if (mxStyles.is())
mxStyles->dispose();
mxStyles = pStyles;
}
void SvXMLImport::SetAutoStyles( SvXMLStylesContext *pAutoStyles )
{
if (pAutoStyles && mxNumberStyles.is())
{
uno::Reference<xml::sax::XFastAttributeList> xAttrList = new sax_fastparser::FastAttributeList(nullptr);
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, name, xAttrList, nKey,
GetDataStylesImport()->GetLanguageForKey(nKey), *pAutoStyles);
pAutoStyles->AddStyle(*pContext);
}
}
}
if (mxAutoStyles.is())
mxAutoStyles->dispose();
mxAutoStyles = pAutoStyles;
GetTextImport()->SetAutoStyles( pAutoStyles );
GetShapeImport()->SetAutoStylesContext( pAutoStyles );
#if !ENABLE_WASM_STRIP_CHART
GetChartImport()->SetAutoStylesContext( pAutoStyles );
#endif
GetFormImport()->setAutoStyleContext( pAutoStyles );
}
void SvXMLImport::SetMasterStyles( SvXMLStylesContext *pMasterStyles )
{
if (mxMasterStyles.is())
mxMasterStyles->dispose();
mxMasterStyles = pMasterStyles;
}
XMLFontStylesContext *SvXMLImport::GetFontDecls()
{
return mxFontDecls.get();
}
SvXMLStylesContext *SvXMLImport::GetStyles()
{
return mxStyles.get();
}
SvXMLStylesContext *SvXMLImport::GetAutoStyles()
{
return mxAutoStyles.get();
}
const XMLFontStylesContext *SvXMLImport::GetFontDecls() const
{
return mxFontDecls.get();
}
const SvXMLStylesContext *SvXMLImport::GetStyles() const
{
return mxStyles.get();
}
const SvXMLStylesContext *SvXMLImport::GetAutoStyles() const
{
return 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 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());
if (!xStor.is())
return bResult;
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::Any( 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( u"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( u"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,
const OUString& rMsg1)
{
Sequence<OUString> aSeq { rMsg1 };
SetError( nId, aSeq );
}
void SvXMLImport::DisposingModel()
{
if( mxFontDecls.is() )
mxFontDecls->dispose();
if( mxStyles.is() )
mxStyles->dispose();
if( mxAutoStyles.is() )
mxAutoStyles->dispose();
if( mxMasterStyles.is() )
mxMasterStyles->dispose();
mxModel.clear();
mxEventListener.clear();
}
::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 = o3tl::toInt32(aBuildId.subView( 0, nIndex ));
sal_Int32 nIndexEnd = aBuildId.indexOf(';', nIndex);
rBuild = (nIndexEnd == -1)
? o3tl::toInt32(aBuildId.subView(nIndex + 1))
: o3tl::toInt32(aBuildId.subView(nIndex + 1, nIndexEnd - nIndex - 1));
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 SvXMLImport::GetODFVersion() const
{
return mpImpl->mxODFVersion ? *mpImpl->mxODFVersion : OUString();
}
bool SvXMLImport::IsOOoXML() const
{
return mpImpl->mbIsOOoXML;
}
bool SvXMLImport::IsMSO() const
{
if (!mpImpl->mbIsMSO.has_value())
{
uno::Reference<document::XDocumentPropertiesSupplier> xSupplier(GetModel(), uno::UNO_QUERY);
if (xSupplier.is())
{
uno::Reference<document::XDocumentProperties> xProps
= xSupplier->getDocumentProperties();
if (xProps.is())
{
mpImpl->mbIsMSO = xProps->getGenerator().startsWith("MicrosoftOffice");
}
}
}
return mpImpl->mbIsMSO.has_value() ? *mpImpl->mbIsMSO : false;
}
// xml:id for RDF metadata
void SvXMLImport::SetXmlId(uno::Reference<uno::XInterface> const & i_xIfc,
OUString const & i_rXmlId)
{
if (i_rXmlId.isEmpty())
return;
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( m_embeddedFontUrlsKnown.count( url ) != 0 )
return true;
m_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();
}
sal_Int32 SvXMLImport::getTokenFromName( std::u16string_view rName )
{
Sequence< sal_Int8 > aLocalNameSeq( reinterpret_cast<sal_Int8 const *>(
OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr()), rName.size() );
return xTokenHandler->getTokenFromUTF8( aLocalNameSeq );
}
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_XML, XML_XML, XML_N_XML ); // implicit "xml" namespace prefix
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)
{
const OUString& rPrefix = aNamespaceDefine.m_aPrefix;
const OUString& rNamespaceURI = aNamespaceDefine.m_aNamespaceURI;
OUString sDecl;
if ( rPrefix.isEmpty() )
sDecl = "xmlns";
else
sDecl = "xmlns:" + rPrefix;
rAttrList->AddAttribute( sDecl, 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( NamespaceDefine(
SvXMLImport::getNamespacePrefixFromURI( rNamespaceURI ), rNamespaceURI) );
m_aNamespaceDefines.push_back( NamespaceDefine(
rNamespacePrefix, rNamespaceURI) );
}
OUString SvXMLImportFastNamespaceHandler::getNamespaceURI( const OUString&/* rNamespacePrefix */ )
{
return OUString();
}
SvXMLLegacyToFastDocHandler::SvXMLLegacyToFastDocHandler( rtl::Reference< SvXMLImport > xImport )
: mrImport(std::move( xImport )),
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 )
{
sal_uInt16 nDefaultNamespace = XML_NAMESPACE_UNKNOWN;
if (!maDefaultNamespaces.empty())
nDefaultNamespace = maDefaultNamespaces.top();
SvXMLImport::processNSAttributes(mrImport->mxNamespaceMap, mrImport.get(), xAttrList);
OUString aLocalName;
sal_uInt16 nPrefix = mrImport->mxNamespaceMap->GetKeyByAttrName( rName, &aLocalName );
sal_Int32 mnElement = NAMESPACE_TOKEN( nPrefix ) | SvXMLImport::getTokenFromName( aLocalName );
mxFastAttributes->clear();
sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
for( sal_Int16 i=0; i < nAttrCount; i++ )
{
const OUString& rAttrName = xAttrList->getNameByIndex( i );
const OUString& rAttrValue = xAttrList->getValueByIndex( i );
if (rAttrName == "xmlns")
{
sal_uInt16 nNamespaceKey = mrImport->mxNamespaceMap->GetKeyByName(rAttrValue);
if (nNamespaceKey != XML_NAMESPACE_UNKNOWN)
{
nDefaultNamespace = nNamespaceKey;
continue;
}
assert(false && "unknown namespace");
}
else if (rAttrName.indexOf(":") == -1 && nDefaultNamespace != XML_NAMESPACE_UNKNOWN)
{
auto const nToken = SvXMLImport::getTokenFromName(rAttrName);
if (nToken == xmloff::XML_TOKEN_INVALID)
{
mxFastAttributes->addUnknown(mrImport->mxNamespaceMap->GetNameByKey(nDefaultNamespace),
OUStringToOString(rAttrName, RTL_TEXTENCODING_UTF8),
OUStringToOString(rAttrValue, RTL_TEXTENCODING_UTF8));
}
else
{
sal_Int32 const nAttr = NAMESPACE_TOKEN(nDefaultNamespace) | nToken;
mxFastAttributes->add(nAttr, OUStringToOString(rAttrValue, RTL_TEXTENCODING_UTF8));
}
continue;
}
OUString aLocalAttrName;
OUString aNamespace;
// don't add unknown namespaces to the map
sal_uInt16 const nAttrPrefix = mrImport->mxNamespaceMap->GetKeyByQName(
rAttrName, nullptr, &aLocalAttrName, &aNamespace, SvXMLNamespaceMap::QNameMode::AttrValue);
if( XML_NAMESPACE_XMLNS == nAttrPrefix )
continue; // ignore
auto const nToken = SvXMLImport::getTokenFromName(aLocalAttrName);
if (XML_NAMESPACE_UNKNOWN == nAttrPrefix || 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));
}
}
mrImport->startFastElement( mnElement, mxFastAttributes );
maDefaultNamespaces.push(nDefaultNamespace);
}
void SAL_CALL SvXMLLegacyToFastDocHandler::endElement( const OUString& rName )
{
OUString aLocalName;
sal_uInt16 nPrefix = mrImport->mxNamespaceMap->GetKeyByAttrName( rName, &aLocalName );
sal_Int32 mnElement = NAMESPACE_TOKEN( nPrefix ) | SvXMLImport::getTokenFromName(aLocalName);
mrImport->endFastElement( mnElement );
maDefaultNamespaces.pop();
}
void SAL_CALL SvXMLLegacyToFastDocHandler::characters( const OUString& aChars )
{
mrImport->characters( aChars );
}
void SAL_CALL SvXMLLegacyToFastDocHandler::ignorableWhitespace( const OUString& )
{
}
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: */