Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/xml/xmlxtexp.cxx
Line
Count
Source
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 <sal/config.h>
21
22
#include <comphelper/diagnose_ex.hxx>
23
#include <tools/urlobj.hxx>
24
#include <com/sun/star/beans/XPropertySet.hpp>
25
#include <com/sun/star/container/XNameContainer.hpp>
26
#include <com/sun/star/embed/XStorage.hpp>
27
#include <com/sun/star/xml/sax/Writer.hpp>
28
#include <com/sun/star/uno/Sequence.hxx>
29
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
30
#include <com/sun/star/drawing/LineDash.hpp>
31
#include <com/sun/star/awt/Gradient.hpp>
32
#include <com/sun/star/awt/XBitmap.hpp>
33
#include <com/sun/star/drawing/Hatch.hpp>
34
#include <com/sun/star/embed/ElementModes.hpp>
35
36
#include <sax/tools/converter.hxx>
37
#include <sfx2/docfile.hxx>
38
#include <tools/fldunit.hxx>
39
#include <tools/stream.hxx>
40
#include <rtl/ustrbuf.hxx>
41
#include <xmloff/xmlnamespace.hxx>
42
#include <xmloff/namespacemap.hxx>
43
44
#include <xmloff/xmltoken.hxx>
45
#include <xmloff/xmlmetae.hxx>
46
#include <xmloff/DashStyle.hxx>
47
#include <xmloff/GradientStyle.hxx>
48
#include <xmloff/HatchStyle.hxx>
49
#include <xmloff/ImageStyle.hxx>
50
#include <xmloff/MarkerStyle.hxx>
51
#include <com/sun/star/embed/XTransactedObject.hpp>
52
#include <comphelper/processfactory.hxx>
53
#include <unotools/streamwrap.hxx>
54
#include <xmloff/xmlgrhlp.hxx>
55
56
#include <xmlxtexp.hxx>
57
58
#include <comphelper/storagehelper.hxx>
59
#include <memory>
60
61
using namespace com::sun::star;
62
using namespace com::sun::star::container;
63
using namespace com::sun::star::document;
64
using namespace com::sun::star::uno;
65
using namespace com::sun::star::awt;
66
using namespace com::sun::star::lang;
67
using namespace com::sun::star::xml::sax;
68
using namespace ::xmloff::token;
69
using namespace cppu;
70
71
using com::sun::star::embed::XTransactedObject;
72
73
namespace {
74
75
class SvxXMLTableEntryExporter
76
{
77
public:
78
0
    explicit SvxXMLTableEntryExporter( SvXMLExport& rExport ) : mrExport( rExport ) {}
79
    virtual ~SvxXMLTableEntryExporter();
80
81
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) = 0;
82
83
protected:
84
    SvXMLExport& mrExport;
85
};
86
87
class SvxXMLColorEntryExporter : public SvxXMLTableEntryExporter
88
{
89
public:
90
    explicit SvxXMLColorEntryExporter( SvXMLExport& rExport );
91
92
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) override;
93
};
94
95
class SvxXMLLineEndEntryExporter : public SvxXMLTableEntryExporter
96
{
97
public:
98
    explicit SvxXMLLineEndEntryExporter( SvXMLExport& rExport );
99
100
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) override;
101
private:
102
    XMLMarkerStyleExport maMarkerStyle;
103
};
104
105
class SvxXMLDashEntryExporter : public SvxXMLTableEntryExporter
106
{
107
public:
108
    explicit SvxXMLDashEntryExporter( SvXMLExport& rExport );
109
110
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) override;
111
112
private:
113
    XMLDashStyleExport maDashStyle;
114
};
115
116
class SvxXMLHatchEntryExporter : public SvxXMLTableEntryExporter
117
{
118
public:
119
    explicit SvxXMLHatchEntryExporter( SvXMLExport& rExport );
120
121
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) override;
122
private:
123
    XMLHatchStyleExport maHatchStyle;
124
};
125
126
class SvxXMLGradientEntryExporter : public SvxXMLTableEntryExporter
127
{
128
public:
129
    explicit SvxXMLGradientEntryExporter( SvXMLExport& rExport );
130
131
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) override;
132
private:
133
    XMLGradientStyleExport maGradientStyle;
134
};
135
136
class SvxXMLBitmapEntryExporter : public SvxXMLTableEntryExporter
137
{
138
public:
139
    explicit SvxXMLBitmapEntryExporter( SvXMLExport& rExport );
140
141
    virtual void exportEntry( const OUString& rStrName, const Any& rValue ) override;
142
};
143
144
}
145
146
SvxXMLXTableExportComponent::SvxXMLXTableExportComponent(
147
    const css::uno::Reference< css::uno::XComponentContext >& rContext,
148
    const uno::Reference<xml::sax::XDocumentHandler> & rHandler,
149
    const uno::Reference<container::XNameContainer >& xTable,
150
    uno::Reference<document::XGraphicStorageHandler> const & xGraphicStorageHandler)
151
0
:   SvXMLExport(rContext, u""_ustr, /*rFileName*/u""_ustr, rHandler, nullptr, FieldUnit::MM_100TH, SvXMLExportFlags::NONE),
152
0
    mxTable( xTable )
153
0
{
154
155
0
    GetNamespaceMap_().Add( GetXMLToken(XML_NP_OOO), GetXMLToken(XML_N_OOO), XML_NAMESPACE_OOO );
156
0
    GetNamespaceMap_().Add( GetXMLToken(XML_NP_OFFICE), GetXMLToken(XML_N_OFFICE), XML_NAMESPACE_OFFICE );
157
0
    GetNamespaceMap_().Add( GetXMLToken(XML_NP_DRAW), GetXMLToken(XML_N_DRAW), XML_NAMESPACE_DRAW );
158
0
    GetNamespaceMap_().Add( GetXMLToken(XML_NP_XLINK), GetXMLToken(XML_N_XLINK), XML_NAMESPACE_XLINK );
159
0
    GetNamespaceMap_().Add( GetXMLToken(XML_NP_SVG), GetXMLToken(XML_N_SVG),  XML_NAMESPACE_SVG );
160
0
    GetNamespaceMap_().Add( GetXMLToken(XML_NP_LO_EXT), GetXMLToken(XML_N_LO_EXT), XML_NAMESPACE_LO_EXT);
161
0
    SetGraphicStorageHandler(xGraphicStorageHandler);
162
0
}
163
164
SvxXMLXTableExportComponent::~SvxXMLXTableExportComponent()
165
0
{
166
0
}
167
168
static void initializeStreamMetadata( const uno::Reference< uno::XInterface > &xOut )
169
0
{
170
0
    uno::Reference< beans::XPropertySet > xProps( xOut, uno::UNO_QUERY );
171
0
    if( !xProps.is() )
172
0
    {
173
0
        OSL_FAIL( "Missing stream metadata interface" );
174
0
        return;
175
0
    }
176
177
0
    try
178
0
    {
179
0
        xProps->setPropertyValue(u"MediaType"_ustr,  uno::Any( u"text/xml"_ustr ) );
180
181
        // use stock encryption
182
0
        xProps->setPropertyValue(u"UseCommonStoragePasswordEncryption"_ustr, uno::Any( true ) );
183
0
    } catch ( const uno::Exception & )
184
0
    {
185
0
        TOOLS_WARN_EXCEPTION("svx", "exception setting stream metadata");
186
0
    }
187
0
}
188
189
static void createStorageStream( uno::Reference < io::XOutputStream > *xOut,
190
                                 rtl::Reference<SvXMLGraphicHelper>&   rxGraphicHelper,
191
                                 const uno::Reference < embed::XStorage >& xSubStorage )
192
0
{
193
0
    uno::Reference < io::XStream > xStream = xSubStorage->openStreamElement(
194
0
                        u"Content.xml"_ustr,
195
0
                        embed::ElementModes::WRITE );
196
0
    rxGraphicHelper = SvXMLGraphicHelper::Create( xSubStorage, SvXMLGraphicHelperMode::Write );
197
0
    initializeStreamMetadata( xStream );
198
0
    *xOut = xStream->getOutputStream();
199
0
}
200
201
bool SvxXMLXTableExportComponent::save(
202
        const OUString& rURL,
203
        const uno::Reference<container::XNameContainer >& xTable,
204
        const uno::Reference<embed::XStorage >& xStorage,
205
        OUString *pOptName )
206
0
{
207
0
    bool bRet = false;
208
0
    std::unique_ptr<SfxMedium> pMedium;
209
0
    rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
210
211
0
    INetURLObject aURLObj( rURL );
212
0
    bool bToStorage = aURLObj.GetProtocol() == INetProtocol::NotValid; // a relative path
213
0
    bool bSaveAsStorage = xTable->getElementType() == cppu::UnoType<awt::XBitmap>::get();
214
215
0
    if( pOptName )
216
0
        *pOptName = rURL;
217
218
0
    try
219
0
    {
220
0
        const uno::Reference< uno::XComponentContext>& xContext( ::comphelper::getProcessComponentContext() );
221
222
0
        uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create( xContext );
223
224
0
        uno::Reference < io::XStream > xStream;
225
0
        uno::Reference < io::XOutputStream > xOut;
226
0
        uno::Reference<embed::XStorage > xSubStorage;
227
0
        uno::Reference<XGraphicStorageHandler> xGraphicStorageHandler;
228
0
        const sal_Int32 eCreate = embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE;
229
230
0
        if( !bToStorage || !xStorage.is() )
231
0
        { // local URL -> SfxMedium route
232
0
            if( bSaveAsStorage )
233
0
            {
234
                // ideally this should use a ZIP_STORAGE_FORMAT_STRING storage
235
                // but changing it to that could cause problems loading the
236
                // file with an old version of LO that expects to find in the
237
                // user profile a PACKAGE_STORAGE_FORMAT_STRING storage
238
0
                xSubStorage = ::comphelper::OStorageHelper::GetStorageFromURL( rURL, eCreate );
239
0
            }
240
0
            else
241
0
            {
242
0
                pMedium.reset(new SfxMedium( rURL, StreamMode::WRITE | StreamMode::TRUNC ));
243
244
0
                SvStream* pStream = pMedium->GetOutStream();
245
0
                if( !pStream )
246
0
                {
247
0
                    OSL_FAIL( "no output stream!" );
248
0
                    return false;
249
0
                }
250
251
0
                xOut = new utl::OOutputStreamWrapper( *pStream );
252
0
            }
253
0
        }
254
0
        else // save into the xSubStorage
255
0
        {
256
0
            OUString aPath = rURL;
257
258
0
            if( bSaveAsStorage )
259
0
            {
260
0
                try {
261
0
                    xSubStorage = xStorage->openStorageElement( aPath, eCreate );
262
0
                } catch (uno::Exception &) {
263
0
                    OSL_FAIL( "no output storage!" );
264
0
                    return false;
265
0
                }
266
0
            }
267
0
            else
268
0
            {
269
0
                aPath += ".xml";
270
0
                try {
271
0
                    xStream = xStorage->openStreamElement( aPath, eCreate );
272
0
                    if( !xStream.is() )
273
0
                        return false;
274
0
                    initializeStreamMetadata( xStream );
275
0
                    xOut = xStream->getOutputStream();
276
0
                } catch (uno::Exception &) {
277
0
                    OSL_FAIL( "no output stream!" );
278
0
                    return false;
279
0
                }
280
0
                if( pOptName )
281
0
                    *pOptName = aPath;
282
0
            }
283
0
        }
284
285
0
        if( !xOut.is() && xSubStorage.is() )
286
0
            createStorageStream( &xOut, xGraphicHelper, xSubStorage );
287
0
        if( !xOut.is() )
288
0
            return false;
289
290
0
        xWriter->setOutputStream( xOut );
291
0
        if( xGraphicHelper.is() )
292
0
            xGraphicStorageHandler = xGraphicHelper.get();
293
294
        // Finally do the export
295
0
        rtl::Reference< SvxXMLXTableExportComponent > xExporter( new SvxXMLXTableExportComponent( xContext, xWriter, xTable, xGraphicStorageHandler ) );
296
0
        bRet = xExporter->exportTable();
297
298
0
        if( xGraphicHelper )
299
0
            xGraphicHelper->dispose();
300
0
        xGraphicHelper.clear();
301
302
0
        if( xSubStorage.is() )
303
0
        {
304
0
            uno::Reference< XTransactedObject > xTrans( xSubStorage, UNO_QUERY );
305
0
            if( xTrans.is() )
306
0
                xTrans->commit();
307
308
0
            xSubStorage->dispose();
309
0
        }
310
0
    }
311
0
    catch( uno::Exception& )
312
0
    {
313
0
        bRet = false;
314
0
    }
315
316
0
    if( pMedium )
317
0
        pMedium->Commit();
318
319
0
    return bRet;
320
0
}
321
322
bool SvxXMLXTableExportComponent::exportTable() noexcept
323
0
{
324
0
    bool bRet = false;
325
326
0
    try
327
0
    {
328
0
        GetDocHandler()->startDocument();
329
330
0
        addChaffWhenEncryptedStorage();
331
332
        // export namespaces
333
0
        sal_uInt16 nPos = GetNamespaceMap().GetFirstKey();
334
0
        while( USHRT_MAX != nPos )
335
0
        {
336
0
            GetAttrList().AddAttribute( GetNamespaceMap().GetAttrNameByKey( nPos ), GetNamespaceMap().GetNameByKey( nPos ) );
337
0
            nPos = GetNamespaceMap().GetNextKey( nPos );
338
0
        }
339
340
0
        do
341
0
        {
342
0
            if( !mxTable.is() )
343
0
                break;
344
345
0
            OUString pEleName;
346
0
            Type aExportType = mxTable->getElementType();
347
0
            std::unique_ptr<SvxXMLTableEntryExporter> pExporter;
348
349
0
            if( aExportType == cppu::UnoType<sal_Int32>::get() )
350
0
            {
351
0
                pExporter.reset(new SvxXMLColorEntryExporter(*this));
352
0
                pEleName = u"color-table"_ustr;
353
0
            }
354
0
            else if( aExportType == cppu::UnoType< drawing::PolyPolygonBezierCoords >::get() )
355
0
            {
356
0
                pExporter.reset(new SvxXMLLineEndEntryExporter(*this));
357
0
                pEleName = u"marker-table"_ustr;
358
0
            }
359
0
            else if( aExportType == cppu::UnoType< drawing::LineDash >::get() )
360
0
            {
361
0
                pExporter.reset(new SvxXMLDashEntryExporter(*this));
362
0
                pEleName = u"dash-table"_ustr;
363
0
            }
364
0
            else if( aExportType == cppu::UnoType< drawing::Hatch >::get() )
365
0
            {
366
0
                pExporter.reset(new SvxXMLHatchEntryExporter(*this));
367
0
                pEleName = u"hatch-table"_ustr;
368
0
            }
369
0
            else if( aExportType == cppu::UnoType< awt::Gradient >::get() )
370
0
            {
371
0
                pExporter.reset(new SvxXMLGradientEntryExporter(*this));
372
0
                pEleName = u"gradient-table"_ustr;
373
0
            }
374
0
            else if( aExportType == cppu::UnoType<awt::XBitmap>::get())
375
0
            {
376
0
                pExporter.reset(new SvxXMLBitmapEntryExporter(*this));
377
0
                pEleName = u"bitmap-table"_ustr;
378
0
            }
379
0
            else
380
0
            {
381
0
                OSL_FAIL( "unknown type for export");
382
0
                break;
383
0
            }
384
385
0
            SvXMLElementExport aElem( *this, XML_NAMESPACE_OOO, pEleName, true, true );
386
387
0
            const Sequence< OUString > aNames = mxTable->getElementNames();
388
0
            Any aAny;
389
390
0
            for( const OUString& rName : aNames )
391
0
            {
392
0
                aAny = mxTable->getByName( rName );
393
0
                pExporter->exportEntry( rName, aAny );
394
0
            }
395
396
0
            bRet = true;
397
0
        }
398
0
        while(false);
399
400
0
        GetDocHandler()->endDocument();
401
0
    }
402
0
    catch( Exception const& )
403
0
    {
404
0
        bRet = false;
405
0
    }
406
407
0
    return bRet;
408
0
}
409
410
// methods without content:
411
0
void SvxXMLXTableExportComponent::ExportAutoStyles_() {}
412
0
void SvxXMLXTableExportComponent::ExportMasterStyles_() {}
413
0
void SvxXMLXTableExportComponent::ExportContent_() {}
414
415
416
SvxXMLTableEntryExporter::~SvxXMLTableEntryExporter()
417
0
{
418
0
}
419
420
421
SvxXMLColorEntryExporter::SvxXMLColorEntryExporter( SvXMLExport& rExport )
422
0
: SvxXMLTableEntryExporter( rExport )
423
0
{
424
0
}
425
426
void SvxXMLColorEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
427
0
{
428
0
    mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rStrName );
429
430
0
    sal_Int32 nColor = 0;
431
0
    rValue >>= nColor;
432
433
0
    OUStringBuffer aOut;
434
0
    ::sax::Converter::convertColor( aOut, nColor );
435
0
    mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_COLOR, aOut.makeStringAndClear() );
436
437
0
    SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_COLOR, true, true );
438
0
}
439
440
441
SvxXMLLineEndEntryExporter::SvxXMLLineEndEntryExporter( SvXMLExport& rExport )
442
0
: SvxXMLTableEntryExporter( rExport ), maMarkerStyle( rExport )
443
0
{
444
0
}
445
446
void SvxXMLLineEndEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
447
0
{
448
0
    maMarkerStyle.exportXML( rStrName, rValue );
449
0
}
450
451
452
SvxXMLDashEntryExporter::SvxXMLDashEntryExporter( SvXMLExport& rExport )
453
0
: SvxXMLTableEntryExporter( rExport ), maDashStyle( rExport )
454
0
{
455
0
}
456
457
void SvxXMLDashEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
458
0
{
459
0
    maDashStyle.exportXML( rStrName, rValue );
460
0
}
461
462
463
SvxXMLHatchEntryExporter::SvxXMLHatchEntryExporter( SvXMLExport& rExport )
464
0
: SvxXMLTableEntryExporter( rExport ), maHatchStyle( rExport )
465
0
{
466
0
}
467
468
void SvxXMLHatchEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
469
0
{
470
0
    maHatchStyle.exportXML( rStrName, rValue );
471
0
}
472
473
474
SvxXMLGradientEntryExporter::SvxXMLGradientEntryExporter( SvXMLExport& rExport )
475
0
: SvxXMLTableEntryExporter( rExport ), maGradientStyle( rExport )
476
0
{
477
0
}
478
479
void SvxXMLGradientEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
480
0
{
481
0
    maGradientStyle.exportXML( rStrName, rValue );
482
0
}
483
484
485
SvxXMLBitmapEntryExporter::SvxXMLBitmapEntryExporter( SvXMLExport& rExport )
486
0
: SvxXMLTableEntryExporter( rExport )
487
0
{
488
0
}
489
490
void SvxXMLBitmapEntryExporter::exportEntry( const OUString& rStrName, const Any& rValue )
491
0
{
492
0
    XMLImageStyle::exportXML(rStrName, rValue, mrExport);
493
0
}
494
495
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */