Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/ucb/source/ucp/file/filtask.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 <config_features.h>
21
22
#include <sal/config.h>
23
#include <sal/log.hxx>
24
25
#if HAVE_FEATURE_MACOSX_SANDBOX
26
#include <sys/stat.h>
27
#endif
28
29
#include <com/sun/star/beans/IllegalTypeException.hpp>
30
#include <com/sun/star/beans/NotRemoveableException.hpp>
31
#include <com/sun/star/beans/PropertyAttribute.hpp>
32
#include <com/sun/star/beans/PropertyExistException.hpp>
33
#include <com/sun/star/io/BufferSizeExceededException.hpp>
34
#include <com/sun/star/io/NotConnectedException.hpp>
35
#include <com/sun/star/io/IOException.hpp>
36
#include <com/sun/star/lang/IllegalAccessException.hpp>
37
#include <com/sun/star/task/InteractionClassification.hpp>
38
#include <com/sun/star/ucb/ContentInfoAttribute.hpp>
39
#include <com/sun/star/ucb/DuplicateCommandIdentifierException.hpp>
40
#include <com/sun/star/ucb/IOErrorCode.hpp>
41
#include <com/sun/star/ucb/InsertCommandArgument.hpp>
42
#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
43
#include <com/sun/star/ucb/NameClash.hpp>
44
#include <com/sun/star/ucb/OpenCommandArgument.hpp>
45
#include <com/sun/star/ucb/Store.hpp>
46
#include <com/sun/star/ucb/TransferInfo.hpp>
47
#include <comphelper/propertysequence.hxx>
48
#include <osl/diagnose.h>
49
#include <rtl/ref.hxx>
50
#include <rtl/uri.hxx>
51
52
#include "filtask.hxx"
53
#include "filcmd.hxx"
54
#include "filglob.hxx"
55
#include "filinpstr.hxx"
56
#include "filprp.hxx"
57
#include "filrset.hxx"
58
#include "filstr.hxx"
59
#include "prov.hxx"
60
61
/******************************************************************************/
62
/*                                                                            */
63
/*                              TaskHandling                                  */
64
/*                                                                            */
65
/******************************************************************************/
66
67
68
using namespace fileaccess;
69
using namespace com::sun::star;
70
using namespace com::sun::star::uno;
71
using namespace com::sun::star::ucb;
72
73
#if OSL_DEBUG_LEVEL > 0
74
#define THROW_WHERE SAL_WHERE
75
#else
76
0
#define THROW_WHERE ""
77
#endif
78
79
393k
TaskManager::UnqPathData::UnqPathData() = default;
80
81
52.1k
TaskManager::UnqPathData::UnqPathData(TaskManager::UnqPathData&&) = default;
82
83
84
TaskManager::UnqPathData::~UnqPathData()
85
445k
{
86
445k
}
87
88
TaskManager::MyProperty::MyProperty( const OUString&                         thePropertyName )
89
1.84M
    : PropertyName( thePropertyName )
90
1.84M
    , Handle(-1)
91
1.84M
    , isNative(false)
92
1.84M
    , State(beans::PropertyState_AMBIGUOUS_VALUE)
93
1.84M
    , Attributes(0)
94
1.84M
{
95
    // empty
96
1.84M
}
97
98
TaskManager::MyProperty::MyProperty( bool                               theisNative,
99
                               const OUString&                    thePropertyName,
100
                               sal_Int32                          theHandle,
101
                               const css::uno::Type&              theTyp,
102
                               const css::uno::Any&               theValue,
103
                               const css::beans::PropertyState&   theState,
104
                               sal_Int16                          theAttributes )
105
180
    : PropertyName( thePropertyName ),
106
180
      Handle( theHandle ),
107
180
      isNative( theisNative ),
108
180
      Typ( theTyp ),
109
180
      Value( theValue ),
110
180
      State( theState ),
111
180
      Attributes( theAttributes )
112
180
{
113
    // empty
114
180
}
115
116
#include "filinl.hxx"
117
118
        // Default properties
119
120
constexpr OUString Title( u"Title"_ustr );
121
constexpr OUString CasePreservingURL( u"CasePreservingURL"_ustr );
122
constexpr OUString IsDocument( u"IsDocument"_ustr );
123
constexpr OUString IsFolder( u"IsFolder"_ustr );
124
constexpr OUString DateModified( u"DateModified"_ustr );
125
constexpr OUString Size( u"Size"_ustr );
126
constexpr OUString IsVolume( u"IsVolume"_ustr );
127
constexpr OUString IsRemoveable( u"IsRemoveable"_ustr );
128
constexpr OUString IsRemote( u"IsRemote"_ustr );
129
constexpr OUString IsCompactDisc( u"IsCompactDisc"_ustr );
130
constexpr OUString IsFloppy( u"IsFloppy"_ustr );
131
constexpr OUString IsHidden( u"IsHidden"_ustr );
132
constexpr OUString ContentType( u"ContentType"_ustr );
133
constexpr OUString IsReadOnly( u"IsReadOnly"_ustr );
134
constexpr OUString CreatableContentsInfo( u"CreatableContentsInfo"_ustr );
135
136
TaskManager::TaskManager( const uno::Reference< uno::XComponentContext >& rxContext,
137
              FileProvider* pProvider, bool bWithConfig )
138
12
    : m_nCommandId( 0 ),
139
12
      m_pProvider( pProvider ),
140
12
      m_xContext( rxContext ),
141
      // Commands
142
12
      m_sCommandInfo{
143
12
          { /* Name    */ u"getCommandInfo"_ustr,
144
12
            /* Handle  */ -1,
145
12
            /* ArgType */ cppu::UnoType<void>::get() },
146
147
12
          { /* Name    */ u"getPropertySetInfo"_ustr,
148
12
            /* Handle  */ -1,
149
12
            /* ArgType */ cppu::UnoType<void>::get() },
150
151
12
          { /* Name    */ u"getPropertyValues"_ustr,
152
12
            /* Handle  */ -1,
153
12
            /* ArgType */ cppu::UnoType<uno::Sequence< beans::Property >>::get() },
154
155
12
          { /* Name    */ u"setPropertyValues"_ustr,
156
12
            /* Handle  */ -1,
157
12
            /* ArgType */ cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get() },
158
159
12
          { /* Name    */ u"open"_ustr,
160
12
            /* Handle  */ -1,
161
12
            /* ArgType */ cppu::UnoType<OpenCommandArgument>::get() },
162
163
12
          { /* Name    */ u"transfer"_ustr,
164
12
            /* Handle  */ -1,
165
12
            /* ArgType */ cppu::UnoType<TransferInfo>::get() },
166
167
12
          { /* Name    */ u"delete"_ustr,
168
12
            /* Handle  */ -1,
169
12
            /* ArgType */ cppu::UnoType<sal_Bool>::get() },
170
171
12
          { /* Name    */ u"insert"_ustr,
172
12
            /* Handle  */ -1,
173
12
            /* ArgType */ cppu::UnoType<InsertCommandArgument>::get() },
174
175
12
          { /* Name    */ u"createNewContent"_ustr,
176
12
            /* Handle  */ -1,
177
12
            /* ArgType */ cppu::UnoType<ucb::ContentInfo>::get() } }
178
12
{
179
    // Title
180
12
    m_aDefaultProperties.insert( MyProperty( true,
181
12
                                             Title,
182
12
                                             -1 ,
183
12
                                             cppu::UnoType<OUString>::get(),
184
12
                                             uno::Any(),
185
12
                                             beans::PropertyState_DEFAULT_VALUE,
186
12
                                             beans::PropertyAttribute::MAYBEVOID
187
12
                                             | beans::PropertyAttribute::BOUND ) );
188
189
    // CasePreservingURL
190
12
    m_aDefaultProperties.insert(
191
12
        MyProperty( true,
192
12
                    CasePreservingURL,
193
12
                    -1 ,
194
12
                    cppu::UnoType<OUString>::get(),
195
12
                    uno::Any(),
196
12
                    beans::PropertyState_DEFAULT_VALUE,
197
12
                    beans::PropertyAttribute::MAYBEVOID
198
12
                    | beans::PropertyAttribute::BOUND
199
12
                    | beans::PropertyAttribute::READONLY ) );
200
201
202
    // IsFolder
203
12
    m_aDefaultProperties.insert( MyProperty( true,
204
12
                                             IsFolder,
205
12
                                             -1 ,
206
12
                                             cppu::UnoType<sal_Bool>::get(),
207
12
                                             uno::Any(),
208
12
                                             beans::PropertyState_DEFAULT_VALUE,
209
12
                                             beans::PropertyAttribute::MAYBEVOID
210
12
                                             | beans::PropertyAttribute::BOUND
211
12
                                             | beans::PropertyAttribute::READONLY ) );
212
213
214
    // IsDocument
215
12
    m_aDefaultProperties.insert( MyProperty( true,
216
12
                                             IsDocument,
217
12
                                             -1 ,
218
12
                                             cppu::UnoType<sal_Bool>::get(),
219
12
                                             uno::Any(),
220
12
                                             beans::PropertyState_DEFAULT_VALUE,
221
12
                                             beans::PropertyAttribute::MAYBEVOID
222
12
                                             | beans::PropertyAttribute::BOUND
223
12
                                             | beans::PropertyAttribute::READONLY ) );
224
225
    // Removable
226
12
    m_aDefaultProperties.insert( MyProperty( true,
227
12
                                             IsVolume,
228
12
                                             -1 ,
229
12
                                             cppu::UnoType<sal_Bool>::get(),
230
12
                                             uno::Any(),
231
12
                                             beans::PropertyState_DEFAULT_VALUE,
232
12
                                             beans::PropertyAttribute::MAYBEVOID
233
12
                                             | beans::PropertyAttribute::BOUND
234
12
                                             | beans::PropertyAttribute::READONLY ) );
235
236
237
    // Removable
238
12
    m_aDefaultProperties.insert( MyProperty( true,
239
12
                                             IsRemoveable,
240
12
                                             -1 ,
241
12
                                             cppu::UnoType<sal_Bool>::get(),
242
12
                                             uno::Any(),
243
12
                                             beans::PropertyState_DEFAULT_VALUE,
244
12
                                             beans::PropertyAttribute::MAYBEVOID
245
12
                                             | beans::PropertyAttribute::BOUND
246
12
                                             | beans::PropertyAttribute::READONLY ) );
247
248
    // Remote
249
12
    m_aDefaultProperties.insert( MyProperty( true,
250
12
                                             IsRemote,
251
12
                                             -1 ,
252
12
                                             cppu::UnoType<sal_Bool>::get(),
253
12
                                             uno::Any(),
254
12
                                             beans::PropertyState_DEFAULT_VALUE,
255
12
                                             beans::PropertyAttribute::MAYBEVOID
256
12
                                             | beans::PropertyAttribute::BOUND
257
12
                                             | beans::PropertyAttribute::READONLY ) );
258
259
    // CompactDisc
260
12
    m_aDefaultProperties.insert( MyProperty( true,
261
12
                                             IsCompactDisc,
262
12
                                             -1 ,
263
12
                                             cppu::UnoType<sal_Bool>::get(),
264
12
                                             uno::Any(),
265
12
                                             beans::PropertyState_DEFAULT_VALUE,
266
12
                                             beans::PropertyAttribute::MAYBEVOID
267
12
                                             | beans::PropertyAttribute::BOUND
268
12
                                             | beans::PropertyAttribute::READONLY ) );
269
270
    // Floppy
271
12
    m_aDefaultProperties.insert( MyProperty( true,
272
12
                                             IsFloppy,
273
12
                                             -1 ,
274
12
                                             cppu::UnoType<sal_Bool>::get(),
275
12
                                             uno::Any(),
276
12
                                             beans::PropertyState_DEFAULT_VALUE,
277
12
                                             beans::PropertyAttribute::MAYBEVOID
278
12
                                             | beans::PropertyAttribute::BOUND
279
12
                                             | beans::PropertyAttribute::READONLY ) );
280
281
    // Hidden
282
12
    m_aDefaultProperties.insert(
283
12
        MyProperty(
284
12
            true,
285
12
            IsHidden,
286
12
            -1 ,
287
12
            cppu::UnoType<sal_Bool>::get(),
288
12
            uno::Any(),
289
12
            beans::PropertyState_DEFAULT_VALUE,
290
12
            beans::PropertyAttribute::MAYBEVOID
291
12
            | beans::PropertyAttribute::BOUND
292
#if defined(_WIN32)
293
        ));
294
#else
295
12
    | beans::PropertyAttribute::READONLY)); // under unix/linux only readable
296
12
#endif
297
298
299
    // ContentType
300
12
    m_aDefaultProperties.insert( MyProperty( false,
301
12
                                             ContentType,
302
12
                                             -1 ,
303
12
                                             cppu::UnoType<OUString>::get(),
304
12
                                             uno::Any(OUString()),
305
12
                                             beans::PropertyState_DEFAULT_VALUE,
306
12
                                             beans::PropertyAttribute::MAYBEVOID
307
12
                                             | beans::PropertyAttribute::BOUND
308
12
                                             | beans::PropertyAttribute::READONLY ) );
309
310
311
    // DateModified
312
12
    m_aDefaultProperties.insert( MyProperty( true,
313
12
                                             DateModified,
314
12
                                             -1 ,
315
12
                                             cppu::UnoType<util::DateTime>::get(),
316
12
                                             uno::Any(),
317
12
                                             beans::PropertyState_DEFAULT_VALUE,
318
12
                                             beans::PropertyAttribute::MAYBEVOID
319
12
                                             | beans::PropertyAttribute::BOUND ) );
320
321
    // Size
322
12
    m_aDefaultProperties.insert( MyProperty( true,
323
12
                                             Size,
324
12
                                             -1,
325
12
                                             cppu::UnoType<sal_Int64>::get(),
326
12
                                             uno::Any(),
327
12
                                             beans::PropertyState_DEFAULT_VALUE,
328
12
                                             beans::PropertyAttribute::MAYBEVOID
329
12
                                             | beans::PropertyAttribute::BOUND ) );
330
331
    // IsReadOnly
332
12
    m_aDefaultProperties.insert( MyProperty( true,
333
12
                                             IsReadOnly,
334
12
                                             -1 ,
335
12
                                             cppu::UnoType<sal_Bool>::get(),
336
12
                                             uno::Any(),
337
12
                                             beans::PropertyState_DEFAULT_VALUE,
338
12
                                             beans::PropertyAttribute::MAYBEVOID
339
12
                                             | beans::PropertyAttribute::BOUND ) );
340
341
342
    // CreatableContentsInfo
343
12
    m_aDefaultProperties.insert( MyProperty( true,
344
12
                                             CreatableContentsInfo,
345
12
                                             -1 ,
346
12
                                             cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
347
12
                                             uno::Any(),
348
12
                                             beans::PropertyState_DEFAULT_VALUE,
349
12
                                             beans::PropertyAttribute::MAYBEVOID
350
12
                                             | beans::PropertyAttribute::BOUND
351
12
                                             | beans::PropertyAttribute::READONLY ) );
352
353
12
    if(bWithConfig)
354
0
    {
355
0
        uno::Reference< XPropertySetRegistryFactory > xRegFac = ucb::Store::create( m_xContext );
356
        // Open/create a registry
357
0
        m_xFileRegistry = xRegFac->createPropertySetRegistry( OUString() );
358
0
    }
359
12
}
360
361
362
TaskManager::~TaskManager()
363
0
{
364
0
}
365
366
367
void
368
TaskManager::startTask(
369
    sal_Int32 CommandId,
370
    const uno::Reference< XCommandEnvironment >& xCommandEnv )
371
158k
{
372
158k
    std::unique_lock aGuard( m_aMutex );
373
158k
    TaskMap::iterator it = m_aTaskMap.find( CommandId );
374
158k
    if( it != m_aTaskMap.end() )
375
0
    {
376
0
        throw DuplicateCommandIdentifierException( OSL_LOG_PREFIX );
377
0
    }
378
158k
    m_aTaskMap.emplace( CommandId, TaskHandling( xCommandEnv ));
379
158k
}
380
381
382
void
383
TaskManager::endTask( sal_Int32 CommandId,
384
                      const OUString& aUncPath,
385
                      BaseContent* pContent)
386
158k
{
387
158k
    std::unique_lock aGuard( m_aMutex );
388
158k
    TaskMap::iterator it = m_aTaskMap.find( CommandId );
389
158k
    if( it == m_aTaskMap.end() )
390
0
        return;
391
392
158k
    TaskHandlerErr ErrorCode = it->second.getInstalledError();
393
158k
    sal_Int32 MinorCode = it->second.getMinorErrorCode();
394
158k
    bool isHandled = it->second.isHandled();
395
396
158k
    Reference< XCommandEnvironment > xComEnv
397
158k
        = it->second.getCommandEnvironment();
398
399
158k
    m_aTaskMap.erase( it );
400
401
158k
    aGuard.unlock();
402
403
158k
    if( ErrorCode != TaskHandlerErr::NO_ERROR )
404
0
        throw_handler(
405
0
            ErrorCode,
406
0
            MinorCode,
407
0
            xComEnv,
408
0
            aUncPath,
409
0
            pContent,
410
0
            isHandled);
411
158k
}
412
413
414
void TaskManager::clearError( sal_Int32 CommandId )
415
0
{
416
0
    std::unique_lock aGuard( m_aMutex );
417
0
    TaskMap::iterator it = m_aTaskMap.find( CommandId );
418
0
    if( it != m_aTaskMap.end() )
419
0
        it->second.clearError();
420
0
}
421
422
423
void TaskManager::retrieveError( sal_Int32 CommandId,
424
                                          TaskHandlerErr &ErrorCode,
425
                                          sal_Int32 &minorCode)
426
0
{
427
0
    std::unique_lock aGuard( m_aMutex );
428
0
    TaskMap::iterator it = m_aTaskMap.find( CommandId );
429
0
    if( it != m_aTaskMap.end() )
430
0
    {
431
0
        ErrorCode = it->second.getInstalledError();
432
0
        minorCode = it->second. getMinorErrorCode();
433
0
    }
434
0
}
435
436
437
void TaskManager::installError( sal_Int32 CommandId,
438
                                         TaskHandlerErr ErrorCode,
439
                                         sal_Int32 MinorCode )
440
0
{
441
0
    std::unique_lock aGuard( m_aMutex );
442
0
    TaskMap::iterator it = m_aTaskMap.find( CommandId );
443
0
    if( it != m_aTaskMap.end() )
444
0
        it->second.installError( ErrorCode,MinorCode );
445
0
}
446
447
448
sal_Int32
449
TaskManager::getCommandId()
450
158k
{
451
158k
    std::unique_lock aGuard( m_aMutex );
452
158k
    return ++m_nCommandId;
453
158k
}
454
455
456
void TaskManager::handleTask(
457
    sal_Int32 CommandId,
458
    const uno::Reference< task::XInteractionRequest >& request )
459
0
{
460
0
    std::unique_lock aGuard( m_aMutex );
461
0
    TaskMap::iterator it = m_aTaskMap.find( CommandId );
462
0
    uno::Reference< task::XInteractionHandler > xInt;
463
0
    if( it != m_aTaskMap.end() )
464
0
    {
465
0
        xInt = it->second.getInteractionHandler();
466
0
        if( xInt.is() )
467
0
            xInt->handle( request );
468
0
        it->second.setHandled();
469
0
    }
470
0
}
471
472
/*********************************************************************************/
473
/*                                                                               */
474
/*                     de/registerNotifier-Implementation                        */
475
/*                                                                               */
476
/*********************************************************************************/
477
478
479
//  This two methods register and deregister a change listener for the content belonging
480
//  to URL aUnqPath
481
482
483
void
484
TaskManager::registerNotifier( const OUString& aUnqPath, Notifier* pNotifier )
485
148k
{
486
148k
    std::unique_lock aGuard( m_aMutex );
487
488
148k
    ContentMap::iterator it =
489
148k
        m_aContent.emplace( aUnqPath, UnqPathData() ).first;
490
491
148k
    std::vector< Notifier* >& nlist = it->second.notifier;
492
493
148k
    std::vector<Notifier*>::iterator it1 = std::find(nlist.begin(), nlist.end(), pNotifier);
494
148k
    if( it1 != nlist.end() )               // Every "Notifier" only once
495
0
    {
496
0
        return;
497
0
    }
498
148k
    nlist.push_back( pNotifier );
499
148k
}
500
501
502
void
503
TaskManager::deregisterNotifier( const OUString& aUnqPath,Notifier* pNotifier )
504
148k
{
505
148k
    std::unique_lock aGuard( m_aMutex );
506
507
148k
    ContentMap::iterator it = m_aContent.find( aUnqPath );
508
148k
    if( it == m_aContent.end() )
509
0
        return;
510
511
148k
    std::erase(it->second.notifier, pNotifier);
512
513
148k
    if( it->second.notifier.empty() )
514
51.8k
        m_aContent.erase( it );
515
148k
}
516
517
518
/*********************************************************************************/
519
/*                                                                               */
520
/*                     de/associate-Implementation                               */
521
/*                                                                               */
522
/*********************************************************************************/
523
524
//  Used to associate and deassociate a new property with
525
//  the content belonging to URL UnqPath.
526
//  The default value and the attributes are input
527
528
529
void
530
TaskManager::associate( const OUString& aUnqPath,
531
                  const OUString& PropertyName,
532
                  const uno::Any& DefaultValue,
533
                  const sal_Int16 Attributes )
534
0
{
535
0
    MyProperty newProperty( false,
536
0
                            PropertyName,
537
0
                            -1,
538
0
                            DefaultValue.getValueType(),
539
0
                            DefaultValue,
540
0
                            beans::PropertyState_DEFAULT_VALUE,
541
0
                            Attributes );
542
543
0
    auto it1 = m_aDefaultProperties.find( newProperty );
544
0
    if( it1 != m_aDefaultProperties.end() )
545
0
        throw beans::PropertyExistException( THROW_WHERE );
546
547
0
    {
548
0
        std::unique_lock aGuard( m_aMutex );
549
550
0
        ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first;
551
552
        // Load the XPersistentPropertySetInfo and create it, if it does not exist
553
0
        load( it,true );
554
555
0
        PropertySet& properties = it->second.properties;
556
0
        it1 = properties.find( newProperty );
557
0
        if( it1 != properties.end() )
558
0
            throw beans::PropertyExistException(THROW_WHERE );
559
560
        // Property does not exist
561
0
        properties.insert( newProperty );
562
0
        it->second.xC->addProperty( PropertyName,Attributes,DefaultValue );
563
0
    }
564
0
    notifyPropertyAdded( getPropertySetListeners( aUnqPath ), PropertyName );
565
0
}
566
567
568
void
569
TaskManager::deassociate( const OUString& aUnqPath,
570
            const OUString& PropertyName )
571
0
{
572
0
    MyProperty oldProperty( PropertyName );
573
574
0
    auto it1 = m_aDefaultProperties.find( oldProperty );
575
0
    if( it1 != m_aDefaultProperties.end() )
576
0
        throw beans::NotRemoveableException( THROW_WHERE );
577
578
0
    std::unique_lock aGuard( m_aMutex );
579
580
0
    ContentMap::iterator it = m_aContent.emplace( aUnqPath,UnqPathData() ).first;
581
582
0
    load( it, false );
583
584
0
    PropertySet& properties = it->second.properties;
585
586
0
    it1 = properties.find( oldProperty );
587
0
    if( it1 == properties.end() )
588
0
        throw beans::UnknownPropertyException( PropertyName );
589
590
0
    properties.erase( it1 );
591
592
0
    if( it->second.xC.is() )
593
0
        it->second.xC->removeProperty( PropertyName );
594
595
0
    if( properties.size() == 9 )
596
0
    {
597
0
        MyProperty ContentTProperty( ContentType );
598
599
0
        if( properties.find( ContentTProperty )->getState() == beans::PropertyState_DEFAULT_VALUE )
600
0
        {
601
0
            it->second.xS = nullptr;
602
0
            it->second.xC = nullptr;
603
0
            it->second.xA = nullptr;
604
0
            if(m_xFileRegistry.is())
605
0
                m_xFileRegistry->removePropertySet( aUnqPath );
606
0
        }
607
0
    }
608
0
    aGuard.unlock();
609
0
    notifyPropertyRemoved( getPropertySetListeners( aUnqPath ), PropertyName );
610
0
}
611
612
613
/*********************************************************************************/
614
/*                                                                               */
615
/*                     page-Implementation                                       */
616
/*                                                                               */
617
/*********************************************************************************/
618
619
//  Given an xOutputStream, this method writes the content of the file belonging to
620
//  URL aUnqPath into the XOutputStream
621
622
623
void TaskManager::page( sal_Int32 CommandId,
624
                           const OUString& aUnqPath,
625
                           const uno::Reference< io::XOutputStream >& xOutputStream )
626
0
{
627
0
    osl::File aFile( aUnqPath );
628
0
    osl::FileBase::RC err = aFile.open( osl_File_OpenFlag_Read );
629
630
0
    if( err != osl::FileBase::E_None )
631
0
    {
632
0
        aFile.close();
633
0
        installError( CommandId,
634
0
                      TaskHandlerErr::OPEN_FILE_FOR_PAGING,
635
0
                      err );
636
0
        return;
637
0
    }
638
639
0
    const sal_uInt64 bfz = 4*1024;
640
0
    sal_Int8 BFF[bfz];
641
0
    sal_uInt64 nrc;  // Retrieved number of Bytes;
642
643
0
    do
644
0
    {
645
0
        err = aFile.read( static_cast<void*>(BFF),bfz,nrc );
646
0
        if(  err == osl::FileBase::E_None )
647
0
        {
648
0
            uno::Sequence< sal_Int8 > seq( BFF, static_cast<sal_uInt32>(nrc) );
649
0
            try
650
0
            {
651
0
                xOutputStream->writeBytes( seq );
652
0
            }
653
0
            catch (const io::NotConnectedException&)
654
0
            {
655
0
                installError( CommandId,
656
0
                              TaskHandlerErr::NOTCONNECTED_FOR_PAGING );
657
0
                break;
658
0
            }
659
0
            catch (const io::BufferSizeExceededException&)
660
0
            {
661
0
                installError( CommandId,
662
0
                              TaskHandlerErr::BUFFERSIZEEXCEEDED_FOR_PAGING );
663
0
                break;
664
0
            }
665
0
            catch (const io::IOException&)
666
0
            {
667
0
                installError( CommandId,
668
0
                              TaskHandlerErr::IOEXCEPTION_FOR_PAGING );
669
0
                break;
670
0
            }
671
0
        }
672
0
        else
673
0
        {
674
0
            installError( CommandId,
675
0
                          TaskHandlerErr::READING_FILE_FOR_PAGING,
676
0
                          err );
677
0
            break;
678
0
        }
679
0
    } while( nrc == bfz );
680
681
682
0
    aFile.close();
683
684
685
0
    try
686
0
    {
687
0
        xOutputStream->closeOutput();
688
0
    }
689
0
    catch (const io::NotConnectedException&)
690
0
    {
691
0
    }
692
0
    catch (const io::BufferSizeExceededException&)
693
0
    {
694
0
    }
695
0
    catch (const io::IOException&)
696
0
    {
697
0
    }
698
0
}
699
700
701
/*********************************************************************************/
702
/*                                                                               */
703
/*                     open-Implementation                                       */
704
/*                                                                               */
705
/*********************************************************************************/
706
707
//  Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file.
708
709
710
uno::Reference< io::XInputStream >
711
TaskManager::open( sal_Int32 CommandId,
712
             const OUString& aUnqPath,
713
             bool bLock )
714
3.67k
{
715
3.67k
    rtl::Reference<XInputStream_impl> pInputStream(new XInputStream_impl( aUnqPath, bLock )); // from filinpstr.hxx
716
717
3.67k
    TaskHandlerErr ErrorCode = pInputStream->CtorSuccess();
718
719
3.67k
    if( ErrorCode != TaskHandlerErr::NO_ERROR )
720
0
    {
721
0
        installError( CommandId,
722
0
                      ErrorCode,
723
0
                      pInputStream->getMinorError() );
724
725
0
        pInputStream.clear();
726
0
    }
727
728
3.67k
    return pInputStream;
729
3.67k
}
730
731
732
/*********************************************************************************/
733
/*                                                                               */
734
/*                     open for read/write access-Implementation                 */
735
/*                                                                               */
736
/*********************************************************************************/
737
738
//  Given a file URL aUnqPath, this methods returns a XStream which can be used
739
//  to read and write from/to the file.
740
741
742
uno::Reference< io::XStream >
743
TaskManager::open_rw( sal_Int32 CommandId,
744
                const OUString& aUnqPath,
745
                bool bLock )
746
38.4k
{
747
38.4k
    rtl::Reference<XStream_impl> pStream(new XStream_impl( aUnqPath, bLock ));  // from filstr.hxx
748
749
38.4k
    TaskHandlerErr ErrorCode = pStream->CtorSuccess();
750
751
38.4k
    if( ErrorCode != TaskHandlerErr::NO_ERROR )
752
0
    {
753
0
        installError( CommandId,
754
0
                      ErrorCode,
755
0
                      pStream->getMinorError() );
756
757
0
        pStream.clear();
758
0
    }
759
38.4k
    return pStream;
760
38.4k
}
761
762
763
/*********************************************************************************/
764
/*                                                                               */
765
/*                       ls-Implementation                                       */
766
/*                                                                               */
767
/*********************************************************************************/
768
769
//  This method returns the result set containing the children of the directory belonging
770
//  to file URL aUnqPath
771
772
773
uno::Reference< XDynamicResultSet >
774
TaskManager::ls( sal_Int32 CommandId,
775
           const OUString& aUnqPath,
776
           const sal_Int32 OpenMode,
777
           const uno::Sequence< beans::Property >& seq,
778
           const uno::Sequence< NumberedSortingInfo >& seqSort )
779
106k
{
780
106k
    rtl::Reference<XResultSet_impl> p(new XResultSet_impl( this,aUnqPath,OpenMode,seq,seqSort ));
781
782
106k
    TaskHandlerErr ErrorCode = p->CtorSuccess();
783
784
106k
    if( ErrorCode != TaskHandlerErr::NO_ERROR )
785
0
    {
786
0
        installError( CommandId,
787
0
                      ErrorCode,
788
0
                      p->getMinorError() );
789
790
0
        p.clear();
791
0
    }
792
793
106k
    return p;
794
106k
}
795
796
797
/*********************************************************************************/
798
/*                                                                               */
799
/*                          info_c implementation                                */
800
/*                                                                               */
801
/*********************************************************************************/
802
// Info for commands
803
804
uno::Reference< XCommandInfo >
805
TaskManager::info_c()
806
0
{
807
0
    return new XCommandInfo_impl( this );
808
0
}
809
810
811
/*********************************************************************************/
812
/*                                                                               */
813
/*                     info_p-Implementation                                     */
814
/*                                                                               */
815
/*********************************************************************************/
816
// Info for the properties
817
818
uno::Reference< beans::XPropertySetInfo >
819
TaskManager::info_p( const OUString& aUnqPath )
820
0
{
821
0
    std::unique_lock aGuard( m_aMutex );
822
0
    return new XPropertySetInfo_impl( this,aUnqPath );
823
0
}
824
825
826
/*********************************************************************************/
827
/*                                                                               */
828
/*                     setv-Implementation                                       */
829
/*                                                                               */
830
/*********************************************************************************/
831
832
//  Sets the values of the properties belonging to fileURL aUnqPath
833
834
835
uno::Sequence< uno::Any >
836
TaskManager::setv( const OUString& aUnqPath,
837
             const uno::Sequence< beans::PropertyValue >& values )
838
0
{
839
0
    std::unique_lock aGuard( m_aMutex );
840
841
0
    sal_Int32 propChanged = 0;
842
0
    uno::Sequence< uno::Any > ret( values.getLength() );
843
0
    auto retRange = asNonConstRange(ret);
844
0
    uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );
845
0
    auto seqChangedRange = asNonConstRange(seqChanged);
846
847
0
    TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
848
0
    PropertySet& properties = it->second.properties;
849
0
    TaskManager::PropertySet::const_iterator it1;
850
0
    uno::Any aAny;
851
852
0
    for( sal_Int32 i = 0; i < values.getLength(); ++i )
853
0
    {
854
0
        MyProperty toset( values[i].Name );
855
0
        it1 = properties.find( toset );
856
0
        if( it1 == properties.end() )
857
0
        {
858
0
            retRange[i] <<= beans::UnknownPropertyException( THROW_WHERE );
859
0
            continue;
860
0
        }
861
862
0
        aAny = it1->getValue();
863
0
        if( aAny == values[i].Value )
864
0
            continue;  // nothing needs to be changed
865
866
0
        if( it1->getAttributes() & beans::PropertyAttribute::READONLY )
867
0
        {
868
0
            retRange[i] <<= lang::IllegalAccessException( THROW_WHERE );
869
0
            continue;
870
0
        }
871
872
0
        seqChangedRange[ propChanged   ].PropertyName = values[i].Name;
873
0
        seqChangedRange[ propChanged   ].PropertyHandle   = -1;
874
0
        seqChangedRange[ propChanged   ].Further   = false;
875
0
        seqChangedRange[ propChanged   ].OldValue = aAny;
876
0
        seqChangedRange[ propChanged++ ].NewValue = values[i].Value;
877
878
0
        it1->setValue( values[i].Value );  // Put the new value into the local cash
879
880
0
        if( ! it1->IsNative() )
881
0
        {
882
            // Also put logical properties into storage
883
0
            if( !it->second.xS.is() )
884
0
                load( it, true );
885
886
0
            if( ( values[i].Name == ContentType ) &&
887
0
                it1->getState() == beans::PropertyState_DEFAULT_VALUE )
888
0
            {   // Special logic for ContentType
889
                //  09.07.01: Not reached anymore, because ContentType is readonly
890
0
                it1->setState( beans::PropertyState_DIRECT_VALUE );
891
0
                it->second.xC->addProperty( values[i].Name,
892
0
                                            beans::PropertyAttribute::MAYBEVOID,
893
0
                                            values[i].Value );
894
0
            }
895
896
0
            try
897
0
            {
898
0
                it->second.xS->setPropertyValue( values[i].Name,values[i].Value );
899
0
            }
900
0
            catch (const uno::Exception&e)
901
0
            {
902
0
                --propChanged; // unsuccessful setting
903
0
                retRange[i] <<= e;
904
0
            }
905
0
        }
906
0
        else
907
0
        {
908
            // native properties
909
            // Setting of physical file properties
910
0
            if( values[i].Name == Size )
911
0
            {
912
0
                sal_Int64 newSize = 0;
913
0
                if( values[i].Value >>= newSize )
914
0
                {   // valid value for the size
915
0
                    osl::File aFile(aUnqPath);
916
0
                    bool err =
917
0
                        aFile.open(osl_File_OpenFlag_Write) != osl::FileBase::E_None ||
918
0
                        aFile.setSize(sal_uInt64(newSize)) != osl::FileBase::E_None ||
919
0
                        aFile.close() != osl::FileBase::E_None;
920
921
0
                    if( err )
922
0
                    {
923
0
                        --propChanged; // unsuccessful setting
924
0
                        uno::Sequence<uno::Any> names(comphelper::InitAnyPropertySequence(
925
0
                        {
926
0
                            {"Uri", uno::Any(aUnqPath)}
927
0
                        }));
928
0
                        retRange[i] <<= InteractiveAugmentedIOException(
929
0
                            OUString(),
930
0
                            nullptr,
931
0
                            task::InteractionClassification_ERROR,
932
0
                            IOErrorCode_GENERAL,
933
0
                            names );
934
0
                    }
935
0
                }
936
0
                else
937
0
                    retRange[i] <<= beans::IllegalTypeException( THROW_WHERE );
938
0
            }
939
0
            else if(values[i].Name == IsReadOnly ||
940
0
                    values[i].Name == IsHidden)
941
0
            {
942
0
                bool value = false;
943
0
                if( values[i].Value >>= value )
944
0
                {
945
0
                    osl::DirectoryItem aDirItem;
946
0
                    osl::FileBase::RC err =
947
0
                        osl::DirectoryItem::get(aUnqPath,aDirItem);
948
0
                    sal_uInt64 nAttributes(0);
949
0
                    if(err == osl::FileBase::E_None)
950
0
                    {
951
0
                        osl::FileStatus aFileStatus(osl_FileStatus_Mask_Attributes);
952
0
                        err = aDirItem.getFileStatus(aFileStatus);
953
0
                        if(err == osl::FileBase::E_None &&
954
0
                           aFileStatus.isValid(osl_FileStatus_Mask_Attributes))
955
0
                            nAttributes = aFileStatus.getAttributes();
956
0
                    }
957
                    // now we have the attributes provided all went well.
958
0
                    if(err == osl::FileBase::E_None) {
959
0
                        if(values[i].Name == IsReadOnly)
960
0
                        {
961
0
                            nAttributes &= ~(osl_File_Attribute_OwnWrite |
962
0
                                             osl_File_Attribute_GrpWrite |
963
0
                                             osl_File_Attribute_OthWrite |
964
0
                                             osl_File_Attribute_ReadOnly);
965
0
                            if(value)
966
0
                                nAttributes |= osl_File_Attribute_ReadOnly;
967
0
                            else
968
0
                                nAttributes |= (
969
0
                                    osl_File_Attribute_OwnWrite |
970
0
                                    osl_File_Attribute_GrpWrite |
971
0
                                    osl_File_Attribute_OthWrite);
972
0
                        }
973
0
                        else if(values[i].Name == IsHidden)
974
0
                        {
975
0
                            nAttributes &= ~(osl_File_Attribute_Hidden);
976
0
                            if(value)
977
0
                                nAttributes |= osl_File_Attribute_Hidden;
978
0
                        }
979
0
                        err = osl::File::setAttributes(
980
0
                            aUnqPath,nAttributes);
981
0
                    }
982
983
0
                    if( err != osl::FileBase::E_None )
984
0
                    {
985
0
                        --propChanged; // unsuccessful setting
986
0
                        uno::Sequence<uno::Any> names(comphelper::InitAnyPropertySequence(
987
0
                        {
988
0
                            {"Uri", uno::Any(aUnqPath)}
989
0
                        }));
990
0
                        IOErrorCode ioError;
991
0
                        switch( err )
992
0
                        {
993
0
                        case osl::FileBase::E_NOMEM:
994
                            // not enough memory for allocating structures <br>
995
0
                            ioError = IOErrorCode_OUT_OF_MEMORY;
996
0
                            break;
997
0
                        case osl::FileBase::E_INVAL:
998
                            // the format of the parameters was not valid<p>
999
0
                            ioError = IOErrorCode_INVALID_PARAMETER;
1000
0
                            break;
1001
0
                        case osl::FileBase::E_NAMETOOLONG:
1002
                            // File name too long<br>
1003
0
                            ioError = IOErrorCode_NAME_TOO_LONG;
1004
0
                            break;
1005
0
                        case osl::FileBase::E_NOENT:
1006
                            // No such file or directory<br>
1007
0
                        case osl::FileBase::E_NOLINK:
1008
                            // Link has been severed<br>
1009
0
                            ioError = IOErrorCode_NOT_EXISTING;
1010
0
                            break;
1011
0
                        case osl::FileBase::E_ROFS:
1012
                            // #i4735# handle ROFS transparently
1013
                            // as ACCESS_DENIED
1014
0
                        case  osl::FileBase::E_PERM:
1015
0
                        case osl::FileBase::E_ACCES:
1016
                            // permission denied<br>
1017
0
                            ioError = IOErrorCode_ACCESS_DENIED;
1018
0
                            break;
1019
0
                        case osl::FileBase::E_LOOP:
1020
                            // Too many symbolic links encountered<br>
1021
0
                        case osl::FileBase::E_FAULT:
1022
                            // Bad address<br>
1023
0
                        case osl::FileBase::E_IO:
1024
                            // I/O error<br>
1025
0
                        case osl::FileBase::E_NOSYS:
1026
                            // Function not implemented<br>
1027
0
                        case osl::FileBase::E_MULTIHOP:
1028
                            // Multihop attempted<br>
1029
0
                        case osl::FileBase::E_INTR:
1030
                            // function call was interrupted<p>
1031
0
                        default:
1032
0
                            ioError = IOErrorCode_GENERAL;
1033
0
                            break;
1034
0
                        }
1035
0
                        retRange[i] <<= InteractiveAugmentedIOException(
1036
0
                            OUString(),
1037
0
                            nullptr,
1038
0
                            task::InteractionClassification_ERROR,
1039
0
                            ioError,
1040
0
                            names );
1041
0
                    }
1042
0
                }
1043
0
                else
1044
0
                    retRange[i] <<= beans::IllegalTypeException( THROW_WHERE );
1045
0
            }
1046
0
        }
1047
0
    }   // end for
1048
1049
0
    aGuard.unlock();
1050
0
    if( propChanged )
1051
0
    {
1052
0
        seqChanged.realloc( propChanged );
1053
0
        notifyPropertyChanges( getPropertyChangeNotifier( aUnqPath ), seqChanged );
1054
0
    }
1055
1056
0
    return ret;
1057
0
}
1058
1059
/*********************************************************************************/
1060
/*                                                                               */
1061
/*                     getv-Implementation                                       */
1062
/*                                                                               */
1063
/*********************************************************************************/
1064
1065
//  Reads the values of the properties belonging to fileURL aUnqPath;
1066
//  Returns an XRow object containing the values in the requested order.
1067
1068
1069
uno::Reference< sdbc::XRow >
1070
TaskManager::getv( sal_Int32 CommandId,
1071
             const OUString& aUnqPath,
1072
             const uno::Sequence< beans::Property >& properties )
1073
9.78k
{
1074
9.78k
    uno::Sequence< uno::Any > seq( properties.getLength() );
1075
1076
9.78k
    sal_Int32 n_Mask;
1077
9.78k
    getMaskFromProperties( n_Mask,properties );
1078
9.78k
    osl::FileStatus aFileStatus( n_Mask );
1079
1080
9.78k
    osl::DirectoryItem aDirItem;
1081
9.78k
    osl::FileBase::RC nError1 = osl::DirectoryItem::get( aUnqPath,aDirItem );
1082
9.78k
    if( nError1 != osl::FileBase::E_None )
1083
0
        installError(CommandId,
1084
0
                     TaskHandlerErr::OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1085
0
                     nError1);
1086
1087
9.78k
    osl::FileBase::RC nError2 = aDirItem.getFileStatus( aFileStatus );
1088
9.78k
    if( nError1 == osl::FileBase::E_None &&
1089
9.78k
        nError2 != osl::FileBase::E_None )
1090
0
        installError(CommandId,
1091
0
                     TaskHandlerErr::OPEN_FILE_FOR_PAGING, // BEAWARE, REUSED
1092
0
                     nError2);
1093
1094
9.78k
    {
1095
9.78k
        std::unique_lock aGuard( m_aMutex );
1096
1097
9.78k
        TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
1098
9.78k
        commit( aGuard, it, aFileStatus );
1099
1100
9.78k
        PropertySet& propset = it->second.properties;
1101
1102
9.78k
        std::transform(properties.begin(), properties.end(), seq.getArray(),
1103
9.78k
            [&propset](const beans::Property& rProp) -> uno::Any {
1104
9.78k
                MyProperty readProp( rProp.Name );
1105
9.78k
                auto it1 = propset.find( readProp );
1106
9.78k
                if( it1 == propset.end() )
1107
0
                    return uno::Any();
1108
9.78k
                return it1->getValue();
1109
9.78k
            });
1110
9.78k
    }
1111
1112
9.78k
    return new XRow_impl( this,seq );
1113
9.78k
}
1114
1115
1116
/********************************************************************************/
1117
/*                                                                              */
1118
/*                         transfer-commandos                                   */
1119
/*                                                                              */
1120
/********************************************************************************/
1121
1122
1123
/********************************************************************************/
1124
/*                                                                              */
1125
/*                         move-implementation                                  */
1126
/*                                                                              */
1127
/********************************************************************************/
1128
1129
//  Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath.
1130
1131
1132
void
1133
TaskManager::move( sal_Int32 CommandId,
1134
             const OUString& srcUnqPath,
1135
             const OUString& dstUnqPathIn,
1136
             const sal_Int32 NameClash )
1137
0
{
1138
    // --> #i88446# Method notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) ); crashes if
1139
    // srcUnqPath and dstUnqPathIn are equal
1140
0
    if( srcUnqPath == dstUnqPathIn )
1141
0
        return;
1142
1143
0
    osl::FileBase::RC nError;
1144
0
    OUString dstUnqPath( dstUnqPathIn );
1145
1146
0
    switch( NameClash )
1147
0
    {
1148
0
    case NameClash::KEEP:
1149
0
        {
1150
0
            nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1151
0
            if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1152
0
            {
1153
0
                installError( CommandId,
1154
0
                              TaskHandlerErr::KEEPERROR_FOR_MOVE,
1155
0
                              nError );
1156
0
                return;
1157
0
            }
1158
0
            break;
1159
0
        }
1160
0
    case NameClash::OVERWRITE:
1161
0
        {
1162
            // stat to determine whether we have a symlink
1163
0
            OUString targetPath(dstUnqPath);
1164
1165
0
            osl::FileStatus aStatus(osl_FileStatus_Mask_Type|osl_FileStatus_Mask_LinkTargetURL);
1166
0
            osl::DirectoryItem aItem;
1167
0
            (void)osl::DirectoryItem::get(dstUnqPath,aItem);
1168
0
            (void)aItem.getFileStatus(aStatus);
1169
1170
0
            if( aStatus.isValid(osl_FileStatus_Mask_Type)          &&
1171
0
                aStatus.isValid(osl_FileStatus_Mask_LinkTargetURL) &&
1172
0
                aStatus.getFileType() == osl::FileStatus::Link )
1173
0
                targetPath = aStatus.getLinkTargetURL();
1174
1175
            // Will do nothing if file does not exist.
1176
0
            osl::File::remove( targetPath );
1177
1178
0
            nError = osl_File_move( srcUnqPath,targetPath );
1179
0
            if( nError != osl::FileBase::E_None )
1180
0
            {
1181
0
                installError( CommandId,
1182
0
                              TaskHandlerErr::OVERWRITE_FOR_MOVE,
1183
0
                              nError );
1184
0
                return;
1185
0
            }
1186
0
            break;
1187
0
        }
1188
0
    case NameClash::RENAME:
1189
0
        {
1190
0
            OUString newDstUnqPath;
1191
0
            nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1192
0
            if( nError == osl::FileBase::E_EXIST )
1193
0
            {
1194
                // "invent" a new valid title.
1195
1196
0
                sal_Int32 nPos = -1;
1197
0
                sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1198
0
                sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1199
0
                if( ( nLastSlash < nLastDot )                  // dot is part of last(!) path segment
1200
0
                    && ( nLastSlash != ( nLastDot - 1 ) ) )    // file name does not start with a dot
1201
0
                    nPos = nLastDot;
1202
0
                else
1203
0
                    nPos = dstUnqPath.getLength();
1204
1205
0
                sal_Int32 nTry = 0;
1206
1207
0
                do
1208
0
                {
1209
0
                    newDstUnqPath = dstUnqPath;
1210
1211
0
                    OUString aPostfix =  "_" + OUString::number( ++nTry );
1212
1213
0
                    newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix );
1214
1215
0
                    nError = osl_File_move( srcUnqPath,newDstUnqPath,true );
1216
0
                }
1217
0
                while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1218
0
            }
1219
1220
0
            if( nError == osl::FileBase::E_EXIST )
1221
0
            {
1222
0
                installError( CommandId,
1223
0
                              TaskHandlerErr::RENAME_FOR_MOVE );
1224
0
                return;
1225
0
            }
1226
0
            else if( nError != osl::FileBase::E_None )
1227
0
            {
1228
0
                installError( CommandId,
1229
0
                              TaskHandlerErr::RENAMEMOVE_FOR_MOVE,
1230
0
                              nError );
1231
0
                return;
1232
0
            }
1233
0
            else
1234
0
                dstUnqPath = newDstUnqPath;
1235
1236
0
            break;
1237
0
        }
1238
0
    case NameClash::ERROR:
1239
0
        {
1240
0
            nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1241
0
            if( nError == osl::FileBase::E_EXIST )
1242
0
            {
1243
0
                installError( CommandId,
1244
0
                              TaskHandlerErr::NAMECLASH_FOR_MOVE );
1245
0
                return;
1246
0
            }
1247
0
            else if( nError != osl::FileBase::E_None )
1248
0
            {
1249
0
                installError( CommandId,
1250
0
                              TaskHandlerErr::NAMECLASHMOVE_FOR_MOVE,
1251
0
                              nError );
1252
0
                return;
1253
0
            }
1254
0
            break;
1255
0
        }
1256
0
        case NameClash::ASK:
1257
0
        default:
1258
0
        {
1259
0
            nError = osl_File_move( srcUnqPath,dstUnqPath,true );
1260
0
            if( nError == osl::FileBase::E_EXIST )
1261
0
            {
1262
0
                installError( CommandId,
1263
0
                              TaskHandlerErr::NAMECLASHSUPPORT_FOR_MOVE,
1264
0
                              NameClash::ASK);
1265
0
                return;
1266
0
            }
1267
0
        }
1268
0
        break;
1269
0
    }
1270
1271
    // Determine, whether we have moved a file or a folder
1272
0
    osl::DirectoryItem aItem;
1273
0
    nError = osl::DirectoryItem::get( dstUnqPath,aItem );
1274
0
    if( nError != osl::FileBase::E_None )
1275
0
    {
1276
0
        installError( CommandId,
1277
0
                      TaskHandlerErr::TRANSFER_BY_MOVE_SOURCE,
1278
0
                      nError );
1279
0
        return;
1280
0
    }
1281
0
    osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
1282
0
    nError = aItem.getFileStatus( aStatus );
1283
0
    if( nError != osl::FileBase::E_None || ! aStatus.isValid( osl_FileStatus_Mask_Type ) )
1284
0
    {
1285
0
        installError( CommandId,
1286
0
                      TaskHandlerErr::TRANSFER_BY_MOVE_SOURCESTAT,
1287
0
                      nError );
1288
0
        return;
1289
0
    }
1290
0
    bool isDocument = ( aStatus.getFileType() == osl::FileStatus::Regular );
1291
1292
1293
0
    copyPersistentSet( srcUnqPath,dstUnqPath,!isDocument );
1294
1295
0
    OUString aDstParent = getParentName( dstUnqPath );
1296
0
    OUString aSrcParent = getParentName( srcUnqPath );
1297
1298
0
    notifyInsert( getContentEventListeners( aDstParent ),dstUnqPath );
1299
0
    if(  aDstParent != aSrcParent )
1300
0
        notifyContentRemoved( getContentEventListeners( aSrcParent ),srcUnqPath );
1301
1302
0
    notifyContentExchanged( getContentExchangedEventListeners( srcUnqPath,dstUnqPath,!isDocument ) );
1303
0
    erasePersistentSet( srcUnqPath,!isDocument );
1304
0
}
1305
1306
1307
/********************************************************************************/
1308
/*                                                                              */
1309
/*                         copy-implementation                                  */
1310
/*                                                                              */
1311
/********************************************************************************/
1312
1313
//  Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories )
1314
1315
1316
namespace {
1317
1318
bool getType(
1319
    TaskManager & task, sal_Int32 id, OUString const & fileUrl,
1320
    osl::DirectoryItem * item, osl::FileStatus::Type * type)
1321
0
{
1322
0
    assert(item != nullptr && type != nullptr);
1323
0
    osl::FileBase::RC err = osl::DirectoryItem::get(fileUrl, *item);
1324
0
    if (err != osl::FileBase::E_None) {
1325
0
        task.installError(id, TaskHandlerErr::TRANSFER_BY_COPY_SOURCE, err);
1326
0
        return false;
1327
0
    }
1328
0
    osl::FileStatus stat(osl_FileStatus_Mask_Type);
1329
0
    err = item->getFileStatus(stat);
1330
0
    if (err != osl::FileBase::E_None) {
1331
0
        task.installError(id, TaskHandlerErr::TRANSFER_BY_COPY_SOURCESTAT, err);
1332
0
        return false;
1333
0
    }
1334
0
    *type = stat.getFileType();
1335
0
    return true;
1336
0
}
1337
1338
}
1339
1340
void
1341
TaskManager::copy(
1342
    sal_Int32 CommandId,
1343
    const OUString& srcUnqPath,
1344
    const OUString& dstUnqPathIn,
1345
    sal_Int32 NameClash )
1346
0
{
1347
0
    osl::FileBase::RC nError;
1348
0
    OUString dstUnqPath( dstUnqPathIn );
1349
1350
    // Resolve symbolic links within the source path.  If srcUnqPath denotes a
1351
    // symbolic link (targeting either a file or a folder), the contents of the
1352
    // target is copied (recursively, in the case of a folder).  However, if
1353
    // recursively copying the contents of a folder causes a symbolic link to be
1354
    // copied, the symbolic link itself is copied.
1355
0
    osl::DirectoryItem item;
1356
0
    osl::FileStatus::Type type;
1357
0
    if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1358
0
        return;
1359
0
    }
1360
0
    OUString rslvdSrcUnqPath;
1361
0
    if (type == osl::FileStatus::Link) {
1362
0
        osl::FileStatus stat(osl_FileStatus_Mask_LinkTargetURL);
1363
0
        nError = item.getFileStatus(stat);
1364
0
        if (nError != osl::FileBase::E_None) {
1365
0
            installError(
1366
0
                CommandId, TaskHandlerErr::TRANSFER_BY_COPY_SOURCESTAT, nError);
1367
0
            return;
1368
0
        }
1369
0
        rslvdSrcUnqPath = stat.getLinkTargetURL();
1370
0
        if (!getType(*this, CommandId, srcUnqPath, &item, &type)) {
1371
0
            return;
1372
0
        }
1373
0
    } else {
1374
0
        rslvdSrcUnqPath = srcUnqPath;
1375
0
    }
1376
1377
0
    bool isDocument
1378
0
        = type != osl::FileStatus::Directory && type != osl::FileStatus::Volume;
1379
0
    FileUrlType IsWhat = isDocument ? FileUrlType::File : FileUrlType::Folder;
1380
1381
0
    switch( NameClash )
1382
0
    {
1383
0
        case NameClash::KEEP:
1384
0
        {
1385
0
            nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1386
0
            if( nError != osl::FileBase::E_None && nError != osl::FileBase::E_EXIST )
1387
0
            {
1388
0
                installError( CommandId,
1389
0
                              TaskHandlerErr::KEEPERROR_FOR_COPY,
1390
0
                              nError );
1391
0
                return;
1392
0
            }
1393
0
            break;
1394
0
        }
1395
0
        case NameClash::OVERWRITE:
1396
0
        {
1397
            // remove (..., MustExist = sal_False).
1398
0
            remove( CommandId, dstUnqPath, IsWhat, false );
1399
1400
            // copy.
1401
0
            nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,false );
1402
0
            if( nError != osl::FileBase::E_None )
1403
0
            {
1404
0
                installError( CommandId,
1405
0
                              TaskHandlerErr::OVERWRITE_FOR_COPY,
1406
0
                              nError );
1407
0
                return;
1408
0
            }
1409
0
            break;
1410
0
        }
1411
0
        case NameClash::RENAME:
1412
0
        {
1413
0
            OUString newDstUnqPath = dstUnqPath;
1414
0
            nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1415
1416
0
            if( nError == osl::FileBase::E_EXIST )
1417
0
            {
1418
                // "invent" a new valid title.
1419
1420
0
                sal_Int32 nPos = -1;
1421
0
                sal_Int32 nLastDot = dstUnqPath.lastIndexOf( '.' );
1422
0
                sal_Int32 nLastSlash = dstUnqPath.lastIndexOf( '/' );
1423
0
                if ( ( nLastSlash < nLastDot ) // dot is part of last(!) path segment
1424
0
                     && ( nLastSlash != ( nLastDot - 1 ) ) ) // file name does not start with a dot
1425
0
                    nPos = nLastDot;
1426
0
                else
1427
0
                    nPos = dstUnqPath.getLength();
1428
1429
0
                sal_Int32 nTry = 0;
1430
1431
0
                do
1432
0
                {
1433
0
                    newDstUnqPath = dstUnqPath;
1434
1435
0
                    OUString aPostfix =  "_" + OUString::number( ++nTry );
1436
1437
0
                    newDstUnqPath = newDstUnqPath.replaceAt( nPos, 0, aPostfix );
1438
1439
0
                    nError = copy_recursive( rslvdSrcUnqPath,newDstUnqPath,IsWhat,true );
1440
0
                }
1441
0
                while( ( nError == osl::FileBase::E_EXIST ) && ( nTry < 10000 ) );
1442
0
            }
1443
1444
0
            if( nError == osl::FileBase::E_EXIST )
1445
0
            {
1446
0
                installError( CommandId,
1447
0
                              TaskHandlerErr::RENAME_FOR_COPY );
1448
0
                return;
1449
0
            }
1450
0
            else if( nError != osl::FileBase::E_None )
1451
0
            {
1452
0
                installError( CommandId,
1453
0
                              TaskHandlerErr::RENAMEMOVE_FOR_COPY,
1454
0
                              nError );
1455
0
                return;
1456
0
            }
1457
0
            else
1458
0
                dstUnqPath = newDstUnqPath;
1459
1460
0
            break;
1461
0
        }
1462
0
        case NameClash::ERROR:
1463
0
        {
1464
0
            nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1465
1466
0
            if( nError == osl::FileBase::E_EXIST )
1467
0
            {
1468
0
                installError( CommandId,
1469
0
                              TaskHandlerErr::NAMECLASH_FOR_COPY );
1470
0
                return;
1471
0
            }
1472
0
            else if( nError != osl::FileBase::E_None )
1473
0
            {
1474
0
                installError( CommandId,
1475
0
                              TaskHandlerErr::NAMECLASHMOVE_FOR_COPY,
1476
0
                              nError );
1477
0
                return;
1478
0
            }
1479
0
            break;
1480
0
        }
1481
0
        case NameClash::ASK:
1482
0
        default:
1483
0
        {
1484
0
            nError = copy_recursive( rslvdSrcUnqPath,dstUnqPath,IsWhat,true );
1485
1486
0
            if( nError == osl::FileBase::E_EXIST )
1487
0
            {
1488
0
                installError( CommandId,
1489
0
                              TaskHandlerErr::NAMECLASHSUPPORT_FOR_COPY,
1490
0
                              NameClash);
1491
0
                return;
1492
0
            }
1493
0
            break;
1494
0
        }
1495
0
    }
1496
1497
0
    copyPersistentSet( srcUnqPath,dstUnqPath, !isDocument );
1498
0
    notifyInsert( getContentEventListeners( getParentName( dstUnqPath ) ),dstUnqPath );
1499
0
}
1500
1501
1502
/********************************************************************************/
1503
/*                                                                              */
1504
/*                         remove-implementation                                */
1505
/*                                                                              */
1506
/********************************************************************************/
1507
1508
//  Deletes the content belonging to fileURL aUnqPath( recursively in case of directory )
1509
//  Return: success of operation
1510
1511
1512
bool
1513
TaskManager::remove( sal_Int32 CommandId,
1514
               const OUString& aUnqPath,
1515
               FileUrlType IsWhat,
1516
               bool  MustExist )
1517
0
{
1518
0
    sal_Int32 nMask = osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileURL;
1519
1520
0
    osl::DirectoryItem aItem;
1521
0
    osl::FileStatus aStatus( nMask );
1522
0
    osl::FileBase::RC nError;
1523
1524
0
    if( IsWhat == FileUrlType::Unknown ) // Determine whether we are removing a directory or a file
1525
0
    {
1526
0
        nError = osl::DirectoryItem::get( aUnqPath, aItem );
1527
0
        if( nError != osl::FileBase::E_None )
1528
0
        {
1529
0
            if (MustExist)
1530
0
            {
1531
0
                installError( CommandId,
1532
0
                              TaskHandlerErr::NOSUCHFILEORDIR_FOR_REMOVE,
1533
0
                              nError );
1534
0
            }
1535
0
            return (!MustExist);
1536
0
        }
1537
1538
0
        nError = aItem.getFileStatus( aStatus );
1539
0
        if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1540
0
        {
1541
0
            installError( CommandId,
1542
0
                          TaskHandlerErr::VALIDFILESTATUS_FOR_REMOVE,
1543
0
                          nError != osl::FileBase::E_None ? nError : 0 );
1544
0
            return false;
1545
0
        }
1546
1547
0
        if( aStatus.getFileType() == osl::FileStatus::Regular ||
1548
0
            aStatus.getFileType() == osl::FileStatus::Link )
1549
0
            IsWhat = FileUrlType::File;
1550
0
        else if(  aStatus.getFileType() == osl::FileStatus::Directory ||
1551
0
                  aStatus.getFileType() == osl::FileStatus::Volume )
1552
0
            IsWhat = FileUrlType::Folder;
1553
0
    }
1554
1555
1556
0
    if( IsWhat == FileUrlType::File )
1557
0
    {
1558
0
        nError = osl::File::remove( aUnqPath );
1559
0
        if( nError != osl::FileBase::E_None )
1560
0
        {
1561
0
            if (MustExist)
1562
0
            {
1563
0
                installError( CommandId,
1564
0
                              TaskHandlerErr::DELETEFILE_FOR_REMOVE,
1565
0
                              nError );
1566
0
            }
1567
0
            return (!MustExist);
1568
0
        }
1569
0
        else
1570
0
        {
1571
0
            notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1572
0
            erasePersistentSet( aUnqPath ); // Removes from XPersistentPropertySet
1573
0
        }
1574
0
    }
1575
0
    else if( IsWhat == FileUrlType::Folder )
1576
0
    {
1577
0
        osl::Directory aDirectory( aUnqPath );
1578
1579
0
        nError = aDirectory.open();
1580
0
        if( nError != osl::FileBase::E_None )
1581
0
        {
1582
0
            if (MustExist)
1583
0
            {
1584
0
                installError( CommandId,
1585
0
                              TaskHandlerErr::OPENDIRECTORY_FOR_REMOVE,
1586
0
                              nError );
1587
0
            }
1588
0
            return (!MustExist);
1589
0
        }
1590
1591
0
        bool whileSuccess = true;
1592
0
        FileUrlType recurse = FileUrlType::Unknown;
1593
0
        OUString name;
1594
1595
0
        nError = aDirectory.getNextItem( aItem );
1596
0
        while( nError == osl::FileBase::E_None )
1597
0
        {
1598
0
            nError = aItem.getFileStatus( aStatus );
1599
0
            if( nError != osl::FileBase::E_None || ! aStatus.isValid( nMask ) )
1600
0
            {
1601
0
                installError( CommandId,
1602
0
                              TaskHandlerErr::VALIDFILESTATUSWHILE_FOR_REMOVE,
1603
0
                              nError != osl::FileBase::E_None ? nError : 0 );
1604
0
                whileSuccess = false;
1605
0
                break;
1606
0
            }
1607
1608
0
            if( aStatus.getFileType() == osl::FileStatus::Regular ||
1609
0
                aStatus.getFileType() == osl::FileStatus::Link )
1610
0
                recurse = FileUrlType::File;
1611
0
            else if( aStatus.getFileType() == osl::FileStatus::Directory ||
1612
0
                     aStatus.getFileType() == osl::FileStatus::Volume )
1613
0
                recurse = FileUrlType::Folder;
1614
1615
0
            name = aStatus.getFileURL();
1616
0
            whileSuccess = remove( CommandId, name, recurse, MustExist );
1617
0
            if( !whileSuccess )
1618
0
                break;
1619
1620
0
            nError = aDirectory.getNextItem( aItem );
1621
0
        }
1622
1623
0
        aDirectory.close();
1624
1625
0
        if( ! whileSuccess )
1626
0
            return false;     // error code is installed
1627
1628
0
        if( nError != osl::FileBase::E_NOENT )
1629
0
        {
1630
0
            installError( CommandId,
1631
0
                          TaskHandlerErr::DIRECTORYEXHAUSTED_FOR_REMOVE,
1632
0
                          nError );
1633
0
            return false;
1634
0
        }
1635
1636
0
        nError = osl::Directory::remove( aUnqPath );
1637
0
        if( nError != osl::FileBase::E_None )
1638
0
        {
1639
0
            if (MustExist)
1640
0
            {
1641
0
                installError( CommandId,
1642
0
                              TaskHandlerErr::DELETEDIRECTORY_FOR_REMOVE,
1643
0
                              nError );
1644
0
            }
1645
0
            return (!MustExist);
1646
0
        }
1647
0
        else
1648
0
        {
1649
0
            notifyContentDeleted( getContentDeletedEventListeners(aUnqPath) );
1650
0
            erasePersistentSet( aUnqPath );
1651
0
        }
1652
0
    }
1653
0
    else   // Don't know what to remove
1654
0
    {
1655
0
        installError( CommandId,
1656
0
                      TaskHandlerErr::FILETYPE_FOR_REMOVE );
1657
0
        return false;
1658
0
    }
1659
1660
0
    return true;
1661
0
}
1662
1663
1664
/********************************************************************************/
1665
/*                                                                              */
1666
/*                         mkdir-implementation                                 */
1667
/*                                                                              */
1668
/********************************************************************************/
1669
1670
//  Creates new directory with given URL, recursively if necessary
1671
//  Return:: success of operation
1672
1673
1674
bool
1675
TaskManager::mkdir( sal_Int32 CommandId,
1676
              const OUString& rUnqPath,
1677
              bool OverWrite )
1678
0
{
1679
0
    OUString aUnqPath;
1680
1681
    // remove trailing slash
1682
0
    if ( rUnqPath.endsWith("/") )
1683
0
        aUnqPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
1684
0
    else
1685
0
        aUnqPath = rUnqPath;
1686
1687
0
    osl::FileBase::RC nError = osl::Directory::create( aUnqPath );
1688
1689
0
    switch ( nError )
1690
0
    {
1691
0
        case osl::FileBase::E_EXIST:   // Directory cannot be overwritten
1692
0
        {
1693
0
            if( !OverWrite )
1694
0
            {
1695
0
                installError( CommandId,
1696
0
                              TaskHandlerErr::FOLDER_EXISTS_MKDIR );
1697
0
                return false;
1698
0
            }
1699
0
            else
1700
0
                return true;
1701
0
        }
1702
0
        case osl::FileBase::E_INVAL:
1703
0
        {
1704
0
            installError(CommandId,
1705
0
                         TaskHandlerErr::INVALID_NAME_MKDIR);
1706
0
            return false;
1707
0
        }
1708
0
        case osl::FileBase::E_None:
1709
0
        {
1710
0
            OUString aPrtPath = getParentName( aUnqPath );
1711
0
            notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1712
0
            return true;
1713
0
        }
1714
0
        default:
1715
0
            return ensuredir(
1716
0
                CommandId,
1717
0
                aUnqPath,
1718
0
                TaskHandlerErr::CREATEDIRECTORY_MKDIR );
1719
0
    }
1720
0
}
1721
1722
1723
/********************************************************************************/
1724
/*                                                                              */
1725
/*                         mkfil-implementation                                 */
1726
/*                                                                              */
1727
/********************************************************************************/
1728
1729
//  Creates new file with given URL.
1730
//  The content of aInputStream becomes the content of the file
1731
//  Return:: success of operation
1732
1733
1734
bool
1735
TaskManager::mkfil( sal_Int32 CommandId,
1736
              const OUString& aUnqPath,
1737
              bool Overwrite,
1738
              const uno::Reference< io::XInputStream >& aInputStream )
1739
0
{
1740
    // return value unimportant
1741
0
    bool bSuccess = write( CommandId,
1742
0
                               aUnqPath,
1743
0
                               Overwrite,
1744
0
                               aInputStream );
1745
0
    if ( bSuccess )
1746
0
    {
1747
0
        OUString aPrtPath = getParentName( aUnqPath );
1748
0
        notifyInsert( getContentEventListeners( aPrtPath ),aUnqPath );
1749
0
    }
1750
0
    return bSuccess;
1751
0
}
1752
1753
1754
/********************************************************************************/
1755
/*                                                                              */
1756
/*                         write-implementation                                 */
1757
/*                                                                              */
1758
/********************************************************************************/
1759
1760
//  writes to the file with given URL.
1761
//  The content of aInputStream becomes the content of the file
1762
//  Return:: success of operation
1763
1764
1765
bool
1766
TaskManager::write( sal_Int32 CommandId,
1767
              const OUString& aUnqPath,
1768
              bool OverWrite,
1769
              const uno::Reference< io::XInputStream >& aInputStream )
1770
0
{
1771
0
    if( ! aInputStream.is() )
1772
0
    {
1773
0
        installError( CommandId,
1774
0
                      TaskHandlerErr::INPUTSTREAM_FOR_WRITE );
1775
0
        return false;
1776
0
    }
1777
1778
    // Create parent path, if necessary.
1779
0
    if ( ! ensuredir( CommandId,
1780
0
                      getParentName( aUnqPath ),
1781
0
                      TaskHandlerErr::ENSUREDIR_FOR_WRITE ) )
1782
0
        return false;
1783
1784
0
    osl::FileBase::RC err;
1785
0
    osl::File aFile( aUnqPath );
1786
1787
0
    if( OverWrite )
1788
0
    {
1789
0
        err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
1790
1791
0
        if( err != osl::FileBase::E_None )
1792
0
        {
1793
0
            aFile.close();
1794
0
            err = aFile.open( osl_File_OpenFlag_Write );
1795
1796
0
            if( err != osl::FileBase::E_None )
1797
0
            {
1798
0
                installError( CommandId,
1799
0
                              TaskHandlerErr::NO_OPEN_FILE_FOR_OVERWRITE,
1800
0
                              err );
1801
0
                return false;
1802
0
            }
1803
1804
            // the existing file was just opened and should be overwritten now,
1805
            // truncate it first
1806
1807
0
            err = aFile.setSize( 0 );
1808
0
            if( err != osl::FileBase::E_None  )
1809
0
            {
1810
0
                installError( CommandId,
1811
0
                              TaskHandlerErr::FILESIZE_FOR_WRITE,
1812
0
                              err );
1813
0
                return false;
1814
0
            }
1815
0
        }
1816
0
    }
1817
0
    else
1818
0
    {
1819
0
        err = aFile.open( osl_File_OpenFlag_Read | osl_File_OpenFlag_NoLock );
1820
0
        if( err == osl::FileBase::E_None )  // The file exists and shall not be overwritten
1821
0
        {
1822
0
            installError( CommandId,
1823
0
                          TaskHandlerErr::NOREPLACE_FOR_WRITE,  // Now an exception
1824
0
                          err );
1825
1826
0
            aFile.close();
1827
0
            return false;
1828
0
        }
1829
1830
        // as a temporary solution the creation does not lock the file at all
1831
        // in future it should be possible to create the file without lock explicitly
1832
0
        err = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create | osl_File_OpenFlag_NoLock );
1833
1834
0
        if( err != osl::FileBase::E_None )
1835
0
        {
1836
0
            aFile.close();
1837
0
            installError( CommandId,
1838
0
                          TaskHandlerErr::NO_OPEN_FILE_FOR_WRITE,
1839
0
                          err );
1840
0
            return false;
1841
0
        }
1842
0
    }
1843
1844
0
    bool bSuccess = true;
1845
1846
0
    sal_uInt64 nWrittenBytes;
1847
0
    sal_Int32 nReadBytes = 0, nRequestedBytes = 32768 /*32k*/;
1848
0
    uno::Sequence< sal_Int8 > seq( nRequestedBytes );
1849
1850
0
    do
1851
0
    {
1852
0
        try
1853
0
        {
1854
0
            nReadBytes = aInputStream->readBytes( seq,
1855
0
                                                  nRequestedBytes );
1856
0
        }
1857
0
        catch( const io::NotConnectedException& )
1858
0
        {
1859
0
            installError( CommandId,
1860
0
                          TaskHandlerErr::NOTCONNECTED_FOR_WRITE );
1861
0
            bSuccess = false;
1862
0
            break;
1863
0
        }
1864
0
        catch( const io::BufferSizeExceededException& )
1865
0
        {
1866
0
            installError( CommandId,
1867
0
                          TaskHandlerErr::BUFFERSIZEEXCEEDED_FOR_WRITE );
1868
0
            bSuccess = false;
1869
0
            break;
1870
0
        }
1871
0
        catch( const io::IOException& )
1872
0
        {
1873
0
            installError( CommandId,
1874
0
                          TaskHandlerErr::IOEXCEPTION_FOR_WRITE );
1875
0
            bSuccess = false;
1876
0
            break;
1877
0
        }
1878
1879
0
        if( nReadBytes )
1880
0
        {
1881
0
            const sal_Int8* p = seq.getConstArray();
1882
1883
0
            err = aFile.write( static_cast<void const *>(p),
1884
0
                               sal_uInt64( nReadBytes ),
1885
0
                               nWrittenBytes );
1886
1887
0
            if( err != osl::FileBase::E_None )
1888
0
            {
1889
0
                installError( CommandId,
1890
0
                              TaskHandlerErr::FILEIOERROR_FOR_WRITE,
1891
0
                              err );
1892
0
                bSuccess = false;
1893
0
                break;
1894
0
            }
1895
0
            else if( nWrittenBytes != sal_uInt64( nReadBytes ) )
1896
0
            {
1897
0
                installError( CommandId,
1898
0
                              TaskHandlerErr::FILEIOERROR_FOR_NO_SPACE );
1899
0
                bSuccess = false;
1900
0
                break;
1901
0
            }
1902
0
        }
1903
0
    } while( nReadBytes == nRequestedBytes );
1904
1905
0
    err = aFile.close();
1906
0
    if( err != osl::FileBase::E_None  )
1907
0
    {
1908
0
        installError( CommandId,
1909
0
                      TaskHandlerErr::FILEIOERROR_FOR_WRITE,
1910
0
                      err );
1911
0
        bSuccess = false;
1912
0
    }
1913
1914
0
    return bSuccess;
1915
0
}
1916
1917
1918
/*********************************************************************************/
1919
/*                                                                               */
1920
/*                 insertDefaultProperties-Implementation                        */
1921
/*                                                                               */
1922
/*********************************************************************************/
1923
1924
1925
void TaskManager::insertDefaultProperties( const OUString& aUnqPath )
1926
148k
{
1927
148k
    std::unique_lock aGuard(m_aMutex);
1928
148k
    insertDefaultProperties(aGuard, aUnqPath);
1929
148k
}
1930
1931
void TaskManager::insertDefaultProperties( std::unique_lock<std::mutex>& /*rGuard*/, const OUString& aUnqPath )
1932
245k
{
1933
245k
    ContentMap::iterator it =
1934
245k
        m_aContent.emplace( aUnqPath,UnqPathData() ).first;
1935
1936
245k
    load( it, false );
1937
1938
245k
    MyProperty ContentTProperty( ContentType );
1939
1940
245k
    PropertySet& properties = it->second.properties;
1941
245k
    bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();
1942
1943
245k
    properties.reserve(properties.size() + m_aDefaultProperties.size());
1944
245k
    for (auto const& defaultprop : m_aDefaultProperties)
1945
3.67M
    {
1946
3.67M
        if( !ContentNotDefau || defaultprop.getPropertyName() != ContentType )
1947
3.48M
            properties.insert( defaultprop );
1948
3.67M
    }
1949
245k
}
1950
1951
1952
/******************************************************************************/
1953
/*                                                                            */
1954
/*                          mapping of file urls                              */
1955
/*                          to uncpath and vice versa                         */
1956
/*                                                                            */
1957
/******************************************************************************/
1958
1959
1960
bool TaskManager::getUnqFromUrl( const OUString& Url, OUString& Unq )
1961
148k
{
1962
148k
    if ( Url == "file:///" || Url == "file://localhost/" || Url == "file://127.0.0.1/" )
1963
0
    {
1964
0
        Unq = "file:///";
1965
0
        return false;
1966
0
    }
1967
1968
148k
    bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Url,Unq );
1969
1970
148k
    Unq = Url;
1971
1972
148k
    sal_Int32 l = Unq.getLength()-1;
1973
148k
    if( ! err && Unq.endsWith("/") &&
1974
0
        Unq.indexOf( '/', RTL_CONSTASCII_LENGTH("//") ) != -1 )
1975
0
        Unq = Unq.copy(0, l);
1976
1977
148k
    return err;
1978
148k
}
1979
1980
1981
bool TaskManager::getUrlFromUnq( const OUString& Unq,OUString& Url )
1982
38.6k
{
1983
38.6k
    bool err = osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL( Unq,Url );
1984
1985
38.6k
    Url = Unq;
1986
1987
38.6k
    return err;
1988
38.6k
}
1989
1990
1991
// Helper function for public copy
1992
1993
osl::FileBase::RC
1994
TaskManager::copy_recursive( const OUString& srcUnqPath,
1995
                       const OUString& dstUnqPath,
1996
                       FileUrlType TypeToCopy,
1997
                       bool testExistBeforeCopy )
1998
0
{
1999
0
    osl::FileBase::RC err = osl::FileBase::E_None;
2000
2001
0
    if( TypeToCopy == FileUrlType::File ) // Document
2002
0
    {
2003
0
        err = osl_File_copy( srcUnqPath,dstUnqPath,testExistBeforeCopy );
2004
0
    }
2005
0
    else if( TypeToCopy == FileUrlType::Folder )
2006
0
    {
2007
0
        osl::Directory aDir( srcUnqPath );
2008
0
        (void)aDir.open();
2009
2010
0
        err = osl::Directory::create( dstUnqPath );
2011
0
        osl::FileBase::RC next = err;
2012
0
        if( err == osl::FileBase::E_None )
2013
0
        {
2014
0
            sal_Int32 const n_Mask = osl_FileStatus_Mask_FileURL | osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_Type;
2015
2016
0
            osl::DirectoryItem aDirItem;
2017
2018
0
            while( err == osl::FileBase::E_None )
2019
0
            {
2020
0
                next = aDir.getNextItem( aDirItem );
2021
0
                if (next != osl::FileBase::E_None )
2022
0
                    break;
2023
0
                bool IsDoc = false;
2024
0
                osl::FileStatus aFileStatus( n_Mask );
2025
0
                aDirItem.getFileStatus( aFileStatus );
2026
0
                if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2027
0
                    IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
2028
2029
                // Getting the information for the next recursive copy
2030
0
                FileUrlType newTypeToCopy = IsDoc ? FileUrlType::File : FileUrlType::Folder;
2031
2032
0
                OUString newSrcUnqPath;
2033
0
                if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2034
0
                    newSrcUnqPath = aFileStatus.getFileURL();
2035
2036
0
                OUString newDstUnqPath = dstUnqPath;
2037
0
                OUString tit;
2038
0
                if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2039
0
                    tit = rtl::Uri::encode( aFileStatus.getFileName(),
2040
0
                                          rtl_UriCharClassPchar,
2041
0
                                          rtl_UriEncodeIgnoreEscapes,
2042
0
                                          RTL_TEXTENCODING_UTF8 );
2043
2044
0
                if( !newDstUnqPath.endsWith( "/" ) )
2045
0
                    newDstUnqPath += "/";
2046
2047
0
                newDstUnqPath += tit;
2048
2049
0
                if ( newSrcUnqPath != dstUnqPath )
2050
0
                    err = copy_recursive( newSrcUnqPath,newDstUnqPath,newTypeToCopy,false );
2051
0
            }
2052
2053
0
            if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
2054
0
                err = next;
2055
0
        }
2056
0
        aDir.close();
2057
0
    }
2058
2059
0
    return err;
2060
0
}
2061
2062
2063
// Helper function for mkfil,mkdir and write
2064
// Creates whole path
2065
// returns success of the operation
2066
2067
2068
bool TaskManager::ensuredir( sal_Int32 CommandId,
2069
                                    const OUString& rUnqPath,
2070
                                    TaskHandlerErr errorCode )
2071
0
{
2072
0
    OUString aPath;
2073
2074
0
    if ( rUnqPath.isEmpty() )
2075
0
        return false;
2076
2077
0
    if ( rUnqPath.endsWith("/") )
2078
0
        aPath = rUnqPath.copy( 0, rUnqPath.getLength() - 1 );
2079
0
    else
2080
0
        aPath = rUnqPath;
2081
2082
#if HAVE_FEATURE_MACOSX_SANDBOX
2083
2084
    // Avoid annoying sandbox messages in the system.log from the
2085
    // below aDirectory.open(), which ends up calling opendir().
2086
    // Surely it is easier to just call stat()? Calling stat() on an
2087
    // arbitrary (?) directory does not seem to cause any sandbox
2088
    // violation, while opendir() does. (Sorry I could not be bothered
2089
    // to use some complex cross-platform abstraction over stat() here
2090
    // in this macOS specific code block.)
2091
2092
    OUString aDirName;
2093
    struct stat s;
2094
    if( osl::FileBase::getSystemPathFromFileURL( aPath, aDirName ) == osl::FileBase::E_None &&
2095
        stat(OUStringToOString( aDirName, RTL_TEXTENCODING_UTF8).getStr(), &s ) == 0 &&
2096
        S_ISDIR( s.st_mode ) )
2097
        return sal_True;
2098
#endif
2099
2100
    // HACK: create directory on a mount point with nobrowse option
2101
    // returns ENOSYS in any case !!
2102
0
    osl::Directory aDirectory( aPath );
2103
0
    osl::FileBase::RC nError = aDirectory.open();
2104
0
    aDirectory.close();
2105
2106
0
    if( nError == osl::File::E_None )
2107
0
        return true;
2108
2109
0
    nError = osl::Directory::create( aPath );
2110
2111
0
    if( nError == osl::File::E_None )
2112
0
        notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2113
2114
0
    bool  bSuccess = ( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2115
2116
0
    if( ! bSuccess )
2117
0
    {
2118
0
        OUString aParentDir = getParentName( aPath );
2119
2120
0
        if ( aParentDir != aPath )
2121
0
        {   // Create first the parent directory
2122
0
            bSuccess = ensuredir( CommandId,
2123
0
                                  getParentName( aPath ),
2124
0
                                  errorCode );
2125
2126
            // After parent directory structure exists try it one's more
2127
2128
0
            if ( bSuccess )
2129
0
            {   // Parent directory exists, retry creation of directory
2130
0
                nError = osl::Directory::create( aPath );
2131
2132
0
                if( nError == osl::File::E_None )
2133
0
                    notifyInsert( getContentEventListeners( getParentName( aPath ) ),aPath );
2134
2135
0
                bSuccess =( nError == osl::File::E_None || nError == osl::FileBase::E_EXIST );
2136
0
            }
2137
0
        }
2138
0
    }
2139
2140
0
    if( ! bSuccess )
2141
0
        installError( CommandId,
2142
0
                      errorCode,
2143
0
                      nError );
2144
2145
0
    return bSuccess;
2146
0
}
2147
2148
2149
//  Given a sequence of properties seq, this method determines the mask
2150
//  used to instantiate an osl::FileStatus, so that a call to
2151
//  osl::DirectoryItem::getFileStatus fills the required fields.
2152
2153
2154
void
2155
TaskManager::getMaskFromProperties(
2156
    sal_Int32& n_Mask,
2157
    const uno::Sequence< beans::Property >& seq )
2158
106k
{
2159
106k
    n_Mask = 0;
2160
106k
    for(const auto& rProp : seq) {
2161
106k
        if(rProp.Name == Title)
2162
96.5k
            n_Mask |= osl_FileStatus_Mask_FileName;
2163
9.78k
        else if(rProp.Name == CasePreservingURL)
2164
0
            n_Mask |= osl_FileStatus_Mask_FileURL;
2165
9.78k
        else if(rProp.Name == IsDocument ||
2166
9.78k
                rProp.Name == IsFolder ||
2167
0
                rProp.Name == IsVolume ||
2168
0
                rProp.Name == IsRemoveable ||
2169
0
                rProp.Name == IsRemote ||
2170
0
                rProp.Name == IsCompactDisc ||
2171
0
                rProp.Name == IsFloppy ||
2172
0
                rProp.Name == ContentType)
2173
9.78k
            n_Mask |= (osl_FileStatus_Mask_Type | osl_FileStatus_Mask_LinkTargetURL);
2174
0
        else if(rProp.Name == Size)
2175
0
            n_Mask |= (osl_FileStatus_Mask_FileSize |
2176
0
                      osl_FileStatus_Mask_Type |
2177
0
                      osl_FileStatus_Mask_LinkTargetURL);
2178
0
        else if(rProp.Name == IsHidden ||
2179
0
                rProp.Name == IsReadOnly)
2180
0
            n_Mask |= osl_FileStatus_Mask_Attributes;
2181
0
        else if(rProp.Name == DateModified)
2182
0
            n_Mask |= osl_FileStatus_Mask_ModifyTime;
2183
106k
    }
2184
106k
}
2185
2186
2187
/*********************************************************************************/
2188
/*                                                                               */
2189
/*                     load-Implementation                                       */
2190
/*                                                                               */
2191
/*********************************************************************************/
2192
2193
//  Load the properties from configuration, if create == true create them.
2194
//  The Properties are stored under the url belonging to it->first.
2195
2196
2197
void
2198
TaskManager::load( const ContentMap::iterator& it, bool create )
2199
245k
{
2200
245k
    if(  ( it->second.xS.is() && it->second.xC.is() && it->second.xA.is() )
2201
245k
        || !m_xFileRegistry.is() )
2202
245k
        return;
2203
2204
2205
0
    uno::Reference< ucb::XPersistentPropertySet > xS = m_xFileRegistry->openPropertySet( it->first,create );
2206
0
    if( xS.is() )
2207
0
    {
2208
0
        it->second.xS = xS;
2209
0
        it->second.xC.set(xS, uno::UNO_QUERY);
2210
0
        it->second.xA.set(xS, uno::UNO_QUERY);
2211
2212
        // Now put in all values in the storage in the local hash;
2213
2214
0
        PropertySet& properties = it->second.properties;
2215
0
        const uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();
2216
2217
0
        for( const auto& rProp : seq )
2218
0
        {
2219
0
            MyProperty readProp( false,
2220
0
                                 rProp.Name,
2221
0
                                 rProp.Handle,
2222
0
                                 rProp.Type,
2223
0
                                 xS->getPropertyValue( rProp.Name ),
2224
0
                                 beans::PropertyState_DIRECT_VALUE,
2225
0
                                 rProp.Attributes );
2226
0
            properties.insert( readProp );
2227
0
        }
2228
0
    }
2229
0
    else if( create )
2230
0
    {
2231
        // Catastrophic error
2232
0
    }
2233
0
}
2234
2235
2236
/*********************************************************************************/
2237
/*                                                                               */
2238
/*                     commit-Implementation                                     */
2239
/*                                                                               */
2240
/*********************************************************************************/
2241
// Commit inserts the determined properties in the filestatus object into
2242
// the internal map, so that is possible to determine on a subsequent
2243
// setting of file properties which properties have changed without filestat
2244
2245
2246
void
2247
TaskManager::commit( std::unique_lock<std::mutex>& rGuard,
2248
               const TaskManager::ContentMap::iterator& it,
2249
               const osl::FileStatus& aFileStatus )
2250
106k
{
2251
106k
    TaskManager::PropertySet::const_iterator it1;
2252
2253
106k
    if( it->second.properties.empty() )
2254
0
    {
2255
0
        OUString aPath = it->first;
2256
0
        insertDefaultProperties( rGuard, aPath );
2257
0
    }
2258
2259
106k
    PropertySet& properties = it->second.properties;
2260
2261
106k
    it1 = properties.find( MyProperty( Title ) );
2262
106k
    if( it1 != properties.end() )
2263
106k
    {
2264
106k
        if( aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
2265
96.5k
        {
2266
96.5k
            it1->setValue( uno::Any(aFileStatus.getFileName()) );
2267
96.5k
        }
2268
106k
    }
2269
2270
106k
    it1 = properties.find( MyProperty( CasePreservingURL ) );
2271
106k
    if( it1 != properties.end() )
2272
106k
    {
2273
106k
        if( aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) )
2274
96.5k
        {
2275
96.5k
            it1->setValue( uno::Any(aFileStatus.getFileURL()) );
2276
96.5k
        }
2277
106k
    }
2278
2279
2280
106k
    bool isDirectory;
2281
2282
106k
    sal_Int64 dirSize = 0;
2283
2284
106k
    if( aFileStatus.isValid( osl_FileStatus_Mask_FileSize ) )
2285
96.5k
        dirSize = aFileStatus.getFileSize();
2286
2287
106k
    if( aFileStatus.isValid( osl_FileStatus_Mask_Type ) )
2288
106k
    {
2289
106k
        bool isFile,isVolume;
2290
106k
        if( osl::FileStatus::Link == aFileStatus.getFileType() &&
2291
0
            aFileStatus.isValid( osl_FileStatus_Mask_LinkTargetURL ) )
2292
0
        {
2293
0
            osl::DirectoryItem aDirItem;
2294
0
            osl::FileStatus aFileStatus2( osl_FileStatus_Mask_Type );
2295
0
            if( osl::FileBase::E_None == osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(),aDirItem ) &&
2296
0
                osl::FileBase::E_None == aDirItem.getFileStatus( aFileStatus2 )    &&
2297
0
                aFileStatus2.isValid( osl_FileStatus_Mask_Type ) )
2298
0
            {
2299
0
                isVolume = osl::FileStatus::Volume == aFileStatus2.getFileType();
2300
0
                isDirectory =
2301
0
                    osl::FileStatus::Volume == aFileStatus2.getFileType() ||
2302
0
                    osl::FileStatus::Directory == aFileStatus2.getFileType();
2303
0
                isFile =
2304
0
                    osl::FileStatus::Regular == aFileStatus2.getFileType();
2305
2306
0
                if( aFileStatus2.isValid( osl_FileStatus_Mask_FileSize ) )
2307
0
                    dirSize = aFileStatus2.getFileSize();
2308
0
            }
2309
0
            else
2310
0
            {
2311
                // extremely ugly, but otherwise default construction
2312
                // of aDirItem and aFileStatus2
2313
                // before the preceding if
2314
0
                isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2315
0
                isDirectory =
2316
0
                    osl::FileStatus::Volume == aFileStatus.getFileType() ||
2317
0
                    osl::FileStatus::Directory == aFileStatus.getFileType();
2318
0
                isFile =
2319
0
                    osl::FileStatus::Regular == aFileStatus.getFileType();
2320
0
            }
2321
0
        }
2322
106k
        else
2323
106k
        {
2324
106k
            isVolume = osl::FileStatus::Volume == aFileStatus.getFileType();
2325
106k
            isDirectory =
2326
106k
                osl::FileStatus::Volume == aFileStatus.getFileType() ||
2327
106k
                osl::FileStatus::Directory == aFileStatus.getFileType();
2328
106k
            isFile =
2329
106k
                osl::FileStatus::Regular == aFileStatus.getFileType();
2330
106k
        }
2331
2332
106k
        it1 = properties.find( MyProperty( IsVolume ) );
2333
106k
        if( it1 != properties.end() )
2334
106k
            it1->setValue( uno::Any( isVolume ) );
2335
2336
106k
        it1 = properties.find( MyProperty( IsFolder ) );
2337
106k
        if( it1 != properties.end() )
2338
106k
            it1->setValue( uno::Any( isDirectory ) );
2339
2340
106k
        it1 = properties.find( MyProperty( IsDocument ) );
2341
106k
        if( it1 != properties.end() )
2342
106k
            it1->setValue( uno::Any( isFile ) );
2343
2344
106k
        osl::VolumeInfo aVolumeInfo( osl_VolumeInfo_Mask_Attributes );
2345
106k
        if( isVolume &&
2346
0
            osl::FileBase::E_None == osl::Directory::getVolumeInfo( it->first,aVolumeInfo ) &&
2347
0
            aVolumeInfo.isValid( osl_VolumeInfo_Mask_Attributes ) )
2348
0
        {
2349
            // Retrieve the flags;
2350
0
            bool isRemote = aVolumeInfo.getRemoteFlag();
2351
0
            bool isRemoveable = aVolumeInfo.getRemoveableFlag();
2352
0
            bool isCompactDisc = aVolumeInfo.getCompactDiscFlag();
2353
0
            bool isFloppy = aVolumeInfo.getFloppyDiskFlag();
2354
2355
0
            it1 = properties.find( MyProperty( IsRemote ) );
2356
0
            if( it1 != properties.end() )
2357
0
                it1->setValue( uno::Any( isRemote ) );
2358
2359
0
            it1 = properties.find( MyProperty( IsRemoveable ) );
2360
0
            if( it1 != properties.end() )
2361
0
                it1->setValue( uno::Any( isRemoveable ) );
2362
2363
0
            it1 = properties.find( MyProperty( IsCompactDisc ) );
2364
0
            if( it1 != properties.end() )
2365
0
                it1->setValue( uno::Any( isCompactDisc ) );
2366
2367
0
            it1 = properties.find( MyProperty( IsFloppy ) );
2368
0
            if( it1 != properties.end() )
2369
0
                it1->setValue( uno::Any( isFloppy ) );
2370
0
        }
2371
106k
        else
2372
106k
        {
2373
106k
            uno::Any aAny(false);
2374
106k
            it1 = properties.find( MyProperty( IsRemote ) );
2375
106k
            if( it1 != properties.end() )
2376
106k
                it1->setValue( aAny );
2377
2378
106k
            it1 = properties.find( MyProperty( IsRemoveable ) );
2379
106k
            if( it1 != properties.end() )
2380
106k
                it1->setValue( aAny );
2381
2382
106k
            it1 = properties.find( MyProperty( IsCompactDisc ) );
2383
106k
            if( it1 != properties.end() )
2384
106k
                it1->setValue( aAny );
2385
2386
106k
            it1 = properties.find( MyProperty( IsFloppy ) );
2387
106k
            if( it1 != properties.end() )
2388
106k
                it1->setValue( aAny );
2389
106k
        }
2390
106k
    }
2391
0
    else
2392
0
    {
2393
0
        isDirectory = false;
2394
0
    }
2395
2396
106k
    it1 = properties.find( MyProperty( Size ) );
2397
106k
    if( it1 != properties.end() )
2398
106k
        it1->setValue( uno::Any( dirSize ) );
2399
2400
106k
    it1 = properties.find( MyProperty( IsReadOnly ) );
2401
106k
    if( it1 != properties.end() )
2402
106k
    {
2403
106k
        if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2404
106k
        {
2405
106k
            sal_uInt64 Attr = aFileStatus.getAttributes();
2406
106k
            bool readonly = ( Attr & osl_File_Attribute_ReadOnly ) != 0;
2407
106k
            it1->setValue( uno::Any( readonly ) );
2408
106k
        }
2409
106k
    }
2410
2411
106k
    it1 = properties.find( MyProperty( IsHidden ) );
2412
106k
    if( it1 != properties.end() )
2413
106k
    {
2414
106k
        if( aFileStatus.isValid( osl_FileStatus_Mask_Attributes ) )
2415
106k
        {
2416
106k
            sal_uInt64 Attr = aFileStatus.getAttributes();
2417
106k
            bool ishidden = ( Attr & osl_File_Attribute_Hidden ) != 0;
2418
106k
            it1->setValue( uno::Any( ishidden ) );
2419
106k
        }
2420
106k
    }
2421
2422
106k
    it1 = properties.find( MyProperty( DateModified ) );
2423
106k
    if( it1 != properties.end() )
2424
106k
    {
2425
106k
        if( aFileStatus.isValid( osl_FileStatus_Mask_ModifyTime ) )
2426
106k
        {
2427
106k
            TimeValue temp = aFileStatus.getModifyTime();
2428
2429
            // Convert system time to local time (for EA)
2430
106k
            TimeValue myLocalTime;
2431
106k
            if (!osl_getLocalTimeFromSystemTime( &temp, &myLocalTime ))
2432
0
            {
2433
0
                SAL_WARN(
2434
0
                    "ucb.ucp.file",
2435
0
                    "cannot convert (" << temp.Seconds << ", " << temp.Nanosec
2436
0
                        << ") to local time");
2437
0
                myLocalTime = temp;
2438
0
            }
2439
2440
106k
            oslDateTime myDateTime;
2441
106k
            osl_getDateTimeFromTimeValue( &myLocalTime, &myDateTime );
2442
106k
            util::DateTime aDateTime;
2443
2444
106k
            aDateTime.NanoSeconds = myDateTime.NanoSeconds;
2445
106k
            aDateTime.Seconds = myDateTime.Seconds;
2446
106k
            aDateTime.Minutes = myDateTime.Minutes;
2447
106k
            aDateTime.Hours = myDateTime.Hours;
2448
106k
            aDateTime.Day = myDateTime.Day;
2449
106k
            aDateTime.Month = myDateTime.Month;
2450
106k
            aDateTime.Year = myDateTime.Year;
2451
106k
            it1->setValue( uno::Any( aDateTime ) );
2452
106k
        }
2453
106k
    }
2454
2455
106k
    it1 = properties.find( MyProperty( CreatableContentsInfo ) );
2456
106k
    if( it1 != properties.end() )
2457
106k
        it1->setValue( uno::Any(
2458
106k
            isDirectory || !aFileStatus.isValid( osl_FileStatus_Mask_Type )
2459
106k
                ? queryCreatableContentsInfo()
2460
106k
                : uno::Sequence< ucb::ContentInfo >() ) );
2461
106k
}
2462
2463
2464
// Special optimized method for getting the properties of a
2465
// directoryitem, which is returned by osl::DirectoryItem::getNextItem()
2466
2467
2468
bool
2469
TaskManager::getv(
2470
    const uno::Sequence< beans::Property >& properties,
2471
    osl::DirectoryItem& aDirItem,
2472
    OUString& aUnqPath,
2473
    bool& aIsRegular,
2474
    uno::Reference< sdbc::XRow > & row )
2475
96.5k
{
2476
96.5k
    uno::Sequence< uno::Any > seq( properties.getLength() );
2477
2478
96.5k
    sal_Int32 n_Mask;
2479
96.5k
    getMaskFromProperties( n_Mask,properties );
2480
2481
    // Always retrieve the type and the target URL because item might be a link
2482
96.5k
    osl::FileStatus aFileStatus( n_Mask |
2483
96.5k
                                 osl_FileStatus_Mask_FileURL |
2484
96.5k
                                 osl_FileStatus_Mask_Type |
2485
96.5k
                                 osl_FileStatus_Mask_LinkTargetURL );
2486
2487
96.5k
    osl::FileBase::RC aRes = aDirItem.getFileStatus( aFileStatus );
2488
96.5k
    if ( aRes != osl::FileBase::E_None )
2489
0
    {
2490
0
        SAL_WARN(
2491
0
            "ucb.ucp.file",
2492
0
            "osl::DirectoryItem::getFileStatus failed with " << +aRes);
2493
0
        return false;
2494
0
    }
2495
2496
96.5k
    aUnqPath = aFileStatus.getFileURL();
2497
2498
    // If the directory item type is a link retrieve the type of the target
2499
2500
96.5k
    if ( aFileStatus.getFileType() == osl::FileStatus::Link )
2501
0
    {
2502
        // Assume failure
2503
0
        aIsRegular = false;
2504
0
        osl::DirectoryItem aTargetItem;
2505
0
        (void)osl::DirectoryItem::get( aFileStatus.getLinkTargetURL(), aTargetItem );
2506
0
        if ( aTargetItem.is() )
2507
0
        {
2508
0
            osl::FileStatus aTargetStatus( osl_FileStatus_Mask_Type );
2509
2510
0
            if ( osl::FileBase::E_None == aTargetItem.getFileStatus( aTargetStatus ) )
2511
0
                aIsRegular =
2512
0
                    aTargetStatus.getFileType() == osl::FileStatus::Regular;
2513
0
        }
2514
0
    }
2515
96.5k
    else
2516
96.5k
        aIsRegular = aFileStatus.getFileType() == osl::FileStatus::Regular;
2517
2518
96.5k
    {
2519
96.5k
        std::unique_lock aGuard( m_aMutex );
2520
2521
96.5k
        insertDefaultProperties( aGuard, aUnqPath );
2522
2523
96.5k
        TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
2524
96.5k
        commit( aGuard, it, aFileStatus );
2525
2526
96.5k
        PropertySet& propset = it->second.properties;
2527
2528
96.5k
        std::transform(properties.begin(), properties.end(), seq.getArray(),
2529
96.5k
            [&propset](const beans::Property& rProp) -> uno::Any {
2530
96.5k
                MyProperty readProp( rProp.Name );
2531
96.5k
                auto it1 = propset.find( readProp );
2532
96.5k
                if( it1 == propset.end() )
2533
0
                    return uno::Any();
2534
96.5k
                return it1->getValue();
2535
96.5k
            });
2536
96.5k
    }
2537
2538
96.5k
    row = new XRow_impl( this,seq );
2539
96.5k
    return true;
2540
96.5k
}
2541
2542
2543
// EventListener
2544
2545
2546
std::vector< ContentEventNotifier >
2547
TaskManager::getContentEventListeners( const OUString& aName )
2548
0
{
2549
0
    std::vector< ContentEventNotifier > listeners;
2550
0
    {
2551
0
        std::unique_lock aGuard( m_aMutex );
2552
0
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2553
0
        if( it != m_aContent.end() && !it->second.notifier.empty() )
2554
0
        {
2555
0
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2556
0
            for (auto const& pointer : listOfNotifiers)
2557
0
            {
2558
0
                std::optional<ContentEventNotifier> notifier = pointer->cCEL();
2559
0
                if( notifier )
2560
0
                    listeners.push_back( std::move(*notifier) );
2561
0
            }
2562
0
        }
2563
0
    }
2564
0
    return listeners;
2565
0
}
2566
2567
2568
std::vector< ContentEventNotifier >
2569
TaskManager::getContentDeletedEventListeners( const OUString& aName )
2570
0
{
2571
0
    std::vector< ContentEventNotifier > listeners;
2572
0
    {
2573
0
        std::unique_lock aGuard( m_aMutex );
2574
0
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2575
0
        if( it != m_aContent.end() && !it->second.notifier.empty() )
2576
0
        {
2577
0
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2578
0
            for (auto const& pointer : listOfNotifiers)
2579
0
            {
2580
0
                std::optional<ContentEventNotifier> notifier = pointer->cDEL();
2581
0
                if( notifier )
2582
0
                    listeners.push_back( std::move(*notifier) );
2583
0
            }
2584
0
        }
2585
0
    }
2586
0
    return listeners;
2587
0
}
2588
2589
void TaskManager::notifyInsert(const std::vector<ContentEventNotifier>& listeners,
2590
                               const OUString& aChildName)
2591
0
{
2592
0
    for (const auto & l : listeners )
2593
0
    {
2594
0
        l.notifyChildInserted( aChildName );
2595
0
    }
2596
0
}
2597
2598
void TaskManager::notifyContentDeleted(
2599
    const std::vector<ContentEventNotifier>& listeners)
2600
0
{
2601
0
    for( auto const & l : listeners )
2602
0
    {
2603
0
        l.notifyDeleted();
2604
0
    }
2605
0
}
2606
2607
void TaskManager::notifyContentRemoved(
2608
    const std::vector<ContentEventNotifier>& listeners, const OUString& aChildName)
2609
0
{
2610
0
    for( auto const & l : listeners )
2611
0
    {
2612
0
        l.notifyRemoved( aChildName );
2613
0
    }
2614
0
}
2615
2616
2617
std::vector< PropertySetInfoChangeNotifier >
2618
TaskManager::getPropertySetListeners( const OUString& aName )
2619
0
{
2620
0
    std::vector< PropertySetInfoChangeNotifier > listeners;
2621
0
    {
2622
0
        std::unique_lock aGuard( m_aMutex );
2623
0
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2624
0
        if( it != m_aContent.end() && !it->second.notifier.empty() )
2625
0
        {
2626
0
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2627
0
            for (auto const& pointer : listOfNotifiers)
2628
0
            {
2629
0
                std::optional<PropertySetInfoChangeNotifier> notifier = pointer->cPSL();
2630
0
                if( notifier )
2631
0
                    listeners.push_back( std::move(*notifier) );
2632
0
            }
2633
0
        }
2634
0
    }
2635
0
    return listeners;
2636
0
}
2637
2638
void TaskManager::notifyPropertyAdded(
2639
    const std::vector<PropertySetInfoChangeNotifier>& listeners,
2640
    const OUString& aPropertyName)
2641
0
{
2642
0
    for( auto const & l : listeners )
2643
0
    {
2644
0
        l.notifyPropertyAdded( aPropertyName );
2645
0
    }
2646
0
}
2647
2648
void TaskManager::notifyPropertyRemoved(
2649
    const std::vector<PropertySetInfoChangeNotifier>& listeners,
2650
    const OUString& aPropertyName)
2651
0
{
2652
0
    for( auto const & l : listeners )
2653
0
    {
2654
0
        l.notifyPropertyRemoved( aPropertyName );
2655
0
    }
2656
0
}
2657
2658
2659
std::vector< ContentEventNotifier >
2660
TaskManager::getContentExchangedEventListeners( const OUString& aOldPrefix,
2661
                                          const OUString& aNewPrefix,
2662
                                          bool withChildren )
2663
0
{
2664
0
    std::vector< ContentEventNotifier > aVector;
2665
2666
0
    sal_Int32 count;
2667
0
    OUString aOldName;
2668
0
    OUString aNewName;
2669
0
    std::vector< OUString > oldChildList;
2670
2671
0
    {
2672
0
        std::unique_lock aGuard( m_aMutex );
2673
2674
0
        if( ! withChildren )
2675
0
        {
2676
0
            aOldName = aOldPrefix;
2677
0
            aNewName = aNewPrefix;
2678
0
            count = 1;
2679
0
        }
2680
0
        else
2681
0
        {
2682
0
            for (auto const& content : m_aContent)
2683
0
            {
2684
0
                if( isChild( aOldPrefix, content.first ) )
2685
0
                {
2686
0
                    oldChildList.push_back( content.first );
2687
0
                }
2688
0
            }
2689
0
            count = oldChildList.size();
2690
0
        }
2691
2692
2693
0
        for( sal_Int32 j = 0; j < count; ++j )
2694
0
        {
2695
0
            if( withChildren )
2696
0
            {
2697
0
                aOldName = oldChildList[j];
2698
0
                aNewName = newName( aNewPrefix,aOldPrefix,aOldName );
2699
0
            }
2700
2701
0
            TaskManager::ContentMap::iterator itold = m_aContent.find( aOldName );
2702
0
            if( itold != m_aContent.end() )
2703
0
            {
2704
0
                TaskManager::ContentMap::iterator itnew = m_aContent.emplace(
2705
0
                    aNewName,UnqPathData() ).first;
2706
2707
                // copy Ownership also
2708
0
                itnew->second.properties = std::move(itold->second.properties);
2709
2710
                // copy existing list
2711
0
                std::vector< Notifier* > copyList;
2712
0
                std::swap(copyList, itnew->second.notifier);
2713
0
                itnew->second.notifier = std::move(itold->second.notifier);
2714
2715
0
                m_aContent.erase( itold );
2716
2717
0
                if (itnew != m_aContent.end())
2718
0
                {
2719
0
                    if (!itnew->second.notifier.empty())
2720
0
                    {
2721
0
                        std::vector<Notifier*>& listOfNotifiers = itnew->second.notifier;
2722
0
                        for (auto const& pointer : listOfNotifiers)
2723
0
                        {
2724
0
                            std::optional<ContentEventNotifier> notifier = pointer->cEXC( aNewName );
2725
0
                            if( notifier )
2726
0
                                aVector.push_back( std::move(*notifier) );
2727
0
                        }
2728
0
                    }
2729
2730
                    // Merge with preexisting notifiers
2731
                    // However, these may be in status BaseContent::Deleted
2732
0
                    itnew->second.notifier.insert(itnew->second.notifier.end(),
2733
0
                        copyList.begin(), copyList.end() );
2734
0
                }
2735
0
            }
2736
0
        }
2737
0
    }
2738
2739
0
    return aVector;
2740
0
}
2741
2742
void TaskManager::notifyContentExchanged(
2743
    const std::vector<ContentEventNotifier>& listeners_vec)
2744
0
{
2745
0
    for( auto & l : listeners_vec)
2746
0
    {
2747
0
        l.notifyExchanged();
2748
0
    }
2749
0
}
2750
2751
2752
std::vector< PropertyChangeNotifier >
2753
TaskManager::getPropertyChangeNotifier( const OUString& aName )
2754
0
{
2755
0
    std::vector< PropertyChangeNotifier > listeners;
2756
0
    {
2757
0
        std::unique_lock aGuard( m_aMutex );
2758
0
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
2759
0
        if( it != m_aContent.end() && !it->second.notifier.empty() )
2760
0
        {
2761
0
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
2762
0
            for (auto const& pointer : listOfNotifiers)
2763
0
            {
2764
0
                std::optional<PropertyChangeNotifier> notifier = pointer->cPCL();
2765
0
                if( notifier )
2766
0
                    listeners.push_back( std::move(*notifier) );
2767
0
            }
2768
0
        }
2769
0
    }
2770
0
    return listeners;
2771
0
}
2772
2773
void TaskManager::notifyPropertyChanges(
2774
    const std::vector<PropertyChangeNotifier>& listeners,
2775
    const uno::Sequence<beans::PropertyChangeEvent>& seqChanged)
2776
0
{
2777
0
    for( auto const & l : listeners )
2778
0
    {
2779
0
        l.notifyPropertyChanged( seqChanged );
2780
0
    }
2781
0
}
2782
2783
2784
/********************************************************************************/
2785
/*                       remove persistent propertyset                          */
2786
/********************************************************************************/
2787
2788
void
2789
TaskManager::erasePersistentSetWithoutChildren( const OUString& aUnqPath )
2790
0
{
2791
0
    {
2792
        // Release possible references
2793
0
        std::unique_lock aGuard( m_aMutex );
2794
0
        ContentMap::iterator it = m_aContent.find( aUnqPath );
2795
0
        if( it != m_aContent.end() )
2796
0
        {
2797
0
            it->second.xS = nullptr;
2798
0
            it->second.xC = nullptr;
2799
0
            it->second.xA = nullptr;
2800
2801
0
            it->second.properties.clear();
2802
0
        }
2803
0
    }
2804
2805
0
    m_xFileRegistry->removePropertySet( aUnqPath );
2806
0
}
2807
2808
void
2809
TaskManager::erasePersistentSet( const OUString& aUnqPath,
2810
                           bool withChildren )
2811
0
{
2812
0
    if( ! m_xFileRegistry.is() )
2813
0
    {
2814
0
        OSL_ASSERT( m_xFileRegistry.is() );
2815
0
        return;
2816
0
    }
2817
2818
0
    if( ! withChildren )
2819
0
    {
2820
0
        erasePersistentSetWithoutChildren(aUnqPath);
2821
0
        return;
2822
0
    }
2823
2824
0
    uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2825
0
    const uno::Sequence< OUString > seqNames = xName->getElementNames();
2826
2827
0
    OUString old_Name = aUnqPath;
2828
2829
0
    for( const auto& rName : seqNames )
2830
0
    {
2831
0
        if( ! ( isChild( old_Name,rName ) ) )
2832
0
            continue;
2833
2834
0
        old_Name = rName;
2835
2836
0
        erasePersistentSetWithoutChildren(old_Name);
2837
0
    }
2838
0
}
2839
2840
2841
/********************************************************************************/
2842
/*                       copy persistent propertyset                            */
2843
/*                       from srcUnqPath to dstUnqPath                          */
2844
/********************************************************************************/
2845
2846
void
2847
TaskManager::copyPersistentSetWithoutChildren( const OUString& srcUnqPath,
2848
                          const OUString& dstUnqPath )
2849
0
{
2850
0
    uno::Reference< XPersistentPropertySet > x_src =
2851
0
            m_xFileRegistry->openPropertySet( srcUnqPath,false );
2852
0
    m_xFileRegistry->removePropertySet( dstUnqPath );
2853
2854
0
    if( ! x_src.is() )
2855
0
        return;
2856
2857
0
    const uno::Sequence< beans::Property > seqProperty =
2858
0
        x_src->getPropertySetInfo()->getProperties();
2859
2860
0
    if( ! seqProperty.hasElements() )
2861
0
        return;
2862
2863
0
    uno::Reference< XPersistentPropertySet >
2864
0
        x_dstS = m_xFileRegistry->openPropertySet( dstUnqPath,true );
2865
0
    uno::Reference< beans::XPropertyContainer >
2866
0
        x_dstC( x_dstS,uno::UNO_QUERY );
2867
2868
0
    for( const auto& rProperty : seqProperty )
2869
0
    {
2870
0
        x_dstC->addProperty( rProperty.Name,
2871
0
                             rProperty.Attributes,
2872
0
                             x_src->getPropertyValue( rProperty.Name ) );
2873
0
    }
2874
0
}
2875
2876
void
2877
TaskManager::copyPersistentSet( const OUString& srcUnqPath,
2878
                          const OUString& dstUnqPath,
2879
                          bool withChildren )
2880
0
{
2881
0
    if( ! m_xFileRegistry.is() )
2882
0
    {
2883
0
        OSL_ASSERT( m_xFileRegistry.is() );
2884
0
        return;
2885
0
    }
2886
2887
0
    if( ! withChildren )
2888
0
    {
2889
0
        copyPersistentSetWithoutChildren(srcUnqPath, dstUnqPath);
2890
0
        return;
2891
0
    }
2892
2893
0
    uno::Reference< container::XNameAccess > xName( m_xFileRegistry,uno::UNO_QUERY );
2894
0
    const uno::Sequence< OUString > seqNames = xName->getElementNames();
2895
2896
0
    OUString new_Name;
2897
2898
0
    for( const auto& rName : seqNames )
2899
0
    {
2900
0
        if( ! ( isChild( srcUnqPath,rName ) ) )
2901
0
            continue;
2902
2903
0
        new_Name = newName( dstUnqPath,srcUnqPath,rName );
2904
2905
0
        copyPersistentSetWithoutChildren(rName, new_Name);
2906
0
    }
2907
0
}
2908
2909
uno::Sequence< ucb::ContentInfo > TaskManager::queryCreatableContentsInfo()
2910
9.78k
{
2911
2912
2913
9.78k
    uno::Sequence< beans::Property > props
2914
9.78k
    {
2915
9.78k
        { u"Title"_ustr, -1, cppu::UnoType<OUString>::get(), beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND }
2916
9.78k
    };
2917
9.78k
    return
2918
9.78k
    {
2919
9.78k
        { FileContentType, ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM | ucb::ContentInfoAttribute::KIND_DOCUMENT, props },
2920
9.78k
        { FolderContentType, ucb::ContentInfoAttribute::KIND_FOLDER, props }
2921
9.78k
    };
2922
9.78k
}
2923
2924
/*******************************************************************************/
2925
/*                                                                             */
2926
/*                 some miscellaneous static functions                        */
2927
/*                                                                             */
2928
/*******************************************************************************/
2929
2930
void
2931
TaskManager::getScheme( OUString& Scheme )
2932
187k
{
2933
187k
  Scheme = "file";
2934
187k
}
2935
2936
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */