Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/embeddedobj/source/general/xcreator.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 <com/sun/star/embed/ElementModes.hpp>
21
#include <com/sun/star/embed/EntryInitModes.hpp>
22
#include <com/sun/star/embed/XEmbedObjectFactory.hpp>
23
#include <com/sun/star/embed/OOoEmbeddedObjectFactory.hpp>
24
#include <com/sun/star/embed/OLEEmbeddedObjectFactory.hpp>
25
#include <com/sun/star/beans/PropertyValue.hpp>
26
#include <com/sun/star/beans/XPropertySet.hpp>
27
#include <com/sun/star/container/XNameAccess.hpp>
28
#include <com/sun/star/lang/NoSupportException.hpp>
29
#include <com/sun/star/lang/XComponent.hpp>
30
31
#include <cppuhelper/supportsservice.hxx>
32
#include <cppuhelper/weak.hxx>
33
#include <comphelper/documentconstants.hxx>
34
#include <officecfg/Office/Common.hxx>
35
36
#include <xcreator.hxx>
37
#include <dummyobject.hxx>
38
39
40
using namespace ::com::sun::star;
41
42
uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitNew(
43
                                            const uno::Sequence< sal_Int8 >& aClassID,
44
                                            const OUString& aClassName,
45
                                            const uno::Reference< embed::XStorage >& xStorage,
46
                                            const OUString& sEntName,
47
                                            const uno::Sequence< beans::PropertyValue >& lObjArgs )
48
26.7k
{
49
26.7k
    if ( officecfg::Office::Common::Security::Scripting::DisableActiveContent::get() )
50
0
        throw lang::NoSupportException(u"Active OLE content is disabled!"_ustr);
51
26.7k
    if ( !xStorage.is() )
52
0
        throw lang::IllegalArgumentException( u"No parent storage is provided!"_ustr,
53
0
                                            static_cast< ::cppu::OWeakObject* >(this),
54
0
                                            3 );
55
56
26.7k
    if ( sEntName.isEmpty() )
57
0
        throw lang::IllegalArgumentException( u"Empty element name is provided!"_ustr,
58
0
                                            static_cast< ::cppu::OWeakObject* >(this),
59
0
                                            4 );
60
61
26.7k
    OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID );
62
26.7k
    if ( aEmbedFactory.isEmpty() )
63
26.7k
    {
64
        // use system fallback
65
        // TODO: in future users factories can be tested
66
26.7k
        aEmbedFactory = "com.sun.star.embed.OLEEmbeddedObjectFactory";
67
26.7k
    }
68
69
26.7k
    uno::Reference < uno::XInterface > xFact( m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext) );
70
26.7k
    uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY );
71
26.7k
    if ( xEmbCreator.is() )
72
33
        return xEmbCreator->createInstanceInitNew( aClassID, aClassName, xStorage, sEntName, lObjArgs );
73
74
26.7k
    uno::Reference < embed::XEmbedObjectFactory > xEmbFact( xFact, uno::UNO_QUERY_THROW );
75
26.7k
    return xEmbFact->createInstanceUserInit( aClassID, aClassName, xStorage, sEntName, embed::EntryInitModes::TRUNCATE_INIT, uno::Sequence < beans::PropertyValue >(), lObjArgs);
76
26.7k
}
77
78
79
uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitFromEntry(
80
                                                                    const uno::Reference< embed::XStorage >& xStorage,
81
                                                                    const OUString& sEntName,
82
                                                                    const uno::Sequence< beans::PropertyValue >& aMedDescr,
83
                                                                    const uno::Sequence< beans::PropertyValue >& lObjArgs )
84
1.45k
{
85
1.45k
    if ( !xStorage.is() )
86
0
        throw lang::IllegalArgumentException( u"No parent storage is provided!"_ustr,
87
0
                                            static_cast< ::cppu::OWeakObject* >(this),
88
0
                                            1 );
89
90
1.45k
    if ( sEntName.isEmpty() )
91
45
        throw lang::IllegalArgumentException( u"Empty element name is provided!"_ustr,
92
45
                                            static_cast< ::cppu::OWeakObject* >(this),
93
45
                                            2 );
94
95
1.41k
    uno::Reference< container::XNameAccess > xNameAccess( xStorage, uno::UNO_QUERY_THROW );
96
97
    // detect entry existence
98
1.41k
    if ( !xNameAccess->hasByName( sEntName ) )
99
776
        throw container::NoSuchElementException();
100
101
638
    OUString aMediaType;
102
638
    OUString aEmbedFactory;
103
638
    if ( xStorage->isStorageElement( sEntName ) )
104
0
    {
105
        // the object must be based on storage
106
0
        uno::Reference< embed::XStorage > xSubStorage =
107
0
                xStorage->openStorageElement( sEntName, embed::ElementModes::READ );
108
109
0
        uno::Reference< beans::XPropertySet > xPropSet( xSubStorage, uno::UNO_QUERY_THROW );
110
111
0
        try {
112
0
            uno::Any aAny = xPropSet->getPropertyValue(u"MediaType"_ustr);
113
0
            aAny >>= aMediaType;
114
0
        }
115
0
        catch ( const uno::Exception& )
116
0
        {
117
0
        }
118
119
0
        try {
120
0
            if ( xSubStorage.is() )
121
0
                xSubStorage->dispose();
122
0
        }
123
0
        catch ( const uno::Exception& )
124
0
        {
125
0
        }
126
0
    }
127
638
    else
128
638
    {
129
        // the object must be based on stream
130
        // it means for now that this is an OLE object
131
132
        // the object will be created as embedded object
133
        // after it is loaded it can detect that it is a link
134
135
638
        uno::Reference< io::XStream > xSubStream =
136
638
                xStorage->openStreamElement( sEntName, embed::ElementModes::READ );
137
138
638
        uno::Reference< beans::XPropertySet > xPropSet( xSubStream, uno::UNO_QUERY_THROW );
139
140
638
        try {
141
638
            uno::Any aAny = xPropSet->getPropertyValue(u"MediaType"_ustr);
142
638
            aAny >>= aMediaType;
143
638
            if ( aMediaType == "application/vnd.sun.star.oleobject" )
144
638
                aEmbedFactory = "com.sun.star.embed.OLEEmbeddedObjectFactory";
145
638
        }
146
638
        catch ( const uno::Exception& )
147
638
        {
148
0
        }
149
150
638
        try {
151
638
            uno::Reference< lang::XComponent > xComp( xSubStream, uno::UNO_QUERY );
152
638
            if ( xComp.is() )
153
638
                xComp->dispose();
154
638
        }
155
638
        catch ( const uno::Exception& )
156
638
        {
157
0
        }
158
638
    }
159
160
638
    OSL_ENSURE( !aMediaType.isEmpty(), "No media type is specified for the object!" );
161
638
    if ( !aMediaType.isEmpty() && aEmbedFactory.isEmpty() )
162
0
    {
163
0
        aEmbedFactory = m_aConfigHelper.GetFactoryNameByMediaType( aMediaType );
164
165
        // If no factory is found, fall back to the FileFormatVersion=6200 filter, Base only has that.
166
0
        if (aEmbedFactory.isEmpty() && aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DATABASE)
167
0
            aEmbedFactory = m_aConfigHelper.GetFactoryNameByMediaType(MIMETYPE_VND_SUN_XML_BASE);
168
0
    }
169
170
638
    if ( !aEmbedFactory.isEmpty()
171
         // when active OLE content is disabled, ignore aEmbedFactory and force
172
         // the embedded object to be an ODummyEmbeddedObject
173
638
         && !officecfg::Office::Common::Security::Scripting::DisableActiveContent::get() )
174
638
    {
175
638
        uno::Reference< uno::XInterface > xFact = m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext);
176
177
638
        uno::Reference< embed::XEmbedObjectCreator > xEmbCreator( xFact, uno::UNO_QUERY );
178
638
        if ( xEmbCreator.is() )
179
0
            return xEmbCreator->createInstanceInitFromEntry( xStorage, sEntName, aMedDescr, lObjArgs );
180
181
638
        uno::Reference < embed::XEmbedObjectFactory > xEmbFact( xFact, uno::UNO_QUERY );
182
638
        if ( xEmbFact.is() )
183
0
            return xEmbFact->createInstanceUserInit( uno::Sequence< sal_Int8 >(), OUString(), xStorage, sEntName, embed::EntryInitModes::DEFAULT_INIT, aMedDescr, lObjArgs);
184
638
    }
185
186
    // the default object should be created, it will allow to store the contents on the next saving
187
638
    uno::Reference< uno::XInterface > xResult( static_cast< cppu::OWeakObject* >( new ODummyEmbeddedObject() ) );
188
638
    uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY_THROW );
189
638
    xPersist->setPersistentEntry( xStorage, sEntName, embed::EntryInitModes::DEFAULT_INIT, aMedDescr, lObjArgs );
190
638
    return xResult;
191
638
}
192
193
/**
194
 * Decides if rFilter should be used to load data into a doc model or real OLE embedding should
195
 * happen. Empty return value means the later.
196
 */
197
static OUString HandleFilter(const OUString& rFilter)
198
0
{
199
0
    OUString aRet = rFilter;
200
201
0
    if (!officecfg::Office::Common::Filter::Microsoft::Import::WinWordToWriter::get())
202
0
    {
203
0
        if (rFilter == "MS Word 97" || rFilter == "MS Word 2007 XML")
204
0
        {
205
0
            aRet.clear();
206
0
        }
207
0
    }
208
209
0
    if (!officecfg::Office::Common::Filter::Microsoft::Import::ExcelToCalc::get())
210
0
    {
211
0
        if (rFilter == "MS Excel 97" || rFilter == "Calc MS Excel 2007 XML")
212
0
        {
213
0
            aRet.clear();
214
0
        }
215
0
    }
216
0
    if (!officecfg::Office::Common::Filter::Microsoft::Import::PowerPointToImpress::get())
217
0
    {
218
0
        if (rFilter == "MS PowerPoint 97" || rFilter == "Impress MS PowerPoint 2007 XML")
219
0
        {
220
0
            aRet.clear();
221
0
        }
222
0
    }
223
0
    if (!officecfg::Office::Common::Filter::Microsoft::Import::VisioToDraw::get())
224
0
    {
225
0
        if (rFilter == "Visio Document")
226
0
        {
227
0
            aRet.clear();
228
0
        }
229
0
    }
230
0
    if (!officecfg::Office::Common::Filter::Adobe::Import::PDFToDraw::get())
231
0
    {
232
0
        if (rFilter == "draw_pdf_import")
233
0
        {
234
0
            aRet.clear();
235
0
        }
236
0
    }
237
238
0
    return aRet;
239
0
}
240
241
uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceInitFromMediaDescriptor(
242
        const uno::Reference< embed::XStorage >& xStorage,
243
        const OUString& sEntName,
244
        const uno::Sequence< beans::PropertyValue >& aMediaDescr,
245
        const uno::Sequence< beans::PropertyValue >& lObjArgs )
246
0
{
247
0
    if ( officecfg::Office::Common::Security::Scripting::DisableActiveContent::get() )
248
0
        throw lang::NoSupportException(u"Active OLE content is disabled!"_ustr);
249
    // TODO: use lObjArgs
250
251
0
    if ( !xStorage.is() )
252
0
        throw lang::IllegalArgumentException( u"No parent storage is provided!"_ustr,
253
0
                                            static_cast< ::cppu::OWeakObject* >(this),
254
0
                                            1 );
255
256
0
    if ( sEntName.isEmpty() )
257
0
        throw lang::IllegalArgumentException( u"Empty element name is provided!"_ustr,
258
0
                                            static_cast< ::cppu::OWeakObject* >(this),
259
0
                                            2 );
260
261
0
    uno::Reference< uno::XInterface > xResult;
262
0
    uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr );
263
264
    // check if there is FilterName
265
0
    OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, false );
266
267
0
    aFilterName = HandleFilter(aFilterName);
268
269
0
    if ( !aFilterName.isEmpty() )
270
0
    {
271
        // the object can be loaded by one of the office application
272
0
        uno::Reference< embed::XEmbeddedObjectCreator > xOOoEmbCreator =
273
0
                            embed::OOoEmbeddedObjectFactory::create( m_xContext );
274
275
0
        xResult = xOOoEmbCreator->createInstanceInitFromMediaDescriptor( xStorage,
276
0
                                                                         sEntName,
277
0
                                                                         aTempMedDescr,
278
0
                                                                         lObjArgs );
279
0
    }
280
0
    else
281
0
    {
282
        // must be an OLE object
283
284
        // TODO: in future, when more object types are possible this place seems
285
        // to be a weak one, probably configuration must provide a type detection service
286
        // for every factory, so any file could go through services until it is recognized
287
        // or there is no more services
288
        // Or for example the typename can be used to detect object type if typedetection
289
        // was also extended.
290
291
0
        uno::Reference< embed::XEmbeddedObjectCreator > xOleEmbCreator =
292
0
                            embed::OLEEmbeddedObjectFactory::create( m_xContext );
293
294
0
        xResult = xOleEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aTempMedDescr, lObjArgs );
295
0
    }
296
297
0
    return xResult;
298
0
}
299
300
301
uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceUserInit(
302
        const uno::Sequence< sal_Int8 >& aClassID,
303
        const OUString& sClassName,
304
        const uno::Reference< embed::XStorage >& xStorage,
305
        const OUString& sEntName,
306
        sal_Int32 nEntryConnectionMode,
307
        const uno::Sequence< beans::PropertyValue >& aArgs,
308
        const uno::Sequence< beans::PropertyValue >& aObjectArgs )
309
0
{
310
0
    if ( officecfg::Office::Common::Security::Scripting::DisableActiveContent::get() )
311
0
        throw lang::NoSupportException(u"Active OLE content is disabled!"_ustr);
312
0
    if ( !xStorage.is() )
313
0
        throw lang::IllegalArgumentException( u"No parent storage is provided!"_ustr,
314
0
                                            static_cast< ::cppu::OWeakObject* >(this),
315
0
                                            3 );
316
317
0
    if ( sEntName.isEmpty() )
318
0
        throw lang::IllegalArgumentException( u"Empty element name is provided!"_ustr,
319
0
                                            static_cast< ::cppu::OWeakObject* >(this),
320
0
                                            4 );
321
322
0
    OUString aEmbedFactory = m_aConfigHelper.GetFactoryNameByClassID( aClassID );
323
0
    uno::Reference< embed::XEmbedObjectFactory > xEmbFactory(
324
0
                        m_xContext->getServiceManager()->createInstanceWithContext(aEmbedFactory, m_xContext),
325
0
                        uno::UNO_QUERY_THROW );
326
327
0
    return xEmbFactory->createInstanceUserInit( aClassID,
328
0
                                                sClassName,
329
0
                                                xStorage,
330
0
                                                sEntName,
331
0
                                                nEntryConnectionMode,
332
0
                                                aArgs,
333
0
                                                aObjectArgs );
334
0
}
335
336
337
uno::Reference< uno::XInterface > SAL_CALL UNOEmbeddedObjectCreator::createInstanceLink(
338
                                            const uno::Reference< embed::XStorage >& xStorage,
339
                                            const OUString& sEntName,
340
                                            const uno::Sequence< beans::PropertyValue >& aMediaDescr,
341
                                            const uno::Sequence< beans::PropertyValue >& lObjArgs )
342
0
{
343
0
    if ( officecfg::Office::Common::Security::Scripting::DisableActiveContent::get() )
344
0
        throw lang::NoSupportException(u"Active OLE content is disabled!"_ustr);
345
346
0
    uno::Reference< uno::XInterface > xResult;
347
348
0
    uno::Sequence< beans::PropertyValue > aTempMedDescr( aMediaDescr );
349
350
    // check if there is URL, URL must exist
351
0
    OUString aURL;
352
0
    for (beans::PropertyValue const& prop : aTempMedDescr)
353
0
        if ( prop.Name == "URL" )
354
0
            prop.Value >>= aURL;
355
356
0
    if ( aURL.isEmpty() )
357
0
        throw lang::IllegalArgumentException( u"No URL for the link is provided!"_ustr,
358
0
                                        static_cast< ::cppu::OWeakObject* >(this),
359
0
                                        3 );
360
361
0
    OUString aFilterName = m_aConfigHelper.UpdateMediaDescriptorWithFilterName( aTempMedDescr, false );
362
363
0
    if ( !aFilterName.isEmpty() )
364
0
    {
365
        // the object can be loaded by one of the office application
366
0
        uno::Reference< embed::XEmbeddedObjectCreator > xOOoLinkCreator =
367
0
                            embed::OOoEmbeddedObjectFactory::create( m_xContext );
368
369
0
        xResult = xOOoLinkCreator->createInstanceLink( xStorage,
370
0
                                                        sEntName,
371
0
                                                        aTempMedDescr,
372
0
                                                        lObjArgs );
373
0
    }
374
0
    else
375
0
    {
376
        // must be an OLE link
377
378
        // TODO: in future, when more object types are possible this place seems
379
        // to be a weak one, probably configuration must provide a type detection service
380
        // for every factory, so any file could go through services until it is recognized
381
        // or there is no more services
382
        // Or for example the typename can be used to detect object type if typedetection
383
        // was also extended.
384
385
0
        if ( !xStorage.is() )
386
0
            throw lang::IllegalArgumentException( u"No parent storage is provided!"_ustr,
387
0
                                                static_cast< ::cppu::OWeakObject* >(this),
388
0
                                                3 );
389
390
0
        if ( sEntName.isEmpty() )
391
0
            throw lang::IllegalArgumentException( u"Empty element name is provided!"_ustr,
392
0
                                                static_cast< ::cppu::OWeakObject* >(this),
393
0
                                                4 );
394
395
0
        uno::Reference< embed::XEmbeddedObjectCreator > xLinkCreator =
396
0
                            embed::OLEEmbeddedObjectFactory::create( m_xContext);
397
398
0
        xResult = xLinkCreator->createInstanceLink( xStorage, sEntName, aTempMedDescr, lObjArgs );
399
0
    }
400
401
0
    return xResult;
402
0
}
403
404
OUString SAL_CALL UNOEmbeddedObjectCreator::getImplementationName()
405
0
{
406
0
    return u"com.sun.star.comp.embed.EmbeddedObjectCreator"_ustr;
407
0
}
408
409
sal_Bool SAL_CALL UNOEmbeddedObjectCreator::supportsService( const OUString& ServiceName )
410
0
{
411
0
    return cppu::supportsService(this, ServiceName);
412
0
}
413
414
uno::Sequence< OUString > SAL_CALL UNOEmbeddedObjectCreator::getSupportedServiceNames()
415
0
{
416
0
    return { u"com.sun.star.embed.EmbeddedObjectCreator"_ustr, u"com.sun.star.comp.embed.EmbeddedObjectCreator"_ustr };
417
0
}
418
419
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
420
embeddedobj_UNOEmbeddedObjectCreator_get_implementation(
421
    css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
422
8
{
423
8
    return cppu::acquire(new UNOEmbeddedObjectCreator(context));
424
8
}
425
426
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */