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