Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/ucb/source/ucp/file/bc.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 <rtl/uri.hxx>
21
#include <rtl/ustrbuf.hxx>
22
#include <rtl/ref.hxx>
23
24
#include <comphelper/diagnose_ex.hxx>
25
#include <com/sun/star/lang/NoSupportException.hpp>
26
#include <com/sun/star/sdbc/SQLException.hpp>
27
#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
28
#include <com/sun/star/ucb/OpenMode.hpp>
29
#include <com/sun/star/beans/IllegalTypeException.hpp>
30
#include <com/sun/star/io/XActiveDataStreamer.hpp>
31
#include <com/sun/star/io/XOutputStream.hpp>
32
#include <com/sun/star/io/XActiveDataSink.hpp>
33
#include <com/sun/star/ucb/NameClash.hpp>
34
#include <comphelper/fileurl.hxx>
35
#include <cppuhelper/supportsservice.hxx>
36
#include <utility>
37
#include "filglob.hxx"
38
#include "filid.hxx"
39
#include "filrow.hxx"
40
#include "bc.hxx"
41
#include "prov.hxx"
42
#include "filerror.hxx"
43
#include "filinsreq.hxx"
44
45
using namespace fileaccess;
46
using namespace com::sun::star;
47
using namespace com::sun::star::uno;
48
using namespace com::sun::star::ucb;
49
50
class fileaccess::PropertyListeners
51
{
52
    typedef comphelper::OInterfaceContainerHelper4<beans::XPropertiesChangeListener> ContainerHelper;
53
    std::unordered_map<OUString, ContainerHelper> m_aMap;
54
55
public:
56
    void disposeAndClear(std::unique_lock<std::mutex>& rGuard, const lang::EventObject& rEvt)
57
0
    {
58
        // create a copy, because do not fire event in a guarded section
59
0
        std::unordered_map<OUString, ContainerHelper> tempMap = std::move(m_aMap);
60
0
        for (auto& rPair : tempMap)
61
0
            rPair.second.disposeAndClear(rGuard, rEvt);
62
0
    }
63
    void addInterface(std::unique_lock<std::mutex>& rGuard, const OUString& rKey, const uno::Reference<beans::XPropertiesChangeListener>& rListener)
64
46.2k
    {
65
46.2k
        m_aMap[rKey].addInterface(rGuard, rListener);
66
46.2k
    }
67
    void removeInterface(std::unique_lock<std::mutex>& rGuard, const OUString& rKey, const uno::Reference<beans::XPropertiesChangeListener>& rListener)
68
46.2k
    {
69
        // search container with id rKey
70
46.2k
        auto iter = m_aMap.find(rKey);
71
        // container found?
72
46.2k
        if (iter != m_aMap.end())
73
46.2k
            iter->second.removeInterface(rGuard, rListener);
74
46.2k
    }
75
    std::vector< OUString > getContainedTypes(std::unique_lock<std::mutex>& rGuard) const
76
0
    {
77
0
        std::vector<OUString> aInterfaceTypes;
78
0
        aInterfaceTypes.reserve(m_aMap.size());
79
0
        for (const auto& rPair : m_aMap)
80
            // are interfaces added to this container?
81
0
            if (rPair.second.getLength(rGuard))
82
                // yes, put the type in the array
83
0
                aInterfaceTypes.push_back(rPair.first);
84
0
        return aInterfaceTypes;
85
0
    }
86
    comphelper::OInterfaceContainerHelper4<beans::XPropertiesChangeListener>* getContainer(std::unique_lock<std::mutex>& , const OUString& rKey)
87
0
    {
88
0
        auto iter = m_aMap.find(rKey);
89
0
        if (iter != m_aMap.end())
90
0
            return &iter->second;
91
0
        return nullptr;
92
0
    }
93
};
94
95
96
/****************************************************************************************/
97
/*                                                                                      */
98
/*                    BaseContent                                                       */
99
/*                                                                                      */
100
/****************************************************************************************/
101
102
103
// Private Constructor for just inserted Contents
104
105
BaseContent::BaseContent( TaskManager* pMyShell,
106
                          OUString parentName,
107
                          bool bFolder )
108
0
    : m_pMyShell( pMyShell ),
109
0
      m_aUncPath(std::move( parentName )),
110
0
      m_bFolder( bFolder ),
111
0
      m_nState( JustInserted )
112
0
{
113
0
    m_pMyShell->m_pProvider->acquire();
114
    // No registering, since we have no name
115
0
}
116
117
118
// Constructor for full featured Contents
119
120
BaseContent::BaseContent( TaskManager* pMyShell,
121
                          const Reference< XContentIdentifier >& xContentIdentifier,
122
                          OUString aUncPath, sal_uInt16 nState )
123
163k
    : m_pMyShell( pMyShell ),
124
163k
      m_xContentIdentifier( xContentIdentifier ),
125
163k
      m_aUncPath(std::move( aUncPath )),
126
163k
      m_bFolder( false ),
127
163k
      m_nState( nState )
128
163k
{
129
163k
    m_pMyShell->m_pProvider->acquire();
130
163k
    m_pMyShell->registerNotifier( m_aUncPath,this );
131
163k
    m_pMyShell->insertDefaultProperties( m_aUncPath );
132
163k
}
133
134
135
BaseContent::~BaseContent( )
136
163k
{
137
163k
    if( ( m_nState & FullFeatured ) || ( m_nState & Deleted ) )
138
163k
    {
139
163k
        m_pMyShell->deregisterNotifier( m_aUncPath,this );
140
163k
    }
141
163k
    m_pMyShell->m_pProvider->release();
142
163k
}
143
144
145
// XComponent
146
147
148
void SAL_CALL
149
BaseContent::addEventListener( const Reference< lang::XEventListener >& Listener )
150
0
{
151
0
    std::unique_lock aGuard( m_aMutex );
152
153
0
    m_aDisposeEventListeners.addInterface( aGuard, Listener );
154
0
}
155
156
157
void SAL_CALL
158
BaseContent::removeEventListener( const Reference< lang::XEventListener >& Listener )
159
0
{
160
0
    std::unique_lock aGuard( m_aMutex );
161
162
0
    m_aDisposeEventListeners.removeInterface( aGuard, Listener );
163
0
}
164
165
166
void SAL_CALL
167
BaseContent::dispose()
168
0
{
169
0
    lang::EventObject aEvt;
170
0
    aEvt.Source = static_cast< XContent* >( this );
171
172
0
    std::unique_lock aGuard( m_aMutex );
173
174
0
    std::unique_ptr<PropertyListeners> pPropertyListener = std::move(m_pPropertyListener);
175
176
0
    m_aDisposeEventListeners.disposeAndClear( aGuard, aEvt );
177
0
    m_aContentEventListeners.disposeAndClear( aGuard, aEvt );
178
179
0
    if( pPropertyListener )
180
0
        pPropertyListener->disposeAndClear( aGuard, aEvt );
181
182
0
    m_aPropertySetInfoChangeListeners.disposeAndClear( aGuard, aEvt );
183
0
}
184
185
//  XServiceInfo
186
OUString SAL_CALL
187
BaseContent::getImplementationName()
188
0
{
189
0
    return u"com.sun.star.comp.ucb.FileContent"_ustr;
190
0
}
191
192
sal_Bool SAL_CALL
193
BaseContent::supportsService( const OUString& ServiceName )
194
0
{
195
0
    return cppu::supportsService( this, ServiceName );
196
0
}
197
198
Sequence< OUString > SAL_CALL
199
BaseContent::getSupportedServiceNames()
200
0
{
201
0
    Sequence<OUString> ret { u"com.sun.star.ucb.FileContent"_ustr };
202
0
    return ret;
203
0
}
204
205
//  XCommandProcessor
206
207
208
sal_Int32 SAL_CALL
209
BaseContent::createCommandIdentifier()
210
174k
{
211
174k
    return m_pMyShell->getCommandId();
212
174k
}
213
214
215
void SAL_CALL
216
BaseContent::abort( sal_Int32 /*CommandId*/ )
217
0
{
218
0
}
219
220
221
Any SAL_CALL
222
BaseContent::execute( const Command& aCommand,
223
                      sal_Int32 CommandId,
224
                      const Reference< XCommandEnvironment >& Environment )
225
174k
{
226
174k
    if( ! CommandId )
227
        // A Command with commandid zero cannot be aborted
228
174k
        CommandId = createCommandIdentifier();
229
230
174k
    m_pMyShell->startTask( CommandId,
231
174k
                           Environment );
232
233
174k
    Any aAny;
234
235
174k
    if (aCommand.Name == "getPropertySetInfo")  // No exceptions
236
0
    {
237
0
        aAny <<= getPropertySetInfo();
238
0
    }
239
174k
    else if (aCommand.Name == "getCommandInfo")  // no exceptions
240
0
    {
241
0
        aAny <<= getCommandInfo();
242
0
    }
243
174k
    else if ( aCommand.Name == "setPropertyValues" )
244
0
    {
245
0
        Sequence< beans::PropertyValue > sPropertyValues;
246
247
0
        if( ! ( aCommand.Argument >>= sPropertyValues ) )
248
0
            m_pMyShell->installError( CommandId,
249
0
                                      TaskHandlerErr::WRONG_SETPROPERTYVALUES_ARGUMENT );
250
0
        else
251
0
            aAny <<= setPropertyValues( CommandId,sPropertyValues );  // calls endTask by itself
252
0
    }
253
174k
    else if ( aCommand.Name == "getPropertyValues" )
254
10.7k
    {
255
10.7k
        Sequence< beans::Property > ListOfRequestedProperties;
256
257
10.7k
        if( ! ( aCommand.Argument >>= ListOfRequestedProperties ) )
258
0
            m_pMyShell->installError( CommandId,
259
0
                                      TaskHandlerErr::WRONG_GETPROPERTYVALUES_ARGUMENT );
260
10.7k
        else
261
10.7k
            aAny <<= getPropertyValues( CommandId,
262
10.7k
                                        ListOfRequestedProperties );
263
10.7k
    }
264
163k
    else if ( aCommand.Name == "open" )
265
163k
    {
266
163k
        OpenCommandArgument2 aOpenArgument;
267
163k
        if( ! ( aCommand.Argument >>= aOpenArgument ) )
268
0
            m_pMyShell->installError( CommandId,
269
0
                                      TaskHandlerErr::WRONG_OPEN_ARGUMENT );
270
163k
        else
271
163k
        {
272
163k
            Reference< XDynamicResultSet > result = open( CommandId,aOpenArgument );
273
163k
            if( result.is() )
274
117k
                aAny <<= result;
275
163k
        }
276
163k
    }
277
0
    else if ( aCommand.Name == "delete" )
278
0
    {
279
0
        if( ! aCommand.Argument.has< bool >() )
280
0
            m_pMyShell->installError( CommandId,
281
0
                                      TaskHandlerErr::WRONG_DELETE_ARGUMENT );
282
0
        else
283
0
            deleteContent( CommandId );
284
0
    }
285
0
    else if ( aCommand.Name == "transfer" )
286
0
    {
287
0
        TransferInfo aTransferInfo;
288
0
        if( ! ( aCommand.Argument >>= aTransferInfo ) )
289
0
            m_pMyShell->installError( CommandId,
290
0
                                      TaskHandlerErr::WRONG_TRANSFER_ARGUMENT );
291
0
        else
292
0
            transfer( CommandId, aTransferInfo );
293
0
    }
294
0
    else if ( aCommand.Name == "insert" )
295
0
    {
296
0
        InsertCommandArgument aInsertArgument;
297
0
        if( ! ( aCommand.Argument >>= aInsertArgument ) )
298
0
            m_pMyShell->installError( CommandId,
299
0
                                      TaskHandlerErr::WRONG_INSERT_ARGUMENT );
300
0
        else
301
0
            insert( CommandId,aInsertArgument );
302
0
    }
303
0
    else if ( aCommand.Name == "getCasePreservingURL" )
304
0
    {
305
0
        Reference< sdbc::XRow > xRow = getPropertyValues( CommandId, { { u"CasePreservingURL"_ustr, -1, cppu::UnoType<sal_Bool>::get(), 0 } });
306
0
        OUString CasePreservingURL = xRow->getString(1);
307
0
        if(!xRow->wasNull())
308
0
            aAny <<= CasePreservingURL;
309
0
    }
310
0
    else if ( aCommand.Name == "createNewContent" )
311
0
    {
312
0
        ucb::ContentInfo aArg;
313
0
        if ( !( aCommand.Argument >>= aArg ) )
314
0
            m_pMyShell->installError( CommandId,
315
0
                                      TaskHandlerErr::WRONG_CREATENEWCONTENT_ARGUMENT );
316
0
        else
317
0
            aAny <<= createNewContent( aArg );
318
0
    }
319
0
    else
320
0
        m_pMyShell->installError( CommandId,
321
0
                                  TaskHandlerErr::UNSUPPORTED_COMMAND );
322
323
324
    // This is the only function allowed to throw an exception
325
174k
    endTask( CommandId );
326
327
174k
    return aAny;
328
174k
}
329
330
331
void SAL_CALL
332
BaseContent::addPropertiesChangeListener(
333
    const Sequence< OUString >& PropertyNames,
334
    const Reference< beans::XPropertiesChangeListener >& Listener )
335
46.2k
{
336
46.2k
    if( ! Listener.is() )
337
0
        return;
338
339
46.2k
    std::unique_lock aGuard( m_aMutex );
340
341
46.2k
    if( ! m_pPropertyListener )
342
46.2k
        m_pPropertyListener.reset( new PropertyListeners );
343
344
345
46.2k
    if( !PropertyNames.hasElements() )
346
46.2k
        m_pPropertyListener->addInterface( aGuard, OUString(),Listener );
347
0
    else
348
0
    {
349
0
        Reference< beans::XPropertySetInfo > xProp = m_pMyShell->info_p( m_aUncPath );
350
0
        for( const auto& rName : PropertyNames )
351
0
            if( xProp->hasPropertyByName( rName ) )
352
0
                m_pPropertyListener->addInterface( aGuard, rName,Listener );
353
0
    }
354
46.2k
}
355
356
357
void SAL_CALL
358
BaseContent::removePropertiesChangeListener( const Sequence< OUString >& PropertyNames,
359
                                             const Reference< beans::XPropertiesChangeListener >& Listener )
360
46.2k
{
361
46.2k
    if( ! Listener.is() )
362
0
        return;
363
364
46.2k
    std::unique_lock aGuard( m_aMutex );
365
366
46.2k
    if( ! m_pPropertyListener )
367
0
        return;
368
369
46.2k
    for( const auto& rName : PropertyNames )
370
0
        m_pPropertyListener->removeInterface( aGuard, rName,Listener );
371
372
46.2k
    m_pPropertyListener->removeInterface( aGuard, OUString(), Listener );
373
46.2k
}
374
375
376
// XContent
377
378
379
Reference< ucb::XContentIdentifier > SAL_CALL
380
BaseContent::getIdentifier()
381
198k
{
382
198k
    return m_xContentIdentifier;
383
198k
}
384
385
386
OUString SAL_CALL
387
BaseContent::getContentType()
388
0
{
389
0
    if( !( m_nState & Deleted ) )
390
0
    {
391
0
        if( m_nState & JustInserted )
392
0
        {
393
0
            if ( m_bFolder )
394
0
                return TaskManager::FolderContentType;
395
0
            else
396
0
                return TaskManager::FileContentType;
397
0
        }
398
0
        else
399
0
        {
400
0
            try
401
0
            {
402
                // Who am I ?
403
0
                Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { u"IsDocument"_ustr, -1, cppu::UnoType<sal_Bool>::get(), 0 } });
404
0
                bool IsDocument = xRow->getBoolean( 1 );
405
406
0
                if ( !xRow->wasNull() )
407
0
                {
408
0
                    if ( IsDocument )
409
0
                        return TaskManager::FileContentType;
410
0
                    else
411
0
                        return TaskManager::FolderContentType;
412
0
                }
413
0
                else
414
0
                {
415
0
                    OSL_FAIL( "BaseContent::getContentType - Property value was null!" );
416
0
                }
417
0
            }
418
0
            catch (const sdbc::SQLException&)
419
0
            {
420
0
                TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
421
0
            }
422
0
        }
423
0
    }
424
425
0
    return OUString();
426
0
}
427
428
429
void SAL_CALL
430
BaseContent::addContentEventListener(
431
    const Reference< XContentEventListener >& Listener )
432
209k
{
433
209k
    std::unique_lock aGuard( m_aMutex );
434
435
209k
    m_aContentEventListeners.addInterface( aGuard, Listener );
436
209k
}
437
438
439
void SAL_CALL
440
BaseContent::removeContentEventListener(
441
    const Reference< XContentEventListener >& Listener )
442
209k
{
443
209k
    std::unique_lock aGuard( m_aMutex );
444
445
209k
    m_aContentEventListeners.removeInterface( aGuard, Listener );
446
209k
}
447
448
449
// XPropertyContainer
450
451
452
void SAL_CALL
453
BaseContent::addProperty(
454
    const OUString& Name,
455
    sal_Int16 Attributes,
456
    const Any& DefaultValue )
457
0
{
458
0
    if( ( m_nState & JustInserted ) || ( m_nState & Deleted ) || Name.isEmpty() )
459
0
    {
460
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
461
0
    }
462
463
0
    m_pMyShell->associate( m_aUncPath,Name,DefaultValue,Attributes );
464
0
}
465
466
467
void SAL_CALL
468
BaseContent::removeProperty( const OUString& Name )
469
0
{
470
0
    if( m_nState & Deleted )
471
0
        throw beans::UnknownPropertyException( Name );
472
473
0
    m_pMyShell->deassociate( m_aUncPath, Name );
474
0
}
475
476
477
// XContentCreator
478
479
480
Sequence< ContentInfo > SAL_CALL
481
BaseContent::queryCreatableContentsInfo()
482
0
{
483
0
    return TaskManager::queryCreatableContentsInfo();
484
0
}
485
486
487
Reference< XContent > SAL_CALL
488
BaseContent::createNewContent( const ContentInfo& Info )
489
0
{
490
    // Check type.
491
0
    if ( Info.Type.isEmpty() )
492
0
        return Reference< XContent >();
493
494
0
    bool bFolder = Info.Type == TaskManager::FolderContentType;
495
0
    if ( !bFolder )
496
0
    {
497
0
        if ( Info.Type != TaskManager::FileContentType )
498
0
        {
499
            // Neither folder nor file to create!
500
0
            return Reference< XContent >();
501
0
        }
502
0
    }
503
504
    // Who am I ?
505
0
    bool IsDocument = false;
506
507
0
    try
508
0
    {
509
0
        Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { u"IsDocument"_ustr, -1, cppu::UnoType<sal_Bool>::get(), 0 } });
510
0
        IsDocument = xRow->getBoolean( 1 );
511
512
0
        if ( xRow->wasNull() )
513
0
        {
514
0
            IsDocument = false;
515
//              OSL_FAIL( //                          "BaseContent::createNewContent - Property value was null!" );
516
//              return Reference< XContent >();
517
0
        }
518
0
    }
519
0
    catch (const sdbc::SQLException&)
520
0
    {
521
0
        TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
522
0
        return Reference< XContent >();
523
0
    }
524
525
0
    OUString dstUncPath;
526
527
0
    if( IsDocument )
528
0
    {
529
        // KSO: Why is a document a XContentCreator? This is quite unusual.
530
0
        dstUncPath = getParentName( m_aUncPath );
531
0
    }
532
0
    else
533
0
        dstUncPath = m_aUncPath;
534
535
0
    return new BaseContent( m_pMyShell, dstUncPath, bFolder );
536
0
}
537
538
539
// XPropertySetInfoChangeNotifier
540
541
542
void SAL_CALL
543
BaseContent::addPropertySetInfoChangeListener(
544
    const Reference< beans::XPropertySetInfoChangeListener >& Listener )
545
0
{
546
0
    std::unique_lock aGuard( m_aMutex );
547
548
0
    m_aPropertySetInfoChangeListeners.addInterface( aGuard, Listener );
549
0
}
550
551
552
void SAL_CALL
553
BaseContent::removePropertySetInfoChangeListener(
554
    const Reference< beans::XPropertySetInfoChangeListener >& Listener )
555
0
{
556
0
    std::unique_lock aGuard( m_aMutex );
557
558
0
    m_aPropertySetInfoChangeListeners.removeInterface( aGuard, Listener );
559
0
}
560
561
562
// XChild
563
564
565
Reference< XInterface > SAL_CALL
566
BaseContent::getParent()
567
0
{
568
0
    OUString ParentUnq = getParentName( m_aUncPath );
569
0
    OUString ParentUrl;
570
571
572
0
    bool err = fileaccess::TaskManager::getUrlFromUnq( ParentUnq, ParentUrl );
573
0
    if( err )
574
0
        return Reference< XInterface >( nullptr );
575
576
0
    rtl::Reference<FileContentIdentifier> Identifier = new FileContentIdentifier( ParentUnq );
577
578
0
    try
579
0
    {
580
0
        return Reference<XInterface>( m_pMyShell->m_pProvider->queryContent( Identifier ), UNO_QUERY );
581
0
    }
582
0
    catch (const IllegalIdentifierException&)
583
0
    {
584
0
        return Reference< XInterface >();
585
0
    }
586
0
}
587
588
589
void SAL_CALL
590
BaseContent::setParent(
591
    const Reference< XInterface >& )
592
0
{
593
0
    throw lang::NoSupportException();
594
0
}
595
596
597
// Private Methods
598
599
600
Reference< XCommandInfo >
601
BaseContent::getCommandInfo()
602
0
{
603
0
    if( m_nState & Deleted )
604
0
        return Reference< XCommandInfo >();
605
606
0
    return m_pMyShell->info_c();
607
0
}
608
609
610
Reference< beans::XPropertySetInfo >
611
BaseContent::getPropertySetInfo()
612
0
{
613
0
    if( m_nState & Deleted )
614
0
        return Reference< beans::XPropertySetInfo >();
615
616
0
    return m_pMyShell->info_p( m_aUncPath );
617
0
}
618
619
Reference< sdbc::XRow >
620
BaseContent::getPropertyValues(
621
    sal_Int32 nMyCommandIdentifier,
622
    const Sequence< beans::Property >& PropertySet )
623
10.7k
{
624
10.7k
    sal_Int32 nProps = PropertySet.getLength();
625
10.7k
    if ( !nProps )
626
0
        return Reference< sdbc::XRow >();
627
628
10.7k
    if( m_nState & Deleted )
629
0
    {
630
0
        Sequence< Any > aValues( nProps );
631
0
        return Reference< sdbc::XRow >( new XRow_impl( m_pMyShell, aValues ) );
632
0
    }
633
634
10.7k
    if( m_nState & JustInserted )
635
0
    {
636
0
        Sequence< Any > aValues( nProps );
637
0
        Any* pValues = aValues.getArray();
638
639
0
        const beans::Property* pProps = PropertySet.getConstArray();
640
641
0
        for ( sal_Int32 n = 0; n < nProps; ++n )
642
0
        {
643
0
            const beans::Property& rProp = pProps[ n ];
644
0
            Any& rValue = pValues[ n ];
645
646
0
            if ( rProp.Name == "ContentType" )
647
0
            {
648
0
                rValue <<= (m_bFolder ? TaskManager::FolderContentType
649
0
                    : TaskManager::FileContentType);
650
0
            }
651
0
            else if ( rProp.Name == "IsFolder" )
652
0
            {
653
0
                rValue <<= m_bFolder;
654
0
            }
655
0
            else if ( rProp.Name == "IsDocument" )
656
0
            {
657
0
                rValue <<= !m_bFolder;
658
0
            }
659
0
        }
660
661
0
        return Reference< sdbc::XRow >(
662
0
            new XRow_impl( m_pMyShell, aValues ) );
663
0
    }
664
665
10.7k
    return m_pMyShell->getv( nMyCommandIdentifier,
666
10.7k
                             m_aUncPath,
667
10.7k
                             PropertySet );
668
10.7k
}
669
670
671
Sequence< Any >
672
BaseContent::setPropertyValues(
673
    sal_Int32 nMyCommandIdentifier,
674
    const Sequence< beans::PropertyValue >& Values )
675
0
{
676
0
    if( m_nState & Deleted )
677
0
    {   //  To do
678
0
        return Sequence< Any >( Values.getLength() );
679
0
    }
680
681
0
    static constexpr OUString Title(u"Title"_ustr);
682
683
    // Special handling for files which have to be inserted
684
0
    if( m_nState & JustInserted )
685
0
    {
686
0
        for( const auto& rValue : Values )
687
0
        {
688
0
            if( rValue.Name == Title )
689
0
            {
690
0
                OUString NewTitle;
691
0
                if( rValue.Value >>= NewTitle )
692
0
                {
693
0
                    if ( m_nState & NameForInsertionSet )
694
0
                    {
695
                        // User wants to set another Title before "insert".
696
                        // m_aUncPath contains previous own URI.
697
698
0
                        sal_Int32 nLastSlash = m_aUncPath.lastIndexOf( '/' );
699
0
                        bool bTrailingSlash = false;
700
0
                        if ( nLastSlash == m_aUncPath.getLength() - 1 )
701
0
                        {
702
0
                            bTrailingSlash = true;
703
0
                            nLastSlash
704
0
                                = m_aUncPath.lastIndexOf( '/', nLastSlash );
705
0
                        }
706
707
0
                        OSL_ENSURE( nLastSlash != -1,
708
0
                                    "BaseContent::setPropertyValues: "
709
0
                                    "Invalid URL!" );
710
711
0
                        OUStringBuffer aBuf(
712
0
                            m_aUncPath.subView( 0, nLastSlash + 1 ) );
713
714
0
                        if ( !NewTitle.isEmpty() )
715
0
                        {
716
0
                            aBuf.append( NewTitle );
717
0
                            if ( bTrailingSlash )
718
0
                                aBuf.append( '/' );
719
0
                        }
720
0
                        else
721
0
                        {
722
0
                            m_nState &= ~NameForInsertionSet;
723
0
                        }
724
725
0
                        m_aUncPath = aBuf.makeStringAndClear();
726
0
                    }
727
0
                    else
728
0
                    {
729
0
                        if ( !NewTitle.isEmpty() )
730
0
                        {
731
                            // Initial Title before "insert".
732
                            // m_aUncPath contains parent's URI.
733
734
0
                            if( !m_aUncPath.endsWith( "/" ) )
735
0
                                m_aUncPath += "/";
736
737
0
                            m_aUncPath += rtl::Uri::encode( NewTitle,
738
0
                                                            rtl_UriCharClassPchar,
739
0
                                                            rtl_UriEncodeIgnoreEscapes,
740
0
                                                            RTL_TEXTENCODING_UTF8 );
741
0
                            m_nState |= NameForInsertionSet;
742
0
                        }
743
0
                    }
744
0
                }
745
0
            }
746
0
        }
747
748
0
        return Sequence< Any >( Values.getLength() );
749
0
    }
750
0
    else
751
0
    {
752
0
        Sequence< Any > ret = m_pMyShell->setv( m_aUncPath,  // Does not handle Title
753
0
                                                Values );
754
0
        auto retRange = asNonConstRange(ret);
755
756
        // Special handling Title: Setting Title is equivalent to a renaming of the underlying file
757
0
        for( sal_Int32 i = 0; i < Values.getLength(); ++i )
758
0
        {
759
0
            if( Values[i].Name != Title )
760
0
                continue;                  // handled by setv
761
762
0
            OUString NewTitle;
763
0
            if( !( Values[i].Value >>= NewTitle ) )
764
0
            {
765
0
                retRange[i] <<= beans::IllegalTypeException();
766
0
                break;
767
0
            }
768
0
            else if( NewTitle.isEmpty() )
769
0
            {
770
0
                retRange[i] <<= lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
771
0
                break;
772
0
            }
773
774
775
0
            OUString aDstName = getParentName( m_aUncPath );
776
0
            if( !aDstName.endsWith("/") )
777
0
                aDstName += "/";
778
779
0
            aDstName += rtl::Uri::encode( NewTitle,
780
0
                                          rtl_UriCharClassPchar,
781
0
                                          rtl_UriEncodeIgnoreEscapes,
782
0
                                          RTL_TEXTENCODING_UTF8 );
783
784
0
            m_pMyShell->move( nMyCommandIdentifier,     // move notifies the children also;
785
0
                              m_aUncPath,
786
0
                              aDstName,
787
0
                              NameClash::KEEP );
788
789
0
            try
790
0
            {
791
0
                endTask( nMyCommandIdentifier );
792
0
            }
793
0
            catch(const Exception& e)
794
0
            {
795
0
                retRange[i] <<= e;
796
0
            }
797
798
            // NameChanges come back through a ContentEvent
799
0
            break; // only handling Title
800
0
        } // end for
801
802
0
        return ret;
803
0
    }
804
0
}
805
806
807
Reference< XDynamicResultSet >
808
BaseContent::open(
809
    sal_Int32 nMyCommandIdentifier,
810
    const OpenCommandArgument2& aCommandArgument )
811
163k
{
812
163k
    Reference< XDynamicResultSet > retValue;
813
814
163k
    if( m_nState & Deleted )
815
0
    {
816
0
        m_pMyShell->installError( nMyCommandIdentifier,
817
0
                                  TaskHandlerErr::DELETED_STATE_IN_OPEN_COMMAND );
818
0
    }
819
163k
    else if( m_nState & JustInserted )
820
0
    {
821
0
        m_pMyShell->installError( nMyCommandIdentifier,
822
0
                                  TaskHandlerErr::INSERTED_STATE_IN_OPEN_COMMAND );
823
0
    }
824
163k
    else
825
163k
    {
826
163k
        if( aCommandArgument.Mode == OpenMode::DOCUMENT ||
827
117k
            aCommandArgument.Mode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
828
829
46.2k
        {
830
46.2k
            Reference< io::XOutputStream > outputStream( aCommandArgument.Sink,UNO_QUERY );
831
46.2k
            if( outputStream.is() )
832
0
            {
833
0
                m_pMyShell->page( nMyCommandIdentifier,
834
0
                                  m_aUncPath,
835
0
                                  outputStream );
836
0
            }
837
838
46.2k
            bool bLock = ( aCommandArgument.Mode != OpenMode::DOCUMENT_SHARE_DENY_NONE );
839
840
46.2k
            Reference< io::XActiveDataSink > activeDataSink( aCommandArgument.Sink,UNO_QUERY );
841
46.2k
            if( activeDataSink.is() )
842
3.93k
            {
843
3.93k
                activeDataSink->setInputStream( m_pMyShell->open( nMyCommandIdentifier,
844
3.93k
                                                                  m_aUncPath,
845
3.93k
                                                                  bLock ) );
846
3.93k
            }
847
848
46.2k
            Reference< io::XActiveDataStreamer > activeDataStreamer( aCommandArgument.Sink,UNO_QUERY );
849
46.2k
            if( activeDataStreamer.is() )
850
42.3k
            {
851
42.3k
                activeDataStreamer->setStream( m_pMyShell->open_rw( nMyCommandIdentifier,
852
42.3k
                                                                    m_aUncPath,
853
42.3k
                                                                    bLock ) );
854
42.3k
            }
855
46.2k
        }
856
117k
        else if ( aCommandArgument.Mode == OpenMode::ALL        ||
857
117k
                  aCommandArgument.Mode == OpenMode::FOLDERS    ||
858
117k
                  aCommandArgument.Mode == OpenMode::DOCUMENTS )
859
117k
        {
860
117k
            retValue = m_pMyShell->ls( nMyCommandIdentifier,
861
117k
                                       m_aUncPath,
862
117k
                                       aCommandArgument.Mode,
863
117k
                                       aCommandArgument.Properties,
864
117k
                                       aCommandArgument.SortingInfo );
865
117k
        }
866
//          else if(  aCommandArgument.Mode ==
867
//                    OpenMode::DOCUMENT_SHARE_DENY_NONE  ||
868
//                    aCommandArgument.Mode ==
869
//                    OpenMode::DOCUMENT_SHARE_DENY_WRITE )
870
//              m_pMyShell->installError( nMyCommandIdentifier,
871
//                                        TaskHandlerErr::UNSUPPORTED_OPEN_MODE,
872
//                                        aCommandArgument.Mode);
873
0
        else
874
0
            m_pMyShell->installError( nMyCommandIdentifier,
875
0
                                      TaskHandlerErr::UNSUPPORTED_OPEN_MODE,
876
0
                                      aCommandArgument.Mode);
877
163k
    }
878
879
163k
    return retValue;
880
163k
}
881
882
883
void
884
BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier )
885
0
{
886
0
    if( m_nState & Deleted )
887
0
        return;
888
889
0
    if( m_pMyShell->remove( nMyCommandIdentifier,m_aUncPath ) )
890
0
        m_nState |= Deleted;
891
0
}
892
893
void
894
BaseContent::transfer( sal_Int32 nMyCommandIdentifier,
895
                       const TransferInfo& aTransferInfo )
896
0
{
897
0
    if( m_nState & Deleted )
898
0
        return;
899
900
0
    if( !comphelper::isFileUrl(aTransferInfo.SourceURL) )
901
0
    {
902
0
        m_pMyShell->installError( nMyCommandIdentifier,
903
0
                                  TaskHandlerErr::TRANSFER_INVALIDSCHEME );
904
0
        return;
905
0
    }
906
907
0
    OUString srcUnc;
908
0
    if( fileaccess::TaskManager::getUnqFromUrl( aTransferInfo.SourceURL,srcUnc ) )
909
0
    {
910
0
        m_pMyShell->installError( nMyCommandIdentifier,
911
0
                                  TaskHandlerErr::TRANSFER_INVALIDURL );
912
0
        return;
913
0
    }
914
915
0
    OUString srcUncPath = srcUnc;
916
917
    // Determine the new title !
918
0
    OUString NewTitle;
919
0
    if( !aTransferInfo.NewTitle.isEmpty() )
920
0
        NewTitle = rtl::Uri::encode( aTransferInfo.NewTitle,
921
0
                                     rtl_UriCharClassPchar,
922
0
                                     rtl_UriEncodeIgnoreEscapes,
923
0
                                     RTL_TEXTENCODING_UTF8 );
924
0
    else
925
0
        NewTitle = srcUncPath.copy( 1 + srcUncPath.lastIndexOf( '/' ) );
926
927
    // Is destination a document or a folder ?
928
0
    Reference< sdbc::XRow > xRow = getPropertyValues( nMyCommandIdentifier,{ { u"IsDocument"_ustr, -1, cppu::UnoType<sal_Bool>::get(), 0 } } );
929
0
    bool IsDocument = xRow->getBoolean( 1 );
930
0
    if( xRow->wasNull() )
931
0
    {   // Destination file type could not be determined
932
0
        m_pMyShell->installError( nMyCommandIdentifier,
933
0
                                  TaskHandlerErr::TRANSFER_DESTFILETYPE );
934
0
        return;
935
0
    }
936
937
0
    OUString dstUncPath;
938
0
    if( IsDocument )
939
0
    {   // as sibling
940
0
        sal_Int32 lastSlash = m_aUncPath.lastIndexOf( '/' );
941
0
        dstUncPath = m_aUncPath.copy(0,lastSlash );
942
0
    }
943
0
    else
944
        // as child
945
0
        dstUncPath = m_aUncPath;
946
947
0
    dstUncPath += "/" + NewTitle;
948
949
0
    sal_Int32 NameClash = aTransferInfo.NameClash;
950
951
0
    if( aTransferInfo.MoveData )
952
0
        m_pMyShell->move( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
953
0
    else
954
0
        m_pMyShell->copy( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
955
0
}
956
957
958
void BaseContent::insert( sal_Int32 nMyCommandIdentifier,
959
                                   const InsertCommandArgument& aInsertArgument )
960
0
{
961
0
    if( m_nState & FullFeatured )
962
0
    {
963
0
        m_pMyShell->write( nMyCommandIdentifier,
964
0
                           m_aUncPath,
965
0
                           aInsertArgument.ReplaceExisting,
966
0
                           aInsertArgument.Data );
967
0
        return;
968
0
    }
969
970
0
    if( ! ( m_nState & JustInserted ) )
971
0
    {
972
0
        m_pMyShell->installError( nMyCommandIdentifier,
973
0
                                  TaskHandlerErr::NOFRESHINSERT_IN_INSERT_COMMAND );
974
0
        return;
975
0
    }
976
977
    // Inserts the content, which has the flag m_bIsFresh
978
979
0
    if( ! (m_nState & NameForInsertionSet) )
980
0
    {
981
0
        m_pMyShell->installError( nMyCommandIdentifier,
982
0
                                  TaskHandlerErr::NONAMESET_INSERT_COMMAND );
983
0
        return;
984
0
    }
985
986
    // Inserting a document or a file?
987
0
    bool bDocument = false;
988
989
0
    Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { u"IsDocument"_ustr, -1, cppu::UnoType<sal_Bool>::get(), 0 } });
990
991
0
    bool contentTypeSet = true;  // is set to false, if contentType not set
992
0
    try
993
0
    {
994
0
        bDocument = xRow->getBoolean( 1 );
995
0
        if( xRow->wasNull() )
996
0
            contentTypeSet = false;
997
998
0
    }
999
0
    catch (const sdbc::SQLException&)
1000
0
    {
1001
0
        TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
1002
0
        contentTypeSet = false;
1003
0
    }
1004
1005
0
    if( ! contentTypeSet )
1006
0
    {
1007
0
        m_pMyShell->installError( nMyCommandIdentifier,
1008
0
                                  TaskHandlerErr::NOCONTENTTYPE_INSERT_COMMAND );
1009
0
        return;
1010
0
    }
1011
1012
1013
0
    bool success = false;
1014
0
    if( bDocument )
1015
0
        success = m_pMyShell->mkfil( nMyCommandIdentifier,
1016
0
                                     m_aUncPath,
1017
0
                                     aInsertArgument.ReplaceExisting,
1018
0
                                     aInsertArgument.Data );
1019
0
    else
1020
0
    {
1021
0
        while( ! success )
1022
0
        {
1023
0
            success = m_pMyShell->mkdir( nMyCommandIdentifier,
1024
0
                                         m_aUncPath,
1025
0
                                         aInsertArgument.ReplaceExisting );
1026
0
            if( success )
1027
0
                break;
1028
1029
0
            XInteractionRequestImpl aRequestImpl(
1030
0
                    rtl::Uri::decode(
1031
0
                        OUString(getTitle(m_aUncPath)),
1032
0
                        rtl_UriDecodeWithCharset,
1033
0
                        RTL_TEXTENCODING_UTF8),
1034
0
                    getXWeak(),
1035
0
                    m_pMyShell,nMyCommandIdentifier);
1036
0
            uno::Reference<task::XInteractionRequest> const& xReq(aRequestImpl.getRequest());
1037
1038
0
            m_pMyShell->handleTask( nMyCommandIdentifier, xReq );
1039
0
            if (aRequestImpl.aborted() || aRequestImpl.newName().isEmpty())
1040
                // means aborting
1041
0
                break;
1042
1043
            // determine new uncpath
1044
0
            m_pMyShell->clearError( nMyCommandIdentifier );
1045
0
            m_aUncPath = getParentName( m_aUncPath );
1046
0
            if( !m_aUncPath.endsWith( "/" ) )
1047
0
                m_aUncPath += "/";
1048
1049
0
            m_aUncPath += rtl::Uri::encode( aRequestImpl.newName(),
1050
0
                                            rtl_UriCharClassPchar,
1051
0
                                            rtl_UriEncodeIgnoreEscapes,
1052
0
                                            RTL_TEXTENCODING_UTF8 );
1053
0
        }
1054
0
    }
1055
1056
0
    if ( ! success )
1057
0
        return;
1058
1059
0
    m_xContentIdentifier.set( new FileContentIdentifier( m_aUncPath ) );
1060
1061
0
    m_pMyShell->registerNotifier( m_aUncPath,this );
1062
0
    m_pMyShell->insertDefaultProperties( m_aUncPath );
1063
1064
0
    m_nState = FullFeatured;
1065
0
}
1066
1067
1068
void BaseContent::endTask( sal_Int32 CommandId )
1069
174k
{
1070
    // This is the only function allowed to throw an exception
1071
174k
    m_pMyShell->endTask( CommandId,m_aUncPath,this );
1072
174k
}
1073
1074
1075
std::optional<ContentEventNotifier>
1076
BaseContent::cDEL()
1077
0
{
1078
0
    m_nState |= Deleted;
1079
1080
0
    std::unique_lock aGuard( m_aMutex );
1081
0
    if( m_aContentEventListeners.getLength(aGuard) == 0 )
1082
0
        return {};
1083
1084
0
    return ContentEventNotifier( m_pMyShell,
1085
0
                                  this,
1086
0
                                  m_xContentIdentifier,
1087
0
                                  m_aContentEventListeners.getElements(aGuard) );
1088
0
}
1089
1090
1091
std::optional<ContentEventNotifier>
1092
BaseContent::cEXC( const OUString& aNewName )
1093
0
{
1094
0
    std::unique_lock aGuard( m_aMutex );
1095
1096
0
    Reference< XContentIdentifier > xOldRef = m_xContentIdentifier;
1097
0
    m_aUncPath = aNewName;
1098
0
    m_xContentIdentifier = new FileContentIdentifier( aNewName );
1099
1100
0
    if( m_aContentEventListeners.getLength(aGuard) == 0 )
1101
0
        return {};
1102
0
    return ContentEventNotifier( m_pMyShell,
1103
0
                                  this,
1104
0
                                  m_xContentIdentifier,
1105
0
                                  xOldRef,
1106
0
                                  m_aContentEventListeners.getElements(aGuard) );
1107
0
}
1108
1109
1110
std::optional<ContentEventNotifier>
1111
BaseContent::cCEL()
1112
0
{
1113
0
    std::unique_lock aGuard( m_aMutex );
1114
0
    if( m_aContentEventListeners.getLength(aGuard) == 0 )
1115
0
        return {};
1116
0
    return ContentEventNotifier( m_pMyShell,
1117
0
                                      this,
1118
0
                                      m_xContentIdentifier,
1119
0
                                      m_aContentEventListeners.getElements(aGuard) );
1120
0
}
1121
1122
std::optional<PropertySetInfoChangeNotifier>
1123
BaseContent::cPSL()
1124
0
{
1125
0
    std::unique_lock aGuard( m_aMutex );
1126
0
    if( m_aPropertySetInfoChangeListeners.getLength(aGuard) == 0  )
1127
0
        return {};
1128
0
    return PropertySetInfoChangeNotifier( this, m_aPropertySetInfoChangeListeners.getElements(aGuard) );
1129
0
}
1130
1131
1132
std::optional<PropertyChangeNotifier>
1133
BaseContent::cPCL()
1134
0
{
1135
0
    std::unique_lock aGuard( m_aMutex );
1136
1137
0
    if (!m_pPropertyListener)
1138
0
        return {};
1139
1140
0
    const std::vector< OUString > seqNames = m_pPropertyListener->getContainedTypes(aGuard);
1141
0
    if( seqNames.empty() )
1142
0
        return {};
1143
1144
0
    ListenerMap listener;
1145
0
    for( const auto& rName : seqNames )
1146
0
    {
1147
0
        comphelper::OInterfaceContainerHelper4<beans::XPropertiesChangeListener>* pContainer = m_pPropertyListener->getContainer(aGuard, rName);
1148
0
        if (!pContainer)
1149
0
            continue;
1150
0
        listener[rName] = pContainer->getElements(aGuard);
1151
0
    }
1152
1153
0
    return PropertyChangeNotifier( this, std::move(listener) );
1154
0
}
1155
1156
1157
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */