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
21 #include <sax/tools/converter.hxx>
22
23 #include <xmloff/SettingsExportHelper.hxx>
24 #include <xmloff/xmltoken.hxx>
25 #include <sal/log.hxx>
26 #include <tools/debug.hxx>
27 #include <tools/diagnose_ex.h>
28 #include <comphelper/base64.hxx>
29 #include <comphelper/extract.hxx>
30
31 #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
32 #include <com/sun/star/i18n/XForbiddenCharacters.hpp>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/container/XNameAccess.hpp>
35 #include <com/sun/star/container/XNameContainer.hpp>
36 #include <com/sun/star/container/XIndexContainer.hpp>
37 #include <com/sun/star/util/PathSubstitution.hpp>
38 #include <com/sun/star/util/DateTime.hpp>
39 #include <com/sun/star/formula/SymbolDescriptor.hpp>
40 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
41 #include <com/sun/star/document/IndexedPropertyValues.hpp>
42 #include <xmloff/XMLSettingsExportContext.hxx>
43 #include "xmlenums.hxx"
44
45 using namespace ::com::sun::star;
46 using namespace ::xmloff::token;
47
48 constexpr OUStringLiteral gsPrinterIndependentLayout( u"PrinterIndependentLayout" );
49 constexpr OUStringLiteral gsColorTableURL( u"ColorTableURL" );
50 constexpr OUStringLiteral gsLineEndTableURL( u"LineEndTableURL" );
51 constexpr OUStringLiteral gsHatchTableURL( u"HatchTableURL" );
52 constexpr OUStringLiteral gsDashTableURL( u"DashTableURL" );
53 constexpr OUStringLiteral gsGradientTableURL( u"GradientTableURL" );
54 constexpr OUStringLiteral gsBitmapTableURL( u"BitmapTableURL" );
55
XMLSettingsExportHelper(::xmloff::XMLSettingsExportContext & i_rContext)56 XMLSettingsExportHelper::XMLSettingsExportHelper( ::xmloff::XMLSettingsExportContext& i_rContext )
57 : m_rContext( i_rContext )
58 {
59 }
60
~XMLSettingsExportHelper()61 XMLSettingsExportHelper::~XMLSettingsExportHelper()
62 {
63 }
64
CallTypeFunction(const uno::Any & rAny,const OUString & rName) const65 void XMLSettingsExportHelper::CallTypeFunction(const uno::Any& rAny,
66 const OUString& rName) const
67 {
68 uno::Any aAny( rAny );
69 ManipulateSetting( aAny, rName );
70
71 uno::TypeClass eClass = aAny.getValueTypeClass();
72 switch (eClass)
73 {
74 case uno::TypeClass_VOID:
75 {
76 /*
77 * This assertion pops up when exporting values which are set to:
78 * PropertyAttribute::MAYBEVOID, and thus are _supposed_ to have
79 * a VOID value...so I'm removing it ...mtg
80 * OSL_FAIL("no type");
81 */
82 }
83 break;
84 case uno::TypeClass_BOOLEAN:
85 {
86 exportBool(::cppu::any2bool(aAny), rName);
87 }
88 break;
89 case uno::TypeClass_BYTE:
90 {
91 exportByte();
92 }
93 break;
94 case uno::TypeClass_SHORT:
95 {
96 sal_Int16 nInt16 = 0;
97 aAny >>= nInt16;
98 exportShort(nInt16, rName);
99 }
100 break;
101 case uno::TypeClass_LONG:
102 {
103 sal_Int32 nInt32 = 0;
104 aAny >>= nInt32;
105 exportInt(nInt32, rName);
106 }
107 break;
108 case uno::TypeClass_HYPER:
109 {
110 sal_Int64 nInt64 = 0;
111 aAny >>= nInt64;
112 exportLong(nInt64, rName);
113 }
114 break;
115 case uno::TypeClass_DOUBLE:
116 {
117 double fDouble = 0.0;
118 aAny >>= fDouble;
119 exportDouble(fDouble, rName);
120 }
121 break;
122 case uno::TypeClass_STRING:
123 {
124 OUString sString;
125 aAny >>= sString;
126 exportString(sString, rName);
127 }
128 break;
129 default:
130 {
131 const uno::Type& aType = aAny.getValueType();
132 if (aType.equals(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get() ) )
133 {
134 uno::Sequence< beans::PropertyValue> aProps;
135 aAny >>= aProps;
136 exportSequencePropertyValue(aProps, rName);
137 }
138 else if( aType.equals(cppu::UnoType<uno::Sequence<sal_Int8>>::get() ) )
139 {
140 uno::Sequence< sal_Int8 > aProps;
141 aAny >>= aProps;
142 exportbase64Binary(aProps, rName);
143 }
144 else if (aType.equals(cppu::UnoType<container::XNameContainer>::get()) ||
145 aType.equals(cppu::UnoType<container::XNameAccess>::get()))
146 {
147 uno::Reference< container::XNameAccess> aNamed;
148 aAny >>= aNamed;
149 exportNameAccess(aNamed, rName);
150 }
151 else if (aType.equals(cppu::UnoType<container::XIndexAccess>::get()) ||
152 aType.equals(cppu::UnoType<container::XIndexContainer>::get()) )
153 {
154 uno::Reference<container::XIndexAccess> aIndexed;
155 aAny >>= aIndexed;
156 exportIndexAccess(aIndexed, rName);
157 }
158 else if (aType.equals(cppu::UnoType<util::DateTime>::get()) )
159 {
160 util::DateTime aDateTime;
161 aAny >>= aDateTime;
162 exportDateTime(aDateTime, rName);
163 }
164 else if( aType.equals(cppu::UnoType<i18n::XForbiddenCharacters>::get()) )
165 {
166 exportForbiddenCharacters( aAny, rName );
167 }
168 else if( aType.equals(cppu::UnoType<uno::Sequence<formula::SymbolDescriptor>>::get() ) )
169 {
170 uno::Sequence< formula::SymbolDescriptor > aProps;
171 aAny >>= aProps;
172 exportSymbolDescriptors(aProps, rName);
173 }
174 else {
175 OSL_FAIL("this type is not implemented now");
176 }
177 }
178 break;
179 }
180 }
181
exportBool(const bool bValue,const OUString & rName) const182 void XMLSettingsExportHelper::exportBool(const bool bValue, const OUString& rName) const
183 {
184 DBG_ASSERT(!rName.isEmpty(), "no name");
185 m_rContext.AddAttribute( XML_NAME, rName );
186 m_rContext.AddAttribute( XML_TYPE, XML_BOOLEAN );
187 m_rContext.StartElement( XML_CONFIG_ITEM );
188 OUString sValue;
189 if (bValue)
190 sValue = GetXMLToken(XML_TRUE);
191 else
192 sValue = GetXMLToken(XML_FALSE);
193 m_rContext.Characters( sValue );
194 m_rContext.EndElement( false );
195 }
196
exportByte()197 void XMLSettingsExportHelper::exportByte()
198 {
199 OSL_ENSURE(false, "XMLSettingsExportHelper::exportByte(): #i114162#:\n"
200 "config-items of type \"byte\" are not valid ODF, "
201 "so storing them is disabled!\n"
202 "Use a different type instead (e.g. \"short\").");
203 }
exportShort(const sal_Int16 nValue,const OUString & rName) const204 void XMLSettingsExportHelper::exportShort(const sal_Int16 nValue, const OUString& rName) const
205 {
206 DBG_ASSERT(!rName.isEmpty(), "no name");
207 m_rContext.AddAttribute( XML_NAME, rName );
208 m_rContext.AddAttribute( XML_TYPE, XML_SHORT );
209 m_rContext.StartElement( XML_CONFIG_ITEM );
210 m_rContext.Characters( OUString::number(nValue) );
211 m_rContext.EndElement( false );
212 }
213
exportInt(const sal_Int32 nValue,const OUString & rName) const214 void XMLSettingsExportHelper::exportInt(const sal_Int32 nValue, const OUString& rName) const
215 {
216 DBG_ASSERT(!rName.isEmpty(), "no name");
217 m_rContext.AddAttribute( XML_NAME, rName );
218 m_rContext.AddAttribute( XML_TYPE, XML_INT );
219 m_rContext.StartElement( XML_CONFIG_ITEM );
220 m_rContext.Characters( OUString::number(nValue) );
221 m_rContext.EndElement( false );
222 }
223
exportLong(const sal_Int64 nValue,const OUString & rName) const224 void XMLSettingsExportHelper::exportLong(const sal_Int64 nValue, const OUString& rName) const
225 {
226 DBG_ASSERT(!rName.isEmpty(), "no name");
227 m_rContext.AddAttribute( XML_NAME, rName );
228 m_rContext.AddAttribute( XML_TYPE, XML_LONG );
229 m_rContext.StartElement( XML_CONFIG_ITEM );
230 m_rContext.Characters( OUString::number(nValue) );
231 m_rContext.EndElement( false );
232 }
233
exportDouble(const double fValue,const OUString & rName) const234 void XMLSettingsExportHelper::exportDouble(const double fValue, const OUString& rName) const
235 {
236 DBG_ASSERT(!rName.isEmpty(), "no name");
237 m_rContext.AddAttribute( XML_NAME, rName );
238 m_rContext.AddAttribute( XML_TYPE, XML_DOUBLE );
239 m_rContext.StartElement( XML_CONFIG_ITEM );
240 OUStringBuffer sBuffer;
241 ::sax::Converter::convertDouble(sBuffer, fValue);
242 m_rContext.Characters( sBuffer.makeStringAndClear() );
243 m_rContext.EndElement( false );
244 }
245
exportString(const OUString & sValue,const OUString & rName) const246 void XMLSettingsExportHelper::exportString(const OUString& sValue, const OUString& rName) const
247 {
248 DBG_ASSERT(!rName.isEmpty(), "no name");
249 m_rContext.AddAttribute( XML_NAME, rName );
250 m_rContext.AddAttribute( XML_TYPE, XML_STRING );
251 m_rContext.StartElement( XML_CONFIG_ITEM );
252 if (!sValue.isEmpty())
253 m_rContext.Characters( sValue );
254 m_rContext.EndElement( false );
255 }
256
exportDateTime(const util::DateTime & aValue,const OUString & rName) const257 void XMLSettingsExportHelper::exportDateTime(const util::DateTime& aValue, const OUString& rName) const
258 {
259 DBG_ASSERT(!rName.isEmpty(), "no name");
260 m_rContext.AddAttribute( XML_NAME, rName );
261 m_rContext.AddAttribute( XML_TYPE, XML_DATETIME );
262 OUStringBuffer sBuffer;
263 ::sax::Converter::convertDateTime(sBuffer, aValue, nullptr);
264 m_rContext.StartElement( XML_CONFIG_ITEM );
265 m_rContext.Characters( sBuffer.makeStringAndClear() );
266 m_rContext.EndElement( false );
267 }
268
exportSequencePropertyValue(const uno::Sequence<beans::PropertyValue> & aProps,const OUString & rName) const269 void XMLSettingsExportHelper::exportSequencePropertyValue(
270 const uno::Sequence<beans::PropertyValue>& aProps,
271 const OUString& rName) const
272 {
273 DBG_ASSERT(!rName.isEmpty(), "no name");
274 if(aProps.hasElements())
275 {
276 m_rContext.AddAttribute( XML_NAME, rName );
277 m_rContext.StartElement( XML_CONFIG_ITEM_SET );
278 for (const auto& rProp : aProps)
279 CallTypeFunction(rProp.Value, rProp.Name);
280 m_rContext.EndElement( true );
281 }
282 }
exportSymbolDescriptors(const uno::Sequence<formula::SymbolDescriptor> & rProps,const OUString & rName) const283 void XMLSettingsExportHelper::exportSymbolDescriptors(
284 const uno::Sequence < formula::SymbolDescriptor > &rProps,
285 const OUString& rName) const
286 {
287 uno::Reference< container::XIndexContainer > xBox = document::IndexedPropertyValues::create(m_rContext.GetComponentContext());
288
289 static const OUStringLiteral sName ( u"Name" );
290 static const OUStringLiteral sExportName ( u"ExportName" );
291 static const OUStringLiteral sSymbolSet ( u"SymbolSet" );
292 static const OUStringLiteral sCharacter ( u"Character" );
293 static const OUStringLiteral sFontName ( u"FontName" );
294 static const OUStringLiteral sCharSet ( u"CharSet" );
295 static const OUStringLiteral sFamily ( u"Family" );
296 static const OUStringLiteral sPitch ( u"Pitch" );
297 static const OUStringLiteral sWeight ( u"Weight" );
298 static const OUStringLiteral sItalic ( u"Italic" );
299
300 sal_Int32 nCount = rProps.getLength();
301 const formula::SymbolDescriptor *pDescriptor = rProps.getConstArray();
302
303 for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++, pDescriptor++ )
304 {
305 uno::Sequence < beans::PropertyValue > aSequence ( XML_SYMBOL_DESCRIPTOR_MAX );
306 beans::PropertyValue *pSymbol = aSequence.getArray();
307
308 pSymbol[XML_SYMBOL_DESCRIPTOR_NAME].Name = sName;
309 pSymbol[XML_SYMBOL_DESCRIPTOR_NAME].Value <<= pDescriptor->sName;
310 pSymbol[XML_SYMBOL_DESCRIPTOR_EXPORT_NAME].Name = sExportName;
311 pSymbol[XML_SYMBOL_DESCRIPTOR_EXPORT_NAME].Value<<= pDescriptor->sExportName;
312 pSymbol[XML_SYMBOL_DESCRIPTOR_FONT_NAME].Name = sFontName;
313 pSymbol[XML_SYMBOL_DESCRIPTOR_FONT_NAME].Value <<= pDescriptor->sFontName;
314 pSymbol[XML_SYMBOL_DESCRIPTOR_CHAR_SET].Name = sCharSet;
315 pSymbol[XML_SYMBOL_DESCRIPTOR_CHAR_SET].Value <<= pDescriptor->nCharSet;
316 pSymbol[XML_SYMBOL_DESCRIPTOR_FAMILY].Name = sFamily;
317 pSymbol[XML_SYMBOL_DESCRIPTOR_FAMILY].Value <<= pDescriptor->nFamily;
318 pSymbol[XML_SYMBOL_DESCRIPTOR_PITCH].Name = sPitch;
319 pSymbol[XML_SYMBOL_DESCRIPTOR_PITCH].Value <<= pDescriptor->nPitch;
320 pSymbol[XML_SYMBOL_DESCRIPTOR_WEIGHT].Name = sWeight;
321 pSymbol[XML_SYMBOL_DESCRIPTOR_WEIGHT].Value <<= pDescriptor->nWeight;
322 pSymbol[XML_SYMBOL_DESCRIPTOR_ITALIC].Name = sItalic;
323 pSymbol[XML_SYMBOL_DESCRIPTOR_ITALIC].Value <<= pDescriptor->nItalic;
324 pSymbol[XML_SYMBOL_DESCRIPTOR_SYMBOL_SET].Name = sSymbolSet;
325 pSymbol[XML_SYMBOL_DESCRIPTOR_SYMBOL_SET].Value <<= pDescriptor->sSymbolSet;
326 pSymbol[XML_SYMBOL_DESCRIPTOR_CHARACTER].Name = sCharacter;
327 pSymbol[XML_SYMBOL_DESCRIPTOR_CHARACTER].Value <<= pDescriptor->nCharacter;
328
329 xBox->insertByIndex(nIndex, uno::makeAny( aSequence ));
330 }
331
332 exportIndexAccess( xBox, rName );
333 }
exportbase64Binary(const uno::Sequence<sal_Int8> & aProps,const OUString & rName) const334 void XMLSettingsExportHelper::exportbase64Binary(
335 const uno::Sequence<sal_Int8>& aProps,
336 const OUString& rName) const
337 {
338 DBG_ASSERT(!rName.isEmpty(), "no name");
339 m_rContext.AddAttribute( XML_NAME, rName );
340 m_rContext.AddAttribute( XML_TYPE, XML_BASE64BINARY );
341 m_rContext.StartElement( XML_CONFIG_ITEM );
342 if(aProps.hasElements())
343 {
344 OUStringBuffer sBuffer;
345 ::comphelper::Base64::encode(sBuffer, aProps);
346 m_rContext.Characters( sBuffer.makeStringAndClear() );
347 }
348 m_rContext.EndElement( false );
349 }
350
exportMapEntry(const uno::Any & rAny,const OUString & rName,const bool bNameAccess) const351 void XMLSettingsExportHelper::exportMapEntry(const uno::Any& rAny,
352 const OUString& rName,
353 const bool bNameAccess) const
354 {
355 DBG_ASSERT((bNameAccess && !rName.isEmpty()) || !bNameAccess, "no name");
356 uno::Sequence<beans::PropertyValue> aProps;
357 rAny >>= aProps;
358 if (aProps.hasElements())
359 {
360 if (bNameAccess)
361 m_rContext.AddAttribute( XML_NAME, rName );
362 m_rContext.StartElement( XML_CONFIG_ITEM_MAP_ENTRY );
363 for (const auto& rProp : std::as_const(aProps))
364 CallTypeFunction(rProp.Value, rProp.Name);
365 m_rContext.EndElement( true );
366 }
367 }
368
exportNameAccess(const uno::Reference<container::XNameAccess> & aNamed,const OUString & rName) const369 void XMLSettingsExportHelper::exportNameAccess(
370 const uno::Reference<container::XNameAccess>& aNamed,
371 const OUString& rName) const
372 {
373 DBG_ASSERT(!rName.isEmpty(), "no name");
374 DBG_ASSERT(aNamed->getElementType().equals(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get() ),
375 "wrong NameAccess" );
376 if(aNamed->hasElements())
377 {
378 m_rContext.AddAttribute( XML_NAME, rName );
379 m_rContext.StartElement( XML_CONFIG_ITEM_MAP_NAMED );
380 const uno::Sequence< OUString > aNames(aNamed->getElementNames());
381 for (const auto& rElementName : aNames)
382 exportMapEntry(aNamed->getByName(rElementName), rElementName, true);
383 m_rContext.EndElement( true );
384 }
385 }
386
exportIndexAccess(const uno::Reference<container::XIndexAccess> & rIndexed,const OUString & rName) const387 void XMLSettingsExportHelper::exportIndexAccess(
388 const uno::Reference<container::XIndexAccess>& rIndexed,
389 const OUString& rName) const
390 {
391 DBG_ASSERT(!rName.isEmpty(), "no name");
392 DBG_ASSERT(rIndexed->getElementType().equals(cppu::UnoType<uno::Sequence<beans::PropertyValue>>::get() ),
393 "wrong IndexAccess" );
394 if (rIndexed->hasElements())
395 {
396 m_rContext.AddAttribute( XML_NAME, rName );
397 m_rContext.StartElement( XML_CONFIG_ITEM_MAP_INDEXED );
398 sal_Int32 nCount = rIndexed->getCount();
399 for (sal_Int32 i = 0; i < nCount; i++)
400 {
401 exportMapEntry(rIndexed->getByIndex(i), "", false);
402 }
403 m_rContext.EndElement( true );
404 }
405 }
406
exportForbiddenCharacters(const uno::Any & rAny,const OUString & rName) const407 void XMLSettingsExportHelper::exportForbiddenCharacters(
408 const uno::Any &rAny,
409 const OUString& rName) const
410 {
411 uno::Reference<i18n::XForbiddenCharacters> xForbChars;
412 uno::Reference<linguistic2::XSupportedLocales> xLocales;
413
414 rAny >>= xForbChars;
415 rAny >>= xLocales;
416
417 SAL_WARN_IF( !(xForbChars.is() && xLocales.is()), "xmloff","XMLSettingsExportHelper::exportForbiddenCharacters: got illegal forbidden characters!" );
418
419 if( !xForbChars.is() || !xLocales.is() )
420 return;
421
422 uno::Reference< container::XIndexContainer > xBox = document::IndexedPropertyValues::create(m_rContext.GetComponentContext());
423 const uno::Sequence< lang::Locale > aLocales( xLocales->getLocales() );
424
425 /* FIXME-BCP47: this stupid and counterpart in
426 * xmloff/source/core/DocumentSettingsContext.cxx
427 * XMLConfigItemMapIndexedContext::EndElement() */
428
429 static const OUStringLiteral sLanguage ( u"Language" );
430 static const OUStringLiteral sCountry ( u"Country" );
431 static const OUStringLiteral sVariant ( u"Variant" );
432 static const OUStringLiteral sBeginLine ( u"BeginLine" );
433 static const OUStringLiteral sEndLine ( u"EndLine" );
434
435 sal_Int32 nPos = 0;
436 for( const auto& rLocale : aLocales )
437 {
438 if( xForbChars->hasForbiddenCharacters( rLocale ) )
439 {
440 const i18n::ForbiddenCharacters aChars( xForbChars->getForbiddenCharacters( rLocale ) );
441
442
443 uno::Sequence < beans::PropertyValue > aSequence ( XML_FORBIDDEN_CHARACTER_MAX );
444 beans::PropertyValue *pForChar = aSequence.getArray();
445
446 pForChar[XML_FORBIDDEN_CHARACTER_LANGUAGE].Name = sLanguage;
447 pForChar[XML_FORBIDDEN_CHARACTER_LANGUAGE].Value <<= rLocale.Language;
448 pForChar[XML_FORBIDDEN_CHARACTER_COUNTRY].Name = sCountry;
449 pForChar[XML_FORBIDDEN_CHARACTER_COUNTRY].Value <<= rLocale.Country;
450 pForChar[XML_FORBIDDEN_CHARACTER_VARIANT].Name = sVariant;
451 pForChar[XML_FORBIDDEN_CHARACTER_VARIANT].Value <<= rLocale.Variant;
452 pForChar[XML_FORBIDDEN_CHARACTER_BEGIN_LINE].Name = sBeginLine;
453 pForChar[XML_FORBIDDEN_CHARACTER_BEGIN_LINE].Value <<= aChars.beginLine;
454 pForChar[XML_FORBIDDEN_CHARACTER_END_LINE].Name = sEndLine;
455 pForChar[XML_FORBIDDEN_CHARACTER_END_LINE].Value <<= aChars.endLine;
456 xBox->insertByIndex(nPos++, uno::makeAny( aSequence ));
457 }
458 }
459
460 exportIndexAccess( xBox, rName );
461 }
462
exportAllSettings(const uno::Sequence<beans::PropertyValue> & aProps,const OUString & rName) const463 void XMLSettingsExportHelper::exportAllSettings(
464 const uno::Sequence<beans::PropertyValue>& aProps,
465 const OUString& rName) const
466 {
467 DBG_ASSERT(!rName.isEmpty(), "no name");
468 exportSequencePropertyValue(aProps, rName);
469 }
470
471
472 /** For some settings we may want to change their API representation
473 * from their XML settings representation. This is your chance to do
474 * so!
475 */
ManipulateSetting(uno::Any & rAny,std::u16string_view rName) const476 void XMLSettingsExportHelper::ManipulateSetting( uno::Any& rAny, std::u16string_view rName ) const
477 {
478 if( rName == gsPrinterIndependentLayout )
479 {
480 sal_Int16 nTmp = sal_Int16();
481 if( rAny >>= nTmp )
482 {
483 if( nTmp == document::PrinterIndependentLayout::LOW_RESOLUTION )
484 rAny <<= OUString("low-resolution");
485 else if( nTmp == document::PrinterIndependentLayout::DISABLED )
486 rAny <<= OUString("disabled");
487 else if( nTmp == document::PrinterIndependentLayout::HIGH_RESOLUTION )
488 rAny <<= OUString("high-resolution");
489 }
490 }
491 else if( (rName == gsColorTableURL) || (rName == gsLineEndTableURL) || (rName == gsHatchTableURL) ||
492 (rName == gsDashTableURL) || (rName == gsGradientTableURL) || (rName == gsBitmapTableURL ) )
493 {
494 if( !mxStringSubstitution.is() )
495 {
496 try
497 {
498 const_cast< XMLSettingsExportHelper* >(this)->mxStringSubstitution =
499 util::PathSubstitution::create( m_rContext.GetComponentContext() );
500 }
501 catch( uno::Exception& )
502 {
503 DBG_UNHANDLED_EXCEPTION("xmloff.core");
504 }
505 }
506
507 if( mxStringSubstitution.is() )
508 {
509 OUString aURL;
510 rAny >>= aURL;
511 aURL = mxStringSubstitution->reSubstituteVariables( aURL );
512 rAny <<= aURL;
513 }
514 }
515 }
516
517 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
518