1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <sal/config.h>
22 #include <sal/log.hxx>
23 
24 #include <stack>
25 #include <optional>
26 
27 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
28 #include <osl/mutex.hxx>
29 #include <tools/urlobj.hxx>
30 #include <vcl/graph.hxx>
31 #include <comphelper/genericpropertyset.hxx>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/io/XInputStream.hpp>
34 #include <com/sun/star/document/XBinaryStreamResolver.hpp>
35 #include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
36 #include <com/sun/star/text/XTextContent.hpp>
37 #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
38 #include <com/sun/star/uri/XUriReferenceFactory.hpp>
39 #include <com/sun/star/uri/UriReferenceFactory.hpp>
40 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
41 #include <com/sun/star/util/MeasureUnit.hpp>
42 #include <i18nlangtag/languagetag.hxx>
43 #include <comphelper/processfactory.hxx>
44 #include <comphelper/propertysetinfo.hxx>
45 #include <xmloff/attrlist.hxx>
46 #include <xmloff/namespacemap.hxx>
47 #include <xmloff/xmluconv.hxx>
48 #include <xmloff/xmlnamespace.hxx>
49 #include <xmloff/xmltoken.hxx>
50 #include <xmloff/xmlexp.hxx>
51 #include <xmloff/xmlnumfe.hxx>
52 #include <xmloff/xmlmetae.hxx>
53 #include <xmloff/XMLSettingsExportContext.hxx>
54 #include <xmloff/XMLEventExport.hxx>
55 #include <xmloff/ProgressBarHelper.hxx>
56 #include <XMLStarBasicExportHandler.hxx>
57 #include <XMLScriptExportHandler.hxx>
58 #include <xmloff/SettingsExportHelper.hxx>
59 #include <com/sun/star/document/XEventsSupplier.hpp>
60 #include <com/sun/star/document/XViewDataSupplier.hpp>
61 #include <com/sun/star/frame/XModel.hpp>
62 #include <com/sun/star/frame/XModule.hpp>
63 #include <xmloff/GradientStyle.hxx>
64 #include <xmloff/HatchStyle.hxx>
65 #include <xmloff/ImageStyle.hxx>
66 #include <TransGradientStyle.hxx>
67 #include <xmloff/MarkerStyle.hxx>
68 #include <xmloff/DashStyle.hxx>
69 #include <xmloff/XMLFontAutoStylePool.hxx>
70 #include <XMLImageMapExport.hxx>
71 #include <XMLBase64Export.hxx>
72 #include <xmloff/xmlerror.hxx>
73 #include <com/sun/star/style/XStyle.hpp>
74 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
75 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
76 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
77 #include <com/sun/star/beans/PropertyAttribute.hpp>
78 #include <xmloff/XMLFilterServiceNames.h>
79 #include <XMLEmbeddedObjectExportFilter.hxx>
80 #include <XMLBasicExportFilter.hxx>
81 #include <cppuhelper/exc_hlp.hxx>
82 #include <cppuhelper/implbase.hxx>
83 #include <cppuhelper/supportsservice.hxx>
84 #include <comphelper/extract.hxx>
85 #include <comphelper/SetFlagContextHelper.hxx>
86 #include <PropertySetMerger.hxx>
87 
88 #include <unotools/docinfohelper.hxx>
89 #include <com/sun/star/document/XDocumentProperties.hpp>
90 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
91 #include <com/sun/star/document/XMLOasisBasicExporter.hpp>
92 #include <com/sun/star/embed/XEncryptionProtectedSource2.hpp>
93 #include <com/sun/star/document/XGraphicStorageHandler.hpp>
94 #include <com/sun/star/rdf/XMetadatable.hpp>
95 #include <RDFaExportHelper.hxx>
96 
97 #include <comphelper/xmltools.hxx>
98 #include <comphelper/graphicmimetype.hxx>
99 
100 using namespace ::osl;
101 using namespace ::com::sun::star;
102 using namespace ::com::sun::star::uno;
103 using namespace ::com::sun::star::frame;
104 using namespace ::com::sun::star::container;
105 using namespace ::com::sun::star::lang;
106 using namespace ::com::sun::star::document;
107 using namespace ::com::sun::star::beans;
108 using namespace ::com::sun::star::xml::sax;
109 using namespace ::com::sun::star::io;
110 using namespace ::xmloff::token;
111 
112 #define XML_MODEL_SERVICE_WRITER    "com.sun.star.text.TextDocument"
113 #define XML_MODEL_SERVICE_CALC      "com.sun.star.sheet.SpreadsheetDocument"
114 #define XML_MODEL_SERVICE_DRAW      "com.sun.star.drawing.DrawingDocument"
115 #define XML_MODEL_SERVICE_IMPRESS   "com.sun.star.presentation.PresentationDocument"
116 #define XML_MODEL_SERVICE_MATH      "com.sun.star.formula.FormulaProperties"
117 #define XML_MODEL_SERVICE_CHART     "com.sun.star.chart.ChartDocument"
118 
119 #define XML_USEPRETTYPRINTING       "UsePrettyPrinting"
120 
121 #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "vnd.sun.star.GraphicObject:"
122 #define XML_EMBEDDEDOBJECT_URL_BASE     "vnd.sun.star.EmbeddedObject:"
123 
124 namespace {
125 
126 struct XMLServiceMapEntry_Impl
127 {
128     const char *sModelService;
129     sal_Int32   nModelServiceLen;
130     const char *sFilterService;
131     sal_Int32   nFilterServiceLen;
132 };
133 
134 }
135 
136 #define SERVICE_MAP_ENTRY( app ) \
137     { XML_MODEL_SERVICE_##app, sizeof(XML_MODEL_SERVICE_##app)-1, \
138       XML_EXPORT_FILTER_##app, sizeof(XML_EXPORT_FILTER_##app)-1 }
139 
140 const XMLServiceMapEntry_Impl aServiceMap[] =
141 {
142     SERVICE_MAP_ENTRY( WRITER ),
143     SERVICE_MAP_ENTRY( CALC ),
144     SERVICE_MAP_ENTRY( IMPRESS ),// Impress supports DrawingDocument, too, so
145     SERVICE_MAP_ENTRY( DRAW ),   // it must appear before Draw
146     SERVICE_MAP_ENTRY( MATH ),
147     SERVICE_MAP_ENTRY( CHART ),
148     { nullptr, 0, nullptr, 0 }
149 };
150 
151 namespace {
152 
153 class SettingsExportFacade : public ::xmloff::XMLSettingsExportContext
154 {
155 public:
SettingsExportFacade(SvXMLExport & i_rExport)156     explicit SettingsExportFacade( SvXMLExport& i_rExport )
157         :m_rExport( i_rExport )
158     {
159     }
160 
~SettingsExportFacade()161     virtual ~SettingsExportFacade()
162     {
163     }
164 
165     virtual void    AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName,
166                                   const OUString& i_rValue ) override;
167     virtual void    AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName,
168                                   enum ::xmloff::token::XMLTokenEnum i_eValue ) override;
169 
170     virtual void    StartElement( enum ::xmloff::token::XMLTokenEnum i_eName ) override;
171     virtual void    EndElement(   const bool i_bIgnoreWhitespace ) override;
172 
173     virtual void    Characters( const OUString& i_rCharacters ) override;
174 
175     virtual css::uno::Reference< css::uno::XComponentContext >
176                     GetComponentContext() const override;
177 private:
178     SvXMLExport&                    m_rExport;
179     ::std::stack< OUString > m_aElements;
180 };
181 
182 }
183 
AddAttribute(enum::xmloff::token::XMLTokenEnum i_eName,const OUString & i_rValue)184 void SettingsExportFacade::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, const OUString& i_rValue )
185 {
186     m_rExport.AddAttribute( XML_NAMESPACE_CONFIG, i_eName, i_rValue );
187 }
188 
AddAttribute(enum::xmloff::token::XMLTokenEnum i_eName,enum::xmloff::token::XMLTokenEnum i_eValue)189 void SettingsExportFacade::AddAttribute( enum ::xmloff::token::XMLTokenEnum i_eName, enum ::xmloff::token::XMLTokenEnum i_eValue )
190 {
191     m_rExport.AddAttribute( XML_NAMESPACE_CONFIG, i_eName, i_eValue );
192 }
193 
StartElement(enum::xmloff::token::XMLTokenEnum i_eName)194 void SettingsExportFacade::StartElement( enum ::xmloff::token::XMLTokenEnum i_eName )
195 {
196     const OUString sElementName( m_rExport.GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_CONFIG, GetXMLToken( i_eName ) ) );
197     m_rExport.StartElement( sElementName, true/*i_bIgnoreWhitespace*/ );
198     m_aElements.push( sElementName );
199 }
200 
EndElement(const bool i_bIgnoreWhitespace)201 void SettingsExportFacade::EndElement( const bool i_bIgnoreWhitespace )
202 {
203     const OUString sElementName( m_aElements.top() );
204     m_rExport.EndElement( sElementName, i_bIgnoreWhitespace );
205     m_aElements.pop();
206 }
207 
Characters(const OUString & i_rCharacters)208 void SettingsExportFacade::Characters( const OUString& i_rCharacters )
209 {
210     m_rExport.GetDocHandler()->characters( i_rCharacters );
211 }
212 
GetComponentContext() const213 Reference< XComponentContext > SettingsExportFacade::GetComponentContext() const
214 {
215     return m_rExport.getComponentContext();
216 }
217 
218 namespace {
219 
220 class SvXMLExportEventListener : public cppu::WeakImplHelper<
221                             css::lang::XEventListener >
222 {
223 private:
224     SvXMLExport*    pExport;
225 
226 public:
227     explicit SvXMLExportEventListener(SvXMLExport* pExport);
228 
229                             // XEventListener
230     virtual void SAL_CALL disposing(const lang::EventObject& rEventObject) override;
231 };
232 
233 }
234 
SvXMLExportEventListener(SvXMLExport * pTempExport)235 SvXMLExportEventListener::SvXMLExportEventListener(SvXMLExport* pTempExport)
236     : pExport(pTempExport)
237 {
238 }
239 
240 // XEventListener
disposing(const lang::EventObject &)241 void SAL_CALL SvXMLExportEventListener::disposing( const lang::EventObject& )
242 {
243     if (pExport)
244     {
245         pExport->DisposingModel();
246         pExport = nullptr;
247     }
248 }
249 
250 class SvXMLExport_Impl
251 {
252 public:
253     SvXMLExport_Impl();
254 
255     ::comphelper::UnoInterfaceToUniqueIdentifierMapper  maInterfaceToIdentifierMapper;
256     uno::Reference< uri::XUriReferenceFactory >         mxUriReferenceFactory;
257     OUString                                            msPackageURI;
258     OUString                                            msPackageURIScheme;
259     // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
260     bool                                                mbOutlineStyleAsNormalListStyle;
261 
262     uno::Reference< embed::XStorage >                   mxTargetStorage;
263 
264     SvtSaveOptions                                      maSaveOptions;
265     std::optional<SvtSaveOptions::ODFSaneDefaultVersion> m_oOverrideODFVersion;
266 
267     /// name of stream in package, e.g., "content.xml"
268     OUString mStreamName;
269 
270     OUString maSrcShellID;
271     OUString maDestShellID;
272 
273     /// stack of backed up namespace maps
274     /// long: depth at which namespace map has been backed up into the stack
275     ::std::stack< ::std::pair< std::unique_ptr<SvXMLNamespaceMap>, tools::Long > > mNamespaceMaps;
276     /// counts depth (number of open elements/start tags)
277     tools::Long mDepth;
278 
279     ::std::unique_ptr< ::xmloff::RDFaExportHelper> mpRDFaHelper;
280 
281     bool                                                mbExportTextNumberElement;
282     bool                                                mbNullDateInitialized;
283 
SetSchemeOf(const OUString & rOrigFileName)284     void SetSchemeOf( const OUString& rOrigFileName )
285     {
286         sal_Int32 nSep = rOrigFileName.indexOf(':');
287         if( nSep != -1 )
288             msPackageURIScheme = rOrigFileName.copy( 0, nSep );
289     }
290 };
291 
SvXMLExport_Impl()292 SvXMLExport_Impl::SvXMLExport_Impl()
293 :    mxUriReferenceFactory( uri::UriReferenceFactory::create(comphelper::getProcessComponentContext()) ),
294     // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
295     mbOutlineStyleAsNormalListStyle( false ),
296     mDepth( 0 ),
297     mbExportTextNumberElement( false ),
298     mbNullDateInitialized( false )
299 {
300 }
301 
SetDocHandler(const uno::Reference<xml::sax::XDocumentHandler> & rHandler)302 void SvXMLExport::SetDocHandler( const uno::Reference< xml::sax::XDocumentHandler > &rHandler )
303 {
304     mxHandler = rHandler;
305     mxExtHandler.set( mxHandler, UNO_QUERY );
306 }
307 
InitCtor_()308 void SvXMLExport::InitCtor_()
309 {
310     // note: it is not necessary to add XML_NP_XML (it is declared implicitly)
311     if( getExportFlags() & ~SvXMLExportFlags::OASIS )
312     {
313         mpNamespaceMap->Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
314         mpNamespaceMap->Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
315     }
316     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::FONTDECLS) )
317     {
318         mpNamespaceMap->Add( GetXMLToken(XML_NP_FO), GetXMLToken(XML_N_FO_COMPAT), XML_NAMESPACE_FO );
319     }
320     if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS|SvXMLExportFlags::SETTINGS) )
321     {
322         mpNamespaceMap->Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
323     }
324     if( getExportFlags() & SvXMLExportFlags::SETTINGS )
325     {
326         mpNamespaceMap->Add( GetXMLToken(XML_NP_CONFIG), GetXMLToken(XML_N_CONFIG), XML_NAMESPACE_CONFIG );
327     }
328 
329     if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
330     {
331         mpNamespaceMap->Add( GetXMLToken(XML_NP_DC), GetXMLToken(XML_N_DC), XML_NAMESPACE_DC );
332         mpNamespaceMap->Add( GetXMLToken(XML_NP_META), GetXMLToken(XML_N_META), XML_NAMESPACE_META );
333     }
334     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::FONTDECLS) )
335     {
336         mpNamespaceMap->Add( GetXMLToken(XML_NP_STYLE), GetXMLToken(XML_N_STYLE), XML_NAMESPACE_STYLE );
337     }
338 
339     // namespaces for documents
340     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
341     {
342         mpNamespaceMap->Add( GetXMLToken(XML_NP_DC),    GetXMLToken(XML_N_DC),      XML_NAMESPACE_DC );
343         mpNamespaceMap->Add( GetXMLToken(XML_NP_TEXT),  GetXMLToken(XML_N_TEXT),    XML_NAMESPACE_TEXT );
344         mpNamespaceMap->Add( GetXMLToken(XML_NP_DRAW),  GetXMLToken(XML_N_DRAW),    XML_NAMESPACE_DRAW );
345         mpNamespaceMap->Add( GetXMLToken(XML_NP_DR3D),  GetXMLToken(XML_N_DR3D),    XML_NAMESPACE_DR3D );
346         mpNamespaceMap->Add( GetXMLToken(XML_NP_SVG),   GetXMLToken(XML_N_SVG_COMPAT),  XML_NAMESPACE_SVG );
347         mpNamespaceMap->Add( GetXMLToken(XML_NP_CHART), GetXMLToken(XML_N_CHART),   XML_NAMESPACE_CHART );
348         mpNamespaceMap->Add( GetXMLToken(XML_NP_RPT),   GetXMLToken(XML_N_RPT),     XML_NAMESPACE_REPORT );
349         mpNamespaceMap->Add( GetXMLToken(XML_NP_TABLE), GetXMLToken(XML_N_TABLE),   XML_NAMESPACE_TABLE );
350         mpNamespaceMap->Add( GetXMLToken(XML_NP_NUMBER),GetXMLToken(XML_N_NUMBER),  XML_NAMESPACE_NUMBER );
351         mpNamespaceMap->Add( GetXMLToken(XML_NP_OOOW),  GetXMLToken(XML_N_OOOW),    XML_NAMESPACE_OOOW );
352         mpNamespaceMap->Add( GetXMLToken(XML_NP_OOOC),  GetXMLToken(XML_N_OOOC),    XML_NAMESPACE_OOOC );
353         mpNamespaceMap->Add( GetXMLToken(XML_NP_OF),    GetXMLToken(XML_N_OF),      XML_NAMESPACE_OF );
354 
355         if (getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
356         {
357             mpNamespaceMap->Add(
358                 GetXMLToken(XML_NP_TABLE_EXT), GetXMLToken(XML_N_TABLE_EXT), XML_NAMESPACE_TABLE_EXT);
359             mpNamespaceMap->Add(
360                 GetXMLToken(XML_NP_CALC_EXT), GetXMLToken(XML_N_CALC_EXT), XML_NAMESPACE_CALC_EXT);
361             mpNamespaceMap->Add(
362                 GetXMLToken(XML_NP_DRAW_EXT), GetXMLToken(XML_N_DRAW_EXT), XML_NAMESPACE_DRAW_EXT);
363             mpNamespaceMap->Add(
364                 GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT),
365                 XML_NAMESPACE_LO_EXT);
366             mpNamespaceMap->Add( GetXMLToken(XML_NP_FIELD), GetXMLToken(XML_N_FIELD), XML_NAMESPACE_FIELD );
367         }
368     }
369     if( getExportFlags() & (SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
370     {
371         mpNamespaceMap->Add( GetXMLToken(XML_NP_MATH), GetXMLToken(XML_N_MATH), XML_NAMESPACE_MATH );
372         mpNamespaceMap->Add( GetXMLToken(XML_NP_FORM), GetXMLToken(XML_N_FORM), XML_NAMESPACE_FORM );
373     }
374     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SCRIPTS) )
375     {
376         mpNamespaceMap->Add( GetXMLToken(XML_NP_SCRIPT), GetXMLToken(XML_N_SCRIPT), XML_NAMESPACE_SCRIPT );
377         mpNamespaceMap->Add( GetXMLToken(XML_NP_DOM), GetXMLToken(XML_N_DOM), XML_NAMESPACE_DOM );
378     }
379     if( getExportFlags() & SvXMLExportFlags::CONTENT )
380     {
381         mpNamespaceMap->Add( GetXMLToken(XML_NP_XFORMS_1_0), GetXMLToken(XML_N_XFORMS_1_0), XML_NAMESPACE_XFORMS );
382         mpNamespaceMap->Add( GetXMLToken(XML_NP_XSD), GetXMLToken(XML_N_XSD), XML_NAMESPACE_XSD );
383         mpNamespaceMap->Add( GetXMLToken(XML_NP_XSI), GetXMLToken(XML_N_XSI), XML_NAMESPACE_XSI );
384         mpNamespaceMap->Add( GetXMLToken(XML_NP_FORMX), GetXMLToken(XML_N_FORMX), XML_NAMESPACE_FORMX );
385     }
386 
387     // RDFa: needed for content and header/footer styles
388     if( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
389     {
390         mpNamespaceMap->Add( GetXMLToken(XML_NP_XHTML),
391             GetXMLToken(XML_N_XHTML), XML_NAMESPACE_XHTML );
392     }
393     // GRDDL: to convert RDFa and meta.xml to RDF
394     if( getExportFlags() & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES|SvXMLExportFlags::CONTENT) )
395     {
396         mpNamespaceMap->Add( GetXMLToken(XML_NP_GRDDL),
397             GetXMLToken(XML_N_GRDDL), XML_NAMESPACE_GRDDL );
398     }
399     // CSS Text Level 3 for distributed text justification.
400     if ( getExportFlags() & (SvXMLExportFlags::STYLES|SvXMLExportFlags::AUTOSTYLES|SvXMLExportFlags::MASTERSTYLES) )
401     {
402         mpNamespaceMap->Add(
403             GetXMLToken(XML_NP_CSS3TEXT), GetXMLToken(XML_N_CSS3TEXT), XML_NAMESPACE_CSS3TEXT );
404     }
405 
406     if (mxModel.is() && !mxEventListener.is())
407     {
408         mxEventListener.set( new SvXMLExportEventListener(this));
409         mxModel->addEventListener(mxEventListener);
410     }
411 
412     // Determine model type (#i51726#)
413     DetermineModelType_();
414 }
415 
416 // Shapes in Writer cannot be named via context menu (#i51726#)
DetermineModelType_()417 void SvXMLExport::DetermineModelType_()
418 {
419     meModelType = SvtModuleOptions::EFactory::UNKNOWN_FACTORY;
420 
421     if ( mxModel.is() )
422     {
423         meModelType = SvtModuleOptions::ClassifyFactoryByModel( mxModel );
424 
425         // note: MATH documents will throw NotInitializedException; maybe unit test problem
426         if (meModelType == SvtModuleOptions::EFactory::WRITER)
427         {
428             uno::Reference<frame::XModule> const xModule(mxModel, uno::UNO_QUERY);
429             bool const isBaseForm(xModule.is() &&
430                 xModule->getIdentifier() == "com.sun.star.sdb.FormDesign");
431             if (isBaseForm)
432             {
433                 switch (mpImpl->maSaveOptions.GetODFSaneDefaultVersion())
434                 {
435                     case SvtSaveOptions::ODFSVER_013_EXTENDED:
436                         SAL_INFO("xmloff.core", "tdf#138209 force form export to ODF 1.2");
437                         mpImpl->m_oOverrideODFVersion = SvtSaveOptions::ODFSVER_012_EXTENDED;
438                         maUnitConv.overrideSaneDefaultVersion(SvtSaveOptions::ODFSVER_012_EXTENDED);
439                         break;
440                     case SvtSaveOptions::ODFSVER_013:
441                         SAL_INFO("xmloff.core", "tdf#138209 force form export to ODF 1.2");
442                         mpImpl->m_oOverrideODFVersion = SvtSaveOptions::ODFSVER_012;
443                         maUnitConv.overrideSaneDefaultVersion(SvtSaveOptions::ODFSVER_012);
444                         break;
445                     default:
446                         break;
447                 }
448             }
449         }
450     }
451 }
452 
SvXMLExport(const uno::Reference<uno::XComponentContext> & xContext,OUString const & implementationName,sal_Int16 const eDefaultMeasureUnit,const enum XMLTokenEnum eClass,SvXMLExportFlags nExportFlags)453 SvXMLExport::SvXMLExport(
454     const uno::Reference< uno::XComponentContext >& xContext,
455     OUString const & implementationName,
456     sal_Int16 const eDefaultMeasureUnit /*css::util::MeasureUnit*/,
457     const enum XMLTokenEnum eClass, SvXMLExportFlags nExportFlags )
458 :   mpImpl( new SvXMLExport_Impl ),
459     m_xContext(xContext), m_implementationName(implementationName),
460     mxAttrList( new SvXMLAttributeList ),
461     mpNamespaceMap( new SvXMLNamespaceMap ),
462     mpAuthorIDs( new SvtSecurityMapPersonalInfo ),
463     maUnitConv(xContext, util::MeasureUnit::MM_100TH, eDefaultMeasureUnit, getSaneDefaultVersion()),
464     meClass( eClass ),
465     mnExportFlags( nExportFlags ),
466     mnErrorFlags( SvXMLErrorFlags::NO ),
467     msWS( GetXMLToken(XML_WS) ),
468     mbSaveLinkedSections(true),
469     mbAutoStylesCollected(false)
470 {
471     SAL_WARN_IF( !xContext.is(), "xmloff.core", "got no service manager" );
472     InitCtor_();
473 }
474 
SvXMLExport(const css::uno::Reference<css::uno::XComponentContext> & xContext,OUString const & implementationName,const OUString & rFileName,sal_Int16 const eDefaultMeasureUnit,const uno::Reference<xml::sax::XDocumentHandler> & rHandler)475 SvXMLExport::SvXMLExport(
476     const css::uno::Reference< css::uno::XComponentContext >& xContext,
477     OUString const & implementationName,
478     const OUString &rFileName,
479     sal_Int16 const eDefaultMeasureUnit /*css::util::MeasureUnit*/,
480     const uno::Reference< xml::sax::XDocumentHandler > & rHandler)
481 :   mpImpl( new SvXMLExport_Impl ),
482     m_xContext(xContext), m_implementationName(implementationName),
483     mxHandler( rHandler ),
484     mxExtHandler( rHandler, uno::UNO_QUERY ),
485     mxAttrList( new SvXMLAttributeList ),
486     msOrigFileName( rFileName ),
487     mpNamespaceMap( new SvXMLNamespaceMap ),
488     mpAuthorIDs( new SvtSecurityMapPersonalInfo ),
489     maUnitConv(xContext, util::MeasureUnit::MM_100TH, eDefaultMeasureUnit, getSaneDefaultVersion()),
490     meClass( XML_TOKEN_INVALID ),
491     mnExportFlags( SvXMLExportFlags::NONE ),
492     mnErrorFlags( SvXMLErrorFlags::NO ),
493     msWS( GetXMLToken(XML_WS) ),
494     mbSaveLinkedSections(true),
495     mbAutoStylesCollected(false)
496 {
497     SAL_WARN_IF( !xContext.is(), "xmloff.core", "got no service manager" );
498     mpImpl->SetSchemeOf( msOrigFileName );
499     InitCtor_();
500 
501     if (mxNumberFormatsSupplier.is())
502         mpNumExport.reset( new SvXMLNumFmtExport(*this, mxNumberFormatsSupplier) );
503 }
504 
SvXMLExport(const css::uno::Reference<css::uno::XComponentContext> & xContext,OUString const & implementationName,const OUString & rFileName,const uno::Reference<xml::sax::XDocumentHandler> & rHandler,const Reference<XModel> & rModel,FieldUnit const eDefaultFieldUnit,SvXMLExportFlags nExportFlag)505 SvXMLExport::SvXMLExport(
506     const css::uno::Reference< css::uno::XComponentContext >& xContext,
507     OUString const & implementationName,
508     const OUString &rFileName,
509     const uno::Reference< xml::sax::XDocumentHandler > & rHandler,
510     const Reference< XModel >& rModel,
511     FieldUnit const eDefaultFieldUnit,
512     SvXMLExportFlags nExportFlag)
513 :   mpImpl( new SvXMLExport_Impl ),
514     m_xContext(xContext), m_implementationName(implementationName),
515     mxModel( rModel ),
516     mxHandler( rHandler ),
517     mxExtHandler( rHandler, uno::UNO_QUERY ),
518     mxNumberFormatsSupplier (rModel, uno::UNO_QUERY),
519     mxAttrList( new SvXMLAttributeList ),
520     msOrigFileName( rFileName ),
521     mpNamespaceMap( new SvXMLNamespaceMap ),
522     mpAuthorIDs( new SvtSecurityMapPersonalInfo ),
523     maUnitConv( xContext,
524                 util::MeasureUnit::MM_100TH,
525                 SvXMLUnitConverter::GetMeasureUnit(eDefaultFieldUnit),
526                 getSaneDefaultVersion()),
527     meClass( XML_TOKEN_INVALID ),
528     mnExportFlags( nExportFlag ),
529     mnErrorFlags( SvXMLErrorFlags::NO ),
530     msWS( GetXMLToken(XML_WS) ),
531     mbSaveLinkedSections(true),
532     mbAutoStylesCollected(false)
533 {
534     SAL_WARN_IF(!xContext.is(), "xmloff.core", "got no service manager" );
535     mpImpl->SetSchemeOf( msOrigFileName );
536     InitCtor_();
537 
538     if (mxNumberFormatsSupplier.is())
539         mpNumExport.reset( new SvXMLNumFmtExport(*this, mxNumberFormatsSupplier) );
540 }
541 
~SvXMLExport()542 SvXMLExport::~SvXMLExport()
543 {
544     mpXMLErrors.reset();
545     mpImageMapExport.reset();
546     mpEventExport.reset();
547     mpNamespaceMap.reset();
548     if (mpProgressBarHelper || mpNumExport)
549     {
550         if (mxExportInfo.is())
551         {
552             uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
553             if (xPropertySetInfo.is())
554             {
555                 if (mpProgressBarHelper)
556                 {
557                     OUString sProgressMax(XML_PROGRESSMAX);
558                     OUString sProgressCurrent(XML_PROGRESSCURRENT);
559                     OUString sRepeat(XML_PROGRESSREPEAT);
560                     if (xPropertySetInfo->hasPropertyByName(sProgressMax) &&
561                         xPropertySetInfo->hasPropertyByName(sProgressCurrent))
562                     {
563                         sal_Int32 nProgressMax(mpProgressBarHelper->GetReference());
564                         sal_Int32 nProgressCurrent(mpProgressBarHelper->GetValue());
565                         mxExportInfo->setPropertyValue(sProgressMax, uno::Any(nProgressMax));
566                         mxExportInfo->setPropertyValue(sProgressCurrent, uno::Any(nProgressCurrent));
567                     }
568                     if (xPropertySetInfo->hasPropertyByName(sRepeat))
569                         mxExportInfo->setPropertyValue(sRepeat, css::uno::makeAny(mpProgressBarHelper->GetRepeat()));
570                 }
571                 if (mpNumExport && (mnExportFlags & (SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::STYLES)))
572                 {
573                     OUString sWrittenNumberFormats(XML_WRITTENNUMBERSTYLES);
574                     if (xPropertySetInfo->hasPropertyByName(sWrittenNumberFormats))
575                     {
576                         mxExportInfo->setPropertyValue(sWrittenNumberFormats, Any(mpNumExport->GetWasUsed()));
577                     }
578                 }
579             }
580         }
581         mpProgressBarHelper.reset();
582         mpNumExport.reset();
583     }
584 
585     if (mxEventListener.is() && mxModel.is())
586         mxModel->removeEventListener(mxEventListener);
587 }
588 
589 // XExporter
setSourceDocument(const uno::Reference<lang::XComponent> & xDoc)590 void SAL_CALL SvXMLExport::setSourceDocument( const uno::Reference< lang::XComponent >& xDoc )
591 {
592     mxModel.set( xDoc, UNO_QUERY );
593     if( !mxModel.is() )
594         throw lang::IllegalArgumentException();
595     if (mxModel.is() && ! mxEventListener.is())
596     {
597         mxEventListener.set( new SvXMLExportEventListener(this));
598         mxModel->addEventListener(mxEventListener);
599     }
600 
601     if(!mxNumberFormatsSupplier.is() )
602     {
603         mxNumberFormatsSupplier.set(mxModel, css::uno::UNO_QUERY);
604         if(mxNumberFormatsSupplier.is() && mxHandler.is())
605             mpNumExport.reset( new SvXMLNumFmtExport(*this, mxNumberFormatsSupplier) );
606     }
607     if (mxExportInfo.is())
608     {
609         uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
610         if (xPropertySetInfo.is())
611         {
612             OUString sUsePrettyPrinting(XML_USEPRETTYPRINTING);
613             if (xPropertySetInfo->hasPropertyByName(sUsePrettyPrinting))
614             {
615                 uno::Any aAny = mxExportInfo->getPropertyValue(sUsePrettyPrinting);
616                 if (::cppu::any2bool(aAny))
617                     mnExportFlags |= SvXMLExportFlags::PRETTY;
618                 else
619                     mnExportFlags &= ~SvXMLExportFlags::PRETTY;
620             }
621 
622             if (mpNumExport && (mnExportFlags & (SvXMLExportFlags::AUTOSTYLES | SvXMLExportFlags::STYLES)))
623             {
624                 OUString sWrittenNumberFormats(XML_WRITTENNUMBERSTYLES);
625                 if (xPropertySetInfo->hasPropertyByName(sWrittenNumberFormats))
626                 {
627                     uno::Any aAny = mxExportInfo->getPropertyValue(sWrittenNumberFormats);
628                     uno::Sequence<sal_Int32> aWasUsed;
629                     if(aAny >>= aWasUsed)
630                         mpNumExport->SetWasUsed(aWasUsed);
631                 }
632             }
633         }
634     }
635 
636     // namespaces for user defined attributes
637     Reference< XMultiServiceFactory > xFactory( mxModel,    UNO_QUERY );
638     if( xFactory.is() )
639     {
640         try
641         {
642             Reference < XInterface > xIfc =
643                 xFactory->createInstance("com.sun.star.xml.NamespaceMap");
644             if( xIfc.is() )
645             {
646                 Reference< XNameAccess > xNamespaceMap( xIfc, UNO_QUERY );
647                 if( xNamespaceMap.is() )
648                 {
649                     const Sequence< OUString > aPrefixes( xNamespaceMap->getElementNames() );
650                     for( OUString const & prefix : aPrefixes )
651                     {
652                         OUString aURL;
653                         if( xNamespaceMap->getByName( prefix ) >>= aURL )
654                             GetNamespaceMap_().Add( prefix, aURL );
655                     }
656                 }
657             }
658         }
659         catch(const css::uno::Exception&)
660         {
661         }
662     }
663 
664     // Determine model type (#i51726#)
665     DetermineModelType_();
666 }
667 
668 // XInitialize
initialize(const uno::Sequence<uno::Any> & aArguments)669 void SAL_CALL SvXMLExport::initialize( const uno::Sequence< uno::Any >& aArguments )
670 {
671     // #93186# we need to queryInterface every single Any with any expected outcome. This variable hold the queryInterface results.
672 
673     for( const auto& rAny : aArguments )
674     {
675         Reference<XInterface> xValue;
676         rAny >>= xValue;
677 
678         // status indicator
679         uno::Reference<task::XStatusIndicator> xTmpStatus( xValue, UNO_QUERY );
680         if ( xTmpStatus.is() )
681             mxStatusIndicator = xTmpStatus;
682 
683         // graphic storage handler
684         uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler(xValue, UNO_QUERY);
685         if (xGraphicStorageHandler.is())
686             mxGraphicStorageHandler = xGraphicStorageHandler;
687 
688         // object resolver
689         uno::Reference<document::XEmbeddedObjectResolver> xTmpObjectResolver(
690             xValue, UNO_QUERY );
691         if ( xTmpObjectResolver.is() )
692             mxEmbeddedResolver = xTmpObjectResolver;
693 
694         // document handler
695         uno::Reference<xml::sax::XDocumentHandler> xTmpDocHandler(
696             xValue, UNO_QUERY );
697         if( xTmpDocHandler.is() )
698         {
699             mxHandler = xTmpDocHandler;
700             rAny >>= mxExtHandler;
701 
702             if (mxNumberFormatsSupplier.is() && mpNumExport == nullptr)
703                 mpNumExport.reset( new SvXMLNumFmtExport(*this, mxNumberFormatsSupplier) );
704         }
705 
706         // property set to transport data across
707         uno::Reference<beans::XPropertySet> xTmpPropertySet(
708             xValue, UNO_QUERY );
709         if( xTmpPropertySet.is() )
710             mxExportInfo = xTmpPropertySet;
711     }
712 
713     if( !mxExportInfo.is() )
714         return;
715 
716     uno::Reference< beans::XPropertySetInfo > xPropertySetInfo =
717         mxExportInfo->getPropertySetInfo();
718     OUString sPropName(
719             "BaseURI"  );
720     if( xPropertySetInfo->hasPropertyByName(sPropName) )
721     {
722         uno::Any aAny = mxExportInfo->getPropertyValue(sPropName);
723         aAny >>= msOrigFileName;
724         mpImpl->msPackageURI = msOrigFileName;
725         mpImpl->SetSchemeOf( msOrigFileName );
726     }
727     OUString sRelPath;
728     sPropName = "StreamRelPath";
729     if( xPropertySetInfo->hasPropertyByName(sPropName) )
730     {
731         uno::Any aAny = mxExportInfo->getPropertyValue(sPropName);
732         aAny >>= sRelPath;
733     }
734     OUString sName;
735     sPropName = "StreamName";
736     if( xPropertySetInfo->hasPropertyByName(sPropName) )
737     {
738         uno::Any aAny = mxExportInfo->getPropertyValue(sPropName);
739         aAny >>= sName;
740     }
741     if( !msOrigFileName.isEmpty() && !sName.isEmpty() )
742     {
743         INetURLObject aBaseURL( msOrigFileName );
744         if( !sRelPath.isEmpty() )
745             aBaseURL.insertName( sRelPath );
746         aBaseURL.insertName( sName );
747         msOrigFileName = aBaseURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
748     }
749     mpImpl->mStreamName = sName; // Note: may be empty (XSLT)
750 
751     // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
752     static const OUStringLiteral sOutlineStyleAsNormalListStyle(
753             u"OutlineStyleAsNormalListStyle" );
754     if( xPropertySetInfo->hasPropertyByName( sOutlineStyleAsNormalListStyle ) )
755     {
756         uno::Any aAny = mxExportInfo->getPropertyValue( sOutlineStyleAsNormalListStyle );
757         aAny >>= mpImpl->mbOutlineStyleAsNormalListStyle;
758     }
759 
760     OUString sTargetStorage( "TargetStorage" );
761     if( xPropertySetInfo->hasPropertyByName( sTargetStorage ) )
762         mxExportInfo->getPropertyValue( sTargetStorage ) >>= mpImpl->mxTargetStorage;
763 
764     static const OUStringLiteral sExportTextNumberElement(
765             u"ExportTextNumberElement" );
766     if( xPropertySetInfo->hasPropertyByName( sExportTextNumberElement ) )
767     {
768         uno::Any aAny = mxExportInfo->getPropertyValue( sExportTextNumberElement );
769         aAny >>= mpImpl->mbExportTextNumberElement;
770     }
771 }
772 
773 // XFilter
filter(const uno::Sequence<beans::PropertyValue> & aDescriptor)774 sal_Bool SAL_CALL SvXMLExport::filter( const uno::Sequence< beans::PropertyValue >& aDescriptor )
775 {
776     // check for xHandler first... should have been supplied in initialize
777     if( !mxHandler.is() )
778         return false;
779 
780     try
781     {
782         const SvXMLExportFlags nTest =
783             SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SETTINGS;
784         if( (mnExportFlags & nTest) == nTest && msOrigFileName.isEmpty() )
785         {
786             // evaluate descriptor only for flat files and if a base URI
787             // has not been provided already
788 
789             for( const auto& rProp : aDescriptor )
790             {
791                 const OUString& rPropName = rProp.Name;
792                 const Any& rValue = rProp.Value;
793 
794                 if ( rPropName == "FileName" )
795                 {
796                     if( !(rValue >>= msOrigFileName ) )
797                         return false;
798                 }
799                 else if ( rPropName == "FilterName" )
800                 {
801                     if( !(rValue >>= msFilterName ) )
802                         return false;
803                 }
804             }
805         }
806 
807         for( const auto& rProp : aDescriptor )
808         {
809             const OUString& rPropName = rProp.Name;
810             const Any& rValue = rProp.Value;
811 
812             if (rPropName == "SourceShellID")
813             {
814                 if (!(rValue >>= mpImpl->maSrcShellID))
815                     return false;
816             }
817             else if (rPropName == "DestinationShellID")
818             {
819                 if (!(rValue >>= mpImpl->maDestShellID))
820                     return false;
821             }
822             else if( rPropName == "ImageFilter")
823             {
824                 if (!(rValue >>= msImgFilterName))
825                     return false;
826             }
827         }
828 
829 
830         exportDoc( meClass );
831     }
832     catch(const uno::Exception& e)
833     {
834         // We must catch exceptions, because according to the
835         // API definition export must not throw one!
836         css::uno::Any ex(cppu::getCaughtException());
837         OUString sMessage( ex.getValueTypeName() + ": \"" + e.Message + "\"");
838         if (e.Context.is())
839         {
840             const char* pContext = typeid(*e.Context).name();
841             sMessage += " (context: " + OUString::createFromAscii(pContext) + " )";
842         }
843         SetError( XMLERROR_FLAG_ERROR | XMLERROR_FLAG_SEVERE | XMLERROR_API,
844                   Sequence<OUString>(), sMessage, nullptr );
845     }
846 
847     // return true only if no error occurred
848     return (mnErrorFlags & (SvXMLErrorFlags::DO_NOTHING|SvXMLErrorFlags::ERROR_OCCURRED)) == SvXMLErrorFlags::NO;
849 }
850 
cancel()851 void SAL_CALL SvXMLExport::cancel()
852 {
853     // stop export
854     Sequence<OUString> aEmptySeq;
855     SetError(XMLERROR_CANCEL|XMLERROR_FLAG_SEVERE, aEmptySeq);
856 }
857 
getName()858 OUString SAL_CALL SvXMLExport::getName(  )
859 {
860     return msFilterName;
861 }
862 
setName(const OUString &)863 void SAL_CALL SvXMLExport::setName( const OUString& )
864 {
865     // do nothing, because it is not possible to set the FilterName
866 }
867 
868 // XServiceInfo
getImplementationName()869 OUString SAL_CALL SvXMLExport::getImplementationName(  )
870 {
871     return m_implementationName;
872 }
873 
supportsService(const OUString & rServiceName)874 sal_Bool SAL_CALL SvXMLExport::supportsService( const OUString& rServiceName )
875 {
876     return cppu::supportsService(this, rServiceName);
877 }
878 
getSupportedServiceNames()879 uno::Sequence< OUString > SAL_CALL SvXMLExport::getSupportedServiceNames(  )
880 {
881     return { "com.sun.star.document.ExportFilter", "com.sun.star.xml.XMLExportFilter" };
882 }
883 
884 OUString
EnsureNamespace(OUString const & i_rNamespace)885 SvXMLExport::EnsureNamespace(OUString const & i_rNamespace)
886 {
887     OUString const aPreferredPrefix("gen");
888     OUString sPrefix;
889     sal_uInt16 nKey( GetNamespaceMap_().GetKeyByName( i_rNamespace ) );
890     if( XML_NAMESPACE_UNKNOWN == nKey )
891     {
892         // There is no prefix for the namespace, so
893         // we have to generate one and have to add it.
894         sPrefix = aPreferredPrefix;
895         nKey = GetNamespaceMap_().GetKeyByPrefix( sPrefix );
896         sal_Int32 n( 0 );
897         OUStringBuffer buf;
898         while( nKey != USHRT_MAX )
899         {
900             buf.append( aPreferredPrefix );
901             buf.append( ++n );
902             sPrefix = buf.makeStringAndClear();
903             nKey = GetNamespaceMap_().GetKeyByPrefix( sPrefix );
904         }
905 
906         if (mpImpl->mNamespaceMaps.empty()
907             || (mpImpl->mNamespaceMaps.top().second != mpImpl->mDepth))
908         {
909             // top was created for lower depth... need a new namespace map!
910             auto pNew = new SvXMLNamespaceMap( *mpNamespaceMap );
911             mpImpl->mNamespaceMaps.push(
912                 ::std::make_pair(std::move(mpNamespaceMap), mpImpl->mDepth) );
913             mpNamespaceMap.reset( pNew );
914         }
915 
916         // add the namespace to the map and as attribute
917         mpNamespaceMap->Add( sPrefix, i_rNamespace );
918         AddAttribute( GetXMLToken(XML_XMLNS) + ":" + sPrefix, i_rNamespace );
919     }
920     else
921     {
922         // If there is a prefix for the namespace, reuse that.
923         sPrefix = GetNamespaceMap_().GetPrefixByKey( nKey );
924     }
925     return sPrefix;
926 }
927 
AddAttributeASCII(sal_uInt16 nPrefixKey,const char * pName,const char * pValue)928 void SvXMLExport::AddAttributeASCII( sal_uInt16 nPrefixKey,
929                                      const char *pName,
930                                        const char *pValue )
931 {
932     OUString sName( OUString::createFromAscii( pName ) );
933     OUString sValue( OUString::createFromAscii( pValue ) );
934 
935     mxAttrList->AddAttribute(
936         GetNamespaceMap_().GetQNameByKey( nPrefixKey, sName ), sValue );
937 }
938 
AddAttribute(sal_uInt16 nPrefixKey,const char * pName,const OUString & rValue)939 void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey, const char *pName,
940                               const OUString& rValue )
941 {
942     OUString sName( OUString::createFromAscii( pName ) );
943 
944     mxAttrList->AddAttribute(
945         GetNamespaceMap_().GetQNameByKey( nPrefixKey, sName ), rValue );
946 }
947 
AddAttribute(sal_uInt16 nPrefixKey,const OUString & rName,const OUString & rValue)948 void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey, const OUString& rName,
949                               const OUString& rValue )
950 {
951     mxAttrList->AddAttribute(
952         GetNamespaceMap_().GetQNameByKey( nPrefixKey, rName ), rValue );
953 }
954 
AddAttribute(sal_uInt16 nPrefixKey,enum XMLTokenEnum eName,const OUString & rValue)955 void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey,
956                                 enum XMLTokenEnum eName,
957                                 const OUString& rValue )
958 {
959     mxAttrList->AddAttribute(
960         GetNamespaceMap_().GetQNameByKey( nPrefixKey, GetXMLToken(eName) ),
961         rValue );
962 }
963 
AddAttribute(sal_uInt16 nPrefixKey,enum XMLTokenEnum eName,enum XMLTokenEnum eValue)964 void SvXMLExport::AddAttribute( sal_uInt16 nPrefixKey,
965                                 enum XMLTokenEnum eName,
966                                 enum XMLTokenEnum eValue)
967 {
968     mxAttrList->AddAttribute(
969         GetNamespaceMap_().GetQNameByKey( nPrefixKey, GetXMLToken(eName) ),
970         GetXMLToken(eValue) );
971 }
972 
AddAttribute(const OUString & rQName,const OUString & rValue)973 void SvXMLExport::AddAttribute( const OUString& rQName,
974                                 const OUString& rValue )
975 {
976       mxAttrList->AddAttribute(
977         rQName,
978         rValue );
979 }
980 
AddAttribute(const OUString & rQName,enum::xmloff::token::XMLTokenEnum eValue)981 void SvXMLExport::AddAttribute( const OUString& rQName,
982                                 enum ::xmloff::token::XMLTokenEnum eValue )
983 {
984       mxAttrList->AddAttribute(
985         rQName,
986         GetXMLToken(eValue) );
987 }
988 
AddLanguageTagAttributes(sal_uInt16 nPrefix,sal_uInt16 nPrefixRfc,const css::lang::Locale & rLocale,bool bWriteEmpty)989 void SvXMLExport::AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc,
990         const css::lang::Locale& rLocale, bool bWriteEmpty )
991 {
992     if (rLocale.Variant.isEmpty())
993     {
994         // Per convention The BCP 47 string is always stored in Variant, if
995         // that is empty we have a plain language-country combination, no need
996         // to convert to LanguageTag first. Also catches the case of empty
997         // locale denoting system locale.
998         xmloff::token::XMLTokenEnum eLanguage, eCountry;
999         eLanguage = XML_LANGUAGE;
1000         eCountry  = XML_COUNTRY;
1001         if (bWriteEmpty || !rLocale.Language.isEmpty())
1002             AddAttribute( nPrefix, eLanguage, rLocale.Language);
1003         if (bWriteEmpty || !rLocale.Country.isEmpty())
1004             AddAttribute( nPrefix, eCountry, rLocale.Country);
1005     }
1006     else
1007     {
1008         LanguageTag aLanguageTag( rLocale);
1009         AddLanguageTagAttributes( nPrefix, nPrefixRfc, aLanguageTag, bWriteEmpty);
1010     }
1011 }
1012 
AddLanguageTagAttributes(sal_uInt16 nPrefix,sal_uInt16 nPrefixRfc,const LanguageTag & rLanguageTag,bool bWriteEmpty)1013 void SvXMLExport::AddLanguageTagAttributes( sal_uInt16 nPrefix, sal_uInt16 nPrefixRfc,
1014         const LanguageTag& rLanguageTag, bool bWriteEmpty )
1015 {
1016     if (rLanguageTag.isIsoODF())
1017     {
1018         if (bWriteEmpty || !rLanguageTag.isSystemLocale())
1019         {
1020             AddAttribute( nPrefix, XML_LANGUAGE, rLanguageTag.getLanguage());
1021             if (rLanguageTag.hasScript() && getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
1022                 AddAttribute( nPrefix, XML_SCRIPT, rLanguageTag.getScript());
1023             if (bWriteEmpty || !rLanguageTag.getCountry().isEmpty())
1024                 AddAttribute( nPrefix, XML_COUNTRY, rLanguageTag.getCountry());
1025         }
1026     }
1027     else
1028     {
1029         if (getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
1030             AddAttribute( nPrefixRfc, XML_RFC_LANGUAGE_TAG, rLanguageTag.getBcp47());
1031         // Also in case of non-pure-ISO tag store best matching fo: attributes
1032         // for consumers not handling *:rfc-language-tag, ensuring that only
1033         // valid ISO codes are stored. Here the bWriteEmpty parameter has no
1034         // meaning.
1035         OUString aLanguage, aScript, aCountry;
1036         rLanguageTag.getIsoLanguageScriptCountry( aLanguage, aScript, aCountry);
1037         if (!aLanguage.isEmpty())
1038         {
1039             AddAttribute( nPrefix, XML_LANGUAGE, aLanguage);
1040             if (!aScript.isEmpty() && getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
1041                 AddAttribute( nPrefix, XML_SCRIPT, aScript);
1042             if (!aCountry.isEmpty())
1043                 AddAttribute( nPrefix, XML_COUNTRY, aCountry);
1044         }
1045     }
1046 }
1047 
AddAttributeList(const uno::Reference<xml::sax::XAttributeList> & xAttrList)1048 void SvXMLExport::AddAttributeList( const uno::Reference< xml::sax::XAttributeList >& xAttrList )
1049 {
1050     if( xAttrList.is())
1051         mxAttrList->AppendAttributeList( xAttrList );
1052 }
1053 
ClearAttrList()1054 void SvXMLExport::ClearAttrList()
1055 {
1056     mxAttrList->Clear();
1057 }
1058 
1059 #ifdef DBG_UTIL
CheckAttrList()1060 void SvXMLExport::CheckAttrList()
1061 {
1062     SAL_WARN_IF( mxAttrList->getLength(), "xmloff.core", "XMLExport::CheckAttrList: list is not empty" );
1063 }
1064 #endif
1065 
ImplExportMeta()1066 void SvXMLExport::ImplExportMeta()
1067 {
1068     CheckAttrList();
1069 
1070     ExportMeta_();
1071 }
1072 
ImplExportSettings()1073 void SvXMLExport::ImplExportSettings()
1074 {
1075     CheckAttrList();
1076 
1077     ::std::vector< SettingsGroup > aSettings;
1078     sal_Int32 nSettingsCount = 0;
1079 
1080     // view settings
1081     uno::Sequence< beans::PropertyValue > aViewSettings;
1082     GetViewSettingsAndViews( aViewSettings );
1083     aSettings.emplace_back( XML_VIEW_SETTINGS, aViewSettings );
1084     nSettingsCount += aViewSettings.getLength();
1085 
1086     // configuration settings
1087     uno::Sequence<beans::PropertyValue> aConfigSettings;
1088     GetConfigurationSettings( aConfigSettings );
1089     aSettings.emplace_back( XML_CONFIGURATION_SETTINGS, aConfigSettings );
1090     nSettingsCount += aConfigSettings.getLength();
1091 
1092     // any document specific settings
1093     nSettingsCount += GetDocumentSpecificSettings( aSettings );
1094 
1095     {
1096         SvXMLElementExport aElem( *this,
1097                                 nSettingsCount != 0,
1098                                 XML_NAMESPACE_OFFICE, XML_SETTINGS,
1099                                 true, true );
1100 
1101         SettingsExportFacade aSettingsExportContext( *this );
1102         XMLSettingsExportHelper aSettingsExportHelper( aSettingsExportContext );
1103 
1104         for (auto const& settings : aSettings)
1105         {
1106             if ( !settings.aSettings.hasElements() )
1107                 continue;
1108 
1109             const OUString& sSettingsName( GetXMLToken( settings.eGroupName ) );
1110             OUString sQName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OOO, sSettingsName );
1111             aSettingsExportHelper.exportAllSettings( settings.aSettings, sQName );
1112         }
1113     }
1114 }
1115 
ImplExportStyles()1116 void SvXMLExport::ImplExportStyles()
1117 {
1118     CheckAttrList();
1119 
1120     {
1121         // <style:styles>
1122         SvXMLElementExport aElem( *this, XML_NAMESPACE_OFFICE, XML_STYLES,
1123                                 true, true );
1124 
1125         ExportStyles_( false );
1126     }
1127 
1128     // transfer style names (+ families) TO other components (if appropriate)
1129     if( ( mnExportFlags & SvXMLExportFlags::CONTENT ) || !mxExportInfo.is() )
1130         return;
1131 
1132     static OUString sStyleNames( "StyleNames" );
1133     static OUString sStyleFamilies( "StyleFamilies" );
1134     uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
1135     if ( xPropertySetInfo->hasPropertyByName( sStyleNames ) && xPropertySetInfo->hasPropertyByName( sStyleFamilies ) )
1136     {
1137         Sequence<sal_Int32> aStyleFamilies;
1138         Sequence<OUString> aStyleNames;
1139         mxAutoStylePool->GetRegisteredNames( aStyleFamilies, aStyleNames );
1140         mxExportInfo->setPropertyValue( sStyleNames, makeAny( aStyleNames ) );
1141         mxExportInfo->setPropertyValue( sStyleFamilies,
1142                                        makeAny( aStyleFamilies ) );
1143     }
1144 }
1145 
ImplExportAutoStyles()1146 void SvXMLExport::ImplExportAutoStyles()
1147 {
1148     // transfer style names (+ families) FROM other components (if appropriate)
1149     OUString sStyleNames( "StyleNames" );
1150     OUString sStyleFamilies( "StyleFamilies" );
1151     if( ( !( mnExportFlags & SvXMLExportFlags::STYLES ) )
1152         && mxExportInfo.is()
1153         && mxExportInfo->getPropertySetInfo()->hasPropertyByName( sStyleNames )
1154         && mxExportInfo->getPropertySetInfo()->hasPropertyByName( sStyleFamilies ) )
1155     {
1156         Sequence<sal_Int32> aStyleFamilies;
1157         mxExportInfo->getPropertyValue( sStyleFamilies ) >>= aStyleFamilies;
1158         Sequence<OUString> aStyleNames;
1159         mxExportInfo->getPropertyValue( sStyleNames ) >>= aStyleNames;
1160         mxAutoStylePool->RegisterNames( aStyleFamilies, aStyleNames );
1161     }
1162 
1163     {
1164         // <style:automatic-styles>
1165         SvXMLElementExport aElem( *this, XML_NAMESPACE_OFFICE,
1166                                   XML_AUTOMATIC_STYLES, true, true );
1167 
1168         ExportAutoStyles_();
1169     }
1170 }
1171 
ImplExportMasterStyles()1172 void SvXMLExport::ImplExportMasterStyles()
1173 {
1174     // <style:master-styles>
1175     SvXMLElementExport aElem( *this, XML_NAMESPACE_OFFICE, XML_MASTER_STYLES,
1176                             true, true );
1177 
1178     ExportMasterStyles_();
1179 }
1180 
ImplExportContent()1181 void SvXMLExport::ImplExportContent()
1182 {
1183     CheckAttrList();
1184 
1185     {
1186         SvXMLElementExport aElement( *this, XML_NAMESPACE_OFFICE, XML_BODY,
1187                                   true, true );
1188         {
1189             XMLTokenEnum eClass = meClass;
1190             if( XML_TEXT_GLOBAL == eClass )
1191             {
1192                 AddAttribute( XML_NAMESPACE_TEXT, XML_GLOBAL,
1193                       GetXMLToken( XML_TRUE ) );
1194                 eClass = XML_TEXT;
1195             }
1196             if ( XML_GRAPHICS == eClass )
1197                 eClass = XML_DRAWING;
1198             // <office:body ...>
1199             SetBodyAttributes();
1200             SvXMLElementExport aElem( *this, meClass != XML_TOKEN_INVALID,
1201                                       XML_NAMESPACE_OFFICE, eClass,
1202                                         true, true );
1203 
1204             ExportContent_();
1205         }
1206     }
1207 }
1208 
SetBodyAttributes()1209 void SvXMLExport::SetBodyAttributes()
1210 {
1211 }
1212 
1213 static void
lcl_AddGrddl(SvXMLExport const & rExport,const SvXMLExportFlags)1214 lcl_AddGrddl(SvXMLExport const & rExport, const SvXMLExportFlags /*nExportMode*/)
1215 {
1216     // check version >= 1.2
1217     switch (rExport.getSaneDefaultVersion()) {
1218         case SvtSaveOptions::ODFSVER_011: // fall through
1219         case SvtSaveOptions::ODFSVER_010: return;
1220         default: break;
1221     }
1222 
1223     // #i115030#: disabled, the XSLT is not finished, and not available via HTTP
1224 #if 0
1225     if (SvXMLExportFlags::SETTINGS != nExportMode) // meta, content, styles
1226     {
1227         rExport.AddAttribute( XML_NAMESPACE_GRDDL, XML_TRANSFORMATION,
1228             OUString("http://FIXME") );
1229     }
1230 #endif
1231 }
1232 
addChaffWhenEncryptedStorage()1233 void SvXMLExport::addChaffWhenEncryptedStorage()
1234 {
1235     uno::Reference< embed::XEncryptionProtectedSource2 > xEncr(mpImpl->mxTargetStorage, uno::UNO_QUERY);
1236 
1237     if (xEncr.is() && xEncr->hasEncryptionData() && mxExtHandler.is())
1238     {
1239         mxExtHandler->comment(OStringToOUString(comphelper::xml::makeXMLChaff(), RTL_TEXTENCODING_ASCII_US));
1240     }
1241 }
1242 
GetODFVersionAttributeValue() const1243 auto SvXMLExport::GetODFVersionAttributeValue() const -> char const*
1244 {
1245     char const* pVersion(nullptr);
1246     switch (getSaneDefaultVersion())
1247     {
1248     case SvtSaveOptions::ODFSVER_013_EXTENDED: [[fallthrough]];
1249     case SvtSaveOptions::ODFSVER_013: pVersion = "1.3"; break;
1250     case SvtSaveOptions::ODFSVER_012_EXTENDED: [[fallthrough]];
1251     case SvtSaveOptions::ODFSVER_012_EXT_COMPAT: [[fallthrough]];
1252     case SvtSaveOptions::ODFSVER_012: pVersion = "1.2"; break;
1253     case SvtSaveOptions::ODFSVER_011: pVersion = "1.1"; break;
1254     case SvtSaveOptions::ODFSVER_010: break;
1255 
1256     default:
1257         assert(!"xmloff::SvXMLExport::exportDoc(), unexpected odf default version!");
1258     }
1259     return pVersion;
1260 }
1261 
exportDoc(enum::xmloff::token::XMLTokenEnum eClass)1262 ErrCode SvXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )
1263 {
1264     bool bOwnGraphicResolver = false;
1265     bool bOwnEmbeddedResolver = false;
1266 
1267     if (!mxGraphicStorageHandler.is() || !mxEmbeddedResolver.is())
1268     {
1269         Reference< XMultiServiceFactory > xFactory( mxModel,    UNO_QUERY );
1270         if( xFactory.is() )
1271         {
1272             try
1273             {
1274                 if (!mxGraphicStorageHandler.is())
1275                 {
1276                     mxGraphicStorageHandler.set(xFactory->createInstance( "com.sun.star.document.ExportGraphicStorageHandler"), UNO_QUERY);
1277                     bOwnGraphicResolver = mxGraphicStorageHandler.is();
1278                 }
1279 
1280                 if( !mxEmbeddedResolver.is() )
1281                 {
1282                     mxEmbeddedResolver.set(
1283                         xFactory->createInstance( "com.sun.star.document.ExportEmbeddedObjectResolver" ), UNO_QUERY);
1284                     bOwnEmbeddedResolver = mxEmbeddedResolver.is();
1285                 }
1286             }
1287             catch(const css::uno::Exception&)
1288             {
1289             }
1290         }
1291     }
1292     if( (getExportFlags() & SvXMLExportFlags::OASIS) == SvXMLExportFlags::NONE )
1293     {
1294         try
1295         {
1296             static ::comphelper::PropertyMapEntry const aInfoMap[] =
1297             {
1298                 { OUString("Class"), 0,
1299                     ::cppu::UnoType<OUString>::get(),
1300                       PropertyAttribute::MAYBEVOID, 0},
1301                 { OUString(), 0, css::uno::Type(), 0, 0 }
1302             };
1303             Reference< XPropertySet > xConvPropSet(
1304                 ::comphelper::GenericPropertySet_CreateInstance(
1305                         new ::comphelper::PropertySetInfo( aInfoMap ) ) );
1306 
1307             xConvPropSet->setPropertyValue( "Class", Any(GetXMLToken( eClass )) );
1308 
1309             Reference< XPropertySet > xPropSet =
1310                 mxExportInfo.is()
1311                 ?  PropertySetMerger_CreateInstance( mxExportInfo,
1312                                                      xConvPropSet )
1313                 : xConvPropSet;
1314 
1315             Sequence<Any> aArgs( 3 );
1316             aArgs[0] <<= mxHandler;
1317             aArgs[1] <<= xPropSet;
1318             aArgs[2] <<= mxModel;
1319 
1320             // get filter component
1321             Reference< xml::sax::XDocumentHandler > xTmpDocHandler(
1322                 m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext("com.sun.star.comp.Oasis2OOoTransformer", aArgs, m_xContext),
1323                 UNO_QUERY);
1324             SAL_WARN_IF(!xTmpDocHandler.is(), "xmloff.core", "can't instantiate OASIS transformer component" );
1325             if( xTmpDocHandler.is() )
1326             {
1327                 mxHandler = xTmpDocHandler;
1328                 mxExtHandler.set( mxHandler, UNO_QUERY );
1329             }
1330         }
1331         catch(const css::uno::Exception&)
1332         {
1333         }
1334     }
1335 
1336     mxHandler->startDocument();
1337 
1338     addChaffWhenEncryptedStorage();
1339 
1340     // <office:document ...>
1341     CheckAttrList();
1342 
1343     // namespace attributes
1344     // ( The namespace decls should be first attributes in the element;
1345     //   some faulty XML parsers (JAXP1.1) have a problem with this,
1346     //   also it's more elegant )
1347     sal_uInt16 nPos = mpNamespaceMap->GetFirstKey();
1348     while( USHRT_MAX != nPos )
1349     {
1350         mxAttrList->AddAttribute( mpNamespaceMap->GetAttrNameByKey( nPos ),
1351                                   mpNamespaceMap->GetNameByKey( nPos ) );
1352         nPos = mpNamespaceMap->GetNextKey( nPos );
1353     }
1354 
1355     // office:version = ...
1356     const char*const pVersion = GetODFVersionAttributeValue();
1357 
1358     if (pVersion)
1359     {
1360         AddAttribute( XML_NAMESPACE_OFFICE, XML_VERSION,
1361                           OUString::createFromAscii(pVersion) );
1362     }
1363 
1364     {
1365         enum XMLTokenEnum eRootService = XML_TOKEN_INVALID;
1366         const SvXMLExportFlags nExportMode = mnExportFlags & (SvXMLExportFlags::META|SvXMLExportFlags::STYLES|SvXMLExportFlags::CONTENT|SvXMLExportFlags::SETTINGS);
1367 
1368         lcl_AddGrddl(*this, nExportMode);
1369 
1370         if( SvXMLExportFlags::META == nExportMode )
1371         {
1372             // export only meta
1373             eRootService = XML_DOCUMENT_META;
1374         }
1375         else if ( SvXMLExportFlags::SETTINGS == nExportMode )
1376         {
1377             // export only settings
1378             eRootService = XML_DOCUMENT_SETTINGS;
1379         }
1380         else if( SvXMLExportFlags::STYLES == nExportMode )
1381         {
1382             // export only styles
1383             eRootService = XML_DOCUMENT_STYLES;
1384         }
1385         else if( SvXMLExportFlags::CONTENT == nExportMode )
1386         {
1387             // export only content
1388             eRootService = XML_DOCUMENT_CONTENT;
1389         }
1390         else
1391         {
1392             // the god'ol one4all element
1393             eRootService = XML_DOCUMENT;
1394             // office:mimetype = ... (only for stream containing the content)
1395             if( eClass != XML_TOKEN_INVALID )
1396             {
1397                 OUString aTmp = "application/vnd.oasis.opendocument." + GetXMLToken( eClass );
1398                 AddAttribute( XML_NAMESPACE_OFFICE, XML_MIMETYPE, aTmp );
1399             }
1400         }
1401 
1402         SvXMLElementExport aElem( *this, XML_NAMESPACE_OFFICE, eRootService, true, true );
1403 
1404         // meta information
1405         if( mnExportFlags & SvXMLExportFlags::META )
1406             ImplExportMeta();
1407 
1408         // settings
1409         if( mnExportFlags & SvXMLExportFlags::SETTINGS )
1410             ImplExportSettings();
1411 
1412         // scripts
1413         if( mnExportFlags & SvXMLExportFlags::SCRIPTS )
1414             ExportScripts_();
1415 
1416         // font declarations
1417         if( mnExportFlags & SvXMLExportFlags::FONTDECLS )
1418             ExportFontDecls_();
1419 
1420         // styles
1421         if( mnExportFlags & SvXMLExportFlags::STYLES )
1422             ImplExportStyles();
1423 
1424         // autostyles
1425         if( mnExportFlags & SvXMLExportFlags::AUTOSTYLES )
1426             ImplExportAutoStyles();
1427 
1428         // masterstyles
1429         if( mnExportFlags & SvXMLExportFlags::MASTERSTYLES )
1430             ImplExportMasterStyles();
1431 
1432         // content
1433         if( mnExportFlags & SvXMLExportFlags::CONTENT )
1434             ImplExportContent();
1435     }
1436 
1437     mxHandler->endDocument();
1438 
1439     if( bOwnGraphicResolver )
1440     {
1441         uno::Reference<XComponent> xComp(mxGraphicStorageHandler, UNO_QUERY);
1442         xComp->dispose();
1443     }
1444 
1445     if( bOwnEmbeddedResolver )
1446     {
1447         Reference< XComponent > xComp( mxEmbeddedResolver, UNO_QUERY );
1448         xComp->dispose();
1449     }
1450 
1451     return ERRCODE_NONE;
1452 }
1453 
ResetNamespaceMap()1454 void SvXMLExport::ResetNamespaceMap()
1455 {
1456     mpNamespaceMap.reset( new SvXMLNamespaceMap );
1457 }
1458 
GetSourceShellID() const1459 OUString const & SvXMLExport::GetSourceShellID() const
1460 {
1461     return mpImpl->maSrcShellID;
1462 }
1463 
GetDestinationShellID() const1464 OUString const & SvXMLExport::GetDestinationShellID() const
1465 {
1466     return mpImpl->maDestShellID;
1467 }
1468 
ExportMeta_()1469 void SvXMLExport::ExportMeta_()
1470 {
1471     OUString generator( ::utl::DocInfoHelper::GetGeneratorString() );
1472     Reference< XDocumentPropertiesSupplier > xDocPropsSupplier(mxModel,
1473         UNO_QUERY);
1474     if (xDocPropsSupplier.is()) {
1475         Reference<XDocumentProperties> xDocProps(
1476             xDocPropsSupplier->getDocumentProperties());
1477         if (!xDocProps.is()) throw;
1478         // update generator here
1479         xDocProps->setGenerator(generator);
1480         rtl::Reference<SvXMLMetaExport> pMeta = new SvXMLMetaExport(*this, xDocProps);
1481         pMeta->Export();
1482     } else {
1483         // office:meta
1484         SvXMLElementExport aElem( *this, XML_NAMESPACE_OFFICE, XML_META,
1485                                 true, true );
1486         {
1487     // BM: #i60323# export generator even if xInfoProp is empty (which is the
1488     // case for charts). The generator does not depend on xInfoProp
1489             SvXMLElementExport anElem( *this, XML_NAMESPACE_META, XML_GENERATOR,
1490                                       true, true );
1491             Characters(generator);
1492         }
1493     }
1494 }
1495 
ExportScripts_()1496 void SvXMLExport::ExportScripts_()
1497 {
1498     SvXMLElementExport aElement( *this, XML_NAMESPACE_OFFICE, XML_SCRIPTS, true, true );
1499 
1500     // export Basic macros (only for FlatXML)
1501     if ( mnExportFlags & SvXMLExportFlags::EMBEDDED )
1502     {
1503         OUString aValue( GetNamespaceMap().GetPrefixByKey( XML_NAMESPACE_OOO ) + ":Basic" );
1504         AddAttribute( XML_NAMESPACE_SCRIPT, XML_LANGUAGE, aValue );
1505 
1506         SvXMLElementExport aElem( *this, XML_NAMESPACE_OFFICE, XML_SCRIPT, true, true );
1507 
1508         // initialize Basic
1509         if ( mxModel.is() )
1510         {
1511             Reference< beans::XPropertySet > xPSet( mxModel, UNO_QUERY );
1512             if ( xPSet.is() )
1513                 xPSet->getPropertyValue("BasicLibraries");
1514         }
1515 
1516         Reference < XDocumentHandler > xHdl( new XMLBasicExportFilter( mxHandler ) );
1517         Reference< document::XXMLBasicExporter > xExporter = document::XMLOasisBasicExporter::createWithHandler( m_xContext, xHdl );
1518 
1519         xExporter->setSourceDocument( mxModel );
1520         Sequence< PropertyValue > aMediaDesc( 0 );
1521         xExporter->filter( aMediaDesc );
1522     }
1523 
1524     // export document events
1525     Reference< document::XEventsSupplier > xEvents( GetModel(), UNO_QUERY );
1526     GetEventExport().Export( xEvents );
1527 }
1528 
ExportFontDecls_()1529 void SvXMLExport::ExportFontDecls_()
1530 {
1531     if( mxFontAutoStylePool.is() )
1532         mxFontAutoStylePool->exportXML();
1533 }
1534 
ExportStyles_(bool)1535 void SvXMLExport::ExportStyles_( bool )
1536 {
1537     uno::Reference< lang::XMultiServiceFactory > xFact( GetModel(), uno::UNO_QUERY );
1538     if( !xFact.is())
1539         return;
1540 
1541     // export (fill-)gradient-styles
1542     try
1543     {
1544         uno::Reference< container::XNameAccess > xGradient( xFact->createInstance("com.sun.star.drawing.GradientTable"), uno::UNO_QUERY );
1545         if( xGradient.is() )
1546         {
1547             XMLGradientStyleExport aGradientStyle( *this );
1548 
1549             if( xGradient->hasElements() )
1550             {
1551                 const uno::Sequence< OUString > aNamesSeq ( xGradient->getElementNames() );
1552                 for( const OUString& rStrName : aNamesSeq )
1553                 {
1554                     try
1555                     {
1556                         uno::Any aValue = xGradient->getByName( rStrName );
1557 
1558                         aGradientStyle.exportXML( rStrName, aValue );
1559                     }
1560                     catch(const container::NoSuchElementException&)
1561                     {
1562                     }
1563                 }
1564             }
1565         }
1566     }
1567     catch(const lang::ServiceNotRegisteredException&)
1568     {
1569     }
1570 
1571     // export (fill-)hatch-styles
1572     try
1573     {
1574         uno::Reference< container::XNameAccess > xHatch( xFact->createInstance("com.sun.star.drawing.HatchTable"), uno::UNO_QUERY );
1575         if( xHatch.is() )
1576         {
1577             XMLHatchStyleExport aHatchStyle( *this );
1578 
1579             if( xHatch->hasElements() )
1580             {
1581                 const uno::Sequence< OUString > aNamesSeq ( xHatch->getElementNames() );
1582                 for( const OUString& rStrName : aNamesSeq )
1583                 {
1584                     try
1585                     {
1586                         uno::Any aValue = xHatch->getByName( rStrName );
1587 
1588                         aHatchStyle.exportXML( rStrName, aValue );
1589                     }
1590                     catch(const container::NoSuchElementException&)
1591                     {}
1592                 }
1593             }
1594         }
1595     }
1596     catch(const lang::ServiceNotRegisteredException&)
1597     {
1598     }
1599 
1600     // export (fill-)bitmap-styles
1601     try
1602     {
1603         uno::Reference< container::XNameAccess > xBitmap( xFact->createInstance("com.sun.star.drawing.BitmapTable"), uno::UNO_QUERY );
1604         if( xBitmap.is() )
1605         {
1606             if( xBitmap->hasElements() )
1607             {
1608                 const uno::Sequence< OUString > aNamesSeq ( xBitmap->getElementNames() );
1609                 for( const OUString& rStrName : aNamesSeq )
1610                 {
1611                     try
1612                     {
1613                         uno::Any aValue = xBitmap->getByName( rStrName );
1614 
1615                         XMLImageStyle::exportXML( rStrName, aValue, *this );
1616                     }
1617                     catch(const container::NoSuchElementException&)
1618                     {
1619                     }
1620                 }
1621             }
1622         }
1623     }
1624     catch(const lang::ServiceNotRegisteredException&)
1625     {
1626     }
1627 
1628     // export transparency-gradient -styles
1629     try
1630     {
1631         uno::Reference< container::XNameAccess > xTransGradient( xFact->createInstance("com.sun.star.drawing.TransparencyGradientTable"), uno::UNO_QUERY );
1632         if( xTransGradient.is() )
1633         {
1634             XMLTransGradientStyleExport aTransGradientstyle( *this );
1635 
1636             if( xTransGradient->hasElements() )
1637             {
1638                 const uno::Sequence< OUString > aNamesSeq ( xTransGradient->getElementNames() );
1639                 for( const OUString& rStrName : aNamesSeq )
1640                 {
1641                     try
1642                     {
1643                         uno::Any aValue = xTransGradient->getByName( rStrName );
1644 
1645                         aTransGradientstyle.exportXML( rStrName, aValue );
1646                     }
1647                     catch(const container::NoSuchElementException&)
1648                     {
1649                     }
1650                 }
1651             }
1652         }
1653     }
1654     catch(const lang::ServiceNotRegisteredException&)
1655     {
1656     }
1657 
1658     // export marker-styles
1659     try
1660     {
1661         uno::Reference< container::XNameAccess > xMarker( xFact->createInstance("com.sun.star.drawing.MarkerTable"), uno::UNO_QUERY );
1662         if( xMarker.is() )
1663         {
1664             XMLMarkerStyleExport aMarkerStyle( *this );
1665 
1666             if( xMarker->hasElements() )
1667             {
1668                 const uno::Sequence< OUString > aNamesSeq ( xMarker->getElementNames() );
1669                 for( const OUString& rStrName : aNamesSeq )
1670                 {
1671                     try
1672                     {
1673                         uno::Any aValue = xMarker->getByName( rStrName );
1674 
1675                         aMarkerStyle.exportXML( rStrName, aValue );
1676                     }
1677                     catch(const container::NoSuchElementException&)
1678                     {
1679                     }
1680                 }
1681             }
1682         }
1683     }
1684     catch(const lang::ServiceNotRegisteredException&)
1685     {
1686     }
1687 
1688     // export dash-styles
1689     try
1690     {
1691         uno::Reference< container::XNameAccess > xDashes( xFact->createInstance("com.sun.star.drawing.DashTable"), uno::UNO_QUERY );
1692         if( xDashes.is() )
1693         {
1694             XMLDashStyleExport aDashStyle( *this );
1695 
1696             if( xDashes->hasElements() )
1697             {
1698                 const uno::Sequence< OUString > aNamesSeq ( xDashes->getElementNames() );
1699                 for( const OUString& rStrName : aNamesSeq )
1700                 {
1701                     try
1702                     {
1703                         uno::Any aValue = xDashes->getByName( rStrName );
1704 
1705                         aDashStyle.exportXML( rStrName, aValue );
1706                     }
1707                     catch(const container::NoSuchElementException&)
1708                     {
1709                     }
1710                 }
1711             }
1712         }
1713     }
1714     catch(const lang::ServiceNotRegisteredException&)
1715     {
1716     }
1717 }
1718 
CreateTextParagraphExport()1719 XMLTextParagraphExport* SvXMLExport::CreateTextParagraphExport()
1720 {
1721     return new XMLTextParagraphExport( *this, *GetAutoStylePool() );
1722 }
1723 
CreateShapeExport()1724 XMLShapeExport* SvXMLExport::CreateShapeExport()
1725 {
1726     return new XMLShapeExport(*this);
1727 }
1728 
CreateAutoStylePool()1729 SvXMLAutoStylePoolP* SvXMLExport::CreateAutoStylePool()
1730 {
1731     return new SvXMLAutoStylePoolP(*this);
1732 }
1733 
collectAutoStyles()1734 void SvXMLExport::collectAutoStyles()
1735 {
1736 }
1737 
CreatePageExport()1738 XMLPageExport* SvXMLExport::CreatePageExport()
1739 {
1740     return new XMLPageExport( *this );
1741 }
1742 
CreateChartExport()1743 SchXMLExportHelper* SvXMLExport::CreateChartExport()
1744 {
1745     return new SchXMLExportHelper(*this, *GetAutoStylePool());
1746 }
1747 
CreateFontAutoStylePool()1748 XMLFontAutoStylePool* SvXMLExport::CreateFontAutoStylePool()
1749 {
1750     return new XMLFontAutoStylePool( *this );
1751 }
1752 
CreateFormExport()1753 xmloff::OFormLayerXMLExport* SvXMLExport::CreateFormExport()
1754 {
1755     return new xmloff::OFormLayerXMLExport(*this);
1756 }
1757 
GetViewSettingsAndViews(uno::Sequence<beans::PropertyValue> & rProps)1758 void SvXMLExport::GetViewSettingsAndViews(uno::Sequence<beans::PropertyValue>& rProps)
1759 {
1760     GetViewSettings(rProps);
1761     uno::Reference<document::XViewDataSupplier> xViewDataSupplier(GetModel(), uno::UNO_QUERY);
1762     if(!xViewDataSupplier.is())
1763         return;
1764 
1765     uno::Reference<container::XIndexAccess> xIndexAccess;
1766     xViewDataSupplier->setViewData( xIndexAccess ); // make sure we get a newly created sequence
1767     {
1768         // tdf#130559: don't export preview view data if active
1769         css::uno::ContextLayer layer(comphelper::NewFlagContext("NoPreviewData"));
1770         xIndexAccess = xViewDataSupplier->getViewData();
1771     }
1772     bool bAdd = false;
1773     uno::Any aAny;
1774     if(xIndexAccess.is() && xIndexAccess->hasElements() )
1775     {
1776         sal_Int32 nCount = xIndexAccess->getCount();
1777         for (sal_Int32 i = 0; i < nCount; i++)
1778         {
1779             aAny = xIndexAccess->getByIndex(i);
1780             uno::Sequence<beans::PropertyValue> aProps;
1781             if( aAny >>= aProps )
1782             {
1783                 if( aProps.hasElements() )
1784                 {
1785                     bAdd = true;
1786                     break;
1787                 }
1788             }
1789         }
1790     }
1791 
1792     if( bAdd )
1793     {
1794         sal_Int32 nOldLength(rProps.getLength());
1795         rProps.realloc(nOldLength + 1);
1796         beans::PropertyValue aProp;
1797         aProp.Name = "Views";
1798         aProp.Value <<= xIndexAccess;
1799         rProps[nOldLength] = aProp;
1800     }
1801 }
1802 
GetViewSettings(uno::Sequence<beans::PropertyValue> &)1803 void SvXMLExport::GetViewSettings(uno::Sequence<beans::PropertyValue>&)
1804 {
1805 }
1806 
GetConfigurationSettings(uno::Sequence<beans::PropertyValue> &)1807 void SvXMLExport::GetConfigurationSettings(uno::Sequence<beans::PropertyValue>&)
1808 {
1809 }
1810 
GetDocumentSpecificSettings(::std::vector<SettingsGroup> &)1811 sal_Int32 SvXMLExport::GetDocumentSpecificSettings( ::std::vector< SettingsGroup >& )
1812 {
1813     return 0;
1814 }
1815 
collectDataStyles(bool bFromUsedStyles)1816 void SvXMLExport::collectDataStyles(bool bFromUsedStyles)
1817 {
1818     Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(GetModel(), uno::UNO_QUERY);
1819     if (!xStyleFamiliesSupplier.is())
1820         return;
1821 
1822     Reference<container::XNameAccess> xStylesFamilies(xStyleFamiliesSupplier->getStyleFamilies());
1823     if (!xStylesFamilies.is())
1824         return;
1825 
1826     Reference<container::XIndexAccess> xCellStyles(xStylesFamilies->getByName("CellStyles"), uno::UNO_QUERY);
1827     if (!xCellStyles.is())
1828         return;
1829 
1830     sal_Int32 nCount(xCellStyles->getCount());
1831     for (sal_Int32 i = 0; i < nCount; ++i)
1832     {
1833         Reference<style::XStyle> xStyle(xCellStyles->getByIndex(i), uno::UNO_QUERY);
1834         if (bFromUsedStyles && !xStyle->isInUse())
1835             continue;
1836 
1837         Reference<beans::XPropertySet> xCellProperties(xStyle, uno::UNO_QUERY);
1838         if (xCellProperties.is())
1839         {
1840             sal_Int32 nNumberFormat = 0;
1841             if (xCellProperties->getPropertyValue("NumberFormat") >>= nNumberFormat)
1842                 addDataStyle(nNumberFormat);
1843         }
1844     }
1845 }
1846 
addDataStyle(const sal_Int32 nNumberFormat,bool)1847 void SvXMLExport::addDataStyle(const sal_Int32 nNumberFormat, bool /*bTimeFormat*/ )
1848 {
1849     if(mpNumExport)
1850         mpNumExport->SetUsed(nNumberFormat);
1851 }
1852 
exportDataStyles()1853 void SvXMLExport::exportDataStyles()
1854 {
1855     if(mpNumExport)
1856         mpNumExport->Export(false);
1857 }
1858 
exportAutoDataStyles()1859 void SvXMLExport::exportAutoDataStyles()
1860 {
1861     if(mpNumExport)
1862         mpNumExport->Export(true);
1863 
1864     if (mxFormExport.is())
1865         mxFormExport->exportAutoControlNumberStyles();
1866 }
1867 
getDataStyleName(const sal_Int32 nNumberFormat,bool) const1868 OUString SvXMLExport::getDataStyleName(const sal_Int32 nNumberFormat, bool /*bTimeFormat*/ ) const
1869 {
1870     OUString sTemp;
1871     if(mpNumExport)
1872         sTemp = mpNumExport->GetStyleName(nNumberFormat);
1873     return sTemp;
1874 }
1875 
exportAnnotationMeta(const uno::Reference<drawing::XShape> &)1876 void SvXMLExport::exportAnnotationMeta(const uno::Reference<drawing::XShape>&)
1877 {
1878 }
1879 
dataStyleForceSystemLanguage(sal_Int32 nFormat) const1880 sal_Int32 SvXMLExport::dataStyleForceSystemLanguage(sal_Int32 nFormat) const
1881 {
1882     return ( mpNumExport != nullptr )
1883                  ? mpNumExport->ForceSystemLanguage( nFormat ) : nFormat;
1884 }
1885 
AddEmbeddedXGraphic(uno::Reference<graphic::XGraphic> const & rxGraphic,OUString & rOutMimeType,OUString const & rRequestedName)1886 OUString SvXMLExport::AddEmbeddedXGraphic(uno::Reference<graphic::XGraphic> const & rxGraphic, OUString & rOutMimeType, OUString const & rRequestedName)
1887 {
1888     OUString sURL;
1889 
1890     Graphic aGraphic(rxGraphic);
1891     OUString aOriginURL = aGraphic.getOriginURL();
1892 
1893     if (!aOriginURL.isEmpty())
1894     {
1895         sURL = GetRelativeReference(aOriginURL);
1896     }
1897     else
1898     {
1899         if (mxGraphicStorageHandler.is())
1900         {
1901             if (!(getExportFlags() & SvXMLExportFlags::EMBEDDED))
1902                 sURL = mxGraphicStorageHandler->saveGraphicByName(rxGraphic, rOutMimeType, rRequestedName);
1903         }
1904     }
1905     return sURL;
1906 }
1907 
GetGraphicMimeTypeFromStream(uno::Reference<graphic::XGraphic> const & rxGraphic,OUString & rOutMimeType)1908 bool SvXMLExport::GetGraphicMimeTypeFromStream(uno::Reference<graphic::XGraphic> const & rxGraphic, OUString & rOutMimeType)
1909 {
1910     if (mxGraphicStorageHandler.is())
1911     {
1912         Reference<XInputStream> xInputStream(mxGraphicStorageHandler->createInputStream(rxGraphic));
1913         if (xInputStream.is())
1914         {
1915             rOutMimeType = comphelper::GraphicMimeTypeHelper::GetMimeTypeForImageStream(xInputStream);
1916             return true;
1917         }
1918     }
1919 
1920     return false;
1921 }
1922 
AddEmbeddedXGraphicAsBase64(uno::Reference<graphic::XGraphic> const & rxGraphic)1923 bool SvXMLExport::AddEmbeddedXGraphicAsBase64(uno::Reference<graphic::XGraphic> const & rxGraphic)
1924 {
1925     if ((getExportFlags() & SvXMLExportFlags::EMBEDDED) &&
1926         mxGraphicStorageHandler.is())
1927     {
1928         Reference<XInputStream> xInputStream(mxGraphicStorageHandler->createInputStream(rxGraphic));
1929         if (xInputStream.is())
1930         {
1931             Graphic aGraphic(rxGraphic);
1932             if (aGraphic.getOriginURL().isEmpty()) // don't add the base64 if the origin URL is set (image is from an external URL)
1933             {
1934                 XMLBase64Export aBase64Exp(*this);
1935                 return aBase64Exp.exportOfficeBinaryDataElement(xInputStream);
1936             }
1937         }
1938     }
1939 
1940     return false;
1941 }
1942 
AddEmbeddedObject(const OUString & rEmbeddedObjectURL)1943 OUString SvXMLExport::AddEmbeddedObject( const OUString& rEmbeddedObjectURL )
1944 {
1945     OUString sRet;
1946     bool bSupportedURL = rEmbeddedObjectURL.startsWith(XML_EMBEDDEDOBJECT_URL_BASE) ||
1947                          rEmbeddedObjectURL.startsWith(XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE);
1948     if (bSupportedURL && mxEmbeddedResolver.is())
1949     {
1950         sRet = mxEmbeddedResolver->resolveEmbeddedObjectURL(rEmbeddedObjectURL);
1951     }
1952     else
1953         sRet = GetRelativeReference( rEmbeddedObjectURL );
1954 
1955     return sRet;
1956 }
1957 
AddEmbeddedObjectAsBase64(const OUString & rEmbeddedObjectURL)1958 bool SvXMLExport::AddEmbeddedObjectAsBase64( const OUString& rEmbeddedObjectURL )
1959 {
1960     bool bRet = false;
1961     bool bSupportedURL = rEmbeddedObjectURL.startsWith(XML_EMBEDDEDOBJECT_URL_BASE) ||
1962                          rEmbeddedObjectURL.startsWith(XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE);
1963     if (bSupportedURL && mxEmbeddedResolver.is())
1964     {
1965         Reference < XNameAccess > xNA( mxEmbeddedResolver, UNO_QUERY );
1966         if( xNA.is() )
1967         {
1968             Any aAny = xNA->getByName( rEmbeddedObjectURL );
1969             Reference < XInputStream > xIn;
1970             aAny >>= xIn;
1971             if( xIn.is() )
1972             {
1973                 XMLBase64Export aBase64Exp( *this );
1974                 bRet = aBase64Exp.exportOfficeBinaryDataElement( xIn );
1975             }
1976         }
1977     }
1978 
1979     return bRet;
1980 }
1981 
EncodeStyleName(const OUString & rName,bool * pEncoded) const1982 OUString SvXMLExport::EncodeStyleName(
1983         const OUString& rName,
1984         bool *pEncoded ) const
1985 {
1986     return GetMM100UnitConverter().encodeStyleName( rName, pEncoded );
1987 }
1988 
GetProgressBarHelper()1989 ProgressBarHelper*  SvXMLExport::GetProgressBarHelper()
1990 {
1991     if (!mpProgressBarHelper)
1992     {
1993         mpProgressBarHelper.reset( new ProgressBarHelper(mxStatusIndicator, true) );
1994 
1995         if (mxExportInfo.is())
1996         {
1997             uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = mxExportInfo->getPropertySetInfo();
1998             if (xPropertySetInfo.is())
1999             {
2000                 OUString sProgressRange(XML_PROGRESSRANGE);
2001                 OUString sProgressMax(XML_PROGRESSMAX);
2002                 OUString sProgressCurrent(XML_PROGRESSCURRENT);
2003                 OUString sRepeat(XML_PROGRESSREPEAT);
2004                 if (xPropertySetInfo->hasPropertyByName(sProgressMax) &&
2005                     xPropertySetInfo->hasPropertyByName(sProgressCurrent) &&
2006                     xPropertySetInfo->hasPropertyByName(sProgressRange))
2007                 {
2008                     uno::Any aAny;
2009                     sal_Int32 nProgressMax(0);
2010                     sal_Int32 nProgressCurrent(0);
2011                     sal_Int32 nProgressRange(0);
2012                     aAny = mxExportInfo->getPropertyValue(sProgressRange);
2013                     if (aAny >>= nProgressRange)
2014                         mpProgressBarHelper->SetRange(nProgressRange);
2015                     aAny = mxExportInfo->getPropertyValue(sProgressMax);
2016                     if (aAny >>= nProgressMax)
2017                         mpProgressBarHelper->SetReference(nProgressMax);
2018                     aAny = mxExportInfo->getPropertyValue(sProgressCurrent);
2019                     if (aAny >>= nProgressCurrent)
2020                         mpProgressBarHelper->SetValue(nProgressCurrent);
2021                 }
2022                 if (xPropertySetInfo->hasPropertyByName(sRepeat))
2023                 {
2024                     uno::Any aAny = mxExportInfo->getPropertyValue(sRepeat);
2025                     if (aAny.getValueType() == cppu::UnoType<bool>::get())
2026                         mpProgressBarHelper->SetRepeat(::cppu::any2bool(aAny));
2027                     else {
2028                         SAL_WARN("xmloff.core", "why is it no boolean?" );
2029                     }
2030                 }
2031             }
2032         }
2033     }
2034     return mpProgressBarHelper.get();
2035 }
2036 
GetEventExport()2037 XMLEventExport& SvXMLExport::GetEventExport()
2038 {
2039     if( nullptr == mpEventExport)
2040     {
2041         // create EventExport on demand
2042         mpEventExport.reset( new XMLEventExport(*this) );
2043 
2044         // and register standard handlers + names
2045         mpEventExport->AddHandler("StarBasic", std::make_unique<XMLStarBasicExportHandler>());
2046         mpEventExport->AddHandler("Script", std::make_unique<XMLScriptExportHandler>());
2047         mpEventExport->AddTranslationTable(aStandardEventTable);
2048     }
2049 
2050     return *mpEventExport;
2051 }
2052 
GetImageMapExport()2053 XMLImageMapExport& SvXMLExport::GetImageMapExport()
2054 {
2055     // image map export, create on-demand
2056     if( nullptr == mpImageMapExport )
2057     {
2058         mpImageMapExport.reset( new XMLImageMapExport(*this) );
2059     }
2060 
2061     return *mpImageMapExport;
2062 }
2063 
2064 // XUnoTunnel & co
2065 UNO3_GETIMPLEMENTATION_IMPL(SvXMLExport);
2066 
ExportEmbeddedOwnObject(Reference<XComponent> const & rComp)2067 void SvXMLExport::ExportEmbeddedOwnObject( Reference< XComponent > const & rComp )
2068 {
2069     OUString sFilterService;
2070 
2071     Reference < lang::XServiceInfo > xServiceInfo( rComp, UNO_QUERY );
2072     if( xServiceInfo.is() )
2073     {
2074         const XMLServiceMapEntry_Impl *pEntry = aServiceMap;
2075         while( pEntry->sModelService )
2076         {
2077             OUString sModelService( pEntry->sModelService,
2078                                     pEntry->nModelServiceLen,
2079                                        RTL_TEXTENCODING_ASCII_US );
2080             if( xServiceInfo->supportsService( sModelService ) )
2081             {
2082                 sFilterService = OUString( pEntry->sFilterService,
2083                                            pEntry->nFilterServiceLen,
2084                                               RTL_TEXTENCODING_ASCII_US );
2085                 break;
2086             }
2087             pEntry++;
2088         }
2089     }
2090 
2091     SAL_WARN_IF( !sFilterService.getLength(), "xmloff.core", "no export filter for own object" );
2092 
2093     if( sFilterService.isEmpty() )
2094         return;
2095 
2096     Reference < XDocumentHandler > xHdl =
2097         new XMLEmbeddedObjectExportFilter( mxHandler );
2098 
2099     Sequence < Any > aArgs( 1 );
2100     aArgs[0] <<= xHdl;
2101 
2102     Reference< document::XExporter > xExporter(
2103         m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(sFilterService, aArgs, m_xContext),
2104         UNO_QUERY);
2105     SAL_WARN_IF( !xExporter.is(), "xmloff.core", "can't instantiate export filter component for own object" );
2106     if( !xExporter.is() )
2107         return;
2108 
2109     xExporter->setSourceDocument( rComp );
2110 
2111     Reference<XFilter> xFilter( xExporter, UNO_QUERY );
2112 
2113     Sequence < PropertyValue > aMediaDesc( 0 );
2114     xFilter->filter( aMediaDesc );
2115 }
2116 
GetRelativeReference(const OUString & rValue)2117 OUString SvXMLExport::GetRelativeReference(const OUString& rValue)
2118 {
2119     OUString sValue( rValue );
2120     // #i65474# handling of fragment URLs ("#...") is undefined
2121     // they are stored 'as is'
2122     uno::Reference< uri::XUriReference > xUriRef;
2123     if(!sValue.isEmpty() && sValue[0] != '#')
2124     {
2125         try
2126         {
2127             xUriRef = mpImpl->mxUriReferenceFactory->parse( rValue );
2128             if( xUriRef.is() && !xUriRef->isAbsolute() )
2129             {
2130                 //#i61943# relative URLs need special handling
2131                 INetURLObject aTemp( mpImpl->msPackageURI );
2132                 bool bWasAbsolute = false;
2133                 sValue = aTemp.smartRel2Abs(sValue, bWasAbsolute ).GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
2134             }
2135         }
2136         catch(const uno::Exception&)
2137         {
2138         }
2139     }
2140     if( xUriRef.is() )//no conversion for empty values or for fragments
2141     {
2142         //conversion for matching schemes only
2143         if( xUriRef->getScheme() == mpImpl->msPackageURIScheme )
2144         {
2145             sValue = INetURLObject::GetRelURL( msOrigFileName, sValue );
2146         }
2147     }
2148     return sValue;
2149 }
2150 
StartElement(sal_uInt16 nPrefix,enum::xmloff::token::XMLTokenEnum eName,bool bIgnWSOutside)2151 void SvXMLExport::StartElement(sal_uInt16 nPrefix,
2152                         enum ::xmloff::token::XMLTokenEnum eName,
2153                         bool bIgnWSOutside )
2154 {
2155     StartElement(GetNamespaceMap_().GetQNameByKey( nPrefix,
2156         GetXMLToken(eName) ), bIgnWSOutside);
2157 }
2158 
StartElement(const OUString & rName,bool bIgnWSOutside)2159 void SvXMLExport::StartElement(const OUString& rName,
2160                         bool bIgnWSOutside )
2161 {
2162     if ((mnErrorFlags & SvXMLErrorFlags::DO_NOTHING) != SvXMLErrorFlags::DO_NOTHING)
2163     {
2164         try
2165         {
2166             if( bIgnWSOutside && ((mnExportFlags & SvXMLExportFlags::PRETTY) == SvXMLExportFlags::PRETTY))
2167                 mxHandler->ignorableWhitespace( msWS );
2168             mxHandler->startElement( rName, GetXAttrList() );
2169         }
2170         catch (const SAXInvalidCharacterException& e)
2171         {
2172             Sequence<OUString> aPars { rName };
2173             SetError( XMLERROR_SAX|XMLERROR_FLAG_WARNING, aPars, e.Message, nullptr );
2174         }
2175         catch (const SAXException& e)
2176         {
2177             Sequence<OUString> aPars { rName };
2178             SetError( XMLERROR_SAX|XMLERROR_FLAG_ERROR|XMLERROR_FLAG_SEVERE,
2179                       aPars, e.Message, nullptr );
2180         }
2181     }
2182     ClearAttrList();
2183     ++mpImpl->mDepth; // increment nesting depth counter
2184 }
2185 
Characters(const OUString & rChars)2186 void SvXMLExport::Characters(const OUString& rChars)
2187 {
2188     if ((mnErrorFlags & SvXMLErrorFlags::DO_NOTHING) == SvXMLErrorFlags::DO_NOTHING)
2189         return;
2190 
2191     try
2192     {
2193         mxHandler->characters(rChars);
2194     }
2195     catch (const SAXInvalidCharacterException& e)
2196     {
2197         Sequence<OUString> aPars { rChars };
2198         SetError( XMLERROR_SAX|XMLERROR_FLAG_WARNING, aPars, e.Message, nullptr );
2199     }
2200     catch (const SAXException& e)
2201     {
2202         Sequence<OUString> aPars { rChars };
2203         SetError( XMLERROR_SAX|XMLERROR_FLAG_ERROR|XMLERROR_FLAG_SEVERE,
2204                   aPars, e.Message, nullptr );
2205     }
2206 }
2207 
EndElement(sal_uInt16 nPrefix,enum::xmloff::token::XMLTokenEnum eName,bool bIgnWSInside)2208 void SvXMLExport::EndElement(sal_uInt16 nPrefix,
2209                         enum ::xmloff::token::XMLTokenEnum eName,
2210                         bool bIgnWSInside )
2211 {
2212     EndElement(GetNamespaceMap_().GetQNameByKey( nPrefix, GetXMLToken(eName) ),
2213         bIgnWSInside);
2214 }
2215 
EndElement(const OUString & rName,bool bIgnWSInside)2216 void SvXMLExport::EndElement(const OUString& rName,
2217                         bool bIgnWSInside )
2218 {
2219     // decrement nesting depth counter & (maybe) restore namespace map
2220     --mpImpl->mDepth;
2221     if (!mpImpl->mNamespaceMaps.empty() &&
2222         (mpImpl->mNamespaceMaps.top().second == mpImpl->mDepth))
2223     {
2224         mpNamespaceMap = std::move(mpImpl->mNamespaceMaps.top().first);
2225         mpImpl->mNamespaceMaps.pop();
2226     }
2227     SAL_WARN_IF(!mpImpl->mNamespaceMaps.empty() &&
2228         (mpImpl->mNamespaceMaps.top().second >= mpImpl->mDepth), "xmloff.core", "SvXMLExport: NamespaceMaps corrupted");
2229 
2230     if ((mnErrorFlags & SvXMLErrorFlags::DO_NOTHING) == SvXMLErrorFlags::DO_NOTHING)
2231         return;
2232 
2233     try
2234     {
2235         if( bIgnWSInside && ((mnExportFlags & SvXMLExportFlags::PRETTY) == SvXMLExportFlags::PRETTY))
2236             mxHandler->ignorableWhitespace( msWS );
2237         mxHandler->endElement( rName );
2238     }
2239     catch (const SAXException& e)
2240     {
2241         Sequence<OUString> aPars { rName };
2242         SetError( XMLERROR_SAX|XMLERROR_FLAG_ERROR|XMLERROR_FLAG_SEVERE,
2243                   aPars, e.Message, nullptr );
2244     }
2245 }
2246 
IgnorableWhitespace()2247 void SvXMLExport::IgnorableWhitespace()
2248 {
2249     if ((mnExportFlags & SvXMLExportFlags::PRETTY) != SvXMLExportFlags::PRETTY)
2250         return;
2251 
2252     if ((mnErrorFlags & SvXMLErrorFlags::DO_NOTHING) == SvXMLErrorFlags::DO_NOTHING)
2253         return;
2254 
2255     try
2256     {
2257         mxHandler->ignorableWhitespace( msWS );
2258     }
2259     catch (const SAXException& e)
2260     {
2261         SetError( XMLERROR_SAX|XMLERROR_FLAG_ERROR|XMLERROR_FLAG_SEVERE,
2262                   {}, e.Message, nullptr );
2263     }
2264 }
2265 
SetError(sal_Int32 nId,const Sequence<OUString> & rMsgParams,const OUString & rExceptionMessage,const Reference<XLocator> & rLocator)2266 void SvXMLExport::SetError(
2267     sal_Int32 nId,
2268     const Sequence<OUString>& rMsgParams,
2269     const OUString& rExceptionMessage,
2270     const Reference<XLocator>& rLocator )
2271 {
2272     // allow multi-threaded access to the cancel() method
2273     static osl::Mutex aMutex;
2274     osl::MutexGuard aGuard(aMutex);
2275 
2276     // maintain error flags
2277     if ( ( nId & XMLERROR_FLAG_ERROR ) != 0 )
2278         mnErrorFlags |= SvXMLErrorFlags::ERROR_OCCURRED;
2279     if ( ( nId & XMLERROR_FLAG_WARNING ) != 0 )
2280         mnErrorFlags |= SvXMLErrorFlags::WARNING_OCCURRED;
2281     if ( ( nId & XMLERROR_FLAG_SEVERE ) != 0 )
2282         mnErrorFlags |= SvXMLErrorFlags::DO_NOTHING;
2283 
2284     // create error list on demand
2285     if ( mpXMLErrors == nullptr )
2286         mpXMLErrors.reset( new XMLErrors() );
2287 
2288     // save error information
2289     mpXMLErrors->AddRecord( nId, rMsgParams, rExceptionMessage, rLocator );
2290 }
2291 
SetError(sal_Int32 nId,const Sequence<OUString> & rMsgParams)2292 void SvXMLExport::SetError(
2293     sal_Int32 nId,
2294     const Sequence<OUString>& rMsgParams)
2295 {
2296     SetError( nId, rMsgParams, "", nullptr );
2297 }
2298 
DisposingModel()2299 void SvXMLExport::DisposingModel()
2300 {
2301     mxModel.clear();
2302     // Shapes in Writer cannot be named via context menu (#i51726#)
2303     meModelType = SvtModuleOptions::EFactory::UNKNOWN_FACTORY;
2304     mxEventListener.clear();
2305 }
2306 
2307 
getInterfaceToIdentifierMapper()2308 ::comphelper::UnoInterfaceToUniqueIdentifierMapper& SvXMLExport::getInterfaceToIdentifierMapper()
2309 {
2310     return mpImpl->maInterfaceToIdentifierMapper;
2311 }
2312 
2313 // Written OpenDocument file format doesn't fit to the created text document (#i69627#)
writeOutlineStyleAsNormalListStyle() const2314 bool SvXMLExport::writeOutlineStyleAsNormalListStyle() const
2315 {
2316     return mpImpl->mbOutlineStyleAsNormalListStyle;
2317 }
2318 
GetTargetStorage() const2319 uno::Reference< embed::XStorage > const & SvXMLExport::GetTargetStorage() const
2320 {
2321     return mpImpl->mxTargetStorage;
2322 }
2323 
getSaneDefaultVersion() const2324 SvtSaveOptions::ODFSaneDefaultVersion SvXMLExport::getSaneDefaultVersion() const
2325 {
2326     if (mpImpl->m_oOverrideODFVersion)
2327     {
2328         return *mpImpl->m_oOverrideODFVersion;
2329     }
2330     return mpImpl->maSaveOptions.GetODFSaneDefaultVersion();
2331 }
2332 
2333 void
AddAttributeIdLegacy(sal_uInt16 const nLegacyPrefix,OUString const & rValue)2334 SvXMLExport::AddAttributeIdLegacy(
2335         sal_uInt16 const nLegacyPrefix, OUString const& rValue)
2336 {
2337     switch (getSaneDefaultVersion()) {
2338         case SvtSaveOptions::ODFSVER_011: // fall through
2339         case SvtSaveOptions::ODFSVER_010: break;
2340         default: // ODF 1.2: xml:id
2341             AddAttribute(XML_NAMESPACE_XML, XML_ID, rValue);
2342     }
2343     // in ODF 1.1 this was form:id, anim:id, draw:id, or text:id
2344     // backward compatibility: in ODF 1.2 write _both_ id attrs
2345     AddAttribute(nLegacyPrefix, XML_ID, rValue);
2346     // FIXME: this function simply assumes that rValue is unique
2347 }
2348 
2349 void
AddAttributeXmlId(uno::Reference<uno::XInterface> const & i_xIfc)2350 SvXMLExport::AddAttributeXmlId(uno::Reference<uno::XInterface> const & i_xIfc)
2351 {
2352     // check version >= 1.2
2353     switch (getSaneDefaultVersion()) {
2354         case SvtSaveOptions::ODFSVER_011: // fall through
2355         case SvtSaveOptions::ODFSVER_010: return;
2356         default: break;
2357     }
2358     const uno::Reference<rdf::XMetadatable> xMeta(i_xIfc,
2359         uno::UNO_QUERY);
2360 //FIXME not yet...
2361     if ( !xMeta.is() )
2362         return;
2363 
2364     const beans::StringPair mdref( xMeta->getMetadataReference() );
2365     if ( mdref.Second.isEmpty() )
2366         return;
2367 
2368     const OUString streamName = mpImpl->mStreamName;
2369     if ( !streamName.isEmpty() )
2370     {
2371         if ( streamName == mdref.First )
2372         {
2373             AddAttribute( XML_NAMESPACE_XML, XML_ID, mdref.Second );
2374         }
2375         else
2376         {
2377             SAL_WARN("xmloff.core","SvXMLExport::AddAttributeXmlId: invalid stream name");
2378         }
2379     }
2380     else
2381     {
2382         // FIXME: this is ugly
2383         // there is no stream name (e.g. XSLT, flat-xml format)!
2384         // but how do we ensure uniqueness in this case?
2385         // a) just omit styles.xml ids -- they are unlikely anyway...
2386         // b) somehow find out whether we are currently exporting styles
2387         //    or content, and prefix "s" or "c" => unique
2388         if ( mdref.First == "content.xml" )
2389         {
2390             AddAttribute( XML_NAMESPACE_XML, XML_ID, mdref.Second );
2391         }
2392         else
2393         {
2394             SAL_INFO("xmloff.core", "SvXMLExport::AddAttributeXmlId: no stream name given: dropping styles.xml xml:id");
2395         }
2396     }
2397 }
2398 
2399 void
AddAttributesRDFa(uno::Reference<text::XTextContent> const & i_xTextContent)2400 SvXMLExport::AddAttributesRDFa(
2401     uno::Reference<text::XTextContent> const & i_xTextContent)
2402 {
2403     // check version >= 1.2
2404     switch (getSaneDefaultVersion()) {
2405         case SvtSaveOptions::ODFSVER_011: // fall through
2406         case SvtSaveOptions::ODFSVER_010: return;
2407         default: break;
2408     }
2409 
2410     const uno::Reference<rdf::XMetadatable> xMeta(
2411         i_xTextContent, uno::UNO_QUERY);
2412     if (!xMeta.is() || xMeta->getMetadataReference().Second.isEmpty())
2413     {
2414         return; // no xml:id => no RDFa
2415     }
2416 
2417     if (!mpImpl->mpRDFaHelper)
2418     {
2419         mpImpl->mpRDFaHelper.reset( new ::xmloff::RDFaExportHelper(*this) );
2420     }
2421     mpImpl->mpRDFaHelper->AddRDFa(xMeta);
2422 }
2423 
exportTextNumberElement() const2424 bool SvXMLExport::exportTextNumberElement() const
2425 {
2426     return mpImpl->mbExportTextNumberElement;
2427 }
2428 
SetNullDateOnUnitConverter()2429 bool SvXMLExport::SetNullDateOnUnitConverter()
2430 {
2431     // if the null date has already been set, don't set it again (performance)
2432     if (!mpImpl->mbNullDateInitialized)
2433         mpImpl->mbNullDateInitialized = GetMM100UnitConverter().setNullDate(GetModel());
2434 
2435     return mpImpl->mbNullDateInitialized;
2436 }
2437 
GetImageFilterName() const2438 OUString const & SvXMLExport::GetImageFilterName() const
2439 {
2440     return msImgFilterName;
2441 }
2442 
StartElement(const sal_uInt16 nPrefixKey,const OUString & rLName,const bool bIgnoreWhitespaceOutside)2443 void SvXMLElementExport::StartElement(
2444     const sal_uInt16 nPrefixKey,
2445     const OUString& rLName,
2446     const bool bIgnoreWhitespaceOutside )
2447 {
2448     maElementName = mrExport.GetNamespaceMap().GetQNameByKey(nPrefixKey, rLName);
2449     mrExport.StartElement(maElementName, bIgnoreWhitespaceOutside);
2450 }
2451 
SvXMLElementExport(SvXMLExport & rExp,sal_uInt16 nPrefixKey,const char * pLName,bool bIWSOutside,bool bIWSInside)2452 SvXMLElementExport::SvXMLElementExport(
2453     SvXMLExport& rExp,
2454     sal_uInt16 nPrefixKey,
2455     const char *pLName,
2456     bool bIWSOutside,
2457     bool bIWSInside )
2458     : mrExport( rExp )
2459     , maElementName()
2460     , mbIgnoreWhitespaceInside( bIWSInside )
2461     , mbDoSomething( true )
2462 {
2463     const OUString sLName( OUString::createFromAscii( pLName ) );
2464     StartElement( nPrefixKey, sLName, bIWSOutside );
2465 }
2466 
SvXMLElementExport(SvXMLExport & rExp,sal_uInt16 nPrefixKey,const OUString & rLName,bool bIWSOutside,bool bIWSInside)2467 SvXMLElementExport::SvXMLElementExport(
2468     SvXMLExport& rExp,
2469     sal_uInt16 nPrefixKey,
2470     const OUString& rLName,
2471     bool bIWSOutside,
2472     bool bIWSInside )
2473     : mrExport( rExp )
2474     , maElementName()
2475     , mbIgnoreWhitespaceInside( bIWSInside )
2476     , mbDoSomething( true )
2477 {
2478     StartElement( nPrefixKey, rLName, bIWSOutside );
2479 }
2480 
SvXMLElementExport(SvXMLExport & rExp,sal_uInt16 nPrefixKey,enum XMLTokenEnum eLName,bool bIWSOutside,bool bIWSInside)2481 SvXMLElementExport::SvXMLElementExport(
2482     SvXMLExport& rExp,
2483     sal_uInt16 nPrefixKey,
2484     enum XMLTokenEnum eLName,
2485     bool bIWSOutside,
2486     bool bIWSInside )
2487     : mrExport( rExp )
2488     , maElementName()
2489     , mbIgnoreWhitespaceInside( bIWSInside )
2490     , mbDoSomething( true )
2491 {
2492     StartElement( nPrefixKey, GetXMLToken(eLName), bIWSOutside );
2493 }
2494 
SvXMLElementExport(SvXMLExport & rExp,bool bDoSth,sal_uInt16 nPrefixKey,enum XMLTokenEnum eLName,bool bIWSOutside,bool bIWSInside)2495 SvXMLElementExport::SvXMLElementExport(
2496     SvXMLExport& rExp,
2497     bool bDoSth,
2498     sal_uInt16 nPrefixKey,
2499     enum XMLTokenEnum eLName,
2500     bool bIWSOutside,
2501     bool bIWSInside )
2502     : mrExport( rExp )
2503     , maElementName()
2504     , mbIgnoreWhitespaceInside( bIWSInside )
2505     , mbDoSomething( bDoSth )
2506 {
2507     if ( mbDoSomething )
2508         StartElement( nPrefixKey, GetXMLToken( eLName ), bIWSOutside );
2509 }
2510 
SvXMLElementExport(SvXMLExport & rExp,const OUString & rQName,bool bIWSOutside,bool bIWSInside)2511 SvXMLElementExport::SvXMLElementExport(
2512     SvXMLExport& rExp,
2513     const OUString& rQName,
2514     bool bIWSOutside,
2515     bool bIWSInside )
2516     : mrExport( rExp )
2517     , maElementName()
2518     , mbIgnoreWhitespaceInside( bIWSInside )
2519     , mbDoSomething( true )
2520 {
2521     maElementName = rQName;
2522     rExp.StartElement( rQName, bIWSOutside );
2523 }
2524 
~SvXMLElementExport()2525 SvXMLElementExport::~SvXMLElementExport()
2526 {
2527     if ( mbDoSomething )
2528     {
2529         mrExport.EndElement( maElementName, mbIgnoreWhitespaceInside );
2530     }
2531 }
2532 
2533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2534