/* -*- 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 <sal/config.h>
#include <sal/log.hxx>
#include <mutex>
#include <stack>
#include <optional>
#include <utility>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <tools/urlobj.hxx>
#include <vcl/graph.hxx>
#include <comphelper/genericpropertyset.hxx>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
#include <com/sun/star/util/MeasureUnit.hpp>
#include <i18nlangtag/languagetag.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertysetinfo.hxx>
#include <comphelper/propertyvalue.hxx>
#include <xmloff/namespacemap.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmlnumfe.hxx>
#include <xmloff/xmlmetae.hxx>
#include <xmloff/XMLSettingsExportContext.hxx>
#include <xmloff/XMLEventExport.hxx>
#include <xmloff/ProgressBarHelper.hxx>
#include <XMLStarBasicExportHandler.hxx>
#include <XMLScriptExportHandler.hxx>
#include <xmloff/SettingsExportHelper.hxx>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/document/XViewDataSupplier.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/frame/XModule.hpp>
#include <xmloff/GradientStyle.hxx>
#include <xmloff/HatchStyle.hxx>
#include <xmloff/ImageStyle.hxx>
#include <TransGradientStyle.hxx>
#include <xmloff/MarkerStyle.hxx>
#include <xmloff/DashStyle.hxx>
#include <xmloff/XMLFontAutoStylePool.hxx>
#include <XMLImageMapExport.hxx>
#include <XMLBase64Export.hxx>
#include <xmloff/xmlerror.hxx>
#include <com/sun/star/style/XStyle.hpp>
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <xmloff/XMLFilterServiceNames.h>
#include <XMLEmbeddedObjectExportFilter.hxx>
#include <XMLBasicExportFilter.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/SetFlagContextHelper.hxx>
#include <PropertySetMerger.hxx>
#include <docmodel/theme/Theme.hxx>
#include <o3tl/enumrange.hxx>
#include <sax/tools/converter.hxx>
#include <unotools/docinfohelper.hxx>
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XMLOasisBasicExporter.hpp>
#include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
#include <com/sun/star/document/XGraphicStorageHandler.hpp>
#include <com/sun/star/rdf/XMetadatable.hpp>
#include <RDFaExportHelper.hxx>
#include <comphelper/xmltools.hxx>
#include <comphelper/graphicmimetype.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::io;
using namespace ::xmloff::token;
constexpr OUString XML_MODEL_SERVICE_WRITER = u
"com.sun.star.text.TextDocument" _ustr
;
constexpr OUString XML_MODEL_SERVICE_CALC = u"com.sun.star.sheet.SpreadsheetDocument" _ustr;
constexpr OUString XML_MODEL_SERVICE_DRAW = u"com.sun.star.drawing.DrawingDocument" _ustr;
constexpr OUString XML_MODEL_SERVICE_IMPRESS = u"com.sun.star.presentation.PresentationDocument" _ustr;
constexpr OUString XML_MODEL_SERVICE_MATH = u"com.sun.star.formula.FormulaProperties" _ustr;
constexpr OUString XML_MODEL_SERVICE_CHART = u"com.sun.star.chart.ChartDocument" _ustr;
constexpr OUStringLiteral XML_USEPRETTYPRINTING = u"UsePrettyPrinting" ;
constexpr OUString XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE = u"vnd.sun.star.GraphicObject:" _ustr;
constexpr OUString XML_EMBEDDEDOBJECT_URL_BASE = u"vnd.sun.star.EmbeddedObject:" _ustr;
const std::pair<OUString, OUString> aServiceMap[] = {
{ XML_MODEL_SERVICE_WRITER, XML_EXPORT_FILTER_WRITER },
{ XML_MODEL_SERVICE_CALC, XML_EXPORT_FILTER_CALC },
{ XML_MODEL_SERVICE_IMPRESS, XML_EXPORT_FILTER_IMPRESS }, // Impress supports DrawingDocument,
{ XML_MODEL_SERVICE_DRAW, XML_EXPORT_FILTER_DRAW }, // too, so it must appear before Draw
{ XML_MODEL_SERVICE_MATH, XML_EXPORT_FILTER_MATH },
{ XML_MODEL_SERVICE_CHART, XML_EXPORT_FILTER_CHART },
};
namespace {
class SettingsExportFacade : public ::xmloff::XMLSettingsExportContext
{
public :
explicit SettingsExportFacade( SvXMLExport& i_rExport )
:m_rExport( i_rExport )
{
}
virtual ~SettingsExportFacade()
{
}
virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName,
const OUString& i_rValue ) override;
virtual void AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName,
enum ::xmloff::token::XMLTokenEnum i_eValue ) override;
virtual void StartElement( enum ::xmloff::token::XMLTokenEnum i_eName ) override;
virtual void EndElement( const bool i_bIgnoreWhitespace ) override;
virtual void Characters( const OUString& i_rCharacters ) override;
virtual css::uno::Reference< css::uno::XComponentContext >
GetComponentContext() const override;
private :
SvXMLExport& m_rExport;
::std::stack< OUString > m_aElements;
};
}
void SettingsExportFacade::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const OUString& i_rValue )
{
m_rExport.AddAttribute( XML_NAMESPACE_CONFIG, i_eName, i_rValue );
}
void SettingsExportFacade::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue )
{
m_rExport.AddAttribute( XML_NAMESPACE_CONFIG, i_eName, i_eValue );
}
void SettingsExportFacade::StartElement( enum ::xmloff::token::XMLTokenEnum i_eName )
{
const OUString sElementName( m_rExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_CONFIG, GetXMLToken( i_eName ) ) );
m_rExport.StartElement( sElementName, true /*i_bIgnoreWhitespace*/ );
m_aElements.push( sElementName );
}
void SettingsExportFacade::EndElement( const bool i_bIgnoreWhitespace )
{
const OUString sElementName( m_aElements.top() );
m_rExport.EndElement( sElementName, i_bIgnoreWhitespace );
m_aElements.pop();
}
void SettingsExportFacade::Characters( const OUString& i_rCharacters )
{
m_rExport.GetDocHandler()->characters( i_rCharacters );
}
Reference< XComponentContext > SettingsExportFacade::GetComponentContext() const
{
return m_rExport.getComponentContext();
}
namespace {
class SvXMLExportEventListener : public cppu::WeakImplHelper<
css::lang::XEventListener >
{
private :
SvXMLExport* pExport;
public :
explicit SvXMLExportEventListener(SvXMLExport* pExport);
// XEventListener
virtual void SAL_CALL disposing(const lang::EventObject& rEventObject) override;
};
}
SvXMLExportEventListener::SvXMLExportEventListener(SvXMLExport* pTempExport)
: pExport(pTempExport)
{
}
// XEventListener
void SAL_CALL SvXMLExportEventListener::disposing( const lang::EventObject& )
{
if (pExport)
{
pExport->DisposingModel();
pExport = nullptr;
}
}
class SvXMLExport_Impl
{
public :
SvXMLExport_Impl();
::comphelper::UnoInterfaceToUniqueIdentifierMapper maInterfaceToIdentifierMapper;
uno::Reference< uri::XUriReferenceFactory > mxUriReferenceFactory;
OUString msPackageURI;
OUString msPackageURIScheme;
// Written OpenDocument file format doesn't fit to the created text document (#i69627#)
bool mbOutlineStyleAsNormalListStyle;
uno::Reference< embed::XStorage > mxTargetStorage;
std::optional<SvtSaveOptions::ODFSaneDefaultVersion> m_oODFVersion;
/// name of stream in package, e.g., "content.xml"
OUString mStreamName;
OUString maSrcShellID;
OUString maDestShellID;
/// stack of backed up namespace maps
/// long: depth at which namespace map has been backed up into the stack
::std::stack< ::std::pair< std::unique_ptr<SvXMLNamespaceMap>, tools::Long > > mNamespaceMaps;
/// counts depth (number of open elements/start tags)
tools::Long mDepth;
::std::unique_ptr< ::xmloff::RDFaExportHelper> mpRDFaHelper;
bool mbExportTextNumberElement;
bool mbNullDateInitialized;
void SetSchemeOf( std::u16string_view rOrigFileName )
{
size_t nSep = rOrigFileName.find(':' );
if ( nSep != std::u16string_view::npos )
msPackageURIScheme = rOrigFileName.substr( 0, nSep );
}
};
SvXMLExport_Impl::SvXMLExport_Impl()
: mxUriReferenceFactory( uri::UriReferenceFactory::create(comphelper::getProcessComponentContext()) ),
// Written OpenDocument file format doesn't fit to the created text document (#i69627#)
mbOutlineStyleAsNormalListStyle( false ),
mDepth( 0 ),
mbExportTextNumberElement( false ),
mbNullDateInitialized( false )
{
}
void SvXMLExport::SetDocHandler( const uno::Reference< xml::sax::XDocumentHandler > &rHandler )
{
mxHandler = rHandler;
mxExtHandler.set( mxHandler, UNO_QUERY );
}
void SvXMLExport::InitCtor_()
{
// note: it is not necessary to add XML_NP_XML (it is declared implicitly)
if ( getExportFlags() & ~SvXMLExportFlags::OASIS )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
mpNamespaceMap->Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
}
if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
}
if ( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::SETTINGS) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
}
if ( getExportFlags() & SvXMLExportFlags::SETTINGS )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_CONFIG), GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
}
if ( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
mpNamespaceMap->Add( GetXMLToken(XML_NP_META), GetXMLToken(XML_N_META), XML_NAMESPACE_META );
}
if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::FONTDECLS) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
}
// namespaces for documents
if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
mpNamespaceMap->Add( GetXMLToken(XML_NP_TEXT), GetXMLToken(XML_N_TEXT), XML_NAMESPACE_TEXT );
mpNamespaceMap->Add( GetXMLToken(XML_NP_DRAW), GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
mpNamespaceMap->Add( GetXMLToken(XML_NP_DR3D), GetXMLToken(XML_N_DR3D), XML_NAMESPACE_DR3D );
mpNamespaceMap->Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG_COMPAT), XML_NAMESPACE_SVG );
mpNamespaceMap->Add( GetXMLToken(XML_NP_CHART), GetXMLToken(XML_N_CHART), XML_NAMESPACE_CHART );
mpNamespaceMap->Add( GetXMLToken(XML_NP_RPT), GetXMLToken(XML_N_RPT), XML_NAMESPACE_REPORT );
mpNamespaceMap->Add( GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE), XML_NAMESPACE_TABLE );
mpNamespaceMap->Add( GetXMLToken(XML_NP_NUMBER),GetXMLToken(XML_N_NUMBER), XML_NAMESPACE_NUMBER );
mpNamespaceMap->Add( GetXMLToken(XML_NP_OOOW), GetXMLToken(XML_N_OOOW), XML_NAMESPACE_OOOW );
mpNamespaceMap->Add( GetXMLToken(XML_NP_OOOC), GetXMLToken(XML_N_OOOC), XML_NAMESPACE_OOOC );
mpNamespaceMap->Add( GetXMLToken(XML_NP_OF), GetXMLToken(XML_N_OF), XML_NAMESPACE_OF );
if (getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
{
mpNamespaceMap->Add(
GetXMLToken(XML_NP_TABLE_EXT), GetXMLToken(XML_N_TABLE_EXT), XML_NAMESPACE_TABLE_EXT);
mpNamespaceMap->Add(
GetXMLToken(XML_NP_CALC_EXT), GetXMLToken(XML_N_CALC_EXT), XML_NAMESPACE_CALC_EXT);
mpNamespaceMap->Add(
GetXMLToken(XML_NP_DRAW_EXT), GetXMLToken(XML_N_DRAW_EXT), XML_NAMESPACE_DRAW_EXT);
mpNamespaceMap->Add(
GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT),
XML_NAMESPACE_LO_EXT);
mpNamespaceMap->Add( GetXMLToken(XML_NP_FIELD), GetXMLToken(XML_N_FIELD), XML_NAMESPACE_FIELD );
}
}
if ( getExportFlags() & (SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_MATH), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
mpNamespaceMap->Add( GetXMLToken(XML_NP_FORM), GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM );
}
if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_SCRIPT), GetXMLToken(XML_N_SCRIPT), XML_NAMESPACE_SCRIPT );
mpNamespaceMap->Add( GetXMLToken(XML_NP_DOM), GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM );
}
if ( getExportFlags() & SvXMLExportFlags::CONTENT )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_XFORMS_1_0), GetXMLToken(XML_N_XFORMS_1_0), XML_NAMESPACE_XFORMS );
mpNamespaceMap->Add( GetXMLToken(XML_NP_XSD), GetXMLToken(XML_N_XSD), XML_NAMESPACE_XSD );
mpNamespaceMap->Add( GetXMLToken(XML_NP_XSI), GetXMLToken(XML_N_XSI), XML_NAMESPACE_XSI );
mpNamespaceMap->Add( GetXMLToken(XML_NP_FORMX), GetXMLToken(XML_N_FORMX), XML_NAMESPACE_FORMX );
}
// RDFa: needed for content and header/footer styles
if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_XHTML),
GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
}
// GRDDL: to convert RDFa and meta.xml to RDF
if ( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
{
mpNamespaceMap->Add( GetXMLToken(XML_NP_GRDDL),
GetXMLToken(XML_N_GRDDL), XML_NAMESPACE_GRDDL );
}
// CSS Text Level 3 for distributed text justification.
if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES) )
{
mpNamespaceMap->Add(
GetXMLToken(XML_NP_CSS3TEXT), GetXMLToken(XML_N_CSS3TEXT), XML_NAMESPACE_CSS3TEXT );
}
if (mxModel.is() && !mxEventListener.is())
{
mxEventListener.set( new SvXMLExportEventListener(this ));
mxModel->addEventListener(mxEventListener);
}
// Determine model type (#i51726#)
DetermineModelType_();
}
// Shapes in Writer cannot be named via context menu (#i51726#)
void SvXMLExport::DetermineModelType_()
{
meModelType = SvtModuleOptions::EFactory::UNKNOWN_FACTORY;
if ( !mxModel.is() )
return ;
meModelType = SvtModuleOptions::ClassifyFactoryByModel( mxModel );
// note: MATH documents will throw NotInitializedException; maybe unit test problem
if (meModelType == SvtModuleOptions::EFactory::WRITER)
{
uno::Reference<frame::XModule> const xModule(mxModel, uno::UNO_QUERY);
bool const isBaseForm(xModule.is() &&
xModule->getIdentifier() == "com.sun.star.sdb.FormDesign" );
if (isBaseForm)
{
switch (GetODFSaneDefaultVersion())
{
case SvtSaveOptions::ODFSVER_013_EXTENDED:
SAL_INFO("xmloff.core" , "tdf#138209 force form export to ODF 1.2" );
mpImpl->m_oODFVersion = SvtSaveOptions::ODFSVER_012_EXTENDED;
maUnitConv.overrideSaneDefaultVersion(SvtSaveOptions::ODFSVER_012_EXTENDED);
break ;
case SvtSaveOptions::ODFSVER_013:
SAL_INFO("xmloff.core" , "tdf#138209 force form export to ODF 1.2" );
mpImpl->m_oODFVersion = SvtSaveOptions::ODFSVER_012;
maUnitConv.overrideSaneDefaultVersion(SvtSaveOptions::ODFSVER_012);
break ;
default :
break ;
}
}
}
}
SvXMLExport::SvXMLExport(
const uno::Reference< uno::XComponentContext >& xContext,
OUString implementationName,
sal_Int16 const eDefaultMeasureUnit /*css::util::MeasureUnit*/,
const enum XMLTokenEnum eClass, SvXMLExportFlags nExportFlags )
: mpImpl( new SvXMLExport_Impl ),
m_xContext(xContext), m_implementationName(std::move(implementationName)),
mxAttrList( new comphelper::AttributeList ),
mpNamespaceMap( new SvXMLNamespaceMap ),
mpAuthorIDs( new SvtSecurityMapPersonalInfo ),
maUnitConv(xContext, util::MeasureUnit::MM_100TH, eDefaultMeasureUnit, getSaneDefaultVersion()),
meClass( eClass ),
mnExportFlags( nExportFlags ),
mnErrorFlags( SvXMLErrorFlags::NO ),
msWS( GetXMLToken(XML_WS) ),
mbSaveLinkedSections(true ),
mbAutoStylesCollected(false )
{
SAL_WARN_IF( !xContext.is(), "xmloff.core" , "got no service manager" );
InitCtor_();
}
SvXMLExport::SvXMLExport(
const css::uno::Reference< css::uno::XComponentContext >& xContext,
OUString implementationName,
OUString fileName,
sal_Int16 const eDefaultMeasureUnit /*css::util::MeasureUnit*/,
const uno::Reference< xml::sax::XDocumentHandler > & rHandler)
: mpImpl( new SvXMLExport_Impl ),
m_xContext(xContext), m_implementationName(std::move(implementationName)),
mxHandler( rHandler ),
mxExtHandler( rHandler, uno::UNO_QUERY ),
mxAttrList( new comphelper::AttributeList ),
msOrigFileName(std::move( fileName )),
mpNamespaceMap( new SvXMLNamespaceMap ),
mpAuthorIDs( new SvtSecurityMapPersonalInfo ),
maUnitConv(xContext, util::MeasureUnit::MM_100TH, eDefaultMeasureUnit, getSaneDefaultVersion()),
meClass( XML_TOKEN_INVALID ),
mnExportFlags( SvXMLExportFlags::NONE ),
mnErrorFlags( SvXMLErrorFlags::NO ),
msWS( GetXMLToken(XML_WS) ),
mbSaveLinkedSections(true ),
mbAutoStylesCollected(false )
{
SAL_WARN_IF( !xContext.is(), "xmloff.core" , "got no service manager" );
mpImpl->SetSchemeOf( msOrigFileName );
InitCtor_();
if (mxNumberFormatsSupplier.is())
mpNumExport.reset( new SvXMLNumFmtExport(*this , mxNumberFormatsSupplier) );
}
SvXMLExport::SvXMLExport(
const css::uno::Reference< css::uno::XComponentContext >& xContext,
OUString implementationName,
OUString fileName,
const uno::Reference< xml::sax::XDocumentHandler > & rHandler,
const Reference< XModel >& rModel,
FieldUnit const eDefaultFieldUnit,
SvXMLExportFlags nExportFlag)
: mpImpl( new SvXMLExport_Impl ),
m_xContext(xContext), m_implementationName(std::move(implementationName)),
mxModel( rModel ),
mxHandler( rHandler ),
mxExtHandler( rHandler, uno::UNO_QUERY ),
mxNumberFormatsSupplier (rModel, uno::UNO_QUERY),
mxAttrList( new comphelper::AttributeList ),
msOrigFileName(std::move( fileName )),
mpNamespaceMap( new SvXMLNamespaceMap ),
mpAuthorIDs( new SvtSecurityMapPersonalInfo ),
maUnitConv( xContext,
util::MeasureUnit::MM_100TH,
SvXMLUnitConverter::GetMeasureUnit(eDefaultFieldUnit),
getSaneDefaultVersion()),
meClass( XML_TOKEN_INVALID ),
mnExportFlags( nExportFlag ),
mnErrorFlags( SvXMLErrorFlags::NO ),
msWS( GetXMLToken(XML_WS) ),
mbSaveLinkedSections(true ),
mbAutoStylesCollected(false )
{
SAL_WARN_IF(!xContext.is(), "xmloff.core" , "got no service manager" );
mpImpl->SetSchemeOf( msOrigFileName );
InitCtor_();
if (mxNumberFormatsSupplier.is())
mpNumExport.reset( new SvXMLNumFmtExport(*this , mxNumberFormatsSupplier) );
}
SvXMLExport::~SvXMLExport()
{
mpXMLErrors.reset();
mpImageMapExport.reset();
mpEventExport.reset();
mpNamespaceMap.reset();
if (mpProgressBarHelper || mpNumExport)
{
if (mxExportInfo.is())
{
uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
if (xPropertySetInfo.is())
{
if (mpProgressBarHelper)
{
static constexpr OUString sProgressMax(XML_PROGRESSMAX);
static constexpr OUString sProgressCurrent(XML_PROGRESSCURRENT);
static constexpr OUString sRepeat(XML_PROGRESSREPEAT);
if (xPropertySetInfo->hasPropertyByName(sProgressMax) &&
xPropertySetInfo->hasPropertyByName(sProgressCurrent))
{
sal_Int32 nProgressMax(mpProgressBarHelper->GetReference());
sal_Int32 nProgressCurrent(mpProgressBarHelper->GetValue());
mxExportInfo->setPropertyValue(sProgressMax, uno::Any(nProgressMax));
mxExportInfo->setPropertyValue(sProgressCurrent, uno::Any(nProgressCurrent));
}
if (xPropertySetInfo->hasPropertyByName(sRepeat))
mxExportInfo->setPropertyValue(sRepeat, css::uno::Any(mpProgressBarHelper->GetRepeat()));
}
if (mpNumExport && (mnExportFlags & (SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::STYLES)))
{
static constexpr OUString sWrittenNumberFormats(XML_WRITTENNUMBERSTYLES);
if (xPropertySetInfo->hasPropertyByName(sWrittenNumberFormats))
{
mxExportInfo->setPropertyValue(sWrittenNumberFormats, Any(mpNumExport->GetWasUsed()));
}
}
}
}
mpProgressBarHelper.reset();
mpNumExport.reset();
}
if (mxEventListener.is() && mxModel.is())
mxModel->removeEventListener(mxEventListener);
}
// XExporter
void SAL_CALL SvXMLExport::setSourceDocument( const uno::Reference< lang::XComponent >& xDoc )
{
mxModel.set( xDoc, UNO_QUERY );
if ( !mxModel.is() )
throw lang::IllegalArgumentException();
if (mxModel.is() && ! mxEventListener.is())
{
mxEventListener.set( new SvXMLExportEventListener(this ));
mxModel->addEventListener(mxEventListener);
}
if (!mxNumberFormatsSupplier.is() )
{
mxNumberFormatsSupplier.set(mxModel, css::uno::UNO_QUERY);
if (mxNumberFormatsSupplier.is() && mxHandler.is())
mpNumExport.reset( new SvXMLNumFmtExport(*this , mxNumberFormatsSupplier) );
}
if (mxExportInfo.is())
{
uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
if (xPropertySetInfo.is())
{
OUString sUsePrettyPrinting(XML_USEPRETTYPRINTING);
if (xPropertySetInfo->hasPropertyByName(sUsePrettyPrinting))
{
uno::Any aAny = mxExportInfo->getPropertyValue(sUsePrettyPrinting);
if (::cppu::any2bool(aAny))
mnExportFlags |= SvXMLExportFlags::PRETTY;
else
mnExportFlags &= ~SvXMLExportFlags::PRETTY;
}
if (mpNumExport && (mnExportFlags & (SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::STYLES)))
{
OUString sWrittenNumberFormats(XML_WRITTENNUMBERSTYLES);
if (xPropertySetInfo->hasPropertyByName(sWrittenNumberFormats))
{
uno::Any aAny = mxExportInfo->getPropertyValue(sWrittenNumberFormats);
uno::Sequence<sal_Int32> aWasUsed;
if (aAny >>= aWasUsed)
mpNumExport->SetWasUsed(aWasUsed);
}
}
}
}
// namespaces for user defined attributes
Reference< XMultiServiceFactory > xFactory( mxModel, UNO_QUERY );
if ( xFactory.is() )
{
try
{
Reference < XInterface > xIfc =
xFactory->createInstance(u"com.sun.star.xml.NamespaceMap" _ustr);
if ( xIfc.is() )
{
Reference< XNameAccess > xNamespaceMap( xIfc, UNO_QUERY );
if ( xNamespaceMap.is() )
{
const Sequence< OUString > aPrefixes( xNamespaceMap->getElementNames() );
for ( OUString const & prefix : aPrefixes )
{
OUString aURL;
if ( xNamespaceMap->getByName( prefix ) >>= aURL )
GetNamespaceMap_().Add( prefix, aURL );
}
}
}
}
catch (const css::uno::Exception&)
{
}
}
// Determine model type (#i51726#)
DetermineModelType_();
}
// XInitialize
void SAL_CALL SvXMLExport::initialize( const uno::Sequence< uno::Any >& aArguments )
{
// #93186# we need to queryInterface every single Any with any expected outcome. This variable hold the queryInterface results.
for ( const auto & rAny : aArguments )
{
Reference<XInterface> xValue;
rAny >>= xValue;
// status indicator
uno::Reference<task::XStatusIndicator> xTmpStatus( xValue, UNO_QUERY );
if ( xTmpStatus.is() )
mxStatusIndicator = std::move(xTmpStatus);
// graphic storage handler
uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler(xValue, UNO_QUERY);
if (xGraphicStorageHandler.is())
mxGraphicStorageHandler = std::move(xGraphicStorageHandler);
// object resolver
uno::Reference<document::XEmbeddedObjectResolver> xTmpObjectResolver(
xValue, UNO_QUERY );
if ( xTmpObjectResolver.is() )
mxEmbeddedResolver = std::move(xTmpObjectResolver);
// document handler
uno::Reference<xml::sax::XDocumentHandler> xTmpDocHandler(
xValue, UNO_QUERY );
if ( xTmpDocHandler.is() )
{
mxHandler = std::move(xTmpDocHandler);
rAny >>= mxExtHandler;
if (mxNumberFormatsSupplier.is() && mpNumExport == nullptr)
mpNumExport.reset( new SvXMLNumFmtExport(*this , mxNumberFormatsSupplier) );
}
// property set to transport data across
uno::Reference<beans::XPropertySet> xTmpPropertySet(
xValue, UNO_QUERY );
if ( xTmpPropertySet.is() )
mxExportInfo = std::move(xTmpPropertySet);
}
if ( !mxExportInfo.is() )
return ;
uno::Reference< beans::XPropertySetInfo > xPropertySetInfo =
mxExportInfo->getPropertySetInfo();
static constexpr OUString sBaseURI = u"BaseURI" _ustr;
if ( xPropertySetInfo->hasPropertyByName(sBaseURI) )
{
uno::Any aAny = mxExportInfo->getPropertyValue(sBaseURI);
aAny >>= msOrigFileName;
mpImpl->msPackageURI = msOrigFileName;
mpImpl->SetSchemeOf( msOrigFileName );
}
OUString sRelPath;
static constexpr OUString sStreamRelPath = u"StreamRelPath" _ustr;
if ( xPropertySetInfo->hasPropertyByName(sStreamRelPath) )
{
uno::Any aAny = mxExportInfo->getPropertyValue(sStreamRelPath);
aAny >>= sRelPath;
}
OUString sName;
static constexpr OUString sStreamName = u"StreamName" _ustr;
if ( xPropertySetInfo->hasPropertyByName(sStreamName) )
{
uno::Any aAny = mxExportInfo->getPropertyValue(sStreamName);
aAny >>= sName;
}
if ( !msOrigFileName.isEmpty() && !sName.isEmpty() )
{
INetURLObject aBaseURL( msOrigFileName );
if ( !sRelPath.isEmpty() )
aBaseURL.insertName( sRelPath );
aBaseURL.insertName( sName );
msOrigFileName = aBaseURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
}
mpImpl->mStreamName = sName; // Note: may be empty (XSLT)
// Written OpenDocument file format doesn't fit to the created text document (#i69627#)
static constexpr OUString sOutlineStyleAsNormalListStyle(
u"OutlineStyleAsNormalListStyle" _ustr );
if ( xPropertySetInfo->hasPropertyByName( sOutlineStyleAsNormalListStyle ) )
{
uno::Any aAny = mxExportInfo->getPropertyValue( sOutlineStyleAsNormalListStyle );
aAny >>= mpImpl->mbOutlineStyleAsNormalListStyle;
}
OUString sTargetStorage( u"TargetStorage" _ustr );
if ( xPropertySetInfo->hasPropertyByName( sTargetStorage ) )
mxExportInfo->getPropertyValue( sTargetStorage ) >>= mpImpl->mxTargetStorage;
static constexpr OUString sExportTextNumberElement(
u"ExportTextNumberElement" _ustr );
if ( xPropertySetInfo->hasPropertyByName( sExportTextNumberElement ) )
{
uno::Any aAny = mxExportInfo->getPropertyValue( sExportTextNumberElement );
aAny >>= mpImpl->mbExportTextNumberElement;
}
}
// XFilter
sal_Bool SAL_CALL SvXMLExport::filter( const uno::Sequence< beans::PropertyValue >& aDescriptor )
{
// check for xHandler first... should have been supplied in initialize
if ( !mxHandler.is() )
return false ;
try
{
const SvXMLExportFlags nTest =
SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SETTINGS;
if ( (mnExportFlags & nTest) == nTest && msOrigFileName.isEmpty() )
{
// evaluate descriptor only for flat files and if a base URI
// has not been provided already
for ( const auto & rProp : aDescriptor )
{
const OUString& rPropName = rProp.Name;
const Any& rValue = rProp.Value;
if ( rPropName == "FileName" )
{
if ( !(rValue >>= msOrigFileName ) )
return false ;
}
else if ( rPropName == "FilterName" )
{
if ( !(rValue >>= msFilterName ) )
return false ;
}
}
}
for ( const auto & rProp : aDescriptor )
{
const OUString& rPropName = rProp.Name;
const Any& rValue = rProp.Value;
if (rPropName == "SourceShellID" )
{
if (!(rValue >>= mpImpl->maSrcShellID))
return false ;
}
else if (rPropName == "DestinationShellID" )
{
if (!(rValue >>= mpImpl->maDestShellID))
return false ;
}
else if ( rPropName == "ImageFilter" )
{
if (!(rValue >>= msImgFilterName))
return false ;
}
}
exportDoc( meClass );
}
catch (const uno::Exception& e)
{
// We must catch exceptions, because according to the
// API definition export must not throw one!
css::uno::Any ex(cppu::getCaughtException());
OUString sMessage( ex.getValueTypeName() + ": \" " + e.Message + " \"" );
if (e.Context.is())
{
const char * pContext = typeid (*e.Context).name();
sMessage += " (context: " + OUString::createFromAscii(pContext) + " )" ;
}
SetError( XMLERROR_FLAG_ERROR | XMLERROR_FLAG_SEVERE | XMLERROR_API,
Sequence<OUString>(), sMessage, nullptr );
}
// return true only if no error occurred
return (mnErrorFlags & (SvXMLErrorFlags::DO_NOTHING|SvXMLErrorFlags::ERROR_OCCURRED)) == SvXMLErrorFlags::NO;
}
void SAL_CALL SvXMLExport::cancel()
{
// stop export
Sequence<OUString> aEmptySeq;
SetError(XMLERROR_CANCEL|XMLERROR_FLAG_SEVERE, aEmptySeq);
}
OUString SAL_CALL SvXMLExport::getName( )
{
return msFilterName;
}
void SAL_CALL SvXMLExport::setName( const OUString& )
{
// do nothing, because it is not possible to set the FilterName
}
// XServiceInfo
OUString SAL_CALL SvXMLExport::getImplementationName( )
{
return m_implementationName;
}
sal_Bool SAL_CALL SvXMLExport::supportsService( const OUString& rServiceName )
{
return cppu::supportsService(this , rServiceName);
}
uno::Sequence< OUString > SAL_CALL SvXMLExport::getSupportedServiceNames( )
{
return { u"com.sun.star.document.ExportFilter" _ustr, u"com.sun.star.xml.XMLExportFilter" _ustr };
}
OUString
SvXMLExport::EnsureNamespace(OUString const & i_rNamespace)
{
static constexpr OUString aPreferredPrefix(u"gen" _ustr);
OUString sPrefix;
sal_uInt16 nKey( GetNamespaceMap_().GetKeyByName( i_rNamespace ) );
if ( XML_NAMESPACE_UNKNOWN == nKey )
{
// There is no prefix for the namespace, so
// we have to generate one and have to add it.
sPrefix = aPreferredPrefix;
nKey = GetNamespaceMap_().GetKeyByPrefix( sPrefix );
sal_Int32 n( 0 );
while ( nKey != USHRT_MAX )
{
sPrefix = aPreferredPrefix + OUString::number(++n);
nKey = GetNamespaceMap_().GetKeyByPrefix( sPrefix );
}
if (mpImpl->mNamespaceMaps.empty()
|| (mpImpl->mNamespaceMaps.top().second != mpImpl->mDepth))
{
// top was created for lower depth... need a new namespace map!
auto pNew = new SvXMLNamespaceMap( *mpNamespaceMap );
mpImpl->mNamespaceMaps.push(
::std::make_pair(std::move(mpNamespaceMap), mpImpl->mDepth) );
mpNamespaceMap.reset( pNew );
}
// add the namespace to the map and as attribute
mpNamespaceMap->Add( sPrefix, i_rNamespace );
AddAttribute( GetXMLToken(XML_XMLNS) + ":" + sPrefix, i_rNamespace );
}
else
{
// If there is a prefix for the namespace, reuse that.
sPrefix = GetNamespaceMap_().GetPrefixByKey( nKey );
}
return sPrefix;
}
void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey, const OUString& rName,
const OUString& rValue )
{
AddAttribute(GetNamespaceMap_().GetQNameByKey(nPrefixKey, rName), rValue);
}
void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey,
enum XMLTokenEnum eName,
const OUString& rValue )
{
AddAttribute(nPrefixKey, GetXMLToken(eName), rValue);
}
void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey,
enum XMLTokenEnum eName,
enum XMLTokenEnum eValue)
{
AddAttribute(nPrefixKey, eName, GetXMLToken(eValue));
}
void SvXMLExport::AddAttribute( const OUString& rQName,
const OUString& rValue )
{
mxAttrList->AddAttribute(
rQName,
rValue );
}
void SvXMLExport::AddAttribute( const OUString& rQName,
enum ::xmloff::token::XMLTokenEnum eValue )
{
AddAttribute(rQName, GetXMLToken(eValue));
}
void SvXMLExport::AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc,
const css::lang::Locale& rLocale, bool bWriteEmpty )
{
if (rLocale.Variant.isEmpty())
{
// Per convention The BCP 47 string is always stored in Variant, if
// that is empty we have a plain language-country combination, no need
// to convert to LanguageTag first. Also catches the case of empty
// locale denoting system locale.
xmloff::token::XMLTokenEnum eLanguage, eCountry;
eLanguage = XML_LANGUAGE;
eCountry = XML_COUNTRY;
if (bWriteEmpty || !rLocale.Language.isEmpty())
AddAttribute( nPrefix, eLanguage, rLocale.Language);
if (bWriteEmpty || !rLocale.Country.isEmpty())
AddAttribute( nPrefix, eCountry, rLocale.Country);
}
else
{
LanguageTag aLanguageTag( rLocale);
AddLanguageTagAttributes( nPrefix, nPrefixRfc, aLanguageTag, bWriteEmpty);
}
}
void SvXMLExport::AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc,
const LanguageTag& rLanguageTag, bool bWriteEmpty )
{
if (rLanguageTag.isIsoODF())
{
if (bWriteEmpty || !rLanguageTag.isSystemLocale())
{
AddAttribute( nPrefix, XML_LANGUAGE, rLanguageTag.getLanguage());
if (rLanguageTag.hasScript() && getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
AddAttribute( nPrefix, XML_SCRIPT, rLanguageTag.getScript());
if (bWriteEmpty || !rLanguageTag.getCountry().isEmpty())
AddAttribute( nPrefix, XML_COUNTRY, rLanguageTag.getCountry());
}
}
else
{
if (getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
AddAttribute( nPrefixRfc, XML_RFC_LANGUAGE_TAG, rLanguageTag.getBcp47());
// Also in case of non-pure-ISO tag store best matching fo: attributes
// for consumers not handling *:rfc-language-tag, ensuring that only
// valid ISO codes are stored. Here the bWriteEmpty parameter has no
// meaning.
OUString aLanguage, aScript, aCountry;
rLanguageTag.getIsoLanguageScriptCountry( aLanguage, aScript, aCountry);
if (!aLanguage.isEmpty())
{
AddAttribute( nPrefix, XML_LANGUAGE, aLanguage);
if (!aScript.isEmpty() && getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
AddAttribute( nPrefix, XML_SCRIPT, aScript);
if (!aCountry.isEmpty())
AddAttribute( nPrefix, XML_COUNTRY, aCountry);
}
}
}
void SvXMLExport::AddAttributeList( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
{
if ( xAttrList.is())
mxAttrList->AppendAttributeList( xAttrList );
}
void SvXMLExport::ClearAttrList()
{
mxAttrList->Clear();
}
#ifdef DBG_UTIL
void SvXMLExport::CheckAttrList()
{
SAL_WARN_IF( mxAttrList->getLength(), "xmloff.core" , "XMLExport::CheckAttrList: list is not empty" );
}
#endif
void SvXMLExport::ImplExportMeta()
{
CheckAttrList();
ExportMeta_();
}
void SvXMLExport::ImplExportSettings()
{
CheckAttrList();
::std::vector< SettingsGroup > aSettings;
sal_Int32 nSettingsCount = 0;
// view settings
uno::Sequence< beans::PropertyValue > aViewSettings;
GetViewSettingsAndViews( aViewSettings );
aSettings.emplace_back( XML_VIEW_SETTINGS, aViewSettings );
nSettingsCount += aViewSettings.getLength();
// configuration settings
uno::Sequence<beans::PropertyValue> aConfigSettings;
GetConfigurationSettings( aConfigSettings );
aSettings.emplace_back( XML_CONFIGURATION_SETTINGS, aConfigSettings );
nSettingsCount += aConfigSettings.getLength();
// any document specific settings
nSettingsCount += GetDocumentSpecificSettings( aSettings );
{
SvXMLElementExport aElem( *this ,
nSettingsCount != 0,
XML_NAMESPACE_OFFICE, XML_SETTINGS,
true , true );
SettingsExportFacade aSettingsExportContext( *this );
XMLSettingsExportHelper aSettingsExportHelper( aSettingsExportContext );
for (auto const & settings : aSettings)
{
if ( !settings.aSettings.hasElements() )
continue ;
const OUString& sSettingsName( GetXMLToken( settings.eGroupName ) );
OUString sQName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OOO, sSettingsName );
aSettingsExportHelper.exportAllSettings( settings.aSettings, sQName );
}
}
}
void SvXMLExport::ImplExportStyles()
{
CheckAttrList();
{
// <style:styles>
SvXMLElementExport aElem( *this , XML_NAMESPACE_OFFICE, XML_STYLES,
true , true );
ExportStyles_( false );
}
// transfer style names (+ families) TO other components (if appropriate)
if ( ( mnExportFlags & SvXMLExportFlags::CONTENT ) || !mxExportInfo.is() )
return ;
static constexpr OUString sStyleNames( u"StyleNames" _ustr );
static constexpr OUString sStyleFamilies( u"StyleFamilies" _ustr );
uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
if ( xPropertySetInfo->hasPropertyByName( sStyleNames ) && xPropertySetInfo->hasPropertyByName( sStyleFamilies ) )
{
Sequence<sal_Int32> aStyleFamilies;
Sequence<OUString> aStyleNames;
mxAutoStylePool->GetRegisteredNames( aStyleFamilies, aStyleNames );
mxExportInfo->setPropertyValue( sStyleNames, Any( aStyleNames ) );
mxExportInfo->setPropertyValue( sStyleFamilies,
Any( aStyleFamilies ) );
}
}
void SvXMLExport::ImplExportAutoStyles()
{
// transfer style names (+ families) FROM other components (if appropriate)
OUString sStyleNames( u"StyleNames" _ustr );
OUString sStyleFamilies( u"StyleFamilies" _ustr );
if ( ( !( mnExportFlags & SvXMLExportFlags::STYLES ) )
&& mxExportInfo.is()
&& mxExportInfo->getPropertySetInfo()->hasPropertyByName( sStyleNames )
&& mxExportInfo->getPropertySetInfo()->hasPropertyByName( sStyleFamilies ) )
{
Sequence<sal_Int32> aStyleFamilies;
mxExportInfo->getPropertyValue( sStyleFamilies ) >>= aStyleFamilies;
Sequence<OUString> aStyleNames;
mxExportInfo->getPropertyValue( sStyleNames ) >>= aStyleNames;
mxAutoStylePool->RegisterNames( aStyleFamilies, aStyleNames );
}
{
// <style:automatic-styles>
SvXMLElementExport aElem( *this , XML_NAMESPACE_OFFICE,
XML_AUTOMATIC_STYLES, true , true );
ExportAutoStyles_();
}
}
void SvXMLExport::ImplExportMasterStyles()
{
// <style:master-styles>
SvXMLElementExport aElem( *this , XML_NAMESPACE_OFFICE, XML_MASTER_STYLES,
true , true );
ExportMasterStyles_();
}
void SvXMLExport::ImplExportContent()
{
CheckAttrList();
{
SvXMLElementExport aElement( *this , XML_NAMESPACE_OFFICE, XML_BODY,
true , true );
{
XMLTokenEnum eClass = meClass;
if ( XML_TEXT_GLOBAL == eClass )
{
AddAttribute( XML_NAMESPACE_TEXT, XML_GLOBAL,
GetXMLToken( XML_TRUE ) );
eClass = XML_TEXT;
}
if ( XML_GRAPHICS == eClass )
eClass = XML_DRAWING;
// <office:body ...>
SetBodyAttributes();
SvXMLElementExport aElem( *this , meClass != XML_TOKEN_INVALID,
XML_NAMESPACE_OFFICE, eClass,
true , true );
ExportContent_();
}
}
}
void SvXMLExport::SetBodyAttributes()
{
}
static void
lcl_AddGrddl(SvXMLExport const & rExport, const SvXMLExportFlags /*nExportMode*/)
{
// check version >= 1.2
switch (rExport.getSaneDefaultVersion()) {
case SvtSaveOptions::ODFSVER_011: // fall through
case SvtSaveOptions::ODFSVER_010: return ;
default : break ;
}
// #i115030#: disabled, the XSLT is not finished, and not available via HTTP
#if 0
if (SvXMLExportFlags::SETTINGS != nExportMode) // meta, content, styles
{
rExport.AddAttribute( XML_NAMESPACE_GRDDL, XML_TRANSFORMATION,
OUString("http://FIXME ") );
}
#endif
}
// note: the point of this is presumably to mitigate SHA/1k info leak of plain text
void SvXMLExport::addChaffWhenEncryptedStorage()
{
uno::Reference<embed::XEncryptionProtectedStorage> const xEncr(mpImpl->mxTargetStorage, uno::UNO_QUERY);
if (xEncr.is() && xEncr->hasEncryptionData() && mxExtHandler.is())
{
uno::Sequence<beans::NamedValue> const algo(xEncr->getEncryptionAlgorithms());
for (auto const & it : algo)
{
if (it.Name == "ChecksumAlgorithm" )
{
if (!it.Value.hasValue())
{
return ; // no checksum => no chaff
}
break ;
}
}
mxExtHandler->comment(OStringToOUString(comphelper::xml::makeXMLChaff(), RTL_TEXTENCODING_ASCII_US));
}
}
auto SvXMLExport::GetODFVersionAttributeValue() const -> char const *
{
char const * pVersion(nullptr);
switch (getSaneDefaultVersion())
{
case SvtSaveOptions::ODFSVER_014_EXTENDED: [[fallthrough]];
case SvtSaveOptions::ODFSVER_014: pVersion = "1.4" ; break ;
case SvtSaveOptions::ODFSVER_013_EXTENDED: [[fallthrough]];
case SvtSaveOptions::ODFSVER_013: pVersion = "1.3" ; break ;
case SvtSaveOptions::ODFSVER_012_EXTENDED: [[fallthrough]];
case SvtSaveOptions::ODFSVER_012_EXT_COMPAT: [[fallthrough]];
case SvtSaveOptions::ODFSVER_012: pVersion = "1.2" ; break ;
case SvtSaveOptions::ODFSVER_011: pVersion = "1.1" ; break ;
case SvtSaveOptions::ODFSVER_010: break ;
default :
assert(!"xmloff::SvXMLExport::exportDoc(), unexpected odf default version!" );
}
return pVersion;
}
ErrCode SvXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
{
bool bOwnGraphicResolver = false ;
bool bOwnEmbeddedResolver = false ;
if (!mxGraphicStorageHandler.is() || !mxEmbeddedResolver.is())
{
Reference< XMultiServiceFactory > xFactory( mxModel, UNO_QUERY );
if ( xFactory.is() )
{
try
{
if (!mxGraphicStorageHandler.is())
{
mxGraphicStorageHandler.set(
getComponentContext()->getServiceManager()->createInstanceWithArgumentsAndContext(
u"com.sun.star.comp.Svx.GraphicExportHelper" _ustr, uno::Sequence<uno::Any>(), getComponentContext()),
uno::UNO_QUERY );
bOwnGraphicResolver = mxGraphicStorageHandler.is();
}
if ( !mxEmbeddedResolver.is() )
{
mxEmbeddedResolver.set(
xFactory->createInstance( u"com.sun.star.document.ExportEmbeddedObjectResolver" _ustr ), UNO_QUERY);
bOwnEmbeddedResolver = mxEmbeddedResolver.is();
}
}
catch (const css::uno::Exception&)
{
}
}
}
if ( (getExportFlags() & SvXMLExportFlags::OASIS) == SvXMLExportFlags::NONE )
{
try
{
static ::comphelper::PropertyMapEntry const aInfoMap[] =
{
{ u"Class" _ustr, 0,
::cppu::UnoType<OUString>::get(),
PropertyAttribute::MAYBEVOID, 0},
};
Reference< XPropertySet > xConvPropSet(
::comphelper::GenericPropertySet_CreateInstance(
new ::comphelper::PropertySetInfo( aInfoMap ) ) );
xConvPropSet->setPropertyValue( u"Class" _ustr, Any(GetXMLToken( eClass )) );
Reference< XPropertySet > xPropSet =
mxExportInfo.is()
? PropertySetMerger_CreateInstance( mxExportInfo,
xConvPropSet )
: xConvPropSet;
Sequence<Any> aArgs{ Any(mxHandler), Any(xPropSet), Any(mxModel) };
// get filter component
Reference< xml::sax::XDocumentHandler > xTmpDocHandler(
m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(u"com.sun.star.comp.Oasis2OOoTransformer" _ustr, aArgs, m_xContext),
UNO_QUERY);
SAL_WARN_IF(!xTmpDocHandler.is(), "xmloff.core" , "can't instantiate OASIS transformer component" );
if ( xTmpDocHandler.is() )
{
mxHandler = std::move(xTmpDocHandler);
mxExtHandler.set( mxHandler, UNO_QUERY );
}
}
catch (const css::uno::Exception&)
{
}
}
mxHandler->startDocument();
addChaffWhenEncryptedStorage();
// <office:document ...>
CheckAttrList();
// namespace attributes
// ( The namespace decls should be first attributes in the element;
// some faulty XML parsers (JAXP1.1) have a problem with this,
// also it's more elegant )
sal_uInt16 nPos = mpNamespaceMap->GetFirstKey();
while ( USHRT_MAX != nPos )
{
mxAttrList->AddAttribute( mpNamespaceMap->GetAttrNameByKey( nPos ),
mpNamespaceMap->GetNameByKey( nPos ) );
nPos = mpNamespaceMap->GetNextKey( nPos );
}
// office:version = ...
const char *const pVersion = GetODFVersionAttributeValue();
if (pVersion)
{
AddAttribute( XML_NAMESPACE_OFFICE, XML_VERSION,
OUString::createFromAscii(pVersion) );
}
{
enum XMLTokenEnum eRootService = XML_TOKEN_INVALID;
const SvXMLExportFlags nExportMode = mnExportFlags & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SETTINGS);
lcl_AddGrddl(*this , nExportMode);
if ( SvXMLExportFlags::META == nExportMode )
{
// export only meta
eRootService = XML_DOCUMENT_META;
}
else if ( SvXMLExportFlags::SETTINGS == nExportMode )
{
// export only settings
eRootService = XML_DOCUMENT_SETTINGS;
}
else if ( SvXMLExportFlags::STYLES == nExportMode )
{
// export only styles
eRootService = XML_DOCUMENT_STYLES;
}
else if ( SvXMLExportFlags::CONTENT == nExportMode )
{
// export only content
eRootService = XML_DOCUMENT_CONTENT;
}
else
{
// the god'ol one4all element
eRootService = XML_DOCUMENT;
// office:mimetype = ... (only for stream containing the content)
if ( eClass != XML_TOKEN_INVALID )
{
OUString aTmp = "application/vnd.oasis.opendocument." + GetXMLToken( eClass );
AddAttribute( XML_NAMESPACE_OFFICE, XML_MIMETYPE, aTmp );
}
}
SvXMLElementExport aElem( *this , XML_NAMESPACE_OFFICE, eRootService, true , true );
// meta information
if ( mnExportFlags & SvXMLExportFlags::META )
ImplExportMeta();
// settings
if ( mnExportFlags & SvXMLExportFlags::SETTINGS )
ImplExportSettings();
// scripts
if ( mnExportFlags & SvXMLExportFlags::SCRIPTS )
ExportScripts_();
// font declarations
if ( mnExportFlags & SvXMLExportFlags::FONTDECLS )
ExportFontDecls_();
// styles
if ( mnExportFlags & SvXMLExportFlags::STYLES )
ImplExportStyles();
// autostyles
if ( mnExportFlags & SvXMLExportFlags::AUTOSTYLES )
ImplExportAutoStyles();
// masterstyles
if ( mnExportFlags & SvXMLExportFlags::MASTERSTYLES )
ImplExportMasterStyles();
// content
if ( mnExportFlags & SvXMLExportFlags::CONTENT )
ImplExportContent();
}
mxHandler->endDocument();
if ( bOwnGraphicResolver )
{
uno::Reference<XComponent> xComp(mxGraphicStorageHandler, UNO_QUERY);
xComp->dispose();
}
if ( bOwnEmbeddedResolver )
{
Reference< XComponent > xComp( mxEmbeddedResolver, UNO_QUERY );
xComp->dispose();
}
return ERRCODE_NONE;
}
void SvXMLExport::ResetNamespaceMap()
{
mpNamespaceMap->Clear();
}
OUString const & SvXMLExport::GetSourceShellID() const
{
return mpImpl->maSrcShellID;
}
OUString const & SvXMLExport::GetDestinationShellID() const
{
return mpImpl->maDestShellID;
}
void SvXMLExport::ExportMeta_()
{
OUString generator( ::utl::DocInfoHelper::GetGeneratorString() );
Reference< XDocumentPropertiesSupplier > xDocPropsSupplier(mxModel,
UNO_QUERY);
if (xDocPropsSupplier.is()) {
Reference<XDocumentProperties> xDocProps(
xDocPropsSupplier->getDocumentProperties());
if (!xDocProps.is()) throw ;
// update generator here
xDocProps->setGenerator(generator);
rtl::Reference<SvXMLMetaExport> pMeta = new SvXMLMetaExport(*this , xDocProps);
pMeta->Export();
} else {
// office:meta
SvXMLElementExport aElem( *this , XML_NAMESPACE_OFFICE, XML_META,
true , true );
{
// BM: #i60323# export generator even if xInfoProp is empty (which is the
// case for charts). The generator does not depend on xInfoProp
SvXMLElementExport anElem( *this , XML_NAMESPACE_META, XML_GENERATOR,
true , true );
Characters(generator);
}
}
}
void SvXMLExport::ExportScripts_()
{
SvXMLElementExport aElement( *this , XML_NAMESPACE_OFFICE, XML_SCRIPTS, true , true );
// export Basic macros (only for FlatXML)
if ( mnExportFlags & SvXMLExportFlags::EMBEDDED )
{
OUString aValue( GetNamespaceMap().GetPrefixByKey( XML_NAMESPACE_OOO ) + ":Basic" );
AddAttribute( XML_NAMESPACE_SCRIPT, XML_LANGUAGE, aValue );
SvXMLElementExport aElem( *this , XML_NAMESPACE_OFFICE, XML_SCRIPT, true , true );
// initialize Basic
if ( mxModel.is() )
{
Reference< beans::XPropertySet > xPSet( mxModel, UNO_QUERY );
if ( xPSet.is() )
xPSet->getPropertyValue(u"BasicLibraries" _ustr);
}
Reference < XDocumentHandler > xHdl( new XMLBasicExportFilter( mxHandler ) );
Reference< document::XXMLBasicExporter > xExporter = document::XMLOasisBasicExporter::createWithHandler( m_xContext, xHdl );
xExporter->setSourceDocument( mxModel );
Sequence< PropertyValue > aMediaDesc( 0 );
xExporter->filter( aMediaDesc );
}
// export document events
Reference< document::XEventsSupplier > xEvents( GetModel(), UNO_QUERY );
GetEventExport().Export( xEvents );
}
void SvXMLExport::ExportFontDecls_()
{
if ( mxFontAutoStylePool.is() )
mxFontAutoStylePool->exportXML();
}
void SvXMLExport::ExportStyles_( bool )
{
uno::Reference< lang::XMultiServiceFactory > xFact( GetModel(), uno::UNO_QUERY );
if ( !xFact.is())
return ;
// export (fill-)gradient-styles
try
{
uno::Reference< container::XNameAccess > xGradient( xFact->createInstance(u"com.sun.star.drawing.GradientTable" _ustr), uno::UNO_QUERY );
if ( xGradient.is() )
{
XMLGradientStyleExport aGradientStyle( *this );
if ( xGradient->hasElements() )
{
const uno::Sequence< OUString > aNamesSeq ( xGradient->getElementNames() );
for ( const OUString& rStrName : aNamesSeq )
{
try
{
uno::Any aValue = xGradient->getByName( rStrName );
aGradientStyle.exportXML( rStrName, aValue );
}
catch (const container::NoSuchElementException&)
{
}
}
}
}
}
catch (const lang::ServiceNotRegisteredException&)
{
}
// export (fill-)hatch-styles
try
{
uno::Reference< container::XNameAccess > xHatch( xFact->createInstance(u"com.sun.star.drawing.HatchTable" _ustr), uno::UNO_QUERY );
if ( xHatch.is() )
{
XMLHatchStyleExport aHatchStyle( *this );
if ( xHatch->hasElements() )
{
const uno::Sequence< OUString > aNamesSeq ( xHatch->getElementNames() );
for ( const OUString& rStrName : aNamesSeq )
{
try
{
uno::Any aValue = xHatch->getByName( rStrName );
aHatchStyle.exportXML( rStrName, aValue );
}
catch (const container::NoSuchElementException&)
{}
}
}
}
}
catch (const lang::ServiceNotRegisteredException&)
{
}
// export (fill-)bitmap-styles
try
{
uno::Reference< container::XNameAccess > xBitmap( xFact->createInstance(u"com.sun.star.drawing.BitmapTable" _ustr), uno::UNO_QUERY );
if ( xBitmap.is() )
{
if ( xBitmap->hasElements() )
{
const uno::Sequence< OUString > aNamesSeq ( xBitmap->getElementNames() );
for ( const OUString& rStrName : aNamesSeq )
{
try
{
uno::Any aValue = xBitmap->getByName( rStrName );
XMLImageStyle::exportXML( rStrName, aValue, *this );
}
catch (const container::NoSuchElementException&)
{
}
}
}
}
}
catch (const lang::ServiceNotRegisteredException&)
{
}
// export transparency-gradient -styles
try
{
uno::Reference< container::XNameAccess > xTransGradient( xFact->createInstance(u"com.sun.star.drawing.TransparencyGradientTable" _ustr), uno::UNO_QUERY );
if ( xTransGradient.is() )
{
XMLTransGradientStyleExport aTransGradientstyle( *this );
if ( xTransGradient->hasElements() )
{
const uno::Sequence< OUString > aNamesSeq ( xTransGradient->getElementNames() );
for ( const OUString& rStrName : aNamesSeq )
{
try
{
uno::Any aValue = xTransGradient->getByName( rStrName );
aTransGradientstyle.exportXML( rStrName, aValue );
}
catch (const container::NoSuchElementException&)
{
}
}
}
}
}
catch (const lang::ServiceNotRegisteredException&)
{
}
// export marker-styles
try
{
uno::Reference< container::XNameAccess > xMarker( xFact->createInstance(u"com.sun.star.drawing.MarkerTable" _ustr), uno::UNO_QUERY );
if ( xMarker.is() )
{
XMLMarkerStyleExport aMarkerStyle( *this );
if ( xMarker->hasElements() )
{
const uno::Sequence< OUString > aNamesSeq ( xMarker->getElementNames() );
for ( const OUString& rStrName : aNamesSeq )
{
try
{
uno::Any aValue = xMarker->getByName( rStrName );
aMarkerStyle.exportXML( rStrName, aValue );
}
catch (const container::NoSuchElementException&)
{
}
}
}
}
}
catch (const lang::ServiceNotRegisteredException&)
{
}
// export dash-styles
try
{
uno::Reference< container::XNameAccess > xDashes( xFact->createInstance(u"com.sun.star.drawing.DashTable" _ustr), uno::UNO_QUERY );
if ( xDashes.is() )
{
XMLDashStyleExport aDashStyle( *this );
if ( xDashes->hasElements() )
{
const uno::Sequence< OUString > aNamesSeq ( xDashes->getElementNames() );
for ( const OUString& rStrName : aNamesSeq )
{
try
{
uno::Any aValue = xDashes->getByName( rStrName );
aDashStyle.exportXML( rStrName, aValue );
}
catch (const container::NoSuchElementException&)
{
}
}
}
}
}
catch (const lang::ServiceNotRegisteredException&)
{
}
}
void SvXMLExport::ExportThemeElement(std::shared_ptr<model::Theme> const & pTheme)
{
if (!pTheme)
return ;
if (!pTheme->GetName().isEmpty())
AddAttribute(XML_NAMESPACE_LO_EXT, XML_NAME, pTheme->GetName());
SvXMLElementExport aTheme(*this , XML_NAMESPACE_LO_EXT, XML_THEME, true , true );
auto pColorSet = pTheme->getColorSet();
if (!pColorSet)
return ;
if (!pColorSet->getName().isEmpty())
AddAttribute(XML_NAMESPACE_LO_EXT, XML_NAME, pColorSet->getName());
SvXMLElementExport aColorTable(*this , XML_NAMESPACE_LO_EXT, XML_THEME_COLORS, true , true );
static const XMLTokenEnum aColorTokens[] =
{
XML_DARK1, // Text 1
XML_LIGHT1, // Background 1
XML_DARK2, // Text 2
XML_LIGHT2, // Background 2
XML_ACCENT1,
XML_ACCENT2,
XML_ACCENT3,
XML_ACCENT4,
XML_ACCENT5,
XML_ACCENT6,
XML_HYPERLINK, // Hyperlink
XML_FOLLOWED_HYPERLINK, // Followed hyperlink
};
for (auto eThemeColorType : o3tl::enumrange<model::ThemeColorType>())
{
if (eThemeColorType == model::ThemeColorType::Unknown)
continue ;
auto nColor = size_t(eThemeColorType);
AddAttribute(XML_NAMESPACE_LO_EXT, XML_NAME, GetXMLToken(aColorTokens[nColor]));
OUStringBuffer sValue;
sax::Converter::convertColor(sValue, pColorSet->getColor(eThemeColorType));
AddAttribute(XML_NAMESPACE_LO_EXT, XML_COLOR, sValue.makeStringAndClear());
SvXMLElementExport aColor(*this , XML_NAMESPACE_LO_EXT, XML_COLOR, true , true );
}
}
XMLTextParagraphExport* SvXMLExport::CreateTextParagraphExport()
{
return new XMLTextParagraphExport( *this , *GetAutoStylePool() );
}
XMLShapeExport* SvXMLExport::CreateShapeExport()
{
return new XMLShapeExport(*this );
}
SvXMLAutoStylePoolP* SvXMLExport::CreateAutoStylePool()
{
return new SvXMLAutoStylePoolP(*this );
}
void SvXMLExport::collectAutoStyles()
{
}
XMLPageExport* SvXMLExport::CreatePageExport()
{
return new XMLPageExport( *this );
}
SchXMLExportHelper* SvXMLExport::CreateChartExport()
{
// WASM_CHART change
// TODO: With Chart extracted this cannot really happen since
// no Chart could've been added at all
#if !ENABLE_WASM_STRIP_CHART
return new SchXMLExportHelper(*this , *GetAutoStylePool());
#else
return nullptr;
#endif
}
XMLFontAutoStylePool* SvXMLExport::CreateFontAutoStylePool()
{
return new XMLFontAutoStylePool( *this );
}
xmloff::OFormLayerXMLExport* SvXMLExport::CreateFormExport()
{
return new xmloff::OFormLayerXMLExport(*this );
}
void SvXMLExport::GetViewSettingsAndViews(uno::Sequence<beans::PropertyValue>& rProps)
{
GetViewSettings(rProps);
uno::Reference<document::XViewDataSupplier> xViewDataSupplier(GetModel(), uno::UNO_QUERY);
if (!xViewDataSupplier.is())
return ;
uno::Reference<container::XIndexAccess> xIndexAccess;
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5 C=94 H=96 G=94
¤ Dauer der Verarbeitung: 0.23 Sekunden
¤
*© Formatika GbR, Deutschland