Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svl/source/fsstor/fsstorage.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <com/sun/star/embed/ElementModes.hpp>
21
#include <com/sun/star/embed/InvalidStorageException.hpp>
22
#include <com/sun/star/embed/StorageWrappedTargetException.hpp>
23
#include <com/sun/star/embed/XTransactedObject.hpp>
24
#include <com/sun/star/packages/NoEncryptionException.hpp>
25
#include <com/sun/star/packages/WrongPasswordException.hpp>
26
#include <com/sun/star/ucb/NameClash.hpp>
27
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
28
29
#include <com/sun/star/ucb/InteractiveIOException.hpp>
30
#include <com/sun/star/ucb/IOErrorCode.hpp>
31
#include <com/sun/star/container/ElementExistException.hpp>
32
#include <com/sun/star/lang/XComponent.hpp>
33
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
34
#include <com/sun/star/io/IOException.hpp>
35
#include <com/sun/star/io/XTruncate.hpp>
36
#include <com/sun/star/io/TempFile.hpp>
37
#include <com/sun/star/sdbc/XResultSet.hpp>
38
#include <com/sun/star/sdbc/XRow.hpp>
39
40
#include <comphelper/fileurl.hxx>
41
#include <comphelper/processfactory.hxx>
42
#include <comphelper/storagehelper.hxx>
43
#include <cppuhelper/queryinterface.hxx>
44
#include <cppuhelper/exc_hlp.hxx>
45
46
#include <osl/diagnose.h>
47
#include <tools/stream.hxx>
48
#include <tools/urlobj.hxx>
49
#include <unotools/ucbhelper.hxx>
50
#include <unotools/ucbstreamhelper.hxx>
51
#include <unotools/streamwrap.hxx>
52
#include <unotools/tempfile.hxx>
53
#include <ucbhelper/content.hxx>
54
55
#include "fsstorage.hxx"
56
#include "oinputstreamcontainer.hxx"
57
#include "ostreamcontainer.hxx"
58
59
using namespace ::com::sun::star;
60
61
FSStorage::FSStorage( const ::ucbhelper::Content& aContent,
62
                    sal_Int32 nMode,
63
                    uno::Reference< uno::XComponentContext > const & xContext )
64
0
: m_aURL( aContent.getURL() )
65
0
, m_aContent( aContent )
66
0
, m_nMode( nMode )
67
0
, m_xContext( xContext )
68
0
{
69
0
    OSL_ENSURE( !m_aURL.isEmpty(), "The URL must not be empty" );
70
    // TODO: use properties
71
0
    if ( !xContext.is() )
72
0
        throw uno::RuntimeException();
73
74
0
    GetContent();
75
0
}
76
77
FSStorage::~FSStorage()
78
0
{
79
0
    std::unique_lock aGuard( m_aMutex );
80
0
    osl_atomic_increment(&m_refCount); // to call dispose
81
0
    try {
82
0
        disposeImpl(aGuard);
83
0
    }
84
0
    catch( uno::RuntimeException& )
85
0
    {}
86
0
}
87
88
bool FSStorage::MakeFolderNoUI( std::u16string_view rFolder )
89
0
{
90
0
    INetURLObject aURL( rFolder );
91
0
    OUString aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
92
0
    aURL.removeSegment();
93
0
    ::ucbhelper::Content aParent;
94
0
    ::ucbhelper::Content aResultContent;
95
96
0
    if ( ::ucbhelper::Content::create( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
97
0
                                 uno::Reference< ucb::XCommandEnvironment >(),
98
0
                                 comphelper::getProcessComponentContext(),
99
0
                                 aParent ) )
100
0
        return ::utl::UCBContentHelper::MakeFolder( aParent, aTitle, aResultContent );
101
102
0
    return false;
103
0
}
104
105
ucbhelper::Content& FSStorage::GetContent()
106
0
{
107
0
    std::unique_lock aGuard( m_aMutex );
108
0
    return m_aContent;
109
0
}
110
111
void FSStorage::CopyStreamToSubStream( const OUString& aSourceURL,
112
                                        const uno::Reference< embed::XStorage >& xDest,
113
                                        const OUString& aNewEntryName )
114
0
{
115
0
    if ( !xDest.is() )
116
0
        throw uno::RuntimeException();
117
118
0
    uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
119
0
    ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() );
120
0
    uno::Reference< io::XInputStream > xSourceInput = aSourceContent.openStream();
121
122
0
    if ( !xSourceInput.is() )
123
0
        throw io::IOException(); // TODO: error handling
124
125
0
    uno::Reference< io::XStream > xSubStream = xDest->openStreamElement(
126
0
                                                aNewEntryName,
127
0
                                                embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
128
0
    if ( !xSubStream.is() )
129
0
        throw uno::RuntimeException();
130
131
0
    uno::Reference< io::XOutputStream > xDestOutput = xSubStream->getOutputStream();
132
0
    if ( !xDestOutput.is() )
133
0
        throw uno::RuntimeException();
134
135
0
    ::comphelper::OStorageHelper::CopyInputToOutput( xSourceInput, xDestOutput );
136
0
    xDestOutput->closeOutput();
137
0
}
138
139
void FSStorage::CopyContentToStorage_Impl(ucbhelper::Content& rContent,
140
                                          const uno::Reference<embed::XStorage>& xDest)
141
0
{
142
    // get list of contents of the Content
143
    // create cursor for access to children
144
0
    uno::Sequence< OUString > aProps( 2 );
145
0
    OUString* pProps = aProps.getArray();
146
0
    pProps[0] = "TargetURL";
147
0
    pProps[1] = "IsFolder";
148
149
0
    try
150
0
    {
151
0
        uno::Reference<sdbc::XResultSet> xResultSet
152
0
            = rContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
153
0
        uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
154
0
        if ( xResultSet.is() )
155
0
        {
156
            // go through the list: insert files as streams, insert folders as substorages using recursion
157
0
            while ( xResultSet->next() )
158
0
            {
159
0
                OUString aSourceURL( xRow->getString( 1 ) );
160
0
                bool bIsFolder( xRow->getBoolean(2) );
161
162
                // TODO/LATER: not sure whether the entry name must be encoded
163
0
                OUString aNewEntryName( INetURLObject( aSourceURL ).getName( INetURLObject::LAST_SEGMENT,
164
0
                                                                                    true,
165
0
                                                                                    INetURLObject::DecodeMechanism::NONE ) );
166
0
                if ( bIsFolder )
167
0
                {
168
0
                    uno::Reference< embed::XStorage > xSubStorage = xDest->openStorageElement( aNewEntryName,
169
0
                                                                                                embed::ElementModes::READWRITE );
170
0
                    if ( !xSubStorage.is() )
171
0
                        throw uno::RuntimeException();
172
173
0
                    uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
174
0
                    ::ucbhelper::Content aSourceContent( aSourceURL, xDummyEnv, comphelper::getProcessComponentContext() );
175
0
                    CopyContentToStorage_Impl( aSourceContent, xSubStorage );
176
0
                }
177
0
                else
178
0
                {
179
0
                    CopyStreamToSubStream( aSourceURL, xDest, aNewEntryName );
180
0
                }
181
0
            }
182
0
        }
183
184
0
        uno::Reference< embed::XTransactedObject > xTransact( xDest, uno::UNO_QUERY );
185
0
        if ( xTransact.is() )
186
0
            xTransact->commit();
187
0
    }
188
0
    catch( ucb::InteractiveIOException& r )
189
0
    {
190
0
        if ( r.Code == ucb::IOErrorCode_NOT_EXISTING )
191
0
            OSL_FAIL( "The folder does not exist!" );
192
0
        else
193
0
            throw;
194
0
    }
195
0
}
196
197
//  XInterface
198
199
uno::Any SAL_CALL FSStorage::queryInterface( const uno::Type& rType )
200
0
{
201
0
    uno::Any aReturn = ::cppu::queryInterface
202
0
                (   rType
203
0
                ,   static_cast<lang::XTypeProvider*> ( this )
204
0
                ,   static_cast<embed::XStorage*> ( this )
205
0
                ,   static_cast<embed::XHierarchicalStorageAccess*> ( this )
206
0
                ,   static_cast<container::XNameAccess*> ( this )
207
0
                ,   static_cast<container::XElementAccess*> ( this )
208
0
                ,   static_cast<lang::XComponent*> ( this )
209
0
                ,   static_cast<beans::XPropertySet*> ( this ) );
210
211
0
    if ( aReturn.hasValue() )
212
0
        return aReturn ;
213
214
0
    return OWeakObject::queryInterface( rType );
215
0
}
216
217
void SAL_CALL FSStorage::acquire() noexcept
218
0
{
219
0
    OWeakObject::acquire();
220
0
}
221
222
void SAL_CALL FSStorage::release() noexcept
223
0
{
224
0
    OWeakObject::release();
225
0
}
226
227
//  XTypeProvider
228
229
uno::Sequence< uno::Type > SAL_CALL FSStorage::getTypes()
230
0
{
231
0
    static const uno::Sequence<uno::Type> aTypes {
232
0
        cppu::UnoType<lang::XTypeProvider>::get(),
233
0
        cppu::UnoType<embed::XStorage>::get(),
234
0
        cppu::UnoType<embed::XHierarchicalStorageAccess>::get(),
235
0
        cppu::UnoType<beans::XPropertySet>::get() };
236
0
    return aTypes;
237
0
}
238
239
uno::Sequence< sal_Int8 > SAL_CALL FSStorage::getImplementationId()
240
0
{
241
0
    return css::uno::Sequence<sal_Int8>();
242
0
}
243
244
//  XStorage
245
246
void SAL_CALL FSStorage::copyToStorage( const uno::Reference< embed::XStorage >& xDest )
247
0
{
248
0
    std::unique_lock aGuard( m_aMutex );
249
250
0
    if ( !xDest.is() || xDest == getXWeak() )
251
0
        throw lang::IllegalArgumentException(); // TODO:
252
253
0
    try
254
0
    {
255
0
        CopyContentToStorage_Impl( m_aContent, xDest );
256
0
    }
257
0
    catch( embed::InvalidStorageException& )
258
0
    {
259
0
        throw;
260
0
    }
261
0
    catch( lang::IllegalArgumentException& )
262
0
    {
263
0
        throw;
264
0
    }
265
0
    catch( embed::StorageWrappedTargetException& )
266
0
    {
267
0
        throw;
268
0
    }
269
0
    catch( io::IOException& )
270
0
    {
271
0
        throw;
272
0
    }
273
0
    catch( uno::RuntimeException& )
274
0
    {
275
0
        throw;
276
0
    }
277
0
    catch( uno::Exception& )
278
0
    {
279
0
        uno::Any aCaught( ::cppu::getCaughtException() );
280
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
281
0
                                                 uno::Reference< io::XInputStream >(),
282
0
                                                 aCaught );
283
0
    }
284
0
}
285
286
uno::Reference< io::XStream > SAL_CALL FSStorage::openStreamElement(
287
    const OUString& aStreamName, sal_Int32 nOpenMode )
288
0
{
289
0
    std::unique_lock aGuard( m_aMutex );
290
0
    return openStreamElementImpl(aGuard, aStreamName, nOpenMode);
291
0
}
292
293
uno::Reference< io::XStream > FSStorage::openStreamElementImpl(
294
    std::unique_lock<std::mutex>& /*rGuard*/,
295
    std::u16string_view aStreamName, sal_Int32 nOpenMode )
296
0
{
297
    // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
298
0
    INetURLObject aFileURL( m_aURL );
299
0
    aFileURL.Append( aStreamName );
300
301
0
    if ( ::utl::UCBContentHelper::IsFolder( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
302
0
        throw io::IOException();
303
304
0
    if ( ( nOpenMode & embed::ElementModes::NOCREATE )
305
0
      && !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
306
0
        throw io::IOException(); // TODO:
307
308
0
    uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
309
0
    uno::Reference< io::XStream > xResult;
310
0
    try
311
0
    {
312
0
        if ( nOpenMode & embed::ElementModes::WRITE )
313
0
        {
314
0
            if ( aFileURL.GetProtocol() == INetProtocol::File )
315
0
            {
316
0
                uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
317
0
                    ucb::SimpleFileAccess::create( m_xContext ) );
318
0
                xResult = xSimpleFileAccess->openFileReadWrite( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
319
0
            }
320
0
            else
321
0
            {
322
                // TODO: test whether it really works for http and fwp
323
0
                std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
324
0
                                                                          StreamMode::STD_WRITE );
325
0
                if ( pStream && !pStream->GetError() )
326
0
                    xResult.set( new ::utl::OStreamWrapper( std::move(pStream) ) );
327
0
            }
328
329
0
            if ( !xResult.is() )
330
0
                throw io::IOException();
331
332
0
            if ( nOpenMode & embed::ElementModes::TRUNCATE )
333
0
            {
334
0
                uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW );
335
0
                xTrunc->truncate();
336
0
            }
337
0
        }
338
0
        else
339
0
        {
340
0
            if ( ( nOpenMode & embed::ElementModes::TRUNCATE )
341
0
              || !::utl::UCBContentHelper::IsDocument( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
342
0
                throw io::IOException(); // TODO: access denied
343
344
0
            ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
345
0
            uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
346
0
            xResult = new OFSInputStreamContainer(xInStream);
347
0
        }
348
0
    }
349
0
    catch( embed::InvalidStorageException& )
350
0
    {
351
0
        throw;
352
0
    }
353
0
    catch( lang::IllegalArgumentException& )
354
0
    {
355
0
        throw;
356
0
    }
357
0
    catch( packages::WrongPasswordException& )
358
0
    {
359
0
        throw;
360
0
    }
361
0
    catch( embed::StorageWrappedTargetException& )
362
0
    {
363
0
        throw;
364
0
    }
365
0
    catch( io::IOException& )
366
0
    {
367
0
        throw;
368
0
    }
369
0
    catch( uno::RuntimeException& )
370
0
    {
371
0
        throw;
372
0
    }
373
0
    catch( uno::Exception& )
374
0
    {
375
0
        uno::Any aCaught( ::cppu::getCaughtException() );
376
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
377
0
                                                 uno::Reference< io::XInputStream >(),
378
0
                                                 aCaught );
379
0
    }
380
381
0
    return xResult;
382
0
}
383
384
uno::Reference< io::XStream > SAL_CALL FSStorage::openEncryptedStreamElement(
385
    const OUString&, sal_Int32, const OUString& )
386
0
{
387
0
    throw packages::NoEncryptionException();
388
0
}
389
390
uno::Reference< embed::XStorage > SAL_CALL FSStorage::openStorageElement(
391
            const OUString& aStorName, sal_Int32 nStorageMode )
392
0
{
393
0
    std::unique_lock aGuard( m_aMutex );
394
0
    return openStorageElementImpl(aGuard, aStorName, nStorageMode);
395
0
}
396
397
uno::Reference< embed::XStorage > FSStorage::openStorageElementImpl(
398
            std::unique_lock<std::mutex>& /*rGuard*/,
399
            std::u16string_view aStorName, sal_Int32 nStorageMode )
400
0
{
401
0
    if ( ( nStorageMode & embed::ElementModes::WRITE )
402
0
      && !( m_nMode & embed::ElementModes::WRITE ) )
403
0
          throw io::IOException(); // TODO: error handling
404
405
    // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
406
0
    INetURLObject aFolderURL( m_aURL );
407
0
    aFolderURL.Append( aStorName );
408
409
0
    bool bFolderExists = ::utl::UCBContentHelper::IsFolder( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
410
0
    if ( !bFolderExists && ::utl::UCBContentHelper::IsDocument( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
411
0
        throw io::IOException(); // TODO:
412
413
0
    if ( ( nStorageMode & embed::ElementModes::NOCREATE ) && !bFolderExists )
414
0
        throw io::IOException(); // TODO:
415
416
0
    uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
417
0
    rtl::Reference< FSStorage > xResult;
418
0
    try
419
0
    {
420
0
        if ( nStorageMode & embed::ElementModes::WRITE )
421
0
        {
422
0
            if ( ( nStorageMode & embed::ElementModes::TRUNCATE ) && bFolderExists )
423
0
            {
424
0
                ::utl::UCBContentHelper::Kill( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
425
0
                bFolderExists =
426
0
                    MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :(
427
0
            }
428
0
            else if ( !bFolderExists )
429
0
            {
430
0
                bFolderExists =
431
0
                    MakeFolderNoUI( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ); // TODO: not atomic :(
432
0
            }
433
0
        }
434
0
        else if ( nStorageMode & embed::ElementModes::TRUNCATE )
435
0
            throw io::IOException(); // TODO: access denied
436
437
0
        if ( !bFolderExists )
438
0
            throw io::IOException(); // there is no such folder
439
440
0
        ::ucbhelper::Content aResultContent( aFolderURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
441
0
        xResult = new FSStorage( aResultContent, nStorageMode, m_xContext );
442
0
    }
443
0
    catch( embed::InvalidStorageException& )
444
0
    {
445
0
        throw;
446
0
    }
447
0
    catch( lang::IllegalArgumentException& )
448
0
    {
449
0
        throw;
450
0
    }
451
0
    catch( embed::StorageWrappedTargetException& )
452
0
    {
453
0
        throw;
454
0
    }
455
0
    catch( io::IOException& )
456
0
    {
457
0
        throw;
458
0
    }
459
0
    catch( uno::RuntimeException& )
460
0
    {
461
0
        throw;
462
0
    }
463
0
    catch( uno::Exception& )
464
0
    {
465
0
        uno::Any aCaught( ::cppu::getCaughtException() );
466
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
467
0
                                                 uno::Reference< io::XInputStream >(),
468
0
                                                 aCaught );
469
0
    }
470
471
0
    return xResult;
472
0
}
473
474
uno::Reference< io::XStream > SAL_CALL FSStorage::cloneStreamElement( const OUString& aStreamName )
475
0
{
476
0
    std::unique_lock aGuard( m_aMutex );
477
478
    // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
479
0
    INetURLObject aFileURL( m_aURL );
480
0
    aFileURL.Append( aStreamName );
481
482
0
    rtl::Reference < utl::TempFileFastService > xTempResult;
483
0
    try
484
0
    {
485
0
        uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
486
0
        ::ucbhelper::Content aResultContent( aFileURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
487
0
        uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
488
489
0
        xTempResult = new utl::TempFileFastService;
490
0
        uno::Reference < io::XOutputStream > xTempOut = xTempResult->getOutputStream();
491
0
        uno::Reference < io::XInputStream > xTempIn = xTempResult->getInputStream();
492
493
0
        ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut );
494
0
        xTempOut->closeOutput();
495
0
    }
496
0
    catch( embed::InvalidStorageException& )
497
0
    {
498
0
        throw;
499
0
    }
500
0
    catch( lang::IllegalArgumentException& )
501
0
    {
502
0
        throw;
503
0
    }
504
0
    catch( packages::WrongPasswordException& )
505
0
    {
506
0
        throw;
507
0
    }
508
0
    catch( io::IOException& )
509
0
    {
510
0
        throw;
511
0
    }
512
0
    catch( embed::StorageWrappedTargetException& )
513
0
    {
514
0
        throw;
515
0
    }
516
0
    catch( uno::RuntimeException& )
517
0
    {
518
0
        throw;
519
0
    }
520
0
    catch( uno::Exception& )
521
0
    {
522
0
        uno::Any aCaught( ::cppu::getCaughtException() );
523
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
524
0
                                                 uno::Reference< io::XInputStream >(),
525
0
                                                 aCaught );
526
0
    }
527
528
0
    return xTempResult;
529
0
}
530
531
uno::Reference< io::XStream > SAL_CALL FSStorage::cloneEncryptedStreamElement(
532
    const OUString&,
533
    const OUString& )
534
0
{
535
0
    throw packages::NoEncryptionException();
536
0
}
537
538
void SAL_CALL FSStorage::copyLastCommitTo(
539
            const uno::Reference< embed::XStorage >& xTargetStorage )
540
0
{
541
0
    copyToStorage( xTargetStorage );
542
0
}
543
544
void SAL_CALL FSStorage::copyStorageElementLastCommitTo(
545
            const OUString& aStorName,
546
            const uno::Reference< embed::XStorage >& xTargetStorage )
547
0
{
548
0
    std::unique_lock aGuard( m_aMutex );
549
550
0
    uno::Reference< embed::XStorage > xSourceStor( openStorageElementImpl(aGuard, aStorName, embed::ElementModes::READ),
551
0
                                                    uno::UNO_SET_THROW );
552
0
    xSourceStor->copyToStorage( xTargetStorage );
553
0
}
554
555
sal_Bool SAL_CALL FSStorage::isStreamElement( const OUString& aElementName )
556
0
{
557
0
    std::unique_lock aGuard( m_aMutex );
558
559
0
    INetURLObject aURL( m_aURL );
560
0
    aURL.Append( aElementName );
561
562
0
    return !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
563
0
}
564
565
sal_Bool SAL_CALL FSStorage::isStorageElement( const OUString& aElementName )
566
0
{
567
0
    std::unique_lock aGuard( m_aMutex );
568
569
0
    INetURLObject aURL( m_aURL );
570
0
    aURL.Append( aElementName );
571
572
0
    return ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
573
0
}
574
575
void SAL_CALL FSStorage::removeElement( const OUString& aElementName )
576
0
{
577
0
    std::unique_lock aGuard( m_aMutex );
578
579
0
    INetURLObject aURL( m_aURL );
580
0
    aURL.Append( aElementName );
581
582
0
    if ( !::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
583
0
      && !::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
584
0
        throw container::NoSuchElementException(); // TODO:
585
586
0
    ::utl::UCBContentHelper::Kill( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
587
0
}
588
589
void SAL_CALL FSStorage::renameElement( const OUString& aElementName, const OUString& aNewName )
590
0
{
591
0
    std::unique_lock aGuard( m_aMutex );
592
593
0
    INetURLObject aOldURL( m_aURL );
594
0
    aOldURL.Append( aElementName );
595
596
0
    INetURLObject aNewURL( m_aURL );
597
0
    aNewURL.Append( aNewName );
598
599
0
    if ( !::utl::UCBContentHelper::IsFolder( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
600
0
      && !::utl::UCBContentHelper::IsDocument( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
601
0
        throw container::NoSuchElementException(); // TODO:
602
603
0
    if ( ::utl::UCBContentHelper::IsFolder( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
604
0
      || ::utl::UCBContentHelper::IsDocument( aNewURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
605
0
          throw container::ElementExistException(); // TODO:
606
607
0
    try
608
0
    {
609
0
        uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
610
0
        ::ucbhelper::Content aSourceContent( aOldURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
611
612
0
        m_aContent.transferContent(aSourceContent, ::ucbhelper::InsertOperation::Move, aNewName,
613
0
                                     ucb::NameClash::ERROR);
614
0
    }
615
0
    catch( embed::InvalidStorageException& )
616
0
    {
617
0
        throw;
618
0
    }
619
0
    catch( lang::IllegalArgumentException& )
620
0
    {
621
0
        throw;
622
0
    }
623
0
    catch( container::NoSuchElementException& )
624
0
    {
625
0
        throw;
626
0
    }
627
0
    catch( container::ElementExistException& )
628
0
    {
629
0
        throw;
630
0
    }
631
0
    catch( io::IOException& )
632
0
    {
633
0
        throw;
634
0
    }
635
0
    catch( embed::StorageWrappedTargetException& )
636
0
    {
637
0
        throw;
638
0
    }
639
0
    catch( uno::RuntimeException& )
640
0
    {
641
0
        throw;
642
0
    }
643
0
    catch( uno::Exception& )
644
0
    {
645
0
        uno::Any aCaught( ::cppu::getCaughtException() );
646
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
647
0
                                                 uno::Reference< io::XInputStream >(),
648
0
                                                 aCaught );
649
0
    }
650
0
}
651
652
void FSStorage::copyElementToImpl(std::unique_lock<std::mutex>& /*rGuard*/,
653
                                  std::u16string_view aElementName,
654
                                  const uno::Reference< embed::XStorage >& xDest,
655
                                  const OUString& aNewName )
656
0
{
657
0
    if ( !xDest.is() )
658
0
        throw uno::RuntimeException();
659
660
0
    INetURLObject aOwnURL( m_aURL );
661
0
    aOwnURL.Append( aElementName );
662
663
0
    if ( xDest->hasByName( aNewName ) )
664
0
          throw container::ElementExistException(); // TODO:
665
666
0
    try
667
0
    {
668
0
        uno::Reference< ucb::XCommandEnvironment > xDummyEnv;
669
0
        if ( ::utl::UCBContentHelper::IsFolder( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
670
0
        {
671
0
            ::ucbhelper::Content aSourceContent( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDummyEnv, comphelper::getProcessComponentContext() );
672
0
            uno::Reference< embed::XStorage > xDestSubStor(
673
0
                                    xDest->openStorageElement( aNewName, embed::ElementModes::READWRITE ),
674
0
                                    uno::UNO_SET_THROW );
675
676
0
            CopyContentToStorage_Impl( aSourceContent, xDestSubStor );
677
0
        }
678
0
        else if ( ::utl::UCBContentHelper::IsDocument( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
679
0
        {
680
0
            CopyStreamToSubStream( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ), xDest, aNewName );
681
0
        }
682
0
        else
683
0
            throw container::NoSuchElementException(); // TODO:
684
0
    }
685
0
    catch( embed::InvalidStorageException& )
686
0
    {
687
0
        throw;
688
0
    }
689
0
    catch( lang::IllegalArgumentException& )
690
0
    {
691
0
        throw;
692
0
    }
693
0
    catch( container::NoSuchElementException& )
694
0
    {
695
0
        throw;
696
0
    }
697
0
    catch( container::ElementExistException& )
698
0
    {
699
0
        throw;
700
0
    }
701
0
    catch( embed::StorageWrappedTargetException& )
702
0
    {
703
0
        throw;
704
0
    }
705
0
    catch( io::IOException& )
706
0
    {
707
0
        throw;
708
0
    }
709
0
    catch( uno::RuntimeException& )
710
0
    {
711
0
        throw;
712
0
    }
713
0
    catch( uno::Exception& )
714
0
    {
715
0
        uno::Any aCaught( ::cppu::getCaughtException() );
716
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
717
0
                                                 uno::Reference< io::XInputStream >(),
718
0
                                                 aCaught );
719
0
    }
720
0
}
721
722
void SAL_CALL FSStorage::copyElementTo( const OUString& aElementName,
723
                                        const uno::Reference< embed::XStorage >& xDest,
724
                                        const OUString& aNewName )
725
0
{
726
0
    std::unique_lock aGuard( m_aMutex );
727
0
    copyElementToImpl(aGuard, aElementName, xDest, aNewName);
728
0
}
729
730
void SAL_CALL FSStorage::moveElementTo( const OUString& aElementName,
731
                                        const uno::Reference< embed::XStorage >& xDest,
732
                                        const OUString& aNewName )
733
0
{
734
0
    std::unique_lock aGuard( m_aMutex );
735
0
    copyElementToImpl(aGuard, aElementName, xDest, aNewName);
736
737
0
    INetURLObject aOwnURL( m_aURL );
738
0
    aOwnURL.Append( aElementName );
739
0
    if ( !::utl::UCBContentHelper::Kill( aOwnURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
740
0
        throw io::IOException(); // TODO: error handling
741
0
}
742
743
//  XNameAccess
744
745
uno::Any SAL_CALL FSStorage::getByName( const OUString& aName )
746
0
{
747
0
    std::unique_lock aGuard( m_aMutex );
748
749
0
    if ( aName.isEmpty() )
750
0
        throw lang::IllegalArgumentException();
751
752
0
    uno::Any aResult;
753
0
    try
754
0
    {
755
0
        INetURLObject aURL( m_aURL );
756
0
        aURL.Append( aName );
757
758
759
0
        if ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
760
0
        {
761
0
            aResult <<= openStorageElementImpl( aGuard, aName, embed::ElementModes::READ );
762
0
        }
763
0
        else if ( ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) )
764
0
        {
765
0
            aResult <<= openStreamElementImpl( aGuard, aName, embed::ElementModes::READ );
766
0
        }
767
0
        else
768
0
            throw container::NoSuchElementException(); // TODO:
769
0
    }
770
0
    catch (const container::NoSuchElementException&)
771
0
    {
772
0
        throw;
773
0
    }
774
0
    catch (const lang::WrappedTargetException&)
775
0
    {
776
0
        throw;
777
0
    }
778
0
    catch (const uno::RuntimeException&)
779
0
    {
780
0
        throw;
781
0
    }
782
0
    catch (const uno::Exception&)
783
0
    {
784
0
        uno::Any aCaught( ::cppu::getCaughtException() );
785
0
        throw lang::WrappedTargetException( u"Can not open element!"_ustr,
786
0
                                            getXWeak(),
787
0
                                            aCaught );
788
0
    }
789
790
0
    return aResult;
791
0
}
792
793
794
uno::Sequence< OUString > SAL_CALL FSStorage::getElementNames()
795
0
{
796
0
    std::unique_lock aGuard( m_aMutex );
797
798
0
    uno::Sequence< OUString > aResult;
799
800
0
    try
801
0
    {
802
0
        uno::Sequence<OUString> aProps { u"Title"_ustr };
803
804
0
        sal_Int32 nSize = 0;
805
0
        uno::Reference<sdbc::XResultSet> xResultSet
806
0
            = m_aContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
807
0
        uno::Reference< sdbc::XRow > xRow( xResultSet, uno::UNO_QUERY );
808
0
        if ( xResultSet.is() )
809
0
        {
810
            // go through the list
811
0
            while ( xResultSet->next() )
812
0
            {
813
0
                aResult.realloc( ++nSize );
814
0
                aResult.getArray()[nSize-1] = xRow->getString(1);
815
0
            }
816
0
        }
817
0
    }
818
0
    catch( const ucb::InteractiveIOException& r )
819
0
    {
820
0
        if ( r.Code == ucb::IOErrorCode_NOT_EXISTING )
821
0
            OSL_FAIL( "The folder does not exist!" );
822
0
        else
823
0
        {
824
0
            uno::Any aCaught( ::cppu::getCaughtException() );
825
0
            throw lang::WrappedTargetRuntimeException( u"Can not open storage!"_ustr,
826
0
                                            getXWeak(),
827
0
                                            aCaught );
828
0
        }
829
0
    }
830
0
    catch (const uno::RuntimeException&)
831
0
    {
832
0
        throw;
833
0
    }
834
0
    catch (const uno::Exception&)
835
0
    {
836
0
        uno::Any aCaught( ::cppu::getCaughtException() );
837
0
        throw lang::WrappedTargetRuntimeException( u"Can not open storage!"_ustr,
838
0
                                            getXWeak(),
839
0
                                            aCaught );
840
0
    }
841
842
0
    return aResult;
843
0
}
844
845
sal_Bool SAL_CALL FSStorage::hasByName( const OUString& aName )
846
0
{
847
0
    std::unique_lock aGuard( m_aMutex );
848
849
0
    if ( aName.isEmpty() )
850
0
        throw lang::IllegalArgumentException();
851
852
0
    INetURLObject aURL( m_aURL );
853
0
    aURL.Append( aName );
854
855
0
    return ( ::utl::UCBContentHelper::IsFolder( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) )
856
0
      || ::utl::UCBContentHelper::IsDocument( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) );
857
0
}
858
859
uno::Type SAL_CALL FSStorage::getElementType()
860
0
{
861
    // it is a multitype container
862
0
    return uno::Type();
863
0
}
864
865
sal_Bool SAL_CALL FSStorage::hasElements()
866
0
{
867
0
    std::unique_lock aGuard( m_aMutex );
868
869
0
    try
870
0
    {
871
0
        uno::Sequence<OUString> aProps { u"TargetURL"_ustr };
872
873
0
        uno::Reference<sdbc::XResultSet> xResultSet
874
0
            = m_aContent.createCursor(aProps, ::ucbhelper::INCLUDE_FOLDERS_AND_DOCUMENTS);
875
0
        return ( xResultSet.is() && xResultSet->next() );
876
0
    }
877
0
    catch (const uno::RuntimeException&)
878
0
    {
879
0
        throw;
880
0
    }
881
0
    catch (const uno::Exception& ex)
882
0
    {
883
0
        css::uno::Any anyEx = cppu::getCaughtException();
884
0
        throw lang::WrappedTargetRuntimeException( ex.Message,
885
0
                        nullptr, anyEx );
886
0
    }
887
0
}
888
889
//  XDisposable
890
void SAL_CALL FSStorage::dispose()
891
0
{
892
0
    std::unique_lock aGuard( m_aMutex );
893
0
    disposeImpl(aGuard);
894
0
}
895
896
void FSStorage::disposeImpl(std::unique_lock<std::mutex>& rGuard)
897
0
{
898
0
    if ( m_aListenersContainer.getLength(rGuard) )
899
0
    {
900
0
        lang::EventObject aSource( getXWeak() );
901
0
        m_aListenersContainer.disposeAndClear( rGuard, aSource );
902
0
    }
903
0
}
904
905
void SAL_CALL FSStorage::addEventListener(
906
            const uno::Reference< lang::XEventListener >& xListener )
907
0
{
908
0
    std::unique_lock aGuard( m_aMutex );
909
910
0
    m_aListenersContainer.addInterface( aGuard, xListener );
911
0
}
912
913
void SAL_CALL FSStorage::removeEventListener(
914
            const uno::Reference< lang::XEventListener >& xListener )
915
0
{
916
0
    std::unique_lock aGuard( m_aMutex );
917
918
0
    m_aListenersContainer.removeInterface( aGuard, xListener );
919
0
}
920
921
//  XPropertySet
922
923
uno::Reference< beans::XPropertySetInfo > SAL_CALL FSStorage::getPropertySetInfo()
924
0
{
925
    //TODO:
926
0
    return uno::Reference< beans::XPropertySetInfo >();
927
0
}
928
929
930
void SAL_CALL FSStorage::setPropertyValue( const OUString& aPropertyName, const uno::Any& )
931
0
{
932
0
    if ( aPropertyName == "URL" || aPropertyName == "OpenMode" )
933
0
        throw beans::PropertyVetoException(); // TODO
934
0
    else
935
0
        throw beans::UnknownPropertyException(aPropertyName); // TODO
936
0
}
937
938
939
uno::Any SAL_CALL FSStorage::getPropertyValue( const OUString& aPropertyName )
940
0
{
941
0
    std::unique_lock aGuard( m_aMutex );
942
943
0
    if ( aPropertyName == "URL" )
944
0
        return uno::Any( m_aURL );
945
0
    else if ( aPropertyName == "OpenMode" )
946
0
        return uno::Any( m_nMode );
947
948
0
    throw beans::UnknownPropertyException(aPropertyName); // TODO
949
0
}
950
951
952
void SAL_CALL FSStorage::addPropertyChangeListener(
953
            const OUString& /*aPropertyName*/,
954
            const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
955
0
{
956
    //TODO:
957
0
}
958
959
960
void SAL_CALL FSStorage::removePropertyChangeListener(
961
            const OUString& /*aPropertyName*/,
962
            const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
963
0
{
964
    //TODO:
965
0
}
966
967
968
void SAL_CALL FSStorage::addVetoableChangeListener(
969
            const OUString& /*PropertyName*/,
970
            const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
971
0
{
972
    //TODO:
973
0
}
974
975
976
void SAL_CALL FSStorage::removeVetoableChangeListener(
977
            const OUString& /*PropertyName*/,
978
            const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
979
0
{
980
    //TODO:
981
0
}
982
983
//  XHierarchicalStorageAccess
984
uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openStreamElementByHierarchicalName( const OUString& sStreamPath, ::sal_Int32 nOpenMode )
985
0
{
986
0
    std::unique_lock aGuard( m_aMutex );
987
988
0
    if ( sStreamPath.toChar() == '/' )
989
0
        throw lang::IllegalArgumentException();
990
991
0
    INetURLObject aBaseURL( m_aURL );
992
0
    if ( !aBaseURL.setFinalSlash() )
993
0
        throw uno::RuntimeException();
994
995
0
    OUString aFileURL = INetURLObject::GetAbsURL(
996
0
                aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
997
0
                sStreamPath );
998
999
0
    if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) )
1000
0
        throw io::IOException();
1001
1002
0
    if ( ( nOpenMode & embed::ElementModes::NOCREATE )
1003
0
      && !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1004
0
        throw io::IOException(); // TODO:
1005
1006
0
    uno::Reference< ucb::XCommandEnvironment > xDummyEnv; // TODO: provide InteractionHandler if any
1007
0
    uno::Reference< io::XStream > xResult;
1008
0
    try
1009
0
    {
1010
0
        if ( nOpenMode & embed::ElementModes::WRITE )
1011
0
        {
1012
0
            if ( comphelper::isFileUrl( aFileURL ) )
1013
0
            {
1014
0
                uno::Reference<ucb::XSimpleFileAccess3> xSimpleFileAccess(
1015
0
                    ucb::SimpleFileAccess::create( m_xContext ) );
1016
0
                uno::Reference< io::XStream > xStream =
1017
0
                    xSimpleFileAccess->openFileReadWrite( aFileURL );
1018
1019
0
                xResult = new OFSStreamContainer(xStream);
1020
0
            }
1021
0
            else
1022
0
            {
1023
                // TODO: test whether it really works for http and fwp
1024
0
                std::unique_ptr<SvStream> pStream = ::utl::UcbStreamHelper::CreateStream( aFileURL,
1025
0
                                                                          StreamMode::STD_WRITE );
1026
0
                if ( pStream && !pStream->GetError() )
1027
0
                {
1028
0
                    uno::Reference< io::XStream > xStream( new ::utl::OStreamWrapper( std::move(pStream) ) );
1029
0
                    xResult = new OFSStreamContainer(xStream);
1030
0
                }
1031
0
            }
1032
1033
0
            if ( !xResult.is() )
1034
0
                throw io::IOException();
1035
1036
0
            if ( nOpenMode & embed::ElementModes::TRUNCATE )
1037
0
            {
1038
0
                uno::Reference< io::XTruncate > xTrunc( xResult->getOutputStream(), uno::UNO_QUERY_THROW );
1039
0
                xTrunc->truncate();
1040
0
            }
1041
0
        }
1042
0
        else
1043
0
        {
1044
0
            if ( ( nOpenMode & embed::ElementModes::TRUNCATE )
1045
0
              || !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1046
0
                throw io::IOException(); // TODO: access denied
1047
1048
0
            ::ucbhelper::Content aResultContent( aFileURL, xDummyEnv, comphelper::getProcessComponentContext() );
1049
0
            uno::Reference< io::XInputStream > xInStream = aResultContent.openStream();
1050
0
            xResult = new OFSInputStreamContainer(xInStream);
1051
0
        }
1052
0
    }
1053
0
    catch( embed::InvalidStorageException& )
1054
0
    {
1055
0
        throw;
1056
0
    }
1057
0
    catch( lang::IllegalArgumentException& )
1058
0
    {
1059
0
        throw;
1060
0
    }
1061
0
    catch( packages::WrongPasswordException& )
1062
0
    {
1063
0
        throw;
1064
0
    }
1065
0
    catch( embed::StorageWrappedTargetException& )
1066
0
    {
1067
0
        throw;
1068
0
    }
1069
0
    catch( io::IOException& )
1070
0
    {
1071
0
        throw;
1072
0
    }
1073
0
    catch( uno::RuntimeException& )
1074
0
    {
1075
0
        throw;
1076
0
    }
1077
0
    catch( uno::Exception& )
1078
0
    {
1079
0
        uno::Any aCaught( ::cppu::getCaughtException() );
1080
0
        throw embed::StorageWrappedTargetException(u"Can't copy raw stream"_ustr,
1081
0
                                                 uno::Reference< io::XInputStream >(),
1082
0
                                                 aCaught );
1083
0
    }
1084
1085
0
    return uno::Reference< embed::XExtendedStorageStream >( xResult, uno::UNO_QUERY_THROW );
1086
0
}
1087
1088
uno::Reference< embed::XExtendedStorageStream > SAL_CALL FSStorage::openEncryptedStreamElementByHierarchicalName( const OUString& /*sStreamName*/, ::sal_Int32 /*nOpenMode*/, const OUString& /*sPassword*/ )
1089
0
{
1090
0
    throw packages::NoEncryptionException();
1091
0
}
1092
1093
void SAL_CALL FSStorage::removeStreamElementByHierarchicalName( const OUString& sStreamPath )
1094
0
{
1095
0
    std::unique_lock aGuard( m_aMutex );
1096
1097
    // TODO/LATER: may need possibility to create folder if it was removed, since the folder can not be locked
1098
0
    INetURLObject aBaseURL( m_aURL );
1099
0
    if ( !aBaseURL.setFinalSlash() )
1100
0
        throw uno::RuntimeException();
1101
1102
0
    OUString aFileURL = INetURLObject::GetAbsURL(
1103
0
                aBaseURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
1104
0
                sStreamPath );
1105
1106
0
    if ( !::utl::UCBContentHelper::IsDocument( aFileURL ) )
1107
0
    {
1108
0
        if ( ::utl::UCBContentHelper::IsFolder( aFileURL ) )
1109
0
            throw lang::IllegalArgumentException();
1110
0
        else
1111
0
            throw container::NoSuchElementException(); // TODO:
1112
0
    }
1113
1114
0
    if ( !::utl::UCBContentHelper::Kill( aFileURL ) )
1115
0
        throw io::IOException(); // TODO: error handling
1116
0
}
1117
1118
1119
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */