Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/ucb/source/ucp/file/prov.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 <osl/security.hxx>
21
#include <osl/file.hxx>
22
#include <osl/socket.h>
23
#include <cppuhelper/queryinterface.hxx>
24
#include <comphelper/processfactory.hxx>
25
#include <com/sun/star/beans/PropertyAttribute.hpp>
26
#include <com/sun/star/ucb/FileSystemNotation.hpp>
27
#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
28
#include <cppuhelper/supportsservice.hxx>
29
#include "filglob.hxx"
30
#include "filid.hxx"
31
#include "filtask.hxx"
32
#include "bc.hxx"
33
#include "prov.hxx"
34
35
using namespace fileaccess;
36
using namespace com::sun::star;
37
using namespace com::sun::star::uno;
38
using namespace com::sun::star::lang;
39
using namespace com::sun::star::beans;
40
using namespace com::sun::star::ucb;
41
42
/****************************************************************************/
43
/*                                                                          */
44
/*                                                                          */
45
/*                        FileProvider                                      */
46
/*                                                                          */
47
/*                                                                          */
48
/****************************************************************************/
49
FileProvider::FileProvider( const Reference< XComponentContext >& rxContext )
50
11
    : m_xContext(rxContext)
51
11
    , m_FileSystemNotation(FileSystemNotation::UNKNOWN_NOTATION)
52
11
{
53
11
}
54
55
FileProvider::~FileProvider()
56
0
{
57
0
}
58
59
// XInitialization
60
void FileProvider::init()
61
284k
{
62
284k
    if( ! m_pMyShell )
63
0
        m_pMyShell.reset( new TaskManager( m_xContext, this, true ) );
64
284k
}
65
66
67
void SAL_CALL
68
FileProvider::initialize(
69
    const Sequence< Any >& aArguments )
70
11
{
71
11
    if( ! m_pMyShell ) {
72
11
        OUString config;
73
11
        if( aArguments.hasElements() &&
74
11
            (aArguments[0] >>= config) &&
75
11
            config == "NoConfig" )
76
11
            m_pMyShell.reset( new TaskManager( m_xContext, this, false ) );
77
0
        else
78
0
            m_pMyShell.reset( new TaskManager( m_xContext, this, true ) );
79
11
    }
80
11
}
81
82
// XServiceInfo methods.
83
OUString SAL_CALL
84
FileProvider::getImplementationName()
85
0
{
86
0
    return u"com.sun.star.comp.ucb.FileProvider"_ustr;
87
0
}
88
89
sal_Bool SAL_CALL FileProvider::supportsService(const OUString& ServiceName )
90
0
{
91
0
    return cppu::supportsService(this, ServiceName);
92
0
}
93
94
Sequence< OUString > SAL_CALL
95
FileProvider::getSupportedServiceNames()
96
0
{
97
0
    return { u"com.sun.star.ucb.FileContentProvider"_ustr };
98
0
}
99
100
// XContent
101
102
Reference< XContent > SAL_CALL
103
FileProvider::queryContent(
104
    const Reference< XContentIdentifier >& xIdentifier )
105
142k
{
106
142k
    init();
107
142k
    OUString aUnc;
108
142k
    bool err = fileaccess::TaskManager::getUnqFromUrl( xIdentifier->getContentIdentifier(),
109
142k
                                              aUnc );
110
111
142k
    if(  err )
112
0
    {
113
0
        throw IllegalIdentifierException();
114
0
    }
115
116
142k
    return Reference<XContent>(new BaseContent(m_pMyShell.get(), xIdentifier, aUnc));
117
142k
}
118
119
sal_Int32 SAL_CALL
120
FileProvider::compareContentIds(
121
                const Reference< XContentIdentifier >& Id1,
122
                const Reference< XContentIdentifier >& Id2 )
123
0
{
124
0
    init();
125
0
    OUString aUrl1 = Id1->getContentIdentifier();
126
0
    OUString aUrl2 = Id2->getContentIdentifier();
127
128
0
    sal_Int32   iComp = aUrl1.compareTo( aUrl2 );
129
130
0
    if ( 0 != iComp )
131
0
    {
132
0
        OUString aPath1, aPath2;
133
134
0
        fileaccess::TaskManager::getUnqFromUrl( aUrl1, aPath1 );
135
0
        fileaccess::TaskManager::getUnqFromUrl( aUrl2, aPath2 );
136
137
0
        osl::FileBase::RC   error;
138
0
        osl::DirectoryItem  aItem1, aItem2;
139
140
0
        error = osl::DirectoryItem::get( aPath1, aItem1 );
141
0
        if ( error == osl::FileBase::E_None )
142
0
            error = osl::DirectoryItem::get( aPath2, aItem2 );
143
144
0
        if ( error != osl::FileBase::E_None )
145
0
            return iComp;
146
147
0
        osl::FileStatus aStatus1( osl_FileStatus_Mask_FileURL );
148
0
        osl::FileStatus aStatus2( osl_FileStatus_Mask_FileURL );
149
0
        error = aItem1.getFileStatus( aStatus1 );
150
0
        if ( error == osl::FileBase::E_None )
151
0
            error = aItem2.getFileStatus( aStatus2 );
152
153
0
        if ( error == osl::FileBase::E_None )
154
0
        {
155
0
            iComp = aStatus1.getFileURL().compareTo( aStatus2.getFileURL() );
156
157
// Quick hack for Windows to treat all file systems as case insensitive
158
#ifdef _WIN32
159
            if ( 0 != iComp )
160
            {
161
                error = osl::FileBase::getSystemPathFromFileURL( aStatus1.getFileURL(), aPath1 );
162
                if ( error == osl::FileBase::E_None )
163
                    error = osl::FileBase::getSystemPathFromFileURL( aStatus2.getFileURL(), aPath2 );
164
165
                if ( error == osl::FileBase::E_None )
166
                    iComp = aPath1.compareToIgnoreAsciiCase( aPath2 );
167
            }
168
#endif
169
0
        }
170
0
    }
171
172
0
    return iComp;
173
0
}
174
175
176
Reference< XContentIdentifier > SAL_CALL
177
FileProvider::createContentIdentifier(
178
                      const OUString& ContentId )
179
142k
{
180
142k
    init();
181
142k
    return new FileContentIdentifier( ContentId,false );
182
142k
}
183
184
185
//XPropertySetInfoImpl
186
187
namespace fileaccess {
188
189
class XPropertySetInfoImpl2
190
    : public cppu::OWeakObject,
191
      public XPropertySetInfo
192
{
193
public:
194
    XPropertySetInfoImpl2();
195
196
    // XInterface
197
    virtual Any SAL_CALL
198
    queryInterface( const Type& aType ) override;
199
200
    virtual void SAL_CALL
201
    acquire()
202
        noexcept override;
203
204
    virtual void SAL_CALL
205
    release()
206
        noexcept override;
207
208
209
    virtual Sequence< Property > SAL_CALL
210
    getProperties() override;
211
212
    virtual Property SAL_CALL
213
    getPropertyByName( const OUString& aName ) override;
214
215
    virtual sal_Bool SAL_CALL
216
    hasPropertyByName( const OUString& Name ) override;
217
218
219
private:
220
    Sequence< Property > m_seq;
221
};
222
223
}
224
225
XPropertySetInfoImpl2::XPropertySetInfoImpl2()
226
0
    : m_seq{ Property( u"HostName"_ustr,
227
0
                         -1,
228
0
                         cppu::UnoType<OUString>::get(),
229
0
                         PropertyAttribute::READONLY ),
230
0
             Property( u"HomeDirectory"_ustr,
231
0
                         -1,
232
0
                         cppu::UnoType<OUString>::get(),
233
0
                         PropertyAttribute::READONLY ),
234
0
             Property( u"FileSystemNotation"_ustr,
235
0
                         -1,
236
0
                         cppu::UnoType<sal_Int32>::get(),
237
0
                         PropertyAttribute::READONLY )}
238
0
{
239
0
}
240
241
void SAL_CALL
242
XPropertySetInfoImpl2::acquire()
243
    noexcept
244
0
{
245
0
    OWeakObject::acquire();
246
0
}
247
248
249
void SAL_CALL
250
XPropertySetInfoImpl2::release()
251
    noexcept
252
0
{
253
0
    OWeakObject::release();
254
0
}
255
256
257
Any SAL_CALL
258
XPropertySetInfoImpl2::queryInterface( const Type& rType )
259
0
{
260
0
    Any aRet = cppu::queryInterface( rType,
261
0
                                     static_cast< XPropertySetInfo* >(this) );
262
0
    return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
263
0
}
264
265
266
Property SAL_CALL
267
XPropertySetInfoImpl2::getPropertyByName( const OUString& aName )
268
0
{
269
0
    auto pProp = std::find_if(std::cbegin(m_seq), std::cend(m_seq),
270
0
            [&aName](const Property& rProp) { return rProp.Name == aName; });
271
0
    if (pProp != std::cend(m_seq))
272
0
        return *pProp;
273
274
0
    throw UnknownPropertyException( aName );
275
0
}
276
277
278
Sequence< Property > SAL_CALL
279
XPropertySetInfoImpl2::getProperties()
280
0
{
281
0
    return m_seq;
282
0
}
283
284
285
sal_Bool SAL_CALL
286
XPropertySetInfoImpl2::hasPropertyByName(
287
    const OUString& aName )
288
0
{
289
0
    return std::any_of(std::cbegin(m_seq), std::cend(m_seq),
290
0
        [&aName](const Property& rProp) { return rProp.Name == aName; });
291
0
}
292
293
294
void FileProvider::initProperties(std::unique_lock<std::mutex>& /*rGuard*/)
295
0
{
296
0
    if(  m_xPropertySetInfo.is() )
297
0
        return;
298
299
0
    osl_getLocalHostname( &m_HostName.pData );
300
301
0
#if defined ( UNX )
302
0
    m_FileSystemNotation = FileSystemNotation::UNIX_NOTATION;
303
#elif defined( _WIN32 )
304
    m_FileSystemNotation = FileSystemNotation::DOS_NOTATION;
305
#else
306
    m_FileSystemNotation = FileSystemNotation::UNKNOWN_NOTATION;
307
#endif
308
0
    osl::Security aSecurity;
309
0
    aSecurity.getHomeDir( m_HomeDirectory );
310
311
    // static const sal_Int32 UNKNOWN_NOTATION = (sal_Int32)0;
312
    // static const sal_Int32 UNIX_NOTATION = (sal_Int32)1;
313
    // static const sal_Int32 DOS_NOTATION = (sal_Int32)2;
314
    // static const sal_Int32 MAC_NOTATION = (sal_Int32)3;
315
316
0
    m_xPropertySetInfo = new XPropertySetInfoImpl2();
317
0
}
318
319
320
// XPropertySet
321
322
Reference< XPropertySetInfo > SAL_CALL
323
FileProvider::getPropertySetInfo(  )
324
0
{
325
0
    std::unique_lock aGuard( m_aMutex );
326
0
    initProperties(aGuard);
327
0
    return m_xPropertySetInfo;
328
0
}
329
330
331
void SAL_CALL
332
FileProvider::setPropertyValue( const OUString& aPropertyName,
333
                                const Any& )
334
0
{
335
0
    if( !(aPropertyName == "FileSystemNotation" ||
336
0
        aPropertyName == "HomeDirectory"      ||
337
0
        aPropertyName == "HostName") )
338
0
        throw UnknownPropertyException( aPropertyName );
339
0
}
340
341
342
Any SAL_CALL
343
FileProvider::getPropertyValue(
344
    const OUString& aPropertyName )
345
0
{
346
0
    std::unique_lock aGuard( m_aMutex );
347
0
    initProperties(aGuard);
348
0
    if( aPropertyName == "FileSystemNotation" )
349
0
    {
350
0
        return Any(m_FileSystemNotation);
351
0
    }
352
0
    else if( aPropertyName == "HomeDirectory" )
353
0
    {
354
0
        return Any(m_HomeDirectory);
355
0
    }
356
0
    else if( aPropertyName == "HostName" )
357
0
    {
358
0
        return Any(m_HostName);
359
0
    }
360
0
    else
361
0
        throw UnknownPropertyException( aPropertyName );
362
0
}
363
364
365
void SAL_CALL
366
FileProvider::addPropertyChangeListener(
367
    const OUString&,
368
    const Reference< XPropertyChangeListener >& )
369
0
{
370
0
}
371
372
373
void SAL_CALL
374
FileProvider::removePropertyChangeListener(
375
    const OUString&,
376
    const Reference< XPropertyChangeListener >& )
377
0
{
378
0
}
379
380
void SAL_CALL
381
FileProvider::addVetoableChangeListener(
382
    const OUString&,
383
    const Reference< XVetoableChangeListener >& )
384
0
{
385
0
}
386
387
388
void SAL_CALL
389
FileProvider::removeVetoableChangeListener(
390
    const OUString&,
391
    const Reference< XVetoableChangeListener >& )
392
0
{
393
0
}
394
395
396
// XFileIdentifierConverter
397
398
sal_Int32 SAL_CALL
399
FileProvider::getFileProviderLocality( const OUString& BaseURL )
400
0
{
401
    // If the base URL is a 'file' URL, return 10 (very 'local'), otherwise
402
    // return -1 (mismatch).  What is missing is a fast comparison to ASCII,
403
    // ignoring case:
404
0
    return BaseURL.getLength() >= 5
405
0
           && (BaseURL[0] == 'F' || BaseURL[0] == 'f')
406
0
           && (BaseURL[1] == 'I' || BaseURL[1] == 'i')
407
0
           && (BaseURL[2] == 'L' || BaseURL[2] == 'l')
408
0
           && (BaseURL[3] == 'E' || BaseURL[3] == 'e')
409
0
           && BaseURL[4] == ':' ?
410
0
               10 : -1;
411
0
}
412
413
OUString SAL_CALL FileProvider::getFileURLFromSystemPath( const OUString&,
414
                                                               const OUString& SystemPath )
415
0
{
416
0
    OUString aNormalizedPath;
417
0
    if ( osl::FileBase::getFileURLFromSystemPath( SystemPath,aNormalizedPath ) != osl::FileBase::E_None )
418
0
        return OUString();
419
420
0
    return aNormalizedPath;
421
0
}
422
423
OUString SAL_CALL FileProvider::getSystemPathFromFileURL( const OUString& URL )
424
0
{
425
0
    OUString aSystemPath;
426
0
    if (osl::FileBase::getSystemPathFromFileURL( URL,aSystemPath ) != osl::FileBase::E_None )
427
0
        return OUString();
428
429
0
    return aSystemPath;
430
0
}
431
432
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
433
ucb_file_FileProvider_get_implementation(
434
    css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
435
11
{
436
11
    return cppu::acquire(new FileProvider(context));
437
11
}
438
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */