Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/package/source/xstor/xstorage.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 <memory>
21
#include <sal/config.h>
22
#include <sal/log.hxx>
23
24
#include <cassert>
25
#include <string_view>
26
27
#include <com/sun/star/beans/PropertyValue.hpp>
28
#include <com/sun/star/embed/ElementModes.hpp>
29
#include <com/sun/star/embed/InvalidStorageException.hpp>
30
#include <com/sun/star/embed/UseBackupException.hpp>
31
#include <com/sun/star/embed/StorageFormats.hpp>
32
#include <com/sun/star/embed/StorageWrappedTargetException.hpp>
33
#include <com/sun/star/packages/NoEncryptionException.hpp>
34
#include <com/sun/star/packages/NoRawFormatException.hpp>
35
#include <com/sun/star/packages/WrongPasswordException.hpp>
36
#include <com/sun/star/io/TempFile.hpp>
37
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
38
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
39
#include <com/sun/star/container/XEnumerationAccess.hpp>
40
#include <com/sun/star/container/XNamed.hpp>
41
#include <com/sun/star/util/XChangesBatch.hpp>
42
43
#include <com/sun/star/lang/XComponent.hpp>
44
#include <com/sun/star/lang/DisposedException.hpp>
45
#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
46
#include <com/sun/star/beans/NamedValue.hpp>
47
48
#include <PackageConstants.hxx>
49
50
#include <comphelper/sequence.hxx>
51
#include <cppuhelper/queryinterface.hxx>
52
#include <cppuhelper/exc_hlp.hxx>
53
54
#include <comphelper/servicehelper.hxx>
55
#include <comphelper/storagehelper.hxx>
56
#include <comphelper/ofopxmlhelper.hxx>
57
#include <utility>
58
#include <comphelper/diagnose_ex.hxx>
59
60
#include "xstorage.hxx"
61
#include "owriteablestream.hxx"
62
#include "switchpersistencestream.hxx"
63
64
using namespace ::com::sun::star;
65
66
// static
67
void OStorage_Impl::completeStorageStreamCopy_Impl(
68
                            const uno::Reference< io::XStream >& xSource,
69
                            const uno::Reference< io::XStream >& xDest,
70
                            sal_Int32 nStorageType,
71
                            const uno::Sequence< uno::Sequence< beans::StringPair > >& aRelInfo )
72
17
{
73
17
        uno::Reference< beans::XPropertySet > xSourceProps( xSource, uno::UNO_QUERY_THROW );
74
17
        uno::Reference< beans::XPropertySet > xDestProps( xDest, uno::UNO_QUERY_THROW );
75
76
17
        uno::Reference< io::XOutputStream > xDestOutStream = xDest->getOutputStream();
77
17
        if ( !xDestOutStream.is() )
78
0
            throw io::IOException();
79
80
17
        uno::Reference< io::XInputStream > xSourceInStream = xSource->getInputStream();
81
17
        if ( !xSourceInStream.is() )
82
0
            throw io::IOException();
83
84
        // TODO: headers of encrypted streams should be copied also
85
17
        ::comphelper::OStorageHelper::CopyInputToOutput( xSourceInStream, xDestOutStream );
86
87
17
        uno::Sequence<OUString> aPropNames { u"Compressed"_ustr, u"MediaType"_ustr,
88
17
                                             u"UseCommonStoragePasswordEncryption"_ustr };
89
90
17
        if ( nStorageType == embed::StorageFormats::OFOPXML )
91
0
        {
92
            // TODO/LATER: in future it might make sense to provide the stream if there is one
93
0
            uno::Reference< embed::XRelationshipAccess > xRelAccess( xDest, uno::UNO_QUERY_THROW );
94
0
            xRelAccess->clearRelationships();
95
0
            xRelAccess->insertRelationships( aRelInfo, false );
96
97
0
            aPropNames.realloc( 2 );
98
0
        }
99
17
        else if ( nStorageType != embed::StorageFormats::PACKAGE )
100
0
        {
101
0
            aPropNames.realloc( 1 );
102
0
        }
103
104
17
        for (const auto& rPropName : aPropNames)
105
51
            xDestProps->setPropertyValue( rPropName, xSourceProps->getPropertyValue( rPropName ) );
106
17
}
107
108
static uno::Reference< io::XInputStream > GetSeekableTempCopy( const uno::Reference< io::XInputStream >& xInStream )
109
0
{
110
0
    rtl::Reference < utl::TempFileFastService > xTempFile = new utl::TempFileFastService;
111
0
    uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
112
0
    uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();
113
114
0
    if ( !xTempOut.is() || !xTempIn.is() )
115
0
        throw io::IOException();
116
117
0
    ::comphelper::OStorageHelper::CopyInputToOutput( xInStream, xTempOut );
118
0
    xTempOut->closeOutput();
119
120
0
    return xTempIn;
121
0
}
122
123
SotElement_Impl::SotElement_Impl(OUString aName, bool bStor, bool bNew)
124
291k
    : m_aOriginalName(std::move(aName))
125
291k
    , m_bIsRemoved(false)
126
291k
    , m_bIsInserted(bNew)
127
291k
    , m_bIsStorage(bStor)
128
291k
{
129
291k
}
130
131
// most of properties are holt by the storage but are not used
132
OStorage_Impl::OStorage_Impl(   uno::Reference< io::XInputStream > const & xInputStream,
133
                                sal_Int32 nMode,
134
                                const uno::Sequence< beans::PropertyValue >& xProperties,
135
                                uno::Reference< uno::XComponentContext > const & xContext,
136
                                sal_Int32 nStorageType )
137
40.8k
: m_xMutex( new comphelper::RefCountedMutex )
138
40.8k
, m_pAntiImpl( nullptr )
139
40.8k
, m_nStorageMode( nMode & ~embed::ElementModes::SEEKABLE )
140
40.8k
, m_bIsModified( ( nMode & ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) ) == ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) )
141
40.8k
, m_bBroadcastModified( false )
142
40.8k
, m_bCommited( false )
143
40.8k
, m_bIsRoot( true )
144
40.8k
, m_bListCreated( false )
145
40.8k
, m_nModifiedListenerCount( 0 )
146
40.8k
, m_xContext( xContext )
147
40.8k
, m_xProperties( xProperties )
148
40.8k
, m_bHasCommonEncryptionData( false )
149
40.8k
, m_pParent( nullptr )
150
40.8k
, m_bControlMediaType( false )
151
40.8k
, m_bMTFallbackUsed( false )
152
40.8k
, m_bControlVersion( false )
153
40.8k
, m_nStorageType( nStorageType )
154
40.8k
, m_pRelStorElement( nullptr )
155
40.8k
, m_nRelInfoStatus( RELINFO_NO_INIT )
156
40.8k
{
157
    // all the checks done below by assertion statements must be done by factory
158
40.8k
    SAL_WARN_IF( !xInputStream.is(), "package.xstor", "No input stream is provided!" );
159
40.8k
    assert(xContext.is());
160
161
40.8k
    m_pSwitchStream = new SwitchablePersistenceStream(xInputStream);
162
40.8k
    m_xInputStream = m_pSwitchStream->getInputStream();
163
164
40.8k
    if ( m_nStorageMode & embed::ElementModes::WRITE )
165
0
    {
166
        // check that the stream allows to write
167
0
        SAL_WARN( "package.xstor", "No stream for writing is provided!" );
168
0
    }
169
40.8k
}
170
171
// most of properties are holt by the storage but are not used
172
OStorage_Impl::OStorage_Impl(   uno::Reference< io::XStream > const & xStream,
173
                                sal_Int32 nMode,
174
                                const uno::Sequence< beans::PropertyValue >& xProperties,
175
                                uno::Reference< uno::XComponentContext > const & xContext,
176
                                sal_Int32 nStorageType )
177
76.7k
: m_xMutex( new comphelper::RefCountedMutex )
178
76.7k
, m_pAntiImpl( nullptr )
179
76.7k
, m_nStorageMode( nMode & ~embed::ElementModes::SEEKABLE )
180
76.7k
, m_bIsModified( ( nMode & ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) ) == ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) )
181
76.7k
, m_bBroadcastModified( false )
182
76.7k
, m_bCommited( false )
183
76.7k
, m_bIsRoot( true )
184
76.7k
, m_bListCreated( false )
185
76.7k
, m_nModifiedListenerCount( 0 )
186
76.7k
, m_xContext( xContext )
187
76.7k
, m_xProperties( xProperties )
188
76.7k
, m_bHasCommonEncryptionData( false )
189
76.7k
, m_pParent( nullptr )
190
76.7k
, m_bControlMediaType( false )
191
76.7k
, m_bMTFallbackUsed( false )
192
76.7k
, m_bControlVersion( false )
193
76.7k
, m_nStorageType( nStorageType )
194
76.7k
, m_pRelStorElement( nullptr )
195
76.7k
, m_nRelInfoStatus( RELINFO_NO_INIT )
196
76.7k
{
197
    // all the checks done below by assertion statements must be done by factory
198
76.7k
    SAL_WARN_IF( !xStream.is(), "package.xstor", "No stream is provided!" );
199
76.7k
    assert(xContext.is());
200
201
76.7k
    if ( m_nStorageMode & embed::ElementModes::WRITE )
202
76.7k
    {
203
76.7k
        m_pSwitchStream = new SwitchablePersistenceStream(xStream);
204
76.7k
        m_xStream = m_pSwitchStream.get();
205
76.7k
    }
206
50
    else
207
50
    {
208
50
        m_pSwitchStream = new SwitchablePersistenceStream(xStream->getInputStream());
209
50
        m_xInputStream = m_pSwitchStream->getInputStream();
210
50
    }
211
76.7k
}
212
213
OStorage_Impl::OStorage_Impl(   OStorage_Impl* pParent,
214
                                sal_Int32 nMode,
215
                                uno::Reference< container::XNameContainer > const & xPackageFolder,
216
                                uno::Reference< lang::XSingleServiceFactory > xPackage,
217
                                uno::Reference< uno::XComponentContext > const & xContext,
218
                                sal_Int32 nStorageType )
219
83.5k
: m_xMutex( new comphelper::RefCountedMutex )
220
83.5k
, m_pAntiImpl( nullptr )
221
83.5k
, m_nStorageMode( nMode & ~embed::ElementModes::SEEKABLE )
222
83.5k
, m_bIsModified( ( nMode & ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) ) == ( embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE ) )
223
83.5k
, m_bBroadcastModified( false )
224
83.5k
, m_bCommited( false )
225
83.5k
, m_bIsRoot( false )
226
83.5k
, m_bListCreated( false )
227
83.5k
, m_nModifiedListenerCount( 0 )
228
83.5k
, m_xPackageFolder( xPackageFolder )
229
83.5k
, m_xPackage(std::move( xPackage ))
230
83.5k
, m_xContext( xContext )
231
83.5k
, m_bHasCommonEncryptionData( false )
232
83.5k
, m_pParent( pParent ) // can be empty in case of temporary readonly substorages and relation storage
233
83.5k
, m_bControlMediaType( false )
234
83.5k
, m_bMTFallbackUsed( false )
235
83.5k
, m_bControlVersion( false )
236
83.5k
, m_nStorageType( nStorageType )
237
83.5k
, m_pRelStorElement( nullptr )
238
83.5k
, m_nRelInfoStatus( RELINFO_NO_INIT )
239
83.5k
{
240
83.5k
    SAL_WARN_IF( !xPackageFolder.is(), "package.xstor", "No package folder!" );
241
83.5k
    assert(xContext.is());
242
83.5k
}
243
244
OStorage_Impl::~OStorage_Impl()
245
201k
{
246
201k
    {
247
201k
        ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
248
201k
        if ( m_pAntiImpl ) // root storage wrapper must set this member to NULL before destruction of object
249
15.5k
        {
250
15.5k
            SAL_WARN_IF( m_bIsRoot, "package.xstor", "The root storage wrapper must be disposed already" );
251
252
15.5k
            try {
253
15.5k
                m_pAntiImpl->InternalDispose( false );
254
15.5k
            }
255
15.5k
            catch ( const uno::Exception& )
256
15.5k
            {
257
0
                TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
258
0
            }
259
15.5k
            m_pAntiImpl = nullptr;
260
15.5k
        }
261
185k
        else if ( !m_aReadOnlyWrapVector.empty() )
262
14.7k
        {
263
14.7k
            for ( auto& rStorage : m_aReadOnlyWrapVector )
264
14.7k
            {
265
14.7k
                rtl::Reference< OStorage > xTmp = rStorage;
266
14.7k
                if ( xTmp.is() )
267
14.7k
                    try {
268
14.7k
                        xTmp->InternalDispose( false );
269
14.7k
                    } catch( const uno::Exception& )
270
14.7k
                    {
271
0
                        TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
272
0
                    }
273
14.7k
            }
274
275
14.7k
            m_aReadOnlyWrapVector.clear();
276
14.7k
        }
277
278
201k
        m_pParent = nullptr;
279
201k
    }
280
281
0
    for (const auto & pair : m_aChildrenMap)
282
275k
        for (auto pElement : pair.second)
283
275k
            delete pElement;
284
201k
    m_aChildrenMap.clear();
285
286
201k
    std::for_each(m_aDeletedVector.begin(), m_aDeletedVector.end(), std::default_delete<SotElement_Impl>());
287
201k
    m_aDeletedVector.clear();
288
289
201k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && m_pRelStorElement )
290
15.5k
    {
291
15.5k
        delete m_pRelStorElement;
292
15.5k
        m_pRelStorElement = nullptr;
293
15.5k
    }
294
295
201k
    m_xPackageFolder.clear();
296
201k
    m_xPackage.clear();
297
298
201k
    OUString aPropertyName = u"URL"_ustr;
299
201k
    for (const auto& rProp : m_xProperties)
300
0
    {
301
0
        if ( rProp.Name == aPropertyName )
302
0
        {
303
            // the storage is URL based so all the streams are opened by factory and should be closed
304
0
            try
305
0
            {
306
0
                if ( m_xInputStream.is() )
307
0
                {
308
0
                    m_xInputStream->closeInput();
309
0
                    m_xInputStream.clear();
310
0
                }
311
312
0
                if ( m_xStream.is() )
313
0
                {
314
0
                    uno::Reference< io::XInputStream > xInStr = m_xStream->getInputStream();
315
0
                    if ( xInStr.is() )
316
0
                        xInStr->closeInput();
317
318
0
                    uno::Reference< io::XOutputStream > xOutStr = m_xStream->getOutputStream();
319
0
                    if ( xOutStr.is() )
320
0
                        xOutStr->closeOutput();
321
322
0
                    m_xStream.clear();
323
0
                }
324
0
            }
325
0
            catch (const uno::Exception&)
326
0
            {
327
0
                TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
328
0
            }
329
0
        }
330
0
    }
331
201k
}
332
333
void OStorage_Impl::SetReadOnlyWrap( OStorage& aStorage )
334
66.2k
{
335
    // Weak reference is used inside the holder so the refcount must not be zero at this point
336
66.2k
    OSL_ENSURE( aStorage.GetRefCount_Impl(), "There must be a reference alive to use this method!" );
337
66.2k
    m_aReadOnlyWrapVector.emplace_back( &aStorage );
338
66.2k
}
339
340
void OStorage_Impl::RemoveReadOnlyWrap( const OStorage& aStorage )
341
51.4k
{
342
51.4k
    for ( StorageHoldersType::iterator pStorageIter = m_aReadOnlyWrapVector.begin();
343
102k
      pStorageIter != m_aReadOnlyWrapVector.end();)
344
51.4k
    {
345
51.4k
        rtl::Reference< OStorage > xTmp = *pStorageIter;
346
51.4k
        if ( !xTmp )
347
3.69k
            pStorageIter = m_aReadOnlyWrapVector.erase(pStorageIter);
348
47.7k
        else if ( xTmp && xTmp.get() == &aStorage )
349
47.7k
        {
350
47.7k
            try {
351
47.7k
                xTmp->InternalDispose( false );
352
47.7k
            } catch( const uno::Exception& )
353
47.7k
            {
354
0
                TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
355
0
            }
356
357
47.7k
            pStorageIter = m_aReadOnlyWrapVector.erase(pStorageIter);
358
47.7k
        }
359
0
        else
360
0
            ++pStorageIter;
361
51.4k
    }
362
51.4k
}
363
364
void OStorage_Impl::OpenOwnPackage()
365
98.4k
{
366
98.4k
    SAL_WARN_IF( !m_bIsRoot, "package.xstor", "Opening of the package has no sense!" );
367
368
98.4k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
369
370
98.4k
    if ( !m_xPackageFolder.is() )
371
98.4k
    {
372
98.4k
        if ( !m_xPackage.is() )
373
98.4k
        {
374
98.4k
            uno::Sequence< uno::Any > aArguments( 2 );
375
98.4k
            auto pArguments = aArguments.getArray();
376
98.4k
            if ( m_nStorageMode & embed::ElementModes::WRITE )
377
76.6k
                pArguments[ 0 ] <<= css::uno::Reference< css::io::XStream >(m_xStream);
378
21.8k
            else
379
21.8k
            {
380
21.8k
                SAL_WARN_IF( !m_xInputStream.is(), "package.xstor", "Input stream must be set for readonly access!" );
381
21.8k
                pArguments[ 0 ] <<= m_xInputStream;
382
                // TODO: if input stream is not seekable or XSeekable interface is supported
383
                // on XStream object a wrapper must be used
384
21.8k
            }
385
386
            // do not allow elements to remove themself from the old container in case of insertion to another container
387
98.4k
            pArguments[ 1 ] <<= beans::NamedValue( u"AllowRemoveOnInsert"_ustr,
388
98.4k
                                                    uno::Any( false ) );
389
390
98.4k
            sal_Int32 nArgNum = 2;
391
98.4k
            for (const auto& rProp : m_xProperties)
392
0
            {
393
0
                if ( rProp.Name == "RepairPackage"
394
0
                  || rProp.Name == "ProgressHandler"
395
0
                  || rProp.Name == "NoFileSync" )
396
0
                {
397
                    // Forward these to the package.
398
0
                    beans::NamedValue aNamedValue( rProp.Name, rProp.Value );
399
0
                    aArguments.realloc( ++nArgNum );
400
0
                    pArguments = aArguments.getArray();
401
0
                    pArguments[nArgNum-1] <<= aNamedValue;
402
0
                    if (rProp.Name == "RepairPackage")
403
0
                        rProp.Value >>= m_bRepairPackage;
404
0
                }
405
0
                else if ( rProp.Name == "Password" )
406
0
                {
407
                    // TODO: implement password setting for documents
408
                    // the password entry must be removed after setting
409
0
                }
410
0
            }
411
412
98.4k
            if ( m_nStorageType == embed::StorageFormats::ZIP )
413
8.06k
            {
414
                // let the package support only plain zip format
415
8.06k
                beans::NamedValue aNamedValue;
416
8.06k
                aNamedValue.Name = "StorageFormat";
417
8.06k
                aNamedValue.Value <<= u"ZipFormat"_ustr;
418
8.06k
                aArguments.realloc( ++nArgNum );
419
8.06k
                pArguments = aArguments.getArray();
420
8.06k
                pArguments[nArgNum-1] <<= aNamedValue;
421
8.06k
            }
422
90.3k
            else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
423
13.7k
            {
424
                // let the package support OFOPXML media type handling
425
13.7k
                beans::NamedValue aNamedValue;
426
13.7k
                aNamedValue.Name = "StorageFormat";
427
13.7k
                aNamedValue.Value <<= u"OFOPXMLFormat"_ustr;
428
13.7k
                aArguments.realloc( ++nArgNum );
429
13.7k
                pArguments = aArguments.getArray();
430
13.7k
                pArguments[nArgNum-1] <<= aNamedValue;
431
13.7k
            }
432
433
98.4k
            m_xPackage.set( m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
434
98.4k
                               u"com.sun.star.packages.comp.ZipPackage"_ustr, aArguments, m_xContext),
435
98.4k
                            uno::UNO_QUERY );
436
98.4k
        }
437
438
98.4k
        uno::Reference< container::XHierarchicalNameAccess > xHNameAccess( m_xPackage, uno::UNO_QUERY );
439
98.4k
        SAL_WARN_IF( !xHNameAccess.is(), "package.xstor", "The package could not be created!" );
440
441
98.4k
        if ( xHNameAccess.is() )
442
96.5k
        {
443
96.5k
            uno::Any aFolder = xHNameAccess->getByHierarchicalName(u"/"_ustr);
444
96.5k
            aFolder >>= m_xPackageFolder;
445
96.5k
        }
446
98.4k
    }
447
448
98.4k
    SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "The package root folder can not be opened!" );
449
98.4k
    if ( !m_xPackageFolder.is() )
450
0
        throw embed::InvalidStorageException();
451
98.4k
}
452
453
bool OStorage_Impl::HasChildren()
454
0
{
455
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
456
457
0
    ReadContents();
458
0
    return !m_aChildrenMap.empty();
459
0
}
460
461
void OStorage_Impl::GetStorageProperties()
462
184k
{
463
184k
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
464
99.3k
        return;
465
466
84.9k
    uno::Reference< beans::XPropertySet > xProps( m_xPackageFolder, uno::UNO_QUERY_THROW );
467
468
84.9k
    if ( !m_bControlMediaType )
469
26.5k
    {
470
26.5k
        uno::Reference< beans::XPropertySet > xPackageProps( m_xPackage, uno::UNO_QUERY_THROW );
471
26.5k
        xPackageProps->getPropertyValue( MEDIATYPE_FALLBACK_USED_PROPERTY ) >>= m_bMTFallbackUsed;
472
473
26.5k
        static constexpr OUStringLiteral sMediaType(u"MediaType");
474
26.5k
        xProps->getPropertyValue( sMediaType ) >>= m_aMediaType;
475
26.5k
        m_bControlMediaType = true;
476
26.5k
    }
477
478
84.9k
    if ( !m_bControlVersion )
479
26.5k
    {
480
26.5k
        xProps->getPropertyValue( u"Version"_ustr ) >>= m_aVersion;
481
26.5k
        m_bControlVersion = true;
482
26.5k
    }
483
484
    // the properties of OFOPXML will be handled directly
485
84.9k
}
486
487
void OStorage_Impl::ReadRelInfoIfNecessary()
488
62.7k
{
489
62.7k
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
490
0
        return;
491
492
62.7k
    if ( m_nRelInfoStatus == RELINFO_NO_INIT )
493
13.7k
    {
494
        // Init from original stream
495
13.7k
        uno::Reference< io::XInputStream > xRelInfoStream
496
13.7k
            = GetRelInfoStreamForName( std::u16string_view() );
497
13.7k
        try
498
13.7k
        {
499
13.7k
            if ( xRelInfoStream.is() )
500
12.0k
                m_aRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
501
12.0k
                                    xRelInfoStream,
502
12.0k
                                    u"_rels/.rels",
503
12.0k
                                    m_xContext );
504
13.7k
            m_nRelInfoStatus = RELINFO_READ;
505
13.7k
        }
506
13.7k
        catch (css::uno::Exception &)
507
13.7k
        {
508
28
            TOOLS_INFO_EXCEPTION("package.xstor", "");
509
28
        }
510
13.7k
    }
511
48.9k
    else if ( m_nRelInfoStatus == RELINFO_CHANGED_STREAM )
512
0
    {
513
        // Init from the new stream
514
0
        try
515
0
        {
516
0
            if ( m_xNewRelInfoStream.is() )
517
0
                m_aRelInfo = ::comphelper::OFOPXMLHelper::ReadRelationsInfoSequence(
518
0
                                        m_xNewRelInfoStream,
519
0
                                        u"_rels/.rels",
520
0
                                        m_xContext );
521
522
0
            m_nRelInfoStatus = RELINFO_CHANGED_STREAM_READ;
523
0
        }
524
0
        catch( const uno::Exception& )
525
0
        {
526
0
            m_nRelInfoStatus = RELINFO_CHANGED_BROKEN;
527
0
        }
528
0
    }
529
62.7k
}
530
531
void OStorage_Impl::ReadContents()
532
661k
{
533
661k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
534
535
661k
    if ( m_bListCreated )
536
479k
        return;
537
538
182k
    if ( m_bIsRoot )
539
98.4k
        OpenOwnPackage();
540
541
182k
    uno::Reference< container::XEnumerationAccess > xEnumAccess( m_xPackageFolder, uno::UNO_QUERY_THROW );
542
182k
    uno::Reference< container::XEnumeration > xEnum = xEnumAccess->createEnumeration();
543
182k
    if ( !xEnum.is() )
544
0
        throw uno::RuntimeException();
545
546
182k
    m_bListCreated = true;
547
548
468k
    while( xEnum->hasMoreElements() )
549
286k
    {
550
286k
        try {
551
286k
            uno::Reference< container::XNamed > xNamed;
552
286k
            xEnum->nextElement() >>= xNamed;
553
554
286k
            if ( !xNamed.is() )
555
0
            {
556
0
                SAL_WARN( "package.xstor", "XNamed is not supported!" );
557
0
                throw uno::RuntimeException();
558
0
            }
559
560
286k
            OUString aName = xNamed->getName();
561
286k
            SAL_WARN_IF( aName.isEmpty(), "package.xstor", "Empty name!" );
562
563
286k
            uno::Reference< container::XNameContainer > xNameContainer( xNamed, uno::UNO_QUERY );
564
565
286k
            std::unique_ptr<SotElement_Impl> xNewElement(new SotElement_Impl(aName, xNameContainer.is(), false));
566
286k
            if ( m_nStorageType == embed::StorageFormats::OFOPXML && aName == "_rels" )
567
15.5k
            {
568
15.5k
                if (!xNewElement->m_bIsStorage)
569
0
                    throw io::IOException(); // TODO: Unexpected format
570
571
15.5k
                m_pRelStorElement = xNewElement.release();
572
15.5k
                CreateRelStorage();
573
15.5k
            }
574
271k
            else
575
271k
            {
576
271k
                if ( ( m_nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
577
0
                {
578
                    // if a storage is truncated all of it elements are marked as deleted
579
0
                    xNewElement->m_bIsRemoved = true;
580
0
                }
581
582
271k
                m_aChildrenMap[aName].push_back(xNewElement.release());
583
271k
            }
584
286k
        }
585
286k
        catch( const container::NoSuchElementException& )
586
286k
        {
587
0
            TOOLS_WARN_EXCEPTION( "package.xstor", "hasMoreElements() implementation has problems!");
588
0
            break;
589
0
        }
590
286k
    }
591
182k
    if ( ( m_nStorageMode & embed::ElementModes::TRUNCATE ) == embed::ElementModes::TRUNCATE )
592
0
    {
593
        // if a storage is truncated the relations information should be cleaned
594
0
        m_xNewRelInfoStream.clear();
595
0
        m_aRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
596
0
        m_nRelInfoStatus = RELINFO_CHANGED;
597
0
    }
598
599
    // cache changeable folder properties
600
182k
    GetStorageProperties();
601
182k
}
602
603
void OStorage_Impl::CopyToStorage( const uno::Reference< embed::XStorage >& xDest, bool bDirect )
604
0
{
605
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
606
607
0
    uno::Reference< beans::XPropertySet > xPropSet( xDest, uno::UNO_QUERY );
608
0
    if ( !xPropSet.is() )
609
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 );
610
611
0
    sal_Int32 nDestMode = embed::ElementModes::READ;
612
0
    xPropSet->getPropertyValue( u"OpenMode"_ustr ) >>= nDestMode;
613
614
0
    if ( !( nDestMode & embed::ElementModes::WRITE ) )
615
0
        throw io::IOException(); // TODO: access_denied
616
617
0
    ReadContents();
618
619
0
    if ( !m_xPackageFolder.is() )
620
0
        throw embed::InvalidStorageException();
621
622
0
    for ( const auto& pair : m_aChildrenMap )
623
0
        for (auto pElement : pair.second)
624
0
        {
625
0
            if ( !pElement->m_bIsRemoved )
626
0
                CopyStorageElement( pElement, xDest, /*aName*/pair.first, bDirect );
627
0
        }
628
629
    // move storage properties to the destination one ( means changeable properties )
630
0
    if ( m_nStorageType == embed::StorageFormats::PACKAGE )
631
0
    {
632
0
        xPropSet->setPropertyValue( u"MediaType"_ustr, uno::Any( m_aMediaType ) );
633
0
        xPropSet->setPropertyValue( u"Version"_ustr, uno::Any( m_aVersion ) );
634
0
    }
635
636
0
    if ( m_nStorageType == embed::StorageFormats::PACKAGE )
637
0
    {
638
        // if this is a root storage, the common key from current one should be moved there
639
0
        bool bIsRoot = false;
640
0
        if ( ( xPropSet->getPropertyValue( u"IsRoot"_ustr ) >>= bIsRoot ) && bIsRoot )
641
0
        {
642
0
            try
643
0
            {
644
0
                uno::Reference< embed::XEncryptionProtectedStorage > xEncr( xDest, uno::UNO_QUERY );
645
0
                if ( xEncr.is() )
646
0
                {
647
0
                    xEncr->setEncryptionData( GetCommonRootEncryptionData().getAsConstNamedValueList() );
648
649
0
                    uno::Sequence< beans::NamedValue > aAlgorithms;
650
0
                    uno::Reference< beans::XPropertySet > xPackPropSet( m_xPackage, uno::UNO_QUERY_THROW );
651
0
                    xPackPropSet->getPropertyValue( ENCRYPTION_ALGORITHMS_PROPERTY )
652
0
                        >>= aAlgorithms;
653
0
                    xEncr->setEncryptionAlgorithms( aAlgorithms );
654
0
                }
655
0
            }
656
0
            catch( const packages::NoEncryptionException& )
657
0
            {
658
0
                TOOLS_INFO_EXCEPTION("package.xstor", "No Encryption");
659
0
            }
660
0
        }
661
0
    }
662
0
    else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
663
0
    {
664
665
        // TODO/LATER: currently the optimization is not active
666
        // uno::Reference< io::XInputStream > xRelInfoStream = GetRelInfoStreamForName( OUString() ); // own stream
667
        // if ( xRelInfoStream.is() )
668
        // {
669
        //  // Relations info stream is a writeonly property, introduced only to optimize copying
670
        //  // Should be used carefully since no check for stream consistency is done, and the stream must not stay locked
671
672
        //  OUString aRelInfoString = "RelationsInfoStream";
673
        //  xPropSet->setPropertyValue( aRelInfoString, uno::makeAny( GetSeekableTempCopy( xRelInfoStream, m_xFactory ) ) );
674
        // }
675
676
0
        uno::Reference< embed::XRelationshipAccess > xRels( xDest, uno::UNO_QUERY );
677
0
        if ( !xRels.is() )
678
0
            throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 );
679
680
0
        xRels->insertRelationships( GetAllRelationshipsIfAny(), false );
681
0
    }
682
683
    // if possible the destination storage should be committed after successful copying
684
0
    uno::Reference< embed::XTransactedObject > xObjToCommit( xDest, uno::UNO_QUERY );
685
0
    if ( xObjToCommit.is() )
686
0
        xObjToCommit->commit();
687
0
}
688
689
void OStorage_Impl::CopyStorageElement( SotElement_Impl* pElement,
690
                                        const uno::Reference< embed::XStorage >& xDest,
691
                                        const OUString& aName,
692
                                        bool bDirect )
693
17
{
694
17
    SAL_WARN_IF( !xDest.is(), "package.xstor", "No destination storage!" );
695
17
    SAL_WARN_IF( aName.isEmpty(), "package.xstor", "Empty element name!" );
696
697
17
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
698
699
17
    uno::Reference< container::XNameAccess > xDestAccess( xDest, uno::UNO_QUERY_THROW );
700
17
    if ( xDestAccess->hasByName( aName )
701
0
      && !( pElement->m_bIsStorage && xDest->isStorageElement( aName ) ) )
702
0
        xDest->removeElement( aName );
703
704
17
    if ( pElement->m_bIsStorage )
705
0
    {
706
0
        uno::Reference< embed::XStorage > xSubDest =
707
0
                                    xDest->openStorageElement(  aName,
708
0
                                                                embed::ElementModes::WRITE );
709
710
0
        SAL_WARN_IF( !xSubDest.is(), "package.xstor", "No destination substorage!" );
711
712
0
        if (!pElement->m_xStorage)
713
0
        {
714
0
            OpenSubStorage( pElement, embed::ElementModes::READ );
715
0
            if (!pElement->m_xStorage)
716
0
                throw io::IOException();
717
0
        }
718
719
0
        pElement->m_xStorage->CopyToStorage(xSubDest, bDirect);
720
0
    }
721
17
    else
722
17
    {
723
17
        if (!pElement->m_xStream)
724
0
        {
725
0
            OpenSubStream( pElement );
726
0
            if (!pElement->m_xStream)
727
0
                throw io::IOException();
728
0
        }
729
730
17
        if (!pElement->m_xStream->IsEncrypted())
731
17
        {
732
17
            if ( bDirect )
733
0
            {
734
                // fill in the properties for the stream
735
0
                uno::Sequence< beans::PropertyValue > aStrProps(0);
736
0
                const uno::Sequence< beans::PropertyValue > aSrcPkgProps = pElement->m_xStream->GetStreamProperties();
737
0
                sal_Int32 nNum = 0;
738
0
                for ( const auto& rSrcPkgProp : aSrcPkgProps )
739
0
                {
740
0
                    if ( rSrcPkgProp.Name == "MediaType" || rSrcPkgProp.Name == "Compressed" )
741
0
                    {
742
0
                        aStrProps.realloc( ++nNum );
743
0
                        auto pStrProps = aStrProps.getArray();
744
0
                        pStrProps[nNum-1].Name = rSrcPkgProp.Name;
745
0
                        pStrProps[nNum-1].Value = rSrcPkgProp.Value;
746
0
                    }
747
0
                }
748
749
0
                if ( m_nStorageType == embed::StorageFormats::PACKAGE )
750
0
                {
751
0
                    aStrProps.realloc( ++nNum );
752
0
                    auto pStrProps = aStrProps.getArray();
753
0
                    pStrProps[nNum-1].Name = "UseCommonStoragePasswordEncryption";
754
0
                    pStrProps[nNum-1].Value <<= pElement->m_xStream->UsesCommonEncryption_Impl();
755
0
                }
756
0
                else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
757
0
                {
758
                    // TODO/LATER: currently the optimization is not active
759
                    // uno::Reference< io::XInputStream > xInStream = GetRelInfoStreamForName( OUString() ); // own rels stream
760
                    // if ( xInStream.is() )
761
                    // {
762
                    //  aStrProps.realloc( ++nNum );
763
                    //  aStrProps[nNum-1].Name = "RelationsInfoStream";
764
                    //  aStrProps[nNum-1].Value <<= GetSeekableTempCopy( xInStream, m_xFactory );
765
                    // }
766
767
0
                    uno::Reference< embed::XRelationshipAccess > xRels( xDest, uno::UNO_QUERY );
768
0
                    if ( !xRels.is() )
769
0
                        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
770
771
0
                    xRels->insertRelationships( GetAllRelationshipsIfAny(), false );
772
0
                }
773
774
0
                uno::Reference< embed::XOptimizedStorage > xOptDest( xDest, uno::UNO_QUERY_THROW );
775
0
                uno::Reference < io::XInputStream > xInputToInsert;
776
777
0
                if (pElement->m_xStream->HasTempFile_Impl() || !pElement->m_xStream->m_xPackageStream.is())
778
0
                {
779
0
                    SAL_WARN_IF(!pElement->m_xStream->m_xPackageStream.is(), "package.xstor", "No package stream!");
780
781
                    // if the stream is modified - the temporary file must be used for insertion
782
0
                    xInputToInsert = pElement->m_xStream->GetTempFileAsInputStream();
783
0
                }
784
0
                else
785
0
                {
786
                    // for now get just nonseekable access to the stream
787
                    // TODO/LATER: the raw stream can be used
788
789
0
                    xInputToInsert = pElement->m_xStream->m_xPackageStream->getDataStream();
790
0
                }
791
792
0
                if ( !xInputToInsert.is() )
793
0
                        throw io::IOException();
794
795
0
                xOptDest->insertStreamElementDirect( aName, xInputToInsert, aStrProps );
796
0
            }
797
17
            else
798
17
            {
799
17
                uno::Reference< io::XStream > xSubStr =
800
17
                                            xDest->openStreamElement( aName,
801
17
                                            embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
802
17
                SAL_WARN_IF( !xSubStr.is(), "package.xstor", "No destination substream!" );
803
804
17
                pElement->m_xStream->CopyInternallyTo_Impl(xSubStr);
805
17
            }
806
17
        }
807
0
        else if ( m_nStorageType != embed::StorageFormats::PACKAGE )
808
0
        {
809
0
            SAL_WARN( "package.xstor", "Encryption is only supported in package storage!" );
810
0
            throw io::IOException();
811
0
        }
812
0
        else if ( pElement->m_xStream->HasCachedEncryptionData()
813
0
             && ( pElement->m_xStream->IsModified() || pElement->m_xStream->HasWriteOwner_Impl() ) )
814
0
        {
815
0
            ::comphelper::SequenceAsHashMap aCommonEncryptionData;
816
0
            bool bHasCommonEncryptionData = false;
817
0
            try
818
0
            {
819
0
                aCommonEncryptionData = GetCommonRootEncryptionData();
820
0
                bHasCommonEncryptionData = true;
821
0
            }
822
0
            catch( const packages::NoEncryptionException& )
823
0
            {
824
0
                TOOLS_INFO_EXCEPTION("package.xstor", "No Encryption");
825
0
            }
826
827
0
            if (bHasCommonEncryptionData && ::package::PackageEncryptionDataLessOrEqual(pElement->m_xStream->GetCachedEncryptionData(), aCommonEncryptionData))
828
0
            {
829
                // If the stream can be opened with the common storage password
830
                // it must be stored with the common storage password as well
831
0
                uno::Reference< io::XStream > xDestStream =
832
0
                                            xDest->openStreamElement( aName,
833
0
                                                embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
834
835
0
                pElement->m_xStream->CopyInternallyTo_Impl( xDestStream );
836
837
0
                uno::Reference< beans::XPropertySet > xProps( xDestStream, uno::UNO_QUERY_THROW );
838
0
                xProps->setPropertyValue(
839
0
                    u"UseCommonStoragePasswordEncryption"_ustr,
840
0
                    uno::Any( true ) );
841
0
            }
842
0
            else
843
0
            {
844
                // the stream is already opened for writing or was changed
845
0
                uno::Reference< embed::XStorage2 > xDest2( xDest, uno::UNO_QUERY_THROW );
846
0
                uno::Reference< io::XStream > xSubStr =
847
0
                                            xDest2->openEncryptedStream( aName,
848
0
                                                embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE,
849
0
                                                pElement->m_xStream->GetCachedEncryptionData().getAsConstNamedValueList() );
850
0
                SAL_WARN_IF( !xSubStr.is(), "package.xstor", "No destination substream!" );
851
852
0
                pElement->m_xStream->CopyInternallyTo_Impl(xSubStr, pElement->m_xStream->GetCachedEncryptionData());
853
0
            }
854
0
        }
855
0
        else
856
0
        {
857
            // the stream is not opened at all, so it can be just opened for reading
858
0
            try
859
0
            {
860
                // If the stream can be opened with the common storage password
861
                // it must be stored with the common storage password as well
862
863
0
                uno::Reference< io::XStream > xOwnStream = pElement->m_xStream->GetStream(embed::ElementModes::READ,
864
0
                                                                                          false);
865
0
                uno::Reference< io::XStream > xDestStream =
866
0
                                            xDest->openStreamElement( aName,
867
0
                                                embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
868
0
                SAL_WARN_IF( !xDestStream.is(), "package.xstor", "No destination substream!" );
869
0
                completeStorageStreamCopy_Impl( xOwnStream, xDestStream, m_nStorageType, GetAllRelationshipsIfAny() );
870
871
0
                uno::Reference< beans::XPropertySet > xProps( xDestStream, uno::UNO_QUERY_THROW );
872
0
                xProps->setPropertyValue(
873
0
                    u"UseCommonStoragePasswordEncryption"_ustr,
874
0
                    uno::Any( true ) );
875
0
            }
876
0
            catch( const packages::WrongPasswordException& )
877
0
            {
878
0
                TOOLS_INFO_EXCEPTION("package.xstor", "Handled exception");
879
880
                // If the common storage password does not allow to open the stream
881
                // it could be copied in raw way, the problem is that the StartKey should be the same
882
                // in the ODF1.2 package, so an invalid package could be produced if the stream
883
                // is copied from ODF1.1 package, where it is allowed to have different StartKeys
884
0
                uno::Reference< embed::XStorageRawAccess > xRawDest( xDest, uno::UNO_QUERY_THROW );
885
0
                uno::Reference< io::XInputStream > xRawInStream = pElement->m_xStream->GetRawInStream();
886
0
                xRawDest->insertRawEncrStreamElement( aName, xRawInStream );
887
0
            }
888
0
        }
889
17
    }
890
17
}
891
892
uno::Sequence< uno::Sequence< beans::StringPair > > OStorage_Impl::GetAllRelationshipsIfAny()
893
62.7k
{
894
62.7k
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
895
0
        return uno::Sequence< uno::Sequence< beans::StringPair > >();
896
897
62.7k
    ReadRelInfoIfNecessary();
898
899
62.7k
    if ( m_nRelInfoStatus != RELINFO_READ
900
28
         && m_nRelInfoStatus != RELINFO_CHANGED_STREAM_READ
901
28
         && m_nRelInfoStatus != RELINFO_CHANGED )
902
28
            throw io::IOException( u"Wrong relinfo stream!"_ustr );
903
    // m_nRelInfoStatus == RELINFO_CHANGED_BROKEN || m_nRelInfoStatus == RELINFO_BROKEN
904
62.7k
    return m_aRelInfo;
905
62.7k
}
906
907
void OStorage_Impl::CopyLastCommitTo( const uno::Reference< embed::XStorage >& xNewStor )
908
0
{
909
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
910
911
0
    SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "A committed storage is incomplete!" );
912
0
    if ( !m_xPackageFolder.is() )
913
0
        throw uno::RuntimeException();
914
915
0
    OStorage_Impl aTempRepresent( nullptr,
916
0
                                embed::ElementModes::READ,
917
0
                                m_xPackageFolder,
918
0
                                m_xPackage,
919
0
                                m_xContext,
920
0
                                m_nStorageType);
921
922
    // TODO/LATER: could use direct copying
923
0
    aTempRepresent.CopyToStorage( xNewStor, false );
924
0
}
925
926
void OStorage_Impl::InsertIntoPackageFolder( const OUString& aName,
927
                                             const uno::Reference< container::XNameContainer >& xParentPackageFolder )
928
0
{
929
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
930
931
0
    SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "An inserted storage is incomplete!" );
932
0
    uno::Reference< uno::XInterface > xTmp( m_xPackageFolder, uno::UNO_QUERY_THROW );
933
0
    xParentPackageFolder->insertByName( aName, uno::Any( xTmp ) );
934
935
0
    m_bCommited = false;
936
0
}
937
938
void OStorage_Impl::Commit()
939
0
{
940
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
941
942
0
    if ( !m_bIsModified )
943
0
        return;
944
945
    // in case of a new empty storage it is possible that the contents are still not read
946
    // ( the storage of course has no contents, but the initialization is postponed till the first use,
947
    //   thus if a new storage was created and committed immediately it must be initialized here )
948
0
    ReadContents();
949
950
    // if storage is committed it should have a valid Package representation
951
0
    SAL_WARN_IF( !m_xPackageFolder.is(), "package.xstor", "The package representation should exist!" );
952
0
    if ( !m_xPackageFolder.is() )
953
0
        throw embed::InvalidStorageException();
954
955
0
    OSL_ENSURE( m_nStorageMode & embed::ElementModes::WRITE,
956
0
                "Commit of readonly storage, should be detected before!" );
957
958
0
    uno::Reference< container::XNameContainer > xNewPackageFolder;
959
960
    // here the storage will switch to the temporary package folder
961
    // if the storage was already committed and the parent was not committed after that
962
    // the switch should not be done since the package folder in use is a temporary one;
963
    // it can be detected by m_bCommited flag ( root storage doesn't need temporary representation )
964
0
    if ( !m_bCommited && !m_bIsRoot )
965
0
    {
966
0
        uno::Sequence< uno::Any > aSeq{ uno::Any(true) };
967
0
        xNewPackageFolder.set( m_xPackage->createInstanceWithArguments( aSeq ),
968
0
                               uno::UNO_QUERY );
969
0
    }
970
0
    else
971
0
        xNewPackageFolder = m_xPackageFolder;
972
973
    // remove replaced removed elements
974
0
    for ( auto& pDeleted : m_aDeletedVector )
975
0
    {
976
977
0
        if ( m_nStorageType == embed::StorageFormats::OFOPXML && !pDeleted->m_bIsStorage )
978
0
            RemoveStreamRelInfo( pDeleted->m_aOriginalName );
979
980
        // the removed elements are not in new temporary storage
981
0
        if ( m_bCommited || m_bIsRoot )
982
0
            xNewPackageFolder->removeByName( pDeleted->m_aOriginalName );
983
0
        delete pDeleted;
984
0
        pDeleted = nullptr;
985
0
    }
986
0
    m_aDeletedVector.clear();
987
988
    // remove removed elements
989
0
    for (auto mapIt = m_aChildrenMap.begin(); mapIt != m_aChildrenMap.end(); )
990
0
    {
991
0
        for (auto it = mapIt->second.begin(); it != mapIt->second.end(); )
992
0
        {
993
            // renamed and inserted elements must be really inserted to package later
994
            // since they can conflict with removed elements
995
0
            auto & pElement = *it;
996
0
            if ( pElement->m_bIsRemoved )
997
0
            {
998
0
                if ( m_nStorageType == embed::StorageFormats::OFOPXML && !pElement->m_bIsStorage )
999
0
                    RemoveStreamRelInfo( pElement->m_aOriginalName );
1000
1001
                // the removed elements are not in new temporary storage
1002
0
                if ( m_bCommited || m_bIsRoot )
1003
0
                    xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1004
1005
0
                delete pElement;
1006
0
                it = mapIt->second.erase(it);
1007
0
            }
1008
0
            else
1009
0
                ++it;
1010
0
        }
1011
0
        if (mapIt->second.empty())
1012
0
            mapIt = m_aChildrenMap.erase(mapIt);
1013
0
        else
1014
0
            ++mapIt;
1015
0
    }
1016
1017
1018
    // there should be no more deleted elements
1019
0
    for ( const auto& pair : m_aChildrenMap )
1020
0
        for (auto pElement : pair.second)
1021
0
        {
1022
            // if it is a 'duplicate commit' inserted elements must be really inserted to package later
1023
            // since they can conflict with renamed elements
1024
0
            if ( !pElement->m_bIsInserted )
1025
0
            {
1026
                // for now stream is opened in direct mode that means that in case
1027
                // storage is committed all the streams from it are committed in current state.
1028
                // following two steps are separated to allow easily implement transacted mode
1029
                // for streams if we need it in future.
1030
                // Only hierarchical access uses transacted streams currently
1031
0
                if ( !pElement->m_bIsStorage && pElement->m_xStream
1032
0
                  && !pElement->m_xStream->IsTransacted() )
1033
0
                    pElement->m_xStream->Commit();
1034
1035
                // if the storage was not open, there is no need to commit it ???
1036
                // the storage should be checked that it is committed
1037
0
                if (pElement->m_bIsStorage && pElement->m_xStorage && pElement->m_xStorage->m_bCommited)
1038
0
                {
1039
                    // it's temporary PackageFolder should be inserted instead of current one
1040
                    // also the new copy of PackageFolder should be used by the children storages
1041
1042
                    // the renamed elements are not in new temporary storage
1043
0
                    if ( m_bCommited || m_bIsRoot )
1044
0
                        xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1045
1046
0
                    pElement->m_xStorage->InsertIntoPackageFolder(/*aName*/pair.first, xNewPackageFolder);
1047
0
                }
1048
0
                else if (!pElement->m_bIsStorage && pElement->m_xStream && pElement->m_xStream->m_bFlushed)
1049
0
                {
1050
0
                    if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1051
0
                        CommitStreamRelInfo( /*aName*/pair.first, pElement );
1052
1053
                    // the renamed elements are not in new temporary storage
1054
0
                    if ( m_bCommited || m_bIsRoot )
1055
0
                        xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1056
1057
0
                    pElement->m_xStream->InsertIntoPackageFolder(/*aName*/pair.first, xNewPackageFolder);
1058
0
                }
1059
0
                else if ( !m_bCommited && !m_bIsRoot )
1060
0
                {
1061
                    // the element must be just copied to the new temporary package folder
1062
                    // the connection with the original package should not be lost just because
1063
                    // the element is still referred by the folder in the original hierarchy
1064
0
                    uno::Any aPackageElement = m_xPackageFolder->getByName( pElement->m_aOriginalName );
1065
0
                    xNewPackageFolder->insertByName( /*aName*/pair.first, aPackageElement );
1066
0
                }
1067
0
                else if ( pair.first != pElement->m_aOriginalName )
1068
0
                {
1069
                    // this is the case when xNewPackageFolder refers to m_xPackageFolder
1070
                    // in case the name was changed and it is not a changed storage - rename the element
1071
0
                    uno::Any aPackageElement = xNewPackageFolder->getByName( pElement->m_aOriginalName );
1072
0
                    xNewPackageFolder->removeByName( pElement->m_aOriginalName );
1073
0
                    xNewPackageFolder->insertByName( /*aName*/pair.first, aPackageElement );
1074
1075
0
                    if ( m_nStorageType == embed::StorageFormats::OFOPXML && !pElement->m_bIsStorage )
1076
0
                    {
1077
0
                        if (!pElement->m_xStream)
1078
0
                        {
1079
0
                            OpenSubStream( pElement );
1080
0
                            if (!pElement->m_xStream)
1081
0
                                throw uno::RuntimeException();
1082
0
                        }
1083
1084
0
                        CommitStreamRelInfo( /*aName*/pair.first, pElement );
1085
0
                    }
1086
0
                }
1087
1088
0
                pElement->m_aOriginalName = pair.first;
1089
0
            }
1090
0
        }
1091
1092
0
    for ( const auto& pair : m_aChildrenMap )
1093
0
        for (auto pElement : pair.second)
1094
0
        {
1095
            // now inserted elements can be inserted to the package
1096
0
            if ( pElement->m_bIsInserted )
1097
0
            {
1098
0
                pElement->m_aOriginalName = pair.first;
1099
1100
0
                if ( pElement->m_bIsStorage )
1101
0
                {
1102
0
                    OSL_ENSURE(pElement->m_xStorage, "An inserted storage is incomplete!");
1103
0
                    if (!pElement->m_xStorage)
1104
0
                        throw uno::RuntimeException();
1105
1106
0
                    if (pElement->m_xStorage->m_bCommited)
1107
0
                    {
1108
0
                        pElement->m_xStorage->InsertIntoPackageFolder(/*aName*/pair.first, xNewPackageFolder);
1109
1110
0
                        pElement->m_bIsInserted = false;
1111
0
                    }
1112
0
                }
1113
0
                else
1114
0
                {
1115
0
                    OSL_ENSURE(pElement->m_xStream, "An inserted stream is incomplete!");
1116
0
                    if (!pElement->m_xStream)
1117
0
                        throw uno::RuntimeException();
1118
1119
0
                    if (!pElement->m_xStream->IsTransacted())
1120
0
                        pElement->m_xStream->Commit();
1121
1122
0
                    if (pElement->m_xStream->m_bFlushed)
1123
0
                    {
1124
0
                        if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1125
0
                            CommitStreamRelInfo( /*aName*/pair.first, pElement );
1126
1127
0
                        pElement->m_xStream->InsertIntoPackageFolder( /*aName*/pair.first, xNewPackageFolder );
1128
1129
0
                        pElement->m_bIsInserted = false;
1130
0
                    }
1131
0
                }
1132
0
            }
1133
0
        }
1134
1135
0
    if ( m_nStorageType == embed::StorageFormats::PACKAGE )
1136
0
    {
1137
        // move properties to the destination package folder
1138
0
        uno::Reference< beans::XPropertySet > xProps( xNewPackageFolder, uno::UNO_QUERY_THROW );
1139
0
        xProps->setPropertyValue( u"MediaType"_ustr, uno::Any( m_aMediaType ) );
1140
0
        xProps->setPropertyValue( u"Version"_ustr, uno::Any( m_aVersion ) );
1141
0
    }
1142
1143
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1144
0
        CommitRelInfo( xNewPackageFolder ); // store own relations and commit complete relations storage
1145
1146
0
    if ( m_bIsRoot )
1147
0
    {
1148
0
        uno::Reference< util::XChangesBatch > xChangesBatch( m_xPackage, uno::UNO_QUERY_THROW );
1149
0
        try
1150
0
        {
1151
0
            xChangesBatch->commitChanges();
1152
0
        }
1153
0
        catch( const lang::WrappedTargetException& r )
1154
0
        {
1155
0
            css::uno::Any ex( cppu::getCaughtException() );
1156
            // the wrapped UseBackupException means that the target medium can be corrupted
1157
0
            embed::UseBackupException aException;
1158
0
            if ( r.TargetException >>= aException )
1159
0
            {
1160
0
                m_xStream.clear();
1161
0
                m_xInputStream.clear();
1162
0
                throw aException;
1163
0
            }
1164
1165
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(ex));
1166
0
            throw;
1167
0
        }
1168
0
    }
1169
0
    else if ( !m_bCommited )
1170
0
    {
1171
0
        m_xPackageFolder = std::move(xNewPackageFolder);
1172
0
        m_bCommited = true;
1173
0
    }
1174
1175
    // after commit the mediatype treated as the correct one
1176
0
    m_bMTFallbackUsed = false;
1177
0
}
1178
1179
void OStorage_Impl::Revert()
1180
4.16k
{
1181
4.16k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1182
1183
4.16k
    if ( !( m_nStorageMode & embed::ElementModes::WRITE ) )
1184
0
        return; // nothing to do
1185
1186
    // all the children must be removed
1187
    // they will be created later on demand
1188
1189
    // rebuild the map - cannot do it in-place, because we're changing some of the key values
1190
4.16k
    std::unordered_map<OUString, std::vector<SotElement_Impl*>> oldMap;
1191
4.16k
    std::swap(oldMap, m_aChildrenMap);
1192
1193
4.16k
    for (const auto & rPair : oldMap)
1194
0
        for (auto pElement : rPair.second)
1195
0
        {
1196
0
            if ( pElement->m_bIsInserted )
1197
0
                delete pElement;
1198
0
            else
1199
0
            {
1200
0
                ClearElement( pElement );
1201
1202
0
                pElement->m_bIsRemoved = false;
1203
1204
0
                m_aChildrenMap[pElement->m_aOriginalName].push_back(pElement);
1205
0
            }
1206
0
        }
1207
1208
    // return replaced removed elements
1209
4.16k
    for ( auto& pDeleted : m_aDeletedVector )
1210
0
    {
1211
0
        m_aChildrenMap[pDeleted->m_aOriginalName].push_back(pDeleted);
1212
1213
0
        ClearElement( pDeleted );
1214
1215
0
        pDeleted->m_bIsRemoved = false;
1216
0
    }
1217
4.16k
    m_aDeletedVector.clear();
1218
1219
4.16k
    m_bControlMediaType = false;
1220
4.16k
    m_bControlVersion = false;
1221
1222
4.16k
    GetStorageProperties();
1223
1224
4.16k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1225
0
    {
1226
        // currently the relations storage is changed only on commit
1227
0
        m_xNewRelInfoStream.clear();
1228
0
        m_aRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
1229
0
        m_nRelInfoStatus = RELINFO_NO_INIT;
1230
0
    }
1231
4.16k
}
1232
1233
::comphelper::SequenceAsHashMap OStorage_Impl::GetCommonRootEncryptionData()
1234
0
{
1235
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() ) ;
1236
1237
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
1238
0
        throw packages::NoEncryptionException();
1239
1240
0
    if ( m_bIsRoot )
1241
0
    {
1242
0
        if ( !m_bHasCommonEncryptionData )
1243
0
            throw packages::NoEncryptionException();
1244
1245
0
        return m_aCommonEncryptionData;
1246
0
    }
1247
0
    else
1248
0
    {
1249
0
        if ( !m_pParent )
1250
0
            throw packages::NoEncryptionException();
1251
1252
0
        return m_pParent->GetCommonRootEncryptionData();
1253
0
    }
1254
0
}
1255
1256
SotElement_Impl* OStorage_Impl::FindElement( const OUString& rName )
1257
487k
{
1258
487k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1259
1260
487k
    SAL_WARN_IF( rName.isEmpty(), "package.xstor", "Name is empty!" );
1261
1262
487k
    ReadContents();
1263
1264
487k
    auto mapIt = m_aChildrenMap.find(rName);
1265
487k
    if (mapIt == m_aChildrenMap.end() && m_bRepairPackage)
1266
0
        mapIt = std::find_if(m_aChildrenMap.begin(), m_aChildrenMap.end(),
1267
0
                             [&rName](const auto& pair)
1268
0
                             { return rName.equalsIgnoreAsciiCase(pair.first); });
1269
487k
    if (mapIt == m_aChildrenMap.end())
1270
171k
        return nullptr;
1271
315k
    for (auto pElement : mapIt->second)
1272
315k
        if (!pElement->m_bIsRemoved)
1273
315k
            return pElement;
1274
1275
314
    return nullptr;
1276
315k
}
1277
1278
SotElement_Impl* OStorage_Impl::InsertStream( const OUString& aName, bool bEncr )
1279
246
{
1280
246
    SAL_WARN_IF( !m_xPackage.is(), "package.xstor", "Not possible to refer to package as to factory!" );
1281
246
    if ( !m_xPackage.is() )
1282
0
        throw embed::InvalidStorageException();
1283
1284
246
    uno::Sequence< uno::Any > aSeq{ uno::Any(false) };
1285
246
    uno::Reference< uno::XInterface > xNewElement( m_xPackage->createInstanceWithArguments( aSeq ) );
1286
1287
246
    SAL_WARN_IF( !xNewElement.is(), "package.xstor", "Not possible to create a new stream!" );
1288
246
    if ( !xNewElement.is() )
1289
0
        throw io::IOException();
1290
1291
246
    uno::Reference< packages::XDataSinkEncrSupport > xPackageSubStream( xNewElement, uno::UNO_QUERY_THROW );
1292
1293
246
    OSL_ENSURE( m_nStorageType == embed::StorageFormats::PACKAGE || !bEncr, "Only package storage supports encryption!" );
1294
246
    if ( m_nStorageType != embed::StorageFormats::PACKAGE && bEncr )
1295
0
        throw packages::NoEncryptionException();
1296
1297
    // the mode is not needed for storage stream internal implementation
1298
246
    SotElement_Impl* pNewElement = InsertElement( aName, false );
1299
246
    pNewElement->m_xStream.reset(new OWriteStream_Impl(this, xPackageSubStream, m_xPackage, m_xContext, bEncr, m_nStorageType, true));
1300
1301
246
    m_aChildrenMap[aName].push_back( pNewElement );
1302
246
    m_bIsModified = true;
1303
246
    m_bBroadcastModified = true;
1304
1305
246
    return pNewElement;
1306
246
}
1307
1308
void OStorage_Impl::InsertRawStream( const OUString& aName, const uno::Reference< io::XInputStream >& xInStream )
1309
0
{
1310
    // insert of raw stream means insert and commit
1311
0
    SAL_WARN_IF( !m_xPackage.is(), "package.xstor", "Not possible to refer to package as to factory!" );
1312
0
    if ( !m_xPackage.is() )
1313
0
        throw embed::InvalidStorageException();
1314
1315
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
1316
0
        throw packages::NoEncryptionException();
1317
1318
0
    uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
1319
0
    uno::Reference< io::XInputStream > xInStrToInsert = xSeek.is() ? xInStream :
1320
0
                                                                     GetSeekableTempCopy( xInStream );
1321
1322
0
    uno::Sequence< uno::Any > aSeq{ uno::Any(false) };
1323
0
    uno::Reference< uno::XInterface > xNewElement( m_xPackage->createInstanceWithArguments( aSeq ) );
1324
1325
0
    SAL_WARN_IF( !xNewElement.is(), "package.xstor", "Not possible to create a new stream!" );
1326
0
    if ( !xNewElement.is() )
1327
0
        throw io::IOException();
1328
1329
0
    uno::Reference< packages::XDataSinkEncrSupport > xPackageSubStream( xNewElement, uno::UNO_QUERY_THROW );
1330
0
    xPackageSubStream->setRawStream( xInStrToInsert );
1331
1332
    // the mode is not needed for storage stream internal implementation
1333
0
    SotElement_Impl* pNewElement = InsertElement( aName, false );
1334
0
    pNewElement->m_xStream.reset(new OWriteStream_Impl(this, xPackageSubStream, m_xPackage, m_xContext, true, m_nStorageType, false));
1335
    // the stream is inserted and must be treated as a committed one
1336
0
    pNewElement->m_xStream->SetToBeCommited();
1337
1338
0
    m_aChildrenMap[aName].push_back( pNewElement );
1339
0
    m_bIsModified = true;
1340
0
    m_bBroadcastModified = true;
1341
0
}
1342
1343
std::unique_ptr<OStorage_Impl> OStorage_Impl::CreateNewStorageImpl( sal_Int32 nStorageMode )
1344
4.16k
{
1345
4.16k
    SAL_WARN_IF( !m_xPackage.is(), "package.xstor", "Not possible to refer to package as to factory!" );
1346
4.16k
    if ( !m_xPackage.is() )
1347
0
        throw embed::InvalidStorageException();
1348
1349
4.16k
    uno::Sequence< uno::Any > aSeq{ uno::Any(true) };
1350
4.16k
    uno::Reference< uno::XInterface > xNewElement( m_xPackage->createInstanceWithArguments( aSeq ) );
1351
1352
4.16k
    SAL_WARN_IF( !xNewElement.is(), "package.xstor", "Not possible to create a new storage!" );
1353
4.16k
    if ( !xNewElement.is() )
1354
0
        throw io::IOException();
1355
1356
4.16k
    uno::Reference< container::XNameContainer > xPackageSubFolder( xNewElement, uno::UNO_QUERY_THROW );
1357
4.16k
    std::unique_ptr<OStorage_Impl> pResult(
1358
4.16k
            new OStorage_Impl( this, nStorageMode, xPackageSubFolder, m_xPackage, m_xContext, m_nStorageType ));
1359
4.16k
    pResult->m_bIsModified = true;
1360
1361
4.16k
    return pResult;
1362
4.16k
}
1363
1364
SotElement_Impl* OStorage_Impl::InsertStorage( const OUString& aName, sal_Int32 nStorageMode )
1365
4.16k
{
1366
4.16k
    SotElement_Impl* pNewElement = InsertElement( aName, true );
1367
1368
4.16k
    pNewElement->m_xStorage = CreateNewStorageImpl(nStorageMode);
1369
1370
4.16k
    m_aChildrenMap[aName].push_back( pNewElement );
1371
1372
4.16k
    return pNewElement;
1373
4.16k
}
1374
1375
SotElement_Impl* OStorage_Impl::InsertElement( const OUString& aName, bool bIsStorage )
1376
4.40k
{
1377
4.40k
    assert( FindElement(aName) == nullptr && "Should not try to insert existing element");
1378
1379
4.40k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1380
1381
4.40k
    SotElement_Impl* pDeletedElm = nullptr;
1382
1383
4.40k
    auto it = m_aChildrenMap.find(aName);
1384
4.40k
    if (it != m_aChildrenMap.end())
1385
0
        for (auto pElement : it->second)
1386
0
        {
1387
0
            SAL_WARN_IF( !pElement->m_bIsRemoved, "package.xstor", "Try to insert an element instead of existing one!" );
1388
0
            if ( pElement->m_bIsRemoved )
1389
0
            {
1390
0
                SAL_WARN_IF( pElement->m_bIsInserted, "package.xstor", "Inserted elements must be deleted immediately!" );
1391
0
                pDeletedElm = pElement;
1392
0
            }
1393
0
        }
1394
1395
4.40k
    if ( pDeletedElm )
1396
0
    {
1397
0
        if ( pDeletedElm->m_bIsStorage )
1398
0
            OpenSubStorage( pDeletedElm, embed::ElementModes::READWRITE );
1399
0
        else
1400
0
            OpenSubStream( pDeletedElm );
1401
1402
0
        auto & rVec = m_aChildrenMap[aName];
1403
0
        std::erase(rVec, pDeletedElm);
1404
0
        if (rVec.empty())
1405
0
            m_aChildrenMap.erase(aName);
1406
0
        m_aDeletedVector.push_back( pDeletedElm );
1407
0
    }
1408
1409
    // create new element
1410
4.40k
    return new SotElement_Impl( aName, bIsStorage, true );
1411
4.40k
}
1412
1413
void OStorage_Impl::OpenSubStorage( SotElement_Impl* pElement, sal_Int32 nStorageMode )
1414
79.4k
{
1415
79.4k
    assert(pElement && "pElement is not set!");
1416
79.4k
    SAL_WARN_IF( !pElement->m_bIsStorage, "package.xstor", "Storage flag is not set!" );
1417
1418
79.4k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1419
1420
79.4k
    if (!pElement->m_xStorage)
1421
79.4k
    {
1422
79.4k
        SAL_WARN_IF( pElement->m_bIsInserted, "package.xstor", "Inserted element must be created already!" );
1423
1424
79.4k
        uno::Reference< uno::XInterface > xTmp;
1425
79.4k
        m_xPackageFolder->getByName( pElement->m_aOriginalName ) >>= xTmp;
1426
79.4k
        if ( !xTmp.is() )
1427
0
            throw container::NoSuchElementException();
1428
1429
79.4k
        uno::Reference< container::XNameContainer > xPackageSubFolder( xTmp, uno::UNO_QUERY_THROW );
1430
79.4k
        pElement->m_xStorage.reset(new OStorage_Impl(this, nStorageMode, xPackageSubFolder, m_xPackage, m_xContext, m_nStorageType));
1431
79.4k
    }
1432
79.4k
}
1433
1434
void OStorage_Impl::OpenSubStream( SotElement_Impl* pElement )
1435
157k
{
1436
157k
    assert(pElement && "pElement is not set!");
1437
157k
    SAL_WARN_IF( pElement->m_bIsStorage, "package.xstor", "Storage flag is set!" );
1438
1439
157k
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1440
1441
157k
    if (pElement->m_xStream)
1442
0
        return;
1443
1444
157k
    SAL_WARN_IF( pElement->m_bIsInserted, "package.xstor", "Inserted element must be created already!" );
1445
1446
157k
    uno::Reference< uno::XInterface > xTmp;
1447
157k
    m_xPackageFolder->getByName( pElement->m_aOriginalName ) >>= xTmp;
1448
157k
    if ( !xTmp.is() )
1449
0
        throw container::NoSuchElementException();
1450
1451
157k
    uno::Reference< packages::XDataSinkEncrSupport > xPackageSubStream( xTmp, uno::UNO_QUERY_THROW );
1452
1453
    // the stream can never be inserted here, because inserted stream element holds the stream till commit or destruction
1454
157k
    pElement->m_xStream.reset(new OWriteStream_Impl(this, xPackageSubStream, m_xPackage, m_xContext, false, m_nStorageType, false, GetRelInfoStreamForName(pElement->m_aOriginalName)));
1455
157k
}
1456
1457
uno::Sequence< OUString > OStorage_Impl::GetElementNames()
1458
0
{
1459
0
    ::osl::MutexGuard aGuard( m_xMutex->GetMutex() );
1460
1461
0
    ReadContents();
1462
1463
0
    sal_Int32 nCnt = 0;
1464
0
    for ( const auto& pair : m_aChildrenMap )
1465
0
        for (auto pElement : pair.second)
1466
0
        {
1467
0
            if ( !pElement->m_bIsRemoved )
1468
0
                nCnt++;
1469
0
        }
1470
1471
0
    uno::Sequence<OUString> aElementNames(nCnt);
1472
0
    OUString* pArray = aElementNames.getArray();
1473
0
    for ( const auto& pair : m_aChildrenMap )
1474
0
        for (auto pElement : pair.second)
1475
0
        {
1476
0
            if ( !pElement->m_bIsRemoved )
1477
0
                *pArray++ = pair.first;
1478
0
        }
1479
1480
0
    return aElementNames;
1481
0
}
1482
1483
void OStorage_Impl::RemoveElement( OUString const & rName, SotElement_Impl* pElement )
1484
0
{
1485
0
    assert(pElement);
1486
1487
0
    if ( (pElement->m_xStorage && ( pElement->m_xStorage->m_pAntiImpl || !pElement->m_xStorage->m_aReadOnlyWrapVector.empty() ))
1488
0
      || (pElement->m_xStream && ( pElement->m_xStream->m_pAntiImpl || !pElement->m_xStream->m_aInputStreamsVector.empty() )) )
1489
0
        throw io::IOException(); // TODO: Access denied
1490
1491
0
    auto mapIt = m_aChildrenMap.find(rName);
1492
0
    for (auto it = mapIt->second.begin(); it != mapIt->second.end(); ++it)
1493
0
        if (pElement == *it)
1494
0
        {
1495
0
            if ( pElement->m_bIsInserted )
1496
0
            {
1497
0
                delete pElement;
1498
0
                std::erase(mapIt->second, pElement);
1499
0
                if (mapIt->second.empty())
1500
0
                    m_aChildrenMap.erase(mapIt);
1501
0
            }
1502
0
            else
1503
0
            {
1504
0
                pElement->m_bIsRemoved = true;
1505
0
                ClearElement( pElement );
1506
0
            }
1507
0
            return;
1508
0
        }
1509
0
    assert(false && "not found");
1510
1511
    // TODO/OFOPXML: the rel stream should be removed as well
1512
0
}
1513
1514
void OStorage_Impl::ClearElement( SotElement_Impl* pElement )
1515
0
{
1516
0
    pElement->m_xStorage.reset();
1517
0
    pElement->m_xStream.reset();
1518
0
}
1519
1520
void OStorage_Impl::CloneStreamElement( const OUString& aStreamName,
1521
                                        bool bEncryptionDataProvided,
1522
                                        const ::comphelper::SequenceAsHashMap& aEncryptionData,
1523
                                        uno::Reference< io::XStream >& xTargetStream )
1524
0
{
1525
0
    SotElement_Impl *pElement = FindElement( aStreamName );
1526
0
    if ( !pElement )
1527
0
    {
1528
        // element does not exist, throw exception
1529
0
        throw io::IOException(); // TODO: access_denied
1530
0
    }
1531
0
    else if ( pElement->m_bIsStorage )
1532
0
        throw io::IOException();
1533
1534
0
    if (!pElement->m_xStream)
1535
0
        OpenSubStream( pElement );
1536
1537
0
    if (!pElement->m_xStream || !pElement->m_xStream->m_xPackageStream.is())
1538
0
        throw io::IOException(); // TODO: general_error
1539
1540
    // the existence of m_pAntiImpl of the child is not interesting,
1541
    // the copy will be created internally
1542
1543
    // usual copying is not applicable here, only last flushed version of the
1544
    // child stream should be used for copying. Probably the children m_xPackageStream
1545
    // can be used as a base of a new stream, that would be copied to result
1546
    // storage. The only problem is that some package streams can be accessed from outside
1547
    // at the same time (now solved by wrappers that remember own position).
1548
1549
0
    if (bEncryptionDataProvided)
1550
0
        pElement->m_xStream->GetCopyOfLastCommit(xTargetStream, aEncryptionData);
1551
0
    else
1552
0
        pElement->m_xStream->GetCopyOfLastCommit(xTargetStream);
1553
0
}
1554
1555
void OStorage_Impl::RemoveStreamRelInfo( std::u16string_view aOriginalName )
1556
0
{
1557
    // this method should be used only in OStorage_Impl::Commit() method
1558
    // the aOriginalName can be empty, in this case the storage relation info should be removed
1559
1560
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && m_xRelStorage.is() )
1561
0
    {
1562
0
        OUString aRelStreamName = OUString::Concat(aOriginalName) + ".rels";
1563
1564
0
        if ( m_xRelStorage->hasByName( aRelStreamName ) )
1565
0
            m_xRelStorage->removeElement( aRelStreamName );
1566
0
    }
1567
0
}
1568
1569
void OStorage_Impl::CreateRelStorage()
1570
15.5k
{
1571
15.5k
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
1572
0
        return;
1573
1574
15.5k
    if ( m_xRelStorage.is() )
1575
0
        return;
1576
1577
15.5k
    if ( !m_pRelStorElement )
1578
0
    {
1579
0
        m_pRelStorElement = new SotElement_Impl( u"_rels"_ustr, true, true );
1580
0
        m_pRelStorElement->m_xStorage = CreateNewStorageImpl(embed::ElementModes::WRITE);
1581
0
        m_pRelStorElement->m_xStorage->m_pParent = nullptr; // the relation storage is completely controlled by parent
1582
0
    }
1583
1584
15.5k
    if (!m_pRelStorElement->m_xStorage)
1585
15.5k
        OpenSubStorage( m_pRelStorElement, embed::ElementModes::WRITE );
1586
1587
15.5k
    if (!m_pRelStorElement->m_xStorage)
1588
0
        throw uno::RuntimeException();
1589
1590
15.5k
    m_xRelStorage = new OStorage(m_pRelStorElement->m_xStorage.get(), false);
1591
15.5k
}
1592
1593
void OStorage_Impl::CommitStreamRelInfo( std::u16string_view rName, SotElement_Impl const * pStreamElement )
1594
0
{
1595
    // this method should be used only in OStorage_Impl::Commit() method
1596
1597
    // the stream element must be provided
1598
0
    if ( !pStreamElement )
1599
0
        throw uno::RuntimeException();
1600
1601
0
    if (m_nStorageType == embed::StorageFormats::OFOPXML && pStreamElement->m_xStream)
1602
0
    {
1603
0
        SAL_WARN_IF( rName.empty(), "package.xstor", "The name must not be empty!" );
1604
1605
0
        if ( !m_xRelStorage.is() )
1606
0
        {
1607
            // Create new rels storage, this is commit scenario so it must be possible
1608
0
            CreateRelStorage();
1609
0
        }
1610
1611
0
        pStreamElement->m_xStream->CommitStreamRelInfo(m_xRelStorage, pStreamElement->m_aOriginalName, rName);
1612
0
    }
1613
0
}
1614
1615
uno::Reference< io::XInputStream > OStorage_Impl::GetRelInfoStreamForName(
1616
    std::u16string_view aName )
1617
171k
{
1618
171k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML )
1619
64.7k
    {
1620
64.7k
        ReadContents();
1621
64.7k
        if ( m_xRelStorage.is() )
1622
30.8k
        {
1623
30.8k
            OUString aRelStreamName = OUString::Concat(aName) + ".rels";
1624
30.8k
            if ( m_xRelStorage->hasByName( aRelStreamName ) )
1625
16.7k
            {
1626
16.7k
                uno::Reference< io::XStream > xStream = m_xRelStorage->openStreamElement( aRelStreamName, embed::ElementModes::READ );
1627
16.7k
                if ( xStream.is() )
1628
15.9k
                    return xStream->getInputStream();
1629
16.7k
            }
1630
30.8k
        }
1631
64.7k
    }
1632
1633
155k
    return uno::Reference< io::XInputStream >();
1634
171k
}
1635
1636
void OStorage_Impl::CommitRelInfo( const uno::Reference< container::XNameContainer >& xNewPackageFolder )
1637
0
{
1638
    // this method should be used only in OStorage_Impl::Commit() method
1639
0
    OUString aRelsStorName(u"_rels"_ustr);
1640
1641
0
    if ( !xNewPackageFolder.is() )
1642
0
        throw uno::RuntimeException();
1643
1644
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
1645
0
        return;
1646
1647
0
    if ( m_nRelInfoStatus == RELINFO_BROKEN || m_nRelInfoStatus == RELINFO_CHANGED_BROKEN )
1648
0
        throw io::IOException();
1649
1650
0
    if (m_nRelInfoStatus == RELINFO_CHANGED)
1651
0
    {
1652
0
        if (m_aRelInfo.hasElements())
1653
0
        {
1654
0
            CreateRelStorage();
1655
1656
0
            uno::Reference<io::XStream> xRelsStream = m_xRelStorage->openStreamElement(
1657
0
                u".rels"_ustr, embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE);
1658
1659
0
            uno::Reference<io::XOutputStream> xOutStream = xRelsStream->getOutputStream();
1660
0
            if (!xOutStream.is())
1661
0
                throw uno::RuntimeException();
1662
1663
0
            ::comphelper::OFOPXMLHelper::WriteRelationsInfoSequence(xOutStream, m_aRelInfo,
1664
0
                                                                    m_xContext);
1665
1666
            // set the mediatype
1667
0
            uno::Reference<beans::XPropertySet> xPropSet(xRelsStream, uno::UNO_QUERY_THROW);
1668
0
            xPropSet->setPropertyValue(
1669
0
                u"MediaType"_ustr, uno::Any(u"application/vnd.openxmlformats-package.relationships+xml"_ustr));
1670
1671
0
            m_nRelInfoStatus = RELINFO_READ;
1672
0
        }
1673
0
        else if (m_xRelStorage.is())
1674
0
            RemoveStreamRelInfo(std::u16string_view()); // remove own rel info
1675
0
    }
1676
0
    else if (m_nRelInfoStatus == RELINFO_CHANGED_STREAM_READ
1677
0
             || m_nRelInfoStatus == RELINFO_CHANGED_STREAM)
1678
0
    {
1679
0
        CreateRelStorage();
1680
1681
0
        uno::Reference<io::XStream> xRelsStream = m_xRelStorage->openStreamElement(
1682
0
            u".rels"_ustr, embed::ElementModes::TRUNCATE | embed::ElementModes::READWRITE);
1683
1684
0
        uno::Reference<io::XOutputStream> xOutputStream = xRelsStream->getOutputStream();
1685
0
        if (!xOutputStream.is())
1686
0
            throw uno::RuntimeException();
1687
1688
0
        uno::Reference<io::XSeekable> xSeek(m_xNewRelInfoStream, uno::UNO_QUERY_THROW);
1689
0
        xSeek->seek(0);
1690
0
        ::comphelper::OStorageHelper::CopyInputToOutput(m_xNewRelInfoStream, xOutputStream);
1691
1692
        // set the mediatype
1693
0
        uno::Reference<beans::XPropertySet> xPropSet(xRelsStream, uno::UNO_QUERY_THROW);
1694
0
        xPropSet->setPropertyValue(
1695
0
            u"MediaType"_ustr,
1696
0
            uno::Any(u"application/vnd.openxmlformats-package.relationships+xml"_ustr));
1697
1698
0
        m_xNewRelInfoStream.clear();
1699
0
        if (m_nRelInfoStatus == RELINFO_CHANGED_STREAM)
1700
0
        {
1701
0
            m_aRelInfo = uno::Sequence<uno::Sequence<beans::StringPair>>();
1702
0
            m_nRelInfoStatus = RELINFO_NO_INIT;
1703
0
        }
1704
0
        else
1705
0
            m_nRelInfoStatus = RELINFO_READ;
1706
0
    }
1707
1708
0
    if ( !m_xRelStorage.is() )
1709
0
        return;
1710
1711
0
    if ( m_xRelStorage->hasElements() )
1712
0
    {
1713
0
        m_xRelStorage->commit();
1714
0
    }
1715
1716
0
    if ( xNewPackageFolder.is() && xNewPackageFolder->hasByName( aRelsStorName ) )
1717
0
        xNewPackageFolder->removeByName( aRelsStorName );
1718
1719
0
    if ( !m_xRelStorage->hasElements() )
1720
0
    {
1721
        // the empty relations storage should not be created
1722
0
        delete m_pRelStorElement;
1723
0
        m_pRelStorElement = nullptr;
1724
0
        m_xRelStorage.clear();
1725
0
    }
1726
0
    else if ( m_pRelStorElement && m_pRelStorElement->m_xStorage && xNewPackageFolder.is() )
1727
0
        m_pRelStorElement->m_xStorage->InsertIntoPackageFolder( aRelsStorName, xNewPackageFolder );
1728
0
}
1729
1730
// OStorage implementation
1731
1732
OStorage::OStorage( uno::Reference< io::XInputStream > const & xInputStream,
1733
                    sal_Int32 nMode,
1734
                    const uno::Sequence< beans::PropertyValue >& xProperties,
1735
                    uno::Reference< uno::XComponentContext > const & xContext,
1736
                    sal_Int32 nStorageType )
1737
40.8k
: m_pImpl( new OStorage_Impl( xInputStream, nMode, xProperties, xContext, nStorageType ) )
1738
40.8k
, m_xSharedMutex( m_pImpl->m_xMutex )
1739
40.8k
, m_aListenersContainer( m_pImpl->m_xMutex->GetMutex() )
1740
40.8k
, m_nStorageType( m_pImpl->m_nStorageType )
1741
40.8k
, m_bReadOnlyWrap( false )
1742
40.8k
{
1743
40.8k
    m_pImpl->m_pAntiImpl = this;
1744
40.8k
}
1745
1746
OStorage::OStorage( uno::Reference< io::XStream > const & xStream,
1747
                    sal_Int32 nMode,
1748
                    const uno::Sequence< beans::PropertyValue >& xProperties,
1749
                    uno::Reference< uno::XComponentContext > const & xContext,
1750
                    sal_Int32 nStorageType )
1751
76.7k
: m_pImpl( new OStorage_Impl( xStream, nMode, xProperties, xContext, nStorageType ) )
1752
76.7k
, m_xSharedMutex( m_pImpl->m_xMutex )
1753
76.7k
, m_aListenersContainer( m_pImpl->m_xMutex->GetMutex() )
1754
76.7k
, m_nStorageType( m_pImpl->m_nStorageType )
1755
76.7k
, m_bReadOnlyWrap( false )
1756
76.7k
{
1757
76.7k
    m_pImpl->m_pAntiImpl = this;
1758
76.7k
}
1759
1760
OStorage::OStorage( OStorage_Impl* pImpl, bool bReadOnlyWrap )
1761
85.9k
: m_pImpl( pImpl )
1762
85.9k
, m_xSharedMutex( m_pImpl->m_xMutex )
1763
85.9k
, m_aListenersContainer( m_pImpl->m_xMutex->GetMutex() )
1764
85.9k
, m_nStorageType( m_pImpl->m_nStorageType )
1765
85.9k
, m_bReadOnlyWrap( bReadOnlyWrap )
1766
85.9k
{
1767
    // this call can be done only from OStorage_Impl implementation to create child storage
1768
85.9k
    assert( m_pImpl && m_pImpl->m_xMutex.is() && "The provided pointer & mutex MUST NOT be empty!" );
1769
1770
85.9k
    OSL_ENSURE( ( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE ) == embed::ElementModes::WRITE ||
1771
85.9k
                    m_bReadOnlyWrap,
1772
85.9k
                "The wrapper can not allow writing in case implementation does not!" );
1773
1774
85.9k
    if ( !bReadOnlyWrap )
1775
19.7k
        m_pImpl->m_pAntiImpl = this;
1776
85.9k
}
1777
1778
OStorage::~OStorage()
1779
203k
{
1780
203k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
1781
203k
    if ( m_pImpl )
1782
55.6k
    {
1783
55.6k
        osl_atomic_increment(&m_refCount); // to call dispose
1784
55.6k
        try {
1785
55.6k
            dispose();
1786
55.6k
        }
1787
55.6k
        catch( const uno::RuntimeException& )
1788
55.6k
        {
1789
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Handled exception");
1790
0
        }
1791
55.6k
    }
1792
203k
}
1793
1794
void OStorage::InternalDispose( bool bNotifyImpl )
1795
251k
{
1796
251k
    if ( !m_pImpl )
1797
0
        return;
1798
1799
    // the source object is also a kind of locker for the current object
1800
    // since the listeners could dispose the object while being notified
1801
251k
    lang::EventObject aSource( getXWeak() );
1802
251k
    m_aListenersContainer.disposeAndClear( aSource );
1803
1804
251k
    if ( !m_pImpl )
1805
0
        return;
1806
1807
251k
    m_pImpl->m_nModifiedListenerCount = 0;
1808
1809
251k
    if ( m_bReadOnlyWrap )
1810
114k
    {
1811
114k
        OSL_ENSURE( m_aOpenSubComponentsVector.empty() || m_pSubElDispListener,
1812
114k
                    "If any subelements are open the listener must exist!" );
1813
1814
114k
        if (m_pSubElDispListener)
1815
86.2k
        {
1816
86.2k
            m_pSubElDispListener->OwnerIsDisposed();
1817
1818
            // iterate through m_pData->m_aOpenSubComponentsVector
1819
            // deregister m_pData->m_pSubElDispListener and dispose all of them
1820
86.2k
            if ( !m_aOpenSubComponentsVector.empty() )
1821
18.0k
            {
1822
18.0k
                for ( const auto& pComp : m_aOpenSubComponentsVector )
1823
36.3k
                {
1824
36.3k
                    uno::Reference< lang::XComponent > xTmp = pComp;
1825
36.3k
                    if ( xTmp.is() )
1826
36.3k
                    {
1827
36.3k
                        xTmp->removeEventListener( uno::Reference< lang::XEventListener >(
1828
36.3k
                            static_cast< lang::XEventListener* >( m_pSubElDispListener.get())));
1829
1830
36.3k
                        try {
1831
36.3k
                            xTmp->dispose();
1832
36.3k
                        } catch( const uno::Exception& )
1833
36.3k
                        {
1834
0
                            TOOLS_INFO_EXCEPTION("package.xstor", "Quiet exception");
1835
0
                        }
1836
36.3k
                    }
1837
36.3k
                }
1838
1839
18.0k
                m_aOpenSubComponentsVector.clear();
1840
18.0k
            }
1841
86.2k
        }
1842
1843
114k
        if ( bNotifyImpl )
1844
51.4k
            m_pImpl->RemoveReadOnlyWrap( *this );
1845
114k
    }
1846
137k
    else
1847
137k
    {
1848
137k
        m_pImpl->m_pAntiImpl = nullptr;
1849
1850
137k
        if ( bNotifyImpl )
1851
121k
        {
1852
121k
            if ( m_pImpl->m_bIsRoot )
1853
117k
                delete m_pImpl;
1854
4.16k
            else
1855
4.16k
            {
1856
                // the non-committed changes for the storage must be removed
1857
4.16k
                m_pImpl->Revert();
1858
4.16k
            }
1859
121k
        }
1860
137k
    }
1861
1862
251k
    m_pImpl = nullptr;
1863
251k
}
1864
1865
void OStorage::ChildIsDisposed( const uno::Reference< uno::XInterface >& xChild )
1866
126k
{
1867
    // this method can only be called by child disposing listener
1868
1869
    // this method must not contain any locking
1870
    // the locking is done in the listener
1871
1872
126k
    auto& rVec = m_aOpenSubComponentsVector;
1873
126k
    std::erase_if(rVec,
1874
218k
        [&xChild](const uno::Reference<lang::XComponent>& xTmp) {
1875
218k
            return !xTmp.is() || xTmp == xChild;
1876
218k
        });
1877
126k
}
1878
1879
void OStorage::BroadcastModifiedIfNecessary()
1880
238k
{
1881
    // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
1882
238k
    if ( !m_pImpl )
1883
0
    {
1884
0
        SAL_INFO("package.xstor", "Disposed");
1885
0
        throw lang::DisposedException();
1886
0
    }
1887
1888
238k
    if ( !m_pImpl->m_bBroadcastModified )
1889
117k
        return;
1890
1891
121k
    m_pImpl->m_bBroadcastModified = false;
1892
1893
121k
    SAL_WARN_IF( m_bReadOnlyWrap, "package.xstor", "The storage can not be modified at all!" );
1894
1895
121k
    lang::EventObject aSource( getXWeak() );
1896
1897
121k
    comphelper::OInterfaceContainerHelper2* pContainer =
1898
121k
            m_aListenersContainer.getContainer(
1899
121k
                cppu::UnoType<util::XModifyListener>::get());
1900
121k
    if ( pContainer )
1901
0
    {
1902
0
           comphelper::OInterfaceIteratorHelper2 pIterator( *pContainer );
1903
0
           while ( pIterator.hasMoreElements( ) )
1904
0
           {
1905
0
               static_cast<util::XModifyListener*>( pIterator.next( ) )->modified( aSource );
1906
0
           }
1907
0
    }
1908
121k
}
1909
1910
void OStorage::BroadcastTransaction( sal_Int8 nMessage )
1911
/*
1912
    1 - preCommit
1913
    2 - committed
1914
    3 - preRevert
1915
    4 - reverted
1916
*/
1917
0
{
1918
    // no need to lock mutex here for the checking of m_pImpl, and m_pData is alive until the object is destructed
1919
0
    if ( !m_pImpl )
1920
0
    {
1921
0
        SAL_INFO("package.xstor", "Disposed");
1922
0
        throw lang::DisposedException();
1923
0
    }
1924
1925
0
    SAL_WARN_IF( m_bReadOnlyWrap, "package.xstor", "The storage can not be modified at all!" );
1926
1927
0
    lang::EventObject aSource( getXWeak() );
1928
1929
0
    comphelper::OInterfaceContainerHelper2* pContainer =
1930
0
            m_aListenersContainer.getContainer(
1931
0
                cppu::UnoType<embed::XTransactionListener>::get());
1932
0
    if ( !pContainer )
1933
0
           return;
1934
1935
0
    comphelper::OInterfaceIteratorHelper2 pIterator( *pContainer );
1936
0
    while ( pIterator.hasMoreElements( ) )
1937
0
    {
1938
0
        OSL_ENSURE( nMessage >= 1 && nMessage <= 4, "Wrong internal notification code is used!" );
1939
1940
0
        switch( nMessage )
1941
0
        {
1942
0
            case STOR_MESS_PRECOMMIT:
1943
0
                   static_cast<embed::XTransactionListener*>( pIterator.next( ) )->preCommit( aSource );
1944
0
                break;
1945
0
            case STOR_MESS_COMMITTED:
1946
0
                   static_cast<embed::XTransactionListener*>( pIterator.next( ) )->commited( aSource );
1947
0
                break;
1948
0
            case STOR_MESS_PREREVERT:
1949
0
                   static_cast<embed::XTransactionListener*>( pIterator.next( ) )->preRevert( aSource );
1950
0
                break;
1951
0
            case STOR_MESS_REVERTED:
1952
0
                   static_cast<embed::XTransactionListener*>( pIterator.next( ) )->reverted( aSource );
1953
0
                break;
1954
0
        }
1955
0
    }
1956
0
}
1957
1958
SotElement_Impl* OStorage::OpenStreamElement_Impl( const OUString& aStreamName, sal_Int32 nOpenMode, bool bEncr )
1959
212k
{
1960
212k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
1961
1962
212k
    OSL_ENSURE( !m_bReadOnlyWrap || ( nOpenMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE,
1963
212k
                "An element can not be opened for writing in readonly storage!" );
1964
1965
212k
    SotElement_Impl *pElement = m_pImpl->FindElement( aStreamName );
1966
212k
    if ( !pElement )
1967
33.0k
    {
1968
        // element does not exist, check if creation is allowed
1969
33.0k
        if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
1970
246
          || (( nOpenMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE )
1971
246
          || ( nOpenMode & embed::ElementModes::NOCREATE ) == embed::ElementModes::NOCREATE )
1972
32.8k
        {
1973
32.8k
            throw io::IOException("Element does not exist and cannot be "
1974
32.8k
                    "created: \"" + aStreamName + "\""); // TODO: access_denied
1975
32.8k
        }
1976
1977
        // create a new StreamElement and insert it into the list
1978
246
        pElement = m_pImpl->InsertStream( aStreamName, bEncr );
1979
246
    }
1980
179k
    else if ( pElement->m_bIsStorage )
1981
0
    {
1982
0
        throw io::IOException();
1983
0
    }
1984
1985
212k
    assert(pElement && "In case element can not be created an exception must be thrown!");
1986
1987
179k
    if (!pElement->m_xStream)
1988
157k
        m_pImpl->OpenSubStream( pElement );
1989
1990
179k
    if (!pElement->m_xStream)
1991
0
        throw io::IOException();
1992
1993
179k
    return pElement;
1994
179k
}
1995
1996
void OStorage::MakeLinkToSubComponent_Impl( const uno::Reference< lang::XComponent >& xComponent )
1997
162k
{
1998
162k
    if ( !xComponent.is() )
1999
0
        throw uno::RuntimeException();
2000
2001
162k
    if (!m_pSubElDispListener)
2002
68.6k
    {
2003
68.6k
        m_pSubElDispListener = new OChildDispListener_Impl( *this );
2004
68.6k
    }
2005
2006
162k
    xComponent->addEventListener( m_pSubElDispListener );
2007
2008
162k
    m_aOpenSubComponentsVector.emplace_back(xComponent );
2009
162k
}
2010
2011
//  XInterface
2012
2013
uno::Any SAL_CALL OStorage::queryInterface( const uno::Type& rType )
2014
768k
{
2015
    // common interfaces
2016
768k
    uno::Any aReturn = ::cppu::queryInterface
2017
768k
                (   rType
2018
768k
                ,   static_cast<lang::XTypeProvider*> ( this )
2019
768k
                ,   static_cast<embed::XStorage*> ( this )
2020
768k
                ,   static_cast<embed::XStorage2*> ( this )
2021
768k
                ,   static_cast<embed::XTransactedObject*> ( this )
2022
768k
                ,   static_cast<embed::XTransactionBroadcaster*> ( this )
2023
768k
                ,   static_cast<util::XModifiable*> ( this )
2024
768k
                ,   static_cast<container::XNameAccess*> ( this )
2025
768k
                ,   static_cast<container::XElementAccess*> ( this )
2026
768k
                ,   static_cast<lang::XComponent*> ( this )
2027
768k
                ,   static_cast<beans::XPropertySet*> ( this )
2028
768k
                ,   static_cast<embed::XOptimizedStorage*> ( this ) );
2029
2030
768k
    if ( aReturn.hasValue() )
2031
368k
        return aReturn ;
2032
2033
400k
    aReturn = ::cppu::queryInterface
2034
400k
                (   rType
2035
400k
                ,   static_cast<embed::XHierarchicalStorageAccess*> ( this )
2036
400k
                ,   static_cast<embed::XHierarchicalStorageAccess2*> ( this ) );
2037
2038
400k
    if ( aReturn.hasValue() )
2039
75.9k
        return aReturn ;
2040
2041
324k
    if ( m_nStorageType == embed::StorageFormats::PACKAGE )
2042
58.6k
    {
2043
58.6k
        if ( m_pImpl->m_bIsRoot )
2044
58.6k
        {
2045
58.6k
            aReturn = ::cppu::queryInterface
2046
58.6k
                        (   rType
2047
58.6k
                        ,   static_cast<embed::XStorageRawAccess*> ( this )
2048
58.6k
                        ,   static_cast<embed::XEncryptionProtectedSource*> ( this )
2049
58.6k
                        ,   static_cast<embed::XEncryptionProtectedSource2*> ( this )
2050
58.6k
                        ,   static_cast<embed::XEncryptionProtectedStorage*> ( this ) );
2051
58.6k
        }
2052
0
        else
2053
0
        {
2054
0
            aReturn = ::cppu::queryInterface
2055
0
                        (   rType
2056
0
                        ,   static_cast<embed::XStorageRawAccess*> ( this ) );
2057
0
        }
2058
58.6k
    }
2059
266k
    else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
2060
100k
    {
2061
100k
        aReturn = ::cppu::queryInterface
2062
100k
                    (   rType
2063
100k
                    ,   static_cast<embed::XRelationshipAccess*> ( this ) );
2064
100k
    }
2065
2066
324k
    if ( aReturn.hasValue() )
2067
118k
        return aReturn ;
2068
2069
206k
    return OWeakObject::queryInterface( rType );
2070
324k
}
2071
2072
void SAL_CALL OStorage::acquire() noexcept
2073
2.54M
{
2074
2.54M
    OWeakObject::acquire();
2075
2.54M
}
2076
2077
void SAL_CALL OStorage::release() noexcept
2078
2.54M
{
2079
2.54M
    OWeakObject::release();
2080
2.54M
}
2081
2082
//  XTypeProvider
2083
uno::Sequence< uno::Type > SAL_CALL OStorage::getTypes()
2084
0
{
2085
0
    if (! m_oTypeCollection)
2086
0
    {
2087
0
        ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2088
2089
0
        if (! m_oTypeCollection)
2090
0
        {
2091
0
            if ( m_nStorageType == embed::StorageFormats::PACKAGE )
2092
0
            {
2093
0
                if ( m_pImpl->m_bIsRoot )
2094
0
                {
2095
0
                    m_oTypeCollection.emplace(
2096
0
                                        cppu::UnoType<lang::XTypeProvider>::get()
2097
0
                                    ,   cppu::UnoType<embed::XStorage>::get()
2098
0
                                    ,   cppu::UnoType<embed::XStorage2>::get()
2099
0
                                    ,   cppu::UnoType<embed::XStorageRawAccess>::get()
2100
0
                                    ,   cppu::UnoType<embed::XTransactedObject>::get()
2101
0
                                    ,   cppu::UnoType<embed::XTransactionBroadcaster>::get()
2102
0
                                    ,   cppu::UnoType<util::XModifiable>::get()
2103
0
                                    ,   cppu::UnoType<embed::XEncryptionProtectedStorage>::get()
2104
0
                                    ,   cppu::UnoType<embed::XEncryptionProtectedSource2>::get()
2105
0
                                    ,   cppu::UnoType<embed::XEncryptionProtectedSource>::get()
2106
0
                                    ,   cppu::UnoType<beans::XPropertySet>::get());
2107
0
                }
2108
0
                else
2109
0
                {
2110
0
                    m_oTypeCollection.emplace(
2111
0
                                        cppu::UnoType<lang::XTypeProvider>::get()
2112
0
                                    ,   cppu::UnoType<embed::XStorage>::get()
2113
0
                                    ,   cppu::UnoType<embed::XStorage2>::get()
2114
0
                                    ,   cppu::UnoType<embed::XStorageRawAccess>::get()
2115
0
                                    ,   cppu::UnoType<embed::XTransactedObject>::get()
2116
0
                                    ,   cppu::UnoType<embed::XTransactionBroadcaster>::get()
2117
0
                                    ,   cppu::UnoType<util::XModifiable>::get()
2118
0
                                    ,   cppu::UnoType<beans::XPropertySet>::get());
2119
0
                }
2120
0
            }
2121
0
            else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
2122
0
            {
2123
0
                m_oTypeCollection.emplace(
2124
0
                                    cppu::UnoType<lang::XTypeProvider>::get()
2125
0
                                ,   cppu::UnoType<embed::XStorage>::get()
2126
0
                                ,   cppu::UnoType<embed::XTransactedObject>::get()
2127
0
                                ,   cppu::UnoType<embed::XTransactionBroadcaster>::get()
2128
0
                                ,   cppu::UnoType<util::XModifiable>::get()
2129
0
                                ,   cppu::UnoType<embed::XRelationshipAccess>::get()
2130
0
                                ,   cppu::UnoType<beans::XPropertySet>::get());
2131
0
            }
2132
0
            else
2133
0
            {
2134
0
                m_oTypeCollection.emplace(
2135
0
                                    cppu::UnoType<lang::XTypeProvider>::get()
2136
0
                                ,   cppu::UnoType<embed::XStorage>::get()
2137
0
                                ,   cppu::UnoType<embed::XTransactedObject>::get()
2138
0
                                ,   cppu::UnoType<embed::XTransactionBroadcaster>::get()
2139
0
                                ,   cppu::UnoType<util::XModifiable>::get()
2140
0
                                ,   cppu::UnoType<beans::XPropertySet>::get());
2141
0
            }
2142
0
        }
2143
0
    }
2144
2145
0
    return m_oTypeCollection->getTypes() ;
2146
0
}
2147
2148
uno::Sequence< sal_Int8 > SAL_CALL OStorage::getImplementationId()
2149
0
{
2150
0
    static const comphelper::UnoIdInit lcl_ImplId;
2151
0
    return lcl_ImplId.getSeq();
2152
0
}
2153
2154
//  XStorage
2155
void SAL_CALL OStorage::copyToStorage( const uno::Reference< embed::XStorage >& xDest )
2156
0
{
2157
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2158
2159
0
    if ( !m_pImpl )
2160
0
    {
2161
0
        SAL_INFO("package.xstor", "Disposed");
2162
0
        throw lang::DisposedException();
2163
0
    }
2164
2165
0
    if ( !xDest.is() || xDest == getXWeak() )
2166
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 );
2167
2168
0
    try {
2169
0
        m_pImpl->CopyToStorage( xDest, false );
2170
0
    }
2171
0
    catch( const embed::InvalidStorageException& )
2172
0
    {
2173
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2174
0
        throw;
2175
0
    }
2176
0
    catch( const lang::IllegalArgumentException& )
2177
0
    {
2178
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2179
0
        throw;
2180
0
    }
2181
0
    catch( const embed::StorageWrappedTargetException& )
2182
0
    {
2183
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2184
0
        throw;
2185
0
    }
2186
0
    catch( const io::IOException& )
2187
0
    {
2188
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2189
0
        throw;
2190
0
    }
2191
0
    catch( const uno::RuntimeException& )
2192
0
    {
2193
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2194
0
        throw;
2195
0
    }
2196
0
    catch( const uno::Exception& )
2197
0
    {
2198
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2199
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2200
2201
0
        throw embed::StorageWrappedTargetException( u"Can't copy storage!"_ustr,
2202
0
                                                 uno::Reference< io::XInputStream >(),
2203
0
                                                 aCaught );
2204
0
    }
2205
0
}
2206
2207
uno::Reference< io::XStream > SAL_CALL OStorage::openStreamElement(
2208
    const OUString& aStreamName, sal_Int32 nOpenMode )
2209
173k
{
2210
173k
    osl::ClearableMutexGuard aGuard(m_xSharedMutex->GetMutex());
2211
2212
173k
    if ( !m_pImpl )
2213
0
    {
2214
0
        SAL_INFO("package.xstor", "Disposed");
2215
0
        throw lang::DisposedException();
2216
0
    }
2217
2218
173k
    if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
2219
9
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2220
2221
173k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
2222
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable element name
2223
2224
173k
    if ( ( nOpenMode & embed::ElementModes::WRITE ) && m_bReadOnlyWrap )
2225
0
        throw io::IOException(); // TODO: access denied
2226
2227
173k
    uno::Reference< io::XStream > xResult;
2228
173k
    try
2229
173k
    {
2230
173k
        SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamName, nOpenMode, false );
2231
173k
        assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
2232
2233
173k
        xResult = pElement->m_xStream->GetStream(nOpenMode, false);
2234
173k
        SAL_WARN_IF( !xResult.is(), "package.xstor", "The method must throw exception instead of removing empty result!" );
2235
2236
173k
        if ( m_bReadOnlyWrap )
2237
96.5k
        {
2238
            // before the storage disposes the stream it must deregister itself as listener
2239
96.5k
            uno::Reference< lang::XComponent > xStreamComponent( xResult, uno::UNO_QUERY_THROW );
2240
96.5k
            MakeLinkToSubComponent_Impl( xStreamComponent );
2241
96.5k
        }
2242
173k
    }
2243
173k
    catch( const embed::InvalidStorageException& )
2244
173k
    {
2245
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2246
0
        throw;
2247
0
    }
2248
173k
    catch( const lang::IllegalArgumentException& )
2249
173k
    {
2250
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2251
0
        throw;
2252
0
    }
2253
173k
    catch( const packages::WrongPasswordException& )
2254
173k
    {
2255
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2256
0
        throw;
2257
0
    }
2258
173k
    catch( const embed::StorageWrappedTargetException& )
2259
173k
    {
2260
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2261
0
        throw;
2262
0
    }
2263
173k
    catch( const io::IOException& )
2264
173k
    {
2265
55.3k
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2266
55.3k
        throw;
2267
55.3k
    }
2268
173k
    catch( const uno::RuntimeException& )
2269
173k
    {
2270
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2271
0
        throw;
2272
0
    }
2273
173k
    catch( const uno::Exception& )
2274
173k
    {
2275
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2276
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2277
2278
0
        throw embed::StorageWrappedTargetException(u"Can't open stream element!"_ustr,
2279
0
                                                 uno::Reference< io::XInputStream >(),
2280
0
                                                 aCaught );
2281
0
    }
2282
2283
117k
    aGuard.clear();
2284
2285
117k
    BroadcastModifiedIfNecessary();
2286
2287
117k
    return xResult;
2288
173k
}
2289
2290
uno::Reference< io::XStream > SAL_CALL OStorage::openEncryptedStreamElement(
2291
    const OUString& aStreamName, sal_Int32 nOpenMode, const OUString& aPass )
2292
0
{
2293
0
    return openEncryptedStream( aStreamName, nOpenMode, ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
2294
0
}
2295
2296
uno::Reference< embed::XStorage > SAL_CALL OStorage::openStorageElement(
2297
            const OUString& aStorName, sal_Int32 nStorageMode )
2298
88.5k
{
2299
88.5k
    return openStorageElement2(aStorName, nStorageMode);
2300
88.5k
}
2301
2302
rtl::Reference< OStorage > OStorage::openStorageElement2(
2303
            const OUString& aStorName, sal_Int32 nStorageMode )
2304
103k
{
2305
103k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2306
2307
103k
    if ( !m_pImpl )
2308
0
    {
2309
0
        SAL_INFO("package.xstor", "Disposed");
2310
0
        throw lang::DisposedException();
2311
0
    }
2312
2313
103k
    if ( aStorName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStorName, false ) )
2314
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2315
2316
103k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aStorName == "_rels" )
2317
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
2318
2319
103k
    if ( ( nStorageMode & embed::ElementModes::WRITE ) && m_bReadOnlyWrap )
2320
0
        throw io::IOException(); // TODO: access denied
2321
2322
103k
    if ( ( nStorageMode & embed::ElementModes::TRUNCATE )
2323
0
      && !( nStorageMode & embed::ElementModes::WRITE ) )
2324
0
        throw io::IOException(); // TODO: access denied
2325
2326
    // it's always possible to read written storage in this implementation
2327
103k
    nStorageMode |= embed::ElementModes::READ;
2328
2329
103k
    rtl::Reference< OStorage > xResult;
2330
103k
    try
2331
103k
    {
2332
103k
        SotElement_Impl *pElement = m_pImpl->FindElement( aStorName );
2333
103k
        if ( !pElement )
2334
37.4k
        {
2335
            // element does not exist, check if creation is allowed
2336
37.4k
            if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
2337
37.4k
              || (( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE )
2338
4.16k
              || ( nStorageMode & embed::ElementModes::NOCREATE ) == embed::ElementModes::NOCREATE )
2339
33.3k
                throw io::IOException(); // TODO: access_denied
2340
2341
            // create a new StorageElement and insert it into the list
2342
4.16k
            pElement = m_pImpl->InsertStorage( aStorName, nStorageMode );
2343
4.16k
        }
2344
66.2k
        else if ( !pElement->m_bIsStorage )
2345
0
        {
2346
0
            throw io::IOException();
2347
0
        }
2348
66.2k
        else if (pElement->m_xStorage)
2349
2.40k
        {
2350
            // storage has already been opened; it may be opened another time, if it the mode allows to do so
2351
2.40k
            if (pElement->m_xStorage->m_pAntiImpl)
2352
0
            {
2353
0
                throw io::IOException(); // TODO: access_denied
2354
0
            }
2355
2.40k
            else if ( !pElement->m_xStorage->m_aReadOnlyWrapVector.empty()
2356
0
                    && ( nStorageMode & embed::ElementModes::WRITE ) )
2357
0
            {
2358
0
                throw io::IOException(); // TODO: access_denied
2359
0
            }
2360
2.40k
            else
2361
2.40k
            {
2362
                // in case parent storage allows writing the readonly mode of the child storage is
2363
                // virtual, that means that it is just enough to change the flag to let it be writable
2364
                // and since there is no AntiImpl nobody should be notified about it
2365
2.40k
                pElement->m_xStorage->m_nStorageMode = nStorageMode | embed::ElementModes::READ;
2366
2367
2.40k
                if ( nStorageMode & embed::ElementModes::TRUNCATE )
2368
0
                {
2369
0
                    for (const auto & rPair : pElement->m_xStorage->m_aChildrenMap)
2370
0
                        for (auto pElementToDel : rPair.second)
2371
0
                            m_pImpl->RemoveElement( /*aName*/rPair.first, pElementToDel );
2372
0
                }
2373
2.40k
            }
2374
2.40k
        }
2375
2376
70.4k
        if (!pElement->m_xStorage)
2377
63.8k
            m_pImpl->OpenSubStorage(pElement, nStorageMode);
2378
2379
70.4k
        if (!pElement->m_xStorage)
2380
0
            throw io::IOException(); // TODO: general_error
2381
2382
70.4k
        bool bReadOnlyWrap = ( ( nStorageMode & embed::ElementModes::WRITE ) != embed::ElementModes::WRITE );
2383
70.4k
        rtl::Reference<OStorage> pResultStorage = new OStorage(pElement->m_xStorage.get(), bReadOnlyWrap);
2384
70.4k
        xResult = pResultStorage;
2385
2386
70.4k
        if ( bReadOnlyWrap )
2387
66.2k
        {
2388
            // Before this call is done the object must be refcounted already
2389
66.2k
            pElement->m_xStorage->SetReadOnlyWrap(*pResultStorage);
2390
2391
            // before the storage disposes the stream it must deregister itself as listener
2392
66.2k
            MakeLinkToSubComponent_Impl( xResult );
2393
66.2k
        }
2394
70.4k
    }
2395
103k
    catch( const embed::InvalidStorageException& )
2396
103k
    {
2397
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2398
0
        throw;
2399
0
    }
2400
103k
    catch( const lang::IllegalArgumentException& )
2401
103k
    {
2402
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2403
0
        throw;
2404
0
    }
2405
103k
    catch( const embed::StorageWrappedTargetException& )
2406
103k
    {
2407
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2408
0
        throw;
2409
0
    }
2410
103k
    catch( const io::IOException& )
2411
103k
    {
2412
33.3k
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2413
33.3k
        throw;
2414
33.3k
    }
2415
103k
    catch( const uno::RuntimeException& )
2416
103k
    {
2417
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2418
0
        throw;
2419
0
    }
2420
103k
    catch( const uno::Exception& )
2421
103k
    {
2422
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2423
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2424
2425
0
        throw embed::StorageWrappedTargetException( u"Can't open storage!"_ustr,
2426
0
                                                 uno::Reference< io::XInputStream >(),
2427
0
                                                 aCaught );
2428
0
    }
2429
2430
70.4k
    return xResult;
2431
103k
}
2432
2433
uno::Reference< io::XStream > SAL_CALL OStorage::cloneStreamElement( const OUString& aStreamName )
2434
0
{
2435
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2436
2437
0
    if ( !m_pImpl )
2438
0
    {
2439
0
        SAL_INFO("package.xstor", "Disposed");
2440
0
        throw lang::DisposedException();
2441
0
    }
2442
2443
0
    if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
2444
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2445
2446
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
2447
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
2448
2449
0
    try
2450
0
    {
2451
0
        uno::Reference< io::XStream > xResult;
2452
0
        m_pImpl->CloneStreamElement( aStreamName, false, ::comphelper::SequenceAsHashMap(), xResult );
2453
0
        if ( !xResult.is() )
2454
0
            throw uno::RuntimeException();
2455
0
        return xResult;
2456
0
    }
2457
0
    catch( const embed::InvalidStorageException& )
2458
0
    {
2459
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2460
0
        throw;
2461
0
    }
2462
0
    catch( const lang::IllegalArgumentException& )
2463
0
    {
2464
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2465
0
        throw;
2466
0
    }
2467
0
    catch( const packages::WrongPasswordException& )
2468
0
    {
2469
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2470
0
        throw;
2471
0
    }
2472
0
    catch( const io::IOException& )
2473
0
    {
2474
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2475
0
        throw;
2476
0
    }
2477
0
    catch( const embed::StorageWrappedTargetException& )
2478
0
    {
2479
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2480
0
        throw;
2481
0
    }
2482
0
    catch( const uno::RuntimeException& )
2483
0
    {
2484
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2485
0
        throw;
2486
0
    }
2487
0
    catch( const uno::Exception& )
2488
0
    {
2489
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2490
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2491
2492
0
        throw embed::StorageWrappedTargetException( u"Can't clone stream!"_ustr,
2493
0
                                                 uno::Reference< io::XInputStream >(),
2494
0
                                                 aCaught );
2495
0
    }
2496
0
}
2497
2498
uno::Reference< io::XStream > SAL_CALL OStorage::cloneEncryptedStreamElement(
2499
    const OUString& aStreamName,
2500
    const OUString& aPass )
2501
0
{
2502
0
    return cloneEncryptedStream( aStreamName, ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
2503
0
}
2504
2505
void SAL_CALL OStorage::copyLastCommitTo(
2506
            const uno::Reference< embed::XStorage >& xTargetStorage )
2507
0
{
2508
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2509
2510
0
    if ( !m_pImpl )
2511
0
    {
2512
0
        SAL_INFO("package.xstor", "Disposed");
2513
0
        throw lang::DisposedException();
2514
0
    }
2515
2516
0
    try
2517
0
    {
2518
0
        m_pImpl->CopyLastCommitTo( xTargetStorage );
2519
0
    }
2520
0
    catch( const embed::InvalidStorageException& )
2521
0
    {
2522
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2523
0
        throw;
2524
0
    }
2525
0
    catch( const lang::IllegalArgumentException& )
2526
0
    {
2527
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2528
0
        throw;
2529
0
    }
2530
0
    catch( const embed::StorageWrappedTargetException& )
2531
0
    {
2532
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2533
0
        throw;
2534
0
    }
2535
0
    catch( const io::IOException& )
2536
0
    {
2537
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2538
0
        throw;
2539
0
    }
2540
0
    catch( const uno::RuntimeException& )
2541
0
    {
2542
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2543
0
        throw;
2544
0
    }
2545
0
    catch( const uno::Exception& )
2546
0
    {
2547
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2548
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2549
2550
0
        throw embed::StorageWrappedTargetException( u"Can't copy last commit version!"_ustr,
2551
0
                                                 uno::Reference< io::XInputStream >(),
2552
0
                                                 aCaught );
2553
0
    }
2554
2555
0
}
2556
2557
void SAL_CALL OStorage::copyStorageElementLastCommitTo(
2558
            const OUString& aStorName,
2559
            const uno::Reference< embed::XStorage >& xTargetStorage )
2560
0
{
2561
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2562
2563
0
    if ( !m_pImpl )
2564
0
    {
2565
0
        SAL_INFO("package.xstor", "Disposed");
2566
0
        throw lang::DisposedException();
2567
0
    }
2568
2569
0
    if ( aStorName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStorName, false ) )
2570
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2571
2572
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aStorName == "_rels" )
2573
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
2574
2575
0
    try
2576
0
    {
2577
0
        SotElement_Impl *pElement = m_pImpl->FindElement( aStorName );
2578
0
        if ( !pElement )
2579
0
        {
2580
            // element does not exist, throw exception
2581
0
            throw io::IOException(); // TODO: access_denied
2582
0
        }
2583
0
        else if ( !pElement->m_bIsStorage )
2584
0
        {
2585
0
            throw io::IOException();
2586
0
        }
2587
2588
0
        if (!pElement->m_xStorage)
2589
0
            m_pImpl->OpenSubStorage( pElement, embed::ElementModes::READ );
2590
2591
0
        if (!pElement->m_xStorage)
2592
0
            throw io::IOException(); // TODO: general_error
2593
2594
        // the existence of m_pAntiImpl of the child is not interesting,
2595
        // the copy will be created internally
2596
2597
0
        pElement->m_xStorage->CopyLastCommitTo(xTargetStorage);
2598
0
    }
2599
0
    catch( const embed::InvalidStorageException& )
2600
0
    {
2601
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2602
0
        throw;
2603
0
    }
2604
0
    catch( const lang::IllegalArgumentException& )
2605
0
    {
2606
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2607
0
        throw;
2608
0
    }
2609
0
    catch( const io::IOException& )
2610
0
    {
2611
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2612
0
        throw;
2613
0
    }
2614
0
    catch( const embed::StorageWrappedTargetException& )
2615
0
    {
2616
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2617
0
        throw;
2618
0
    }
2619
0
    catch( const uno::RuntimeException& )
2620
0
    {
2621
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2622
0
        throw;
2623
0
    }
2624
0
    catch( const uno::Exception& )
2625
0
    {
2626
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2627
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2628
2629
0
        throw embed::StorageWrappedTargetException( u"Can't copy last commit element version!"_ustr,
2630
0
                                                 uno::Reference< io::XInputStream >(),
2631
0
                                                 aCaught );
2632
0
    }
2633
0
}
2634
2635
sal_Bool SAL_CALL OStorage::isStreamElement( const OUString& aElementName )
2636
6.70k
{
2637
6.70k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2638
2639
6.70k
    if ( !m_pImpl )
2640
0
    {
2641
0
        SAL_INFO("package.xstor", "Disposed");
2642
0
        throw lang::DisposedException();
2643
0
    }
2644
2645
6.70k
    if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false ) )
2646
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2647
2648
6.70k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels" )
2649
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable name
2650
2651
6.70k
    SotElement_Impl* pElement = nullptr;
2652
2653
6.70k
    try
2654
6.70k
    {
2655
6.70k
        pElement = m_pImpl->FindElement( aElementName );
2656
6.70k
    }
2657
6.70k
    catch( const embed::InvalidStorageException& )
2658
6.70k
    {
2659
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2660
0
        throw;
2661
0
    }
2662
6.70k
    catch( const lang::IllegalArgumentException& )
2663
6.70k
    {
2664
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2665
0
        throw;
2666
0
    }
2667
6.70k
    catch( const container::NoSuchElementException& )
2668
6.70k
    {
2669
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2670
0
        throw;
2671
0
    }
2672
6.70k
    catch( const uno::RuntimeException& )
2673
6.70k
    {
2674
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2675
0
        throw;
2676
0
    }
2677
6.70k
    catch( const uno::Exception& )
2678
6.70k
    {
2679
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2680
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2681
2682
0
        throw lang::WrappedTargetRuntimeException( u"Can't detect whether it is a stream!"_ustr,
2683
0
                                                 uno::Reference< io::XInputStream >(),
2684
0
                                                 aCaught );
2685
0
    }
2686
2687
6.70k
    if ( !pElement )
2688
6.70k
        throw container::NoSuchElementException(); //???
2689
2690
0
    return !pElement->m_bIsStorage;
2691
6.70k
}
2692
2693
sal_Bool SAL_CALL OStorage::isStorageElement( const OUString& aElementName )
2694
73.7k
{
2695
73.7k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2696
2697
73.7k
    if ( !m_pImpl )
2698
0
    {
2699
0
        SAL_INFO("package.xstor", "Disposed");
2700
0
        throw lang::DisposedException();
2701
0
    }
2702
2703
73.7k
    if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false ) )
2704
6
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2705
2706
73.7k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels" )
2707
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 );
2708
2709
73.7k
    SotElement_Impl* pElement = nullptr;
2710
2711
73.7k
    try
2712
73.7k
    {
2713
73.7k
        pElement = m_pImpl->FindElement( aElementName );
2714
73.7k
    }
2715
73.7k
    catch( const embed::InvalidStorageException& )
2716
73.7k
    {
2717
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2718
0
        throw;
2719
0
    }
2720
73.7k
    catch( const lang::IllegalArgumentException& )
2721
73.7k
    {
2722
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2723
0
        throw;
2724
0
    }
2725
73.7k
    catch( const container::NoSuchElementException& )
2726
73.7k
    {
2727
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2728
0
        throw;
2729
0
    }
2730
73.7k
    catch( const uno::RuntimeException& )
2731
73.7k
    {
2732
6
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2733
6
        throw;
2734
6
    }
2735
73.7k
    catch( const uno::Exception& )
2736
73.7k
    {
2737
308
        uno::Any aCaught( ::cppu::getCaughtException() );
2738
308
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2739
2740
308
        throw lang::WrappedTargetRuntimeException( u"can't detect whether it is a storage"_ustr,
2741
308
                                                 uno::Reference< io::XInputStream >(),
2742
308
                                                 aCaught );
2743
308
    }
2744
2745
73.4k
    if ( !pElement )
2746
21.4k
        throw container::NoSuchElementException(); //???
2747
2748
51.9k
    return pElement->m_bIsStorage;
2749
73.4k
}
2750
2751
void SAL_CALL OStorage::removeElement( const OUString& aElementName )
2752
0
{
2753
0
    {
2754
0
        osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
2755
2756
0
        if (!m_pImpl)
2757
0
        {
2758
0
            SAL_INFO("package.xstor", "Disposed");
2759
0
            throw lang::DisposedException();
2760
0
        }
2761
2762
0
        if (aElementName.isEmpty()
2763
0
            || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aElementName, false))
2764
0
            throw lang::IllegalArgumentException(u"Unexpected entry name syntax."_ustr,
2765
0
                                                 uno::Reference<uno::XInterface>(), 1);
2766
2767
0
        if (m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels")
2768
0
            throw lang::IllegalArgumentException(u""_ustr, uno::Reference<uno::XInterface>(),
2769
0
                                                 1); // TODO: unacceptable name
2770
2771
0
        if (!(m_pImpl->m_nStorageMode & embed::ElementModes::WRITE))
2772
0
            throw io::IOException(); // TODO: access denied
2773
2774
0
        try
2775
0
        {
2776
0
            auto pElement = m_pImpl->FindElement(aElementName);
2777
0
            if ( !pElement )
2778
0
                throw container::NoSuchElementException(); //???
2779
2780
0
            m_pImpl->RemoveElement(aElementName, pElement);
2781
2782
0
            m_pImpl->m_bIsModified = true;
2783
0
            m_pImpl->m_bBroadcastModified = true;
2784
0
        }
2785
0
        catch (const embed::InvalidStorageException&)
2786
0
        {
2787
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2788
0
            throw;
2789
0
        }
2790
0
        catch (const lang::IllegalArgumentException&)
2791
0
        {
2792
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2793
0
            throw;
2794
0
        }
2795
0
        catch (const container::NoSuchElementException&)
2796
0
        {
2797
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2798
0
            throw;
2799
0
        }
2800
0
        catch (const io::IOException&)
2801
0
        {
2802
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2803
0
            throw;
2804
0
        }
2805
0
        catch (const embed::StorageWrappedTargetException&)
2806
0
        {
2807
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2808
0
            throw;
2809
0
        }
2810
0
        catch (const uno::RuntimeException&)
2811
0
        {
2812
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2813
0
            throw;
2814
0
        }
2815
0
        catch (const uno::Exception&)
2816
0
        {
2817
0
            uno::Any aCaught(::cppu::getCaughtException());
2818
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2819
2820
0
            throw embed::StorageWrappedTargetException(u"Can't remove element!"_ustr,
2821
0
                                                       uno::Reference<io::XInputStream>(), aCaught);
2822
0
        }
2823
0
    }
2824
2825
0
    BroadcastModifiedIfNecessary();
2826
0
}
2827
2828
void SAL_CALL OStorage::renameElement( const OUString& aElementName, const OUString& aNewName )
2829
0
{
2830
0
    {
2831
0
        osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
2832
2833
0
        if (!m_pImpl)
2834
0
        {
2835
0
            SAL_INFO("package.xstor", "Disposed");
2836
0
            throw lang::DisposedException();
2837
0
        }
2838
2839
0
        if (aElementName.isEmpty()
2840
0
            || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aElementName, false)
2841
0
            || aNewName.isEmpty()
2842
0
            || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aNewName, false))
2843
0
            throw lang::IllegalArgumentException(u"Unexpected entry name syntax."_ustr,
2844
0
                                                 uno::Reference<uno::XInterface>(), 1);
2845
2846
0
        if (m_nStorageType == embed::StorageFormats::OFOPXML
2847
0
            && (aElementName == "_rels" || aNewName == "_rels"))
2848
0
            throw lang::IllegalArgumentException(u""_ustr, uno::Reference<uno::XInterface>(),
2849
0
                                                 0); // TODO: unacceptable element name
2850
2851
0
        if (!(m_pImpl->m_nStorageMode & embed::ElementModes::WRITE))
2852
0
            throw io::IOException(); // TODO: access denied
2853
2854
0
        try
2855
0
        {
2856
0
            SotElement_Impl* pRefElement = m_pImpl->FindElement(aNewName);
2857
0
            if (pRefElement)
2858
0
                throw container::ElementExistException(); //???
2859
2860
0
            auto pElement = m_pImpl->FindElement( aElementName );
2861
0
            if ( !pElement )
2862
0
                throw container::NoSuchElementException(); //???
2863
2864
0
            auto mapIt = m_pImpl->m_aChildrenMap.find(aElementName);
2865
0
            auto rVec = mapIt->second;
2866
0
            for (auto it = rVec.begin(); it != rVec.end(); ++it)
2867
0
                if (pElement == *it)
2868
0
                {
2869
0
                    std::erase(rVec, pElement);
2870
0
                    if (rVec.empty())
2871
0
                        m_pImpl->m_aChildrenMap.erase(mapIt);
2872
0
                    break;
2873
0
                }
2874
0
            m_pImpl->m_aChildrenMap[aNewName].push_back(pElement);
2875
0
            m_pImpl->m_bIsModified = true;
2876
0
            m_pImpl->m_bBroadcastModified = true;
2877
0
        }
2878
0
        catch (const embed::InvalidStorageException&)
2879
0
        {
2880
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2881
0
            throw;
2882
0
        }
2883
0
        catch (const lang::IllegalArgumentException&)
2884
0
        {
2885
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2886
0
            throw;
2887
0
        }
2888
0
        catch (const container::NoSuchElementException&)
2889
0
        {
2890
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2891
0
            throw;
2892
0
        }
2893
0
        catch (const container::ElementExistException&)
2894
0
        {
2895
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2896
0
            throw;
2897
0
        }
2898
0
        catch (const io::IOException&)
2899
0
        {
2900
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2901
0
            throw;
2902
0
        }
2903
0
        catch (const embed::StorageWrappedTargetException&)
2904
0
        {
2905
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2906
0
            throw;
2907
0
        }
2908
0
        catch (const uno::RuntimeException&)
2909
0
        {
2910
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2911
0
            throw;
2912
0
        }
2913
0
        catch (const uno::Exception&)
2914
0
        {
2915
0
            uno::Any aCaught(::cppu::getCaughtException());
2916
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
2917
2918
0
            throw embed::StorageWrappedTargetException(u"Can't rename element!"_ustr,
2919
0
                                                       uno::Reference<io::XInputStream>(), aCaught);
2920
0
        }
2921
0
    }
2922
2923
0
    BroadcastModifiedIfNecessary();
2924
0
}
2925
2926
void SAL_CALL OStorage::copyElementTo(  const OUString& aElementName,
2927
                                        const uno::Reference< embed::XStorage >& xDest,
2928
                                        const OUString& aNewName )
2929
17
{
2930
17
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
2931
2932
17
    if ( !m_pImpl )
2933
0
    {
2934
0
        SAL_INFO("package.xstor", "Disposed");
2935
0
        throw lang::DisposedException();
2936
0
    }
2937
2938
17
    if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false )
2939
17
      || aNewName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aNewName, false ) )
2940
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
2941
2942
17
    if ( !xDest.is() )
2943
        // || xDest == getXWeak() )
2944
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 2 );
2945
2946
17
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && ( aElementName == "_rels" || aNewName == "_rels" ) )
2947
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 ); // unacceptable element name
2948
2949
17
    try
2950
17
    {
2951
17
        SotElement_Impl* pElement = m_pImpl->FindElement( aElementName );
2952
17
        if ( !pElement )
2953
0
            throw container::NoSuchElementException();
2954
2955
17
        uno::Reference< XNameAccess > xNameAccess( xDest, uno::UNO_QUERY_THROW );
2956
17
        if ( xNameAccess->hasByName( aNewName ) )
2957
0
            throw container::ElementExistException();
2958
2959
17
        m_pImpl->CopyStorageElement( pElement, xDest, aNewName, false );
2960
17
    }
2961
17
    catch( const embed::InvalidStorageException& )
2962
17
    {
2963
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2964
0
        throw;
2965
0
    }
2966
17
    catch( const lang::IllegalArgumentException& )
2967
17
    {
2968
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2969
0
        throw;
2970
0
    }
2971
17
    catch( const container::NoSuchElementException& )
2972
17
    {
2973
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2974
0
        throw;
2975
0
    }
2976
17
    catch( const container::ElementExistException& )
2977
17
    {
2978
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2979
0
        throw;
2980
0
    }
2981
17
    catch( const embed::StorageWrappedTargetException& )
2982
17
    {
2983
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2984
0
        throw;
2985
0
    }
2986
17
    catch( const io::IOException& )
2987
17
    {
2988
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2989
0
        throw;
2990
0
    }
2991
17
    catch( const uno::RuntimeException& )
2992
17
    {
2993
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
2994
0
        throw;
2995
0
    }
2996
17
    catch( const uno::Exception& )
2997
17
    {
2998
0
        uno::Any aCaught( ::cppu::getCaughtException() );
2999
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3000
3001
0
        throw embed::StorageWrappedTargetException( u"Can't copy element!"_ustr,
3002
0
                                                 uno::Reference< io::XInputStream >(),
3003
0
                                                 aCaught );
3004
0
    }
3005
17
}
3006
3007
void SAL_CALL OStorage::moveElementTo(  const OUString& aElementName,
3008
                                        const uno::Reference< embed::XStorage >& xDest,
3009
                                        const OUString& aNewName )
3010
0
{
3011
0
    {
3012
0
        osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
3013
3014
0
        if (!m_pImpl)
3015
0
        {
3016
0
            SAL_INFO("package.xstor", "Disposed");
3017
0
            throw lang::DisposedException();
3018
0
        }
3019
3020
0
        if (aElementName.isEmpty()
3021
0
            || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aElementName, false)
3022
0
            || aNewName.isEmpty()
3023
0
            || !::comphelper::OStorageHelper::IsValidZipEntryFileName(aNewName, false))
3024
0
            throw lang::IllegalArgumentException(u"Unexpected entry name syntax."_ustr,
3025
0
                                                 uno::Reference<uno::XInterface>(), 1);
3026
3027
0
        if (!xDest.is() || xDest == getXWeak())
3028
0
            throw lang::IllegalArgumentException(u""_ustr, uno::Reference<uno::XInterface>(), 2);
3029
3030
0
        if (m_nStorageType == embed::StorageFormats::OFOPXML
3031
0
            && (aElementName == "_rels" || aNewName == "_rels"))
3032
0
            throw lang::IllegalArgumentException(u""_ustr, uno::Reference<uno::XInterface>(),
3033
0
                                                 0); // unacceptable element name
3034
3035
0
        if (!(m_pImpl->m_nStorageMode & embed::ElementModes::WRITE))
3036
0
            throw io::IOException(); // TODO: access denied
3037
3038
0
        try
3039
0
        {
3040
0
            auto pElement = m_pImpl->FindElement( aElementName );
3041
0
            if ( !pElement )
3042
0
                throw container::NoSuchElementException(); //???
3043
3044
0
            uno::Reference<XNameAccess> xNameAccess(xDest, uno::UNO_QUERY_THROW);
3045
0
            if (xNameAccess->hasByName(aNewName))
3046
0
                throw container::ElementExistException();
3047
3048
0
            m_pImpl->CopyStorageElement(pElement, xDest, aNewName, false);
3049
3050
0
            m_pImpl->RemoveElement(aElementName, pElement);
3051
3052
0
            m_pImpl->m_bIsModified = true;
3053
0
            m_pImpl->m_bBroadcastModified = true;
3054
0
        }
3055
0
        catch (const embed::InvalidStorageException&)
3056
0
        {
3057
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3058
0
            throw;
3059
0
        }
3060
0
        catch (const lang::IllegalArgumentException&)
3061
0
        {
3062
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3063
0
            throw;
3064
0
        }
3065
0
        catch (const container::NoSuchElementException&)
3066
0
        {
3067
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3068
0
            throw;
3069
0
        }
3070
0
        catch (const container::ElementExistException&)
3071
0
        {
3072
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3073
0
            throw;
3074
0
        }
3075
0
        catch (const embed::StorageWrappedTargetException&)
3076
0
        {
3077
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3078
0
            throw;
3079
0
        }
3080
0
        catch (const io::IOException&)
3081
0
        {
3082
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3083
0
            throw;
3084
0
        }
3085
0
        catch (const uno::RuntimeException&)
3086
0
        {
3087
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3088
0
            throw;
3089
0
        }
3090
0
        catch (const uno::Exception&)
3091
0
        {
3092
0
            uno::Any aCaught(::cppu::getCaughtException());
3093
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3094
3095
0
            throw embed::StorageWrappedTargetException(u"Can't move element!"_ustr,
3096
0
                                                       uno::Reference<io::XInputStream>(), aCaught);
3097
0
        }
3098
0
    }
3099
3100
0
    BroadcastModifiedIfNecessary();
3101
0
}
3102
3103
//  XStorage2
3104
uno::Reference< io::XStream > SAL_CALL OStorage::openEncryptedStream(
3105
    const OUString& aStreamName, sal_Int32 nOpenMode, const uno::Sequence< beans::NamedValue >& aEncryptionData )
3106
0
{
3107
0
    osl::ClearableMutexGuard aGuard( m_xSharedMutex->GetMutex() );
3108
3109
0
    if ( !m_pImpl )
3110
0
    {
3111
0
        SAL_INFO("package.xstor", "Disposed");
3112
0
        throw lang::DisposedException();
3113
0
    }
3114
3115
0
    if ( ( nOpenMode & embed::ElementModes::WRITE ) && m_bReadOnlyWrap )
3116
0
        throw io::IOException(); // TODO: access denied
3117
3118
0
    if ( !aEncryptionData.hasElements() )
3119
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 3 );
3120
3121
0
    uno::Reference< io::XStream > xResult;
3122
0
    try
3123
0
    {
3124
0
        SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamName, nOpenMode, true );
3125
0
        assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
3126
3127
0
        xResult = pElement->m_xStream->GetStream(nOpenMode, aEncryptionData, false);
3128
0
        SAL_WARN_IF( !xResult.is(), "package.xstor", "The method must throw exception instead of removing empty result!" );
3129
3130
0
        if ( m_bReadOnlyWrap )
3131
0
        {
3132
            // before the storage disposes the stream it must deregister itself as listener
3133
0
            uno::Reference< lang::XComponent > xStreamComponent( xResult, uno::UNO_QUERY_THROW );
3134
0
            MakeLinkToSubComponent_Impl( xStreamComponent );
3135
0
        }
3136
0
    }
3137
0
    catch( const embed::InvalidStorageException& )
3138
0
    {
3139
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3140
0
        throw;
3141
0
    }
3142
0
    catch( const lang::IllegalArgumentException& )
3143
0
    {
3144
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3145
0
        throw;
3146
0
    }
3147
0
    catch( const packages::NoEncryptionException& )
3148
0
    {
3149
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3150
0
        throw;
3151
0
    }
3152
0
    catch( const packages::WrongPasswordException& )
3153
0
    {
3154
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3155
0
        throw;
3156
0
    }
3157
0
    catch( const embed::StorageWrappedTargetException& )
3158
0
    {
3159
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3160
0
        throw;
3161
0
    }
3162
0
    catch( const io::IOException& )
3163
0
    {
3164
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3165
0
        throw;
3166
0
    }
3167
0
    catch( const uno::RuntimeException& )
3168
0
    {
3169
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3170
0
        throw;
3171
0
    }
3172
0
    catch( const uno::Exception& )
3173
0
    {
3174
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3175
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3176
3177
0
        throw embed::StorageWrappedTargetException( u"Can't open encrypted stream!"_ustr,
3178
0
                                                 uno::Reference< io::XInputStream >(),
3179
0
                                                 aCaught );
3180
0
    }
3181
3182
0
    aGuard.clear();
3183
3184
0
    BroadcastModifiedIfNecessary();
3185
3186
0
    return xResult;
3187
0
}
3188
3189
uno::Reference< io::XStream > SAL_CALL OStorage::cloneEncryptedStream(
3190
    const OUString& aStreamName,
3191
    const uno::Sequence< beans::NamedValue >& aEncryptionData )
3192
0
{
3193
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3194
3195
0
    if ( !m_pImpl )
3196
0
    {
3197
0
        SAL_INFO("package.xstor", "Disposed");
3198
0
        throw lang::DisposedException();
3199
0
    }
3200
3201
0
    if ( !aEncryptionData.hasElements() )
3202
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 2 );
3203
3204
0
    try
3205
0
    {
3206
0
        uno::Reference< io::XStream > xResult;
3207
0
        m_pImpl->CloneStreamElement( aStreamName, true, aEncryptionData, xResult );
3208
0
        if ( !xResult.is() )
3209
0
            throw uno::RuntimeException();
3210
0
        return xResult;
3211
0
    }
3212
0
    catch( const embed::InvalidStorageException& )
3213
0
    {
3214
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3215
0
        throw;
3216
0
    }
3217
0
    catch( const lang::IllegalArgumentException& )
3218
0
    {
3219
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3220
0
        throw;
3221
0
    }
3222
0
    catch( const packages::NoEncryptionException& )
3223
0
    {
3224
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3225
0
        throw;
3226
0
    }
3227
0
    catch( const packages::WrongPasswordException& )
3228
0
    {
3229
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3230
0
        throw;
3231
0
    }
3232
0
    catch( const io::IOException& )
3233
0
    {
3234
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3235
0
        throw;
3236
0
    }
3237
0
    catch( const embed::StorageWrappedTargetException& )
3238
0
    {
3239
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3240
0
        throw;
3241
0
    }
3242
0
    catch( const uno::RuntimeException& )
3243
0
    {
3244
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3245
0
        throw;
3246
0
    }
3247
0
    catch( const uno::Exception& )
3248
0
    {
3249
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3250
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3251
3252
0
        throw embed::StorageWrappedTargetException( u"Can't clone encrypted stream!"_ustr,
3253
0
                                                 uno::Reference< io::XInputStream >(),
3254
0
                                                 aCaught );
3255
0
    }
3256
0
}
3257
3258
//  XStorageRawAccess
3259
uno::Reference< io::XInputStream > SAL_CALL OStorage::getPlainRawStreamElement(
3260
            const OUString& sStreamName )
3261
0
{
3262
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3263
3264
0
    if ( !m_pImpl )
3265
0
    {
3266
0
        SAL_INFO("package.xstor", "Disposed");
3267
0
        throw lang::DisposedException();
3268
0
    }
3269
3270
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML )
3271
0
        throw uno::RuntimeException(); // the interface is not supported and must not be accessible
3272
3273
0
    if ( sStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( sStreamName, false ) )
3274
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
3275
3276
0
    uno::Reference < io::XInputStream > xTempIn;
3277
0
    try
3278
0
    {
3279
0
        SotElement_Impl* pElement = m_pImpl->FindElement( sStreamName );
3280
0
        if ( !pElement )
3281
0
            throw container::NoSuchElementException();
3282
3283
0
        if (!pElement->m_xStream)
3284
0
        {
3285
0
            m_pImpl->OpenSubStream( pElement );
3286
0
            if (!pElement->m_xStream)
3287
0
                throw io::IOException();
3288
0
        }
3289
3290
0
        uno::Reference<io::XInputStream> xRawInStream = pElement->m_xStream->GetPlainRawInStream();
3291
0
        if ( !xRawInStream.is() )
3292
0
            throw io::IOException();
3293
3294
0
        rtl::Reference < utl::TempFileFastService > xTempFile = new utl::TempFileFastService;
3295
0
        uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
3296
0
        xTempIn = xTempFile->getInputStream();
3297
3298
0
        if ( !xTempOut.is() || !xTempIn.is() )
3299
0
            throw io::IOException();
3300
3301
        // Copy temporary file to a new one
3302
0
        ::comphelper::OStorageHelper::CopyInputToOutput( xRawInStream, xTempOut );
3303
0
        xTempOut->closeOutput();
3304
0
        xTempFile->seek( 0 );
3305
0
    }
3306
0
    catch( const embed::InvalidStorageException& )
3307
0
    {
3308
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3309
0
        throw;
3310
0
    }
3311
0
    catch( const lang::IllegalArgumentException& )
3312
0
    {
3313
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3314
0
        throw;
3315
0
    }
3316
0
    catch( const container::NoSuchElementException& )
3317
0
    {
3318
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3319
0
        throw;
3320
0
    }
3321
0
    catch( const embed::StorageWrappedTargetException& )
3322
0
    {
3323
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3324
0
        throw;
3325
0
    }
3326
0
    catch( const io::IOException& )
3327
0
    {
3328
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3329
0
        throw;
3330
0
    }
3331
0
    catch( const uno::RuntimeException& )
3332
0
    {
3333
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3334
0
        throw;
3335
0
    }
3336
0
    catch( const uno::Exception& )
3337
0
    {
3338
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3339
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3340
3341
0
        throw embed::StorageWrappedTargetException( u"Can't get plain raw stream!"_ustr,
3342
0
                                                 uno::Reference< io::XInputStream >(),
3343
0
                                                 aCaught );
3344
0
    }
3345
3346
0
    return xTempIn;
3347
0
}
3348
3349
uno::Reference< io::XInputStream > SAL_CALL OStorage::getRawEncrStreamElement(
3350
            const OUString& sStreamName )
3351
0
{
3352
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3353
3354
0
    if ( !m_pImpl )
3355
0
    {
3356
0
        SAL_INFO("package.xstor", "Disposed");
3357
0
        throw lang::DisposedException();
3358
0
    }
3359
3360
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
3361
0
        throw packages::NoEncryptionException();
3362
3363
0
    if ( sStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( sStreamName, false ) )
3364
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
3365
3366
0
    rtl::Reference < utl::TempFileFastService > xTempIn;
3367
0
    try
3368
0
    {
3369
0
        SotElement_Impl* pElement = m_pImpl->FindElement( sStreamName );
3370
0
        if ( !pElement )
3371
0
            throw container::NoSuchElementException();
3372
3373
0
        if (!pElement->m_xStream)
3374
0
        {
3375
0
            m_pImpl->OpenSubStream( pElement );
3376
0
            if (!pElement->m_xStream)
3377
0
                throw io::IOException();
3378
0
        }
3379
3380
0
        if (!pElement->m_xStream->IsEncrypted())
3381
0
            throw packages::NoEncryptionException();
3382
3383
0
        uno::Reference< io::XInputStream > xRawInStream = pElement->m_xStream->GetRawInStream();
3384
0
        if ( !xRawInStream.is() )
3385
0
            throw io::IOException();
3386
3387
0
        xTempIn = new utl::TempFileFastService;
3388
3389
0
        if ( !xTempIn )
3390
0
            throw io::IOException();
3391
3392
        // Copy temporary file to a new one
3393
0
        ::comphelper::OStorageHelper::CopyInputToOutput( xRawInStream, xTempIn );
3394
0
        xTempIn->closeOutput();
3395
0
        xTempIn->seek( 0 );
3396
3397
0
    }
3398
0
    catch( const embed::InvalidStorageException& )
3399
0
    {
3400
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3401
0
        throw;
3402
0
    }
3403
0
    catch( const lang::IllegalArgumentException& )
3404
0
    {
3405
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3406
0
        throw;
3407
0
    }
3408
0
    catch( const packages::NoEncryptionException& )
3409
0
    {
3410
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3411
0
        throw;
3412
0
    }
3413
0
    catch( const container::NoSuchElementException& )
3414
0
    {
3415
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3416
0
        throw;
3417
0
    }
3418
0
    catch( const embed::StorageWrappedTargetException& )
3419
0
    {
3420
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3421
0
        throw;
3422
0
    }
3423
0
    catch( const io::IOException& )
3424
0
    {
3425
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3426
0
        throw;
3427
0
    }
3428
0
    catch( const uno::RuntimeException& )
3429
0
    {
3430
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow");
3431
0
        throw;
3432
0
    }
3433
0
    catch( const uno::Exception& )
3434
0
    {
3435
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3436
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3437
3438
0
        throw embed::StorageWrappedTargetException( u"Can't get raw stream!"_ustr,
3439
0
                                                 uno::Reference< io::XInputStream >(),
3440
0
                                                 aCaught );
3441
0
    }
3442
3443
0
    return xTempIn;
3444
0
}
3445
3446
void SAL_CALL OStorage::insertRawEncrStreamElement( const OUString& aStreamName,
3447
                                const uno::Reference< io::XInputStream >& xInStream )
3448
0
{
3449
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3450
3451
0
    if ( !m_pImpl )
3452
0
    {
3453
0
        SAL_INFO("package.xstor", "Disposed");
3454
0
        throw lang::DisposedException();
3455
0
    }
3456
3457
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
3458
0
        throw embed::InvalidStorageException();
3459
3460
0
    if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
3461
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
3462
3463
0
    if ( !xInStream.is() )
3464
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 2 );
3465
3466
0
    if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE ) )
3467
0
        throw io::IOException(); // TODO: access denied
3468
3469
0
    try
3470
0
    {
3471
0
        SotElement_Impl* pElement = m_pImpl->FindElement( aStreamName );
3472
0
        if ( pElement )
3473
0
            throw container::ElementExistException();
3474
3475
0
        m_pImpl->InsertRawStream( aStreamName, xInStream );
3476
0
    }
3477
0
    catch( const embed::InvalidStorageException& )
3478
0
    {
3479
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3480
0
        throw;
3481
0
    }
3482
0
    catch( const lang::IllegalArgumentException& )
3483
0
    {
3484
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3485
0
        throw;
3486
0
    }
3487
0
    catch( const packages::NoRawFormatException& )
3488
0
    {
3489
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3490
0
        throw;
3491
0
    }
3492
0
    catch( const container::ElementExistException& )
3493
0
    {
3494
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3495
0
        throw;
3496
0
    }
3497
0
    catch( const embed::StorageWrappedTargetException& )
3498
0
    {
3499
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3500
0
        throw;
3501
0
    }
3502
0
    catch( const io::IOException& )
3503
0
    {
3504
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3505
0
        throw;
3506
0
    }
3507
0
    catch( const uno::RuntimeException& )
3508
0
    {
3509
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3510
0
        throw;
3511
0
    }
3512
0
    catch( const uno::Exception& )
3513
0
    {
3514
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3515
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3516
3517
0
        throw embed::StorageWrappedTargetException( u"Can't insert raw stream!"_ustr,
3518
0
                                                 uno::Reference< io::XInputStream >(),
3519
0
                                                 aCaught );
3520
0
    }
3521
0
}
3522
3523
//  XTransactedObject
3524
void SAL_CALL OStorage::commit()
3525
0
{
3526
0
    uno::Reference< util::XModifiable > xParentModif;
3527
3528
0
    try {
3529
0
        BroadcastTransaction( STOR_MESS_PRECOMMIT );
3530
3531
0
        ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3532
3533
0
        if ( !m_pImpl )
3534
0
        {
3535
0
            SAL_INFO("package.xstor", "Disposed");
3536
0
            throw lang::DisposedException();
3537
0
        }
3538
3539
0
        if ( m_bReadOnlyWrap )
3540
0
            throw io::IOException(); // TODO: access_denied
3541
3542
0
        m_pImpl->Commit(); // the root storage initiates the storing to source
3543
3544
        // when the storage is committed the parent is modified
3545
0
        if ( m_pImpl->m_pParent && m_pImpl->m_pParent->m_pAntiImpl )
3546
0
            xParentModif = static_cast<util::XModifiable*>(m_pImpl->m_pParent->m_pAntiImpl);
3547
0
    }
3548
0
    catch( const io::IOException& )
3549
0
    {
3550
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3551
0
        throw;
3552
0
    }
3553
0
    catch( const embed::StorageWrappedTargetException& )
3554
0
    {
3555
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3556
0
        throw;
3557
0
    }
3558
0
    catch( const uno::RuntimeException& )
3559
0
    {
3560
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3561
0
        throw;
3562
0
    }
3563
0
    catch( const uno::Exception& )
3564
0
    {
3565
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3566
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3567
3568
0
        throw embed::StorageWrappedTargetException( u"Problems on commit!"_ustr,
3569
0
                                  getXWeak(),
3570
0
                                  aCaught );
3571
0
    }
3572
3573
0
    setModified( false );
3574
0
    if ( xParentModif.is() )
3575
0
        xParentModif->setModified( true );
3576
3577
0
    BroadcastTransaction( STOR_MESS_COMMITTED );
3578
0
}
3579
3580
void SAL_CALL OStorage::revert()
3581
0
{
3582
    // the method removes all the changes done after last commit
3583
3584
0
    BroadcastTransaction( STOR_MESS_PREREVERT );
3585
3586
0
    {
3587
0
        osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
3588
3589
0
        if (!m_pImpl)
3590
0
        {
3591
0
            SAL_INFO("package.xstor", "Disposed");
3592
0
            throw lang::DisposedException(u"" u""_ustr);
3593
0
        }
3594
3595
0
        for (const auto & rPair : m_pImpl->m_aChildrenMap)
3596
0
            for (auto pElement : rPair.second)
3597
0
            {
3598
0
                bool bThrow = (pElement->m_xStorage
3599
0
                        && (pElement->m_xStorage->m_pAntiImpl
3600
0
                            || !pElement->m_xStorage->m_aReadOnlyWrapVector.empty()))
3601
0
                       || (pElement->m_xStream
3602
0
                           && (pElement->m_xStream->m_pAntiImpl
3603
0
                               || !pElement->m_xStream->m_aInputStreamsVector.empty()));
3604
0
                if (bThrow)
3605
0
                    throw io::IOException(u"" u""_ustr); // TODO: access denied
3606
0
            }
3607
3608
0
        if (m_bReadOnlyWrap || !m_pImpl->m_bListCreated)
3609
0
            return; // nothing to do
3610
3611
0
        try
3612
0
        {
3613
0
            m_pImpl->Revert();
3614
0
            m_pImpl->m_bIsModified = false;
3615
0
            m_pImpl->m_bBroadcastModified = true;
3616
0
        }
3617
0
        catch (const io::IOException&)
3618
0
        {
3619
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3620
0
            throw;
3621
0
        }
3622
0
        catch (const embed::StorageWrappedTargetException&)
3623
0
        {
3624
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3625
0
            throw;
3626
0
        }
3627
0
        catch (const uno::RuntimeException&)
3628
0
        {
3629
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3630
0
            throw;
3631
0
        }
3632
0
        catch (const uno::Exception&)
3633
0
        {
3634
0
            uno::Any aCaught(::cppu::getCaughtException());
3635
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3636
3637
0
            throw embed::StorageWrappedTargetException(u"Problems on revert!"_ustr,
3638
0
                                                       getXWeak(),
3639
0
                                                       aCaught);
3640
0
        }
3641
0
    }
3642
3643
0
    setModified( false );
3644
0
    BroadcastTransaction( STOR_MESS_REVERTED );
3645
0
}
3646
3647
//  XTransactionBroadcaster
3648
void SAL_CALL OStorage::addTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3649
0
{
3650
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3651
3652
0
    if ( !m_pImpl )
3653
0
    {
3654
0
        SAL_INFO("package.xstor", "Disposed");
3655
0
        throw lang::DisposedException();
3656
0
    }
3657
3658
0
    m_aListenersContainer.addInterface( cppu::UnoType<embed::XTransactionListener>::get(),
3659
0
                                                aListener );
3660
0
}
3661
3662
void SAL_CALL OStorage::removeTransactionListener( const uno::Reference< embed::XTransactionListener >& aListener )
3663
0
{
3664
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3665
3666
0
    if ( !m_pImpl )
3667
0
    {
3668
0
        SAL_INFO("package.xstor", "Disposed");
3669
0
        throw lang::DisposedException();
3670
0
    }
3671
3672
0
    m_aListenersContainer.removeInterface( cppu::UnoType<embed::XTransactionListener>::get(),
3673
0
                                                    aListener );
3674
0
}
3675
3676
//  XModifiable
3677
//  TODO: if there will be no demand on this interface it will be removed from implementation,
3678
//        I do not want to remove it now since it is still possible that it will be inserted
3679
//        to the service back.
3680
3681
sal_Bool SAL_CALL OStorage::isModified()
3682
0
{
3683
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3684
3685
0
    if ( !m_pImpl )
3686
0
    {
3687
0
        SAL_INFO("package.xstor", "Disposed");
3688
0
        throw lang::DisposedException();
3689
0
    }
3690
3691
0
    return m_pImpl->m_bIsModified;
3692
0
}
3693
3694
void SAL_CALL OStorage::setModified( sal_Bool bModified )
3695
0
{
3696
0
    {
3697
0
        osl::MutexGuard aGuard(m_xSharedMutex->GetMutex());
3698
3699
0
        if (!m_pImpl)
3700
0
        {
3701
0
            SAL_INFO("package.xstor", "Disposed");
3702
0
            throw lang::DisposedException(u"" u""_ustr);
3703
0
        }
3704
3705
0
        if (m_bReadOnlyWrap)
3706
0
            throw beans::PropertyVetoException(u"" u""_ustr); // TODO: access denied
3707
3708
0
        if (m_pImpl->m_bIsModified != bool(bModified))
3709
0
            m_pImpl->m_bIsModified = bModified;
3710
0
    }
3711
3712
0
    if ( bModified )
3713
0
    {
3714
0
        m_pImpl->m_bBroadcastModified = true;
3715
0
        BroadcastModifiedIfNecessary();
3716
0
    }
3717
0
}
3718
3719
void SAL_CALL OStorage::addModifyListener(
3720
            const uno::Reference< util::XModifyListener >& aListener )
3721
0
{
3722
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3723
3724
0
    if ( !m_pImpl )
3725
0
    {
3726
0
        SAL_INFO("package.xstor", "Disposed");
3727
0
        throw lang::DisposedException();
3728
0
    }
3729
3730
0
    osl_atomic_increment( &m_pImpl->m_nModifiedListenerCount );
3731
0
    m_aListenersContainer.addInterface(
3732
0
                                cppu::UnoType<util::XModifyListener>::get(), aListener );
3733
0
}
3734
3735
void SAL_CALL OStorage::removeModifyListener(
3736
            const uno::Reference< util::XModifyListener >& aListener )
3737
0
{
3738
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3739
3740
0
    if ( !m_pImpl )
3741
0
    {
3742
0
        SAL_INFO("package.xstor", "Disposed");
3743
0
        throw lang::DisposedException();
3744
0
    }
3745
3746
0
    osl_atomic_decrement( &m_pImpl->m_nModifiedListenerCount );
3747
0
    m_aListenersContainer.removeInterface(
3748
0
                                cppu::UnoType<util::XModifyListener>::get(), aListener );
3749
0
}
3750
3751
//  XNameAccess
3752
3753
uno::Any SAL_CALL OStorage::getByName( const OUString& aName )
3754
0
{
3755
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3756
3757
0
    if ( !m_pImpl )
3758
0
    {
3759
0
        SAL_INFO("package.xstor", "Disposed");
3760
0
        throw lang::DisposedException();
3761
0
    }
3762
3763
0
    if ( aName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aName, false ) )
3764
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
3765
3766
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aName == "_rels" )
3767
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable element name
3768
3769
0
    uno::Any aResult;
3770
0
    try
3771
0
    {
3772
0
        SotElement_Impl* pElement = m_pImpl->FindElement( aName );
3773
0
        if ( !pElement )
3774
0
            throw container::NoSuchElementException();
3775
3776
0
        if ( pElement->m_bIsStorage )
3777
0
            aResult <<= openStorageElement( aName, embed::ElementModes::READ );
3778
0
        else
3779
0
            aResult <<= openStreamElement( aName, embed::ElementModes::READ );
3780
0
    }
3781
0
    catch( const container::NoSuchElementException& )
3782
0
    {
3783
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3784
0
        throw;
3785
0
    }
3786
0
    catch( const lang::WrappedTargetException& )
3787
0
    {
3788
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3789
0
        throw;
3790
0
    }
3791
0
    catch( const uno::RuntimeException& )
3792
0
    {
3793
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3794
0
        throw;
3795
0
    }
3796
0
    catch( const uno::Exception& )
3797
0
    {
3798
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3799
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3800
3801
0
        throw lang::WrappedTargetException( u"Can not open storage!"_ustr,
3802
0
                                            getXWeak(),
3803
0
                                            aCaught );
3804
0
    }
3805
3806
0
    return aResult;
3807
0
}
3808
3809
uno::Sequence< OUString > SAL_CALL OStorage::getElementNames()
3810
0
{
3811
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3812
3813
0
    if ( !m_pImpl )
3814
0
    {
3815
0
        SAL_INFO("package.xstor", "Disposed");
3816
0
        throw lang::DisposedException();
3817
0
    }
3818
3819
0
    try
3820
0
    {
3821
0
        return m_pImpl->GetElementNames();
3822
0
    }
3823
0
    catch( const uno::RuntimeException& )
3824
0
    {
3825
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3826
0
        throw;
3827
0
    }
3828
0
    catch ( const uno::Exception& )
3829
0
    {
3830
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3831
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3832
3833
0
        throw lang::WrappedTargetRuntimeException( u"Can not open storage!"_ustr,
3834
0
                                            getXWeak(),
3835
0
                                            aCaught );
3836
0
    }
3837
0
}
3838
3839
sal_Bool SAL_CALL OStorage::hasByName( const OUString& aName )
3840
90.5k
{
3841
90.5k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3842
3843
90.5k
    if ( !m_pImpl )
3844
0
    {
3845
0
        SAL_INFO("package.xstor", "Disposed");
3846
0
        throw lang::DisposedException();
3847
0
    }
3848
3849
90.5k
    if ( aName.isEmpty() )
3850
0
        return false;
3851
3852
90.5k
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aName == "_rels" )
3853
0
        return false;
3854
3855
90.5k
    SotElement_Impl* pElement = nullptr;
3856
90.5k
    try
3857
90.5k
    {
3858
90.5k
        pElement = m_pImpl->FindElement( aName );
3859
90.5k
    }
3860
90.5k
    catch( const uno::RuntimeException& )
3861
90.5k
    {
3862
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3863
0
        throw;
3864
0
    }
3865
90.5k
    catch ( const uno::Exception& )
3866
90.5k
    {
3867
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3868
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3869
3870
0
        throw lang::WrappedTargetRuntimeException( u"Can not open storage!"_ustr,
3871
0
                                            getXWeak(),
3872
0
                                            aCaught );
3873
0
    }
3874
3875
90.5k
    return ( pElement != nullptr );
3876
90.5k
}
3877
3878
uno::Type SAL_CALL OStorage::getElementType()
3879
0
{
3880
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3881
3882
0
    if ( !m_pImpl )
3883
0
    {
3884
0
        SAL_INFO("package.xstor", "Disposed");
3885
0
        throw lang::DisposedException();
3886
0
    }
3887
3888
    // it is a multitype container
3889
0
    return uno::Type();
3890
0
}
3891
3892
sal_Bool SAL_CALL OStorage::hasElements()
3893
0
{
3894
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3895
3896
0
    if ( !m_pImpl )
3897
0
    {
3898
0
        SAL_INFO("package.xstor", "Disposed");
3899
0
        throw lang::DisposedException();
3900
0
    }
3901
3902
0
    try
3903
0
    {
3904
0
        return m_pImpl->HasChildren();
3905
0
    }
3906
0
    catch( const uno::RuntimeException& )
3907
0
    {
3908
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3909
0
        throw;
3910
0
    }
3911
0
    catch( const uno::Exception& )
3912
0
    {
3913
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3914
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3915
3916
0
        throw lang::WrappedTargetRuntimeException( u"Can not open storage!"_ustr,
3917
0
                                            getXWeak(),
3918
0
                                            aCaught );
3919
0
    }
3920
0
}
3921
3922
//  XComponent
3923
void SAL_CALL OStorage::dispose()
3924
173k
{
3925
173k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3926
3927
173k
    if ( !m_pImpl )
3928
0
    {
3929
0
        SAL_INFO("package.xstor", "Disposed");
3930
0
        throw lang::DisposedException();
3931
0
    }
3932
3933
173k
    try
3934
173k
    {
3935
173k
        InternalDispose( true );
3936
173k
    }
3937
173k
    catch( const uno::RuntimeException& )
3938
173k
    {
3939
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
3940
0
        throw;
3941
0
    }
3942
173k
    catch( const uno::Exception& )
3943
173k
    {
3944
0
        uno::Any aCaught( ::cppu::getCaughtException() );
3945
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
3946
3947
0
        throw lang::WrappedTargetRuntimeException( u"Can not open storage!"_ustr,
3948
0
                                            getXWeak(),
3949
0
                                            aCaught );
3950
0
    }
3951
173k
}
3952
3953
void SAL_CALL OStorage::addEventListener(
3954
            const uno::Reference< lang::XEventListener >& xListener )
3955
66.2k
{
3956
66.2k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3957
3958
66.2k
    if ( !m_pImpl )
3959
0
    {
3960
0
        SAL_INFO("package.xstor", "Disposed");
3961
0
        throw lang::DisposedException();
3962
0
    }
3963
3964
66.2k
    m_aListenersContainer.addInterface(
3965
66.2k
                                cppu::UnoType<lang::XEventListener>::get(), xListener );
3966
66.2k
}
3967
3968
void SAL_CALL OStorage::removeEventListener(
3969
            const uno::Reference< lang::XEventListener >& xListener )
3970
36.3k
{
3971
36.3k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3972
3973
36.3k
    if ( !m_pImpl )
3974
0
    {
3975
0
        SAL_INFO("package.xstor", "Disposed");
3976
0
        throw lang::DisposedException();
3977
0
    }
3978
3979
36.3k
    m_aListenersContainer.removeInterface(
3980
36.3k
                                cppu::UnoType<lang::XEventListener>::get(), xListener );
3981
36.3k
}
3982
3983
//  XEncryptionProtectedSource
3984
3985
void SAL_CALL OStorage::setEncryptionPassword( const OUString& aPass )
3986
0
{
3987
0
    setEncryptionData( ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPass ) );
3988
0
}
3989
3990
void SAL_CALL OStorage::removeEncryption()
3991
0
{
3992
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
3993
3994
0
    if ( !m_pImpl )
3995
0
    {
3996
0
        SAL_INFO("package.xstor", "Disposed");
3997
0
        throw lang::DisposedException();
3998
0
    }
3999
4000
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
4001
0
        throw uno::RuntimeException(); // the interface must be visible only for package storage
4002
4003
0
    SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "removeEncryption() method is not available for nonroot storages!" );
4004
0
    if ( !m_pImpl->m_bIsRoot )
4005
0
        return;
4006
4007
0
    try {
4008
0
        m_pImpl->ReadContents();
4009
0
    }
4010
0
    catch ( const uno::RuntimeException& )
4011
0
    {
4012
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4013
0
        throw;
4014
0
    }
4015
0
    catch ( const uno::Exception& )
4016
0
    {
4017
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4018
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4019
4020
0
        throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4021
0
                                            getXWeak(),
4022
0
                                            aCaught );
4023
0
    }
4024
4025
    // TODO: check if the password is valid
4026
    // update all streams that was encrypted with old password
4027
4028
0
    uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4029
0
    try
4030
0
    {
4031
0
        xPackPropSet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY,
4032
0
                                        uno::Any( uno::Sequence< beans::NamedValue >() ) );
4033
4034
0
        m_pImpl->m_bHasCommonEncryptionData = false;
4035
0
        m_pImpl->m_aCommonEncryptionData.clear();
4036
0
    }
4037
0
    catch( const uno::RuntimeException& )
4038
0
    {
4039
0
        TOOLS_WARN_EXCEPTION( "package.xstor", "The call must not fail, it is pretty simple!" );
4040
0
        throw;
4041
0
    }
4042
0
    catch( const uno::Exception& )
4043
0
    {
4044
0
        TOOLS_WARN_EXCEPTION( "package.xstor", "The call must not fail, it is pretty simple!" );
4045
0
        throw io::IOException();
4046
0
    }
4047
0
}
4048
4049
//  XEncryptionProtectedSource2
4050
4051
void SAL_CALL OStorage::setEncryptionData( const uno::Sequence< beans::NamedValue >& aEncryptionData )
4052
0
{
4053
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4054
4055
0
    if ( !m_pImpl )
4056
0
    {
4057
0
        SAL_INFO("package.xstor", "Disposed");
4058
0
        throw lang::DisposedException();
4059
0
    }
4060
4061
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
4062
0
        throw uno::RuntimeException(); // the interface must be visible only for package storage
4063
4064
0
    if ( !aEncryptionData.hasElements() )
4065
0
        throw uno::RuntimeException( u"" u"Unexpected empty encryption data!"_ustr );
4066
4067
0
    SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "setEncryptionData() method is not available for nonroot storages!" );
4068
0
    if ( !m_pImpl->m_bIsRoot )
4069
0
        return;
4070
4071
0
    try {
4072
0
        m_pImpl->ReadContents();
4073
0
    }
4074
0
    catch ( const uno::RuntimeException& )
4075
0
    {
4076
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4077
0
        throw;
4078
0
    }
4079
0
    catch ( const uno::Exception& )
4080
0
    {
4081
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4082
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4083
4084
0
        throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4085
0
                            getXWeak(),
4086
0
                            aCaught );
4087
0
    }
4088
4089
0
    uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4090
0
    try
4091
0
    {
4092
0
        ::comphelper::SequenceAsHashMap aEncryptionMap( aEncryptionData );
4093
0
        xPackPropSet->setPropertyValue( STORAGE_ENCRYPTION_KEYS_PROPERTY,
4094
0
                                        uno::Any( aEncryptionMap.getAsConstNamedValueList() ) );
4095
4096
0
        m_pImpl->m_bHasCommonEncryptionData = true;
4097
0
        m_pImpl->m_aCommonEncryptionData = std::move(aEncryptionMap);
4098
0
    }
4099
0
    catch( const uno::Exception& )
4100
0
    {
4101
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:" );
4102
4103
0
        throw io::IOException();
4104
0
    }
4105
0
}
4106
4107
sal_Bool SAL_CALL OStorage::hasEncryptionData()
4108
0
{
4109
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4110
4111
0
    return m_pImpl && m_pImpl->m_bHasCommonEncryptionData;
4112
0
}
4113
4114
//  XEncryptionProtectedStorage
4115
4116
void SAL_CALL OStorage::setEncryptionAlgorithms( const uno::Sequence< beans::NamedValue >& aAlgorithms )
4117
58.3k
{
4118
58.3k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4119
4120
58.3k
    if ( !m_pImpl )
4121
0
    {
4122
0
        SAL_INFO("package.xstor", "Disposed");
4123
0
        throw lang::DisposedException();
4124
0
    }
4125
4126
58.3k
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
4127
0
        throw uno::RuntimeException(); // the interface must be visible only for package storage
4128
4129
58.3k
    if ( !aAlgorithms.hasElements() )
4130
0
        throw uno::RuntimeException( u"" u"Unexpected empty encryption algorithms list!"_ustr );
4131
4132
58.3k
    SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "setEncryptionAlgorithms() method is not available for nonroot storages!" );
4133
58.3k
    if ( !m_pImpl->m_bIsRoot )
4134
0
        return;
4135
4136
58.3k
    try {
4137
58.3k
        m_pImpl->ReadContents();
4138
58.3k
    }
4139
58.3k
    catch ( const uno::RuntimeException& )
4140
58.3k
    {
4141
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4142
0
        throw;
4143
0
    }
4144
58.3k
    catch ( const uno::Exception& )
4145
58.3k
    {
4146
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4147
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4148
4149
0
        throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4150
0
                                            getXWeak(),
4151
0
                                            aCaught );
4152
0
    }
4153
4154
58.3k
    uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4155
58.3k
    try
4156
58.3k
    {
4157
58.3k
        xPackPropSet->setPropertyValue( ENCRYPTION_ALGORITHMS_PROPERTY,
4158
58.3k
                                        uno::Any( aAlgorithms ) );
4159
58.3k
    }
4160
58.3k
    catch ( const uno::RuntimeException& )
4161
58.3k
    {
4162
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4163
0
        throw;
4164
0
    }
4165
58.3k
    catch( const uno::Exception& )
4166
58.3k
    {
4167
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4168
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4169
4170
0
        throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4171
0
                                            getXWeak(),
4172
0
                                            aCaught );
4173
0
    }
4174
58.3k
}
4175
4176
void SAL_CALL OStorage::setGpgProperties( const uno::Sequence< uno::Sequence< beans::NamedValue > >& aProps )
4177
0
{
4178
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4179
4180
0
    if ( !m_pImpl )
4181
0
    {
4182
0
        SAL_INFO("package.xstor", "Disposed");
4183
0
        throw lang::DisposedException();
4184
0
    }
4185
4186
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
4187
0
        throw uno::RuntimeException(); // the interface must be visible only for package storage
4188
4189
0
    if ( !aProps.hasElements() )
4190
0
        throw uno::RuntimeException( u"" u"Unexpected empty encryption algorithms list!"_ustr );
4191
4192
0
    SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "setGpgProperties() method is not available for nonroot storages!" );
4193
0
    if ( !m_pImpl->m_bIsRoot )
4194
0
        return;
4195
4196
0
    try {
4197
0
        m_pImpl->ReadContents();
4198
0
    }
4199
0
    catch ( const uno::RuntimeException& aRuntimeException )
4200
0
    {
4201
0
        SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
4202
0
        throw;
4203
0
    }
4204
0
    catch ( const uno::Exception& )
4205
0
    {
4206
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4207
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4208
4209
0
        throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4210
0
                                            getXWeak(),
4211
0
                                            aCaught );
4212
0
    }
4213
4214
0
    uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4215
0
    try
4216
0
    {
4217
0
        xPackPropSet->setPropertyValue( ENCRYPTION_GPG_PROPERTIES,
4218
0
                                        uno::Any( aProps ) );
4219
0
    }
4220
0
    catch ( const uno::RuntimeException& aRuntimeException )
4221
0
    {
4222
0
        SAL_INFO("package.xstor", "Rethrow: " << aRuntimeException.Message);
4223
0
        throw;
4224
0
    }
4225
0
    catch( const uno::Exception& )
4226
0
    {
4227
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4228
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4229
4230
0
        throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4231
0
                                            getXWeak(),
4232
0
                                            aCaught );
4233
0
    }
4234
0
}
4235
4236
uno::Sequence< beans::NamedValue > SAL_CALL OStorage::getEncryptionAlgorithms()
4237
0
{
4238
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4239
4240
0
    if ( !m_pImpl )
4241
0
    {
4242
0
        SAL_INFO("package.xstor", "Disposed");
4243
0
        throw lang::DisposedException();
4244
0
    }
4245
4246
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
4247
0
        throw uno::RuntimeException(); // the interface must be visible only for package storage
4248
4249
0
    uno::Sequence< beans::NamedValue > aResult;
4250
0
    SAL_WARN_IF( !m_pImpl->m_bIsRoot, "package.xstor", "getEncryptionAlgorithms() method is not available for nonroot storages!" );
4251
0
    if ( m_pImpl->m_bIsRoot )
4252
0
    {
4253
0
        try {
4254
0
            m_pImpl->ReadContents();
4255
0
        }
4256
0
        catch ( const uno::RuntimeException& )
4257
0
        {
4258
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4259
0
            throw;
4260
0
        }
4261
0
        catch ( const uno::Exception& )
4262
0
        {
4263
0
            uno::Any aCaught( ::cppu::getCaughtException() );
4264
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4265
4266
0
            throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4267
0
                                                getXWeak(),
4268
0
                                                aCaught );
4269
0
        }
4270
4271
0
        uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4272
0
        try
4273
0
        {
4274
0
            xPackPropSet->getPropertyValue( ENCRYPTION_ALGORITHMS_PROPERTY ) >>= aResult;
4275
0
        }
4276
0
        catch ( const uno::RuntimeException& )
4277
0
        {
4278
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4279
0
            throw;
4280
0
        }
4281
0
        catch( const uno::Exception& )
4282
0
        {
4283
0
            uno::Any aCaught( ::cppu::getCaughtException() );
4284
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4285
4286
0
            throw lang::WrappedTargetRuntimeException( u"Can not open package!"_ustr,
4287
0
                                                getXWeak(),
4288
0
                                                aCaught );
4289
0
        }
4290
0
    }
4291
4292
0
    return aResult;
4293
0
}
4294
4295
//  XPropertySet
4296
4297
uno::Reference< beans::XPropertySetInfo > SAL_CALL OStorage::getPropertySetInfo()
4298
0
{
4299
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4300
4301
0
    if ( !m_pImpl )
4302
0
    {
4303
0
        SAL_INFO("package.xstor", "Disposed");
4304
0
        throw lang::DisposedException();
4305
0
    }
4306
4307
    //TODO:
4308
0
    return uno::Reference< beans::XPropertySetInfo >();
4309
0
}
4310
4311
void SAL_CALL OStorage::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
4312
120k
{
4313
120k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4314
4315
120k
    if ( !m_pImpl )
4316
0
    {
4317
0
        SAL_INFO("package.xstor", "Disposed");
4318
0
        throw lang::DisposedException();
4319
0
    }
4320
4321
    //TODO: think about interaction handler
4322
4323
    // WORKAROUND:
4324
    // The old document might have no version in the manifest.xml, so we have to allow to set the version
4325
    // even for readonly storages, so that the version from content.xml can be used.
4326
120k
    if ( m_bReadOnlyWrap && aPropertyName != "Version" )
4327
0
        throw uno::RuntimeException(); // TODO: Access denied
4328
4329
120k
    if ( m_nStorageType == embed::StorageFormats::ZIP )
4330
0
        throw beans::UnknownPropertyException( aPropertyName );
4331
120k
    else if ( m_nStorageType == embed::StorageFormats::PACKAGE )
4332
120k
    {
4333
120k
        if ( aPropertyName == "MediaType" )
4334
62.5k
        {
4335
62.5k
            aValue >>= m_pImpl->m_aMediaType;
4336
62.5k
            m_pImpl->m_bControlMediaType = true;
4337
4338
62.5k
            m_pImpl->m_bBroadcastModified = true;
4339
62.5k
            m_pImpl->m_bIsModified = true;
4340
62.5k
        }
4341
58.3k
        else if ( aPropertyName == "Version" )
4342
58.3k
        {
4343
58.3k
            aValue >>= m_pImpl->m_aVersion;
4344
58.3k
            m_pImpl->m_bControlVersion = true;
4345
4346
            // this property can be set even for readonly storage
4347
58.3k
            if ( !m_bReadOnlyWrap )
4348
58.3k
            {
4349
58.3k
                m_pImpl->m_bBroadcastModified = true;
4350
58.3k
                m_pImpl->m_bIsModified = true;
4351
58.3k
            }
4352
58.3k
        }
4353
0
        else if ( ( m_pImpl->m_bIsRoot && ( aPropertyName == HAS_ENCRYPTED_ENTRIES_PROPERTY
4354
0
                                    || aPropertyName == HAS_NONENCRYPTED_ENTRIES_PROPERTY
4355
0
                                    || aPropertyName == IS_INCONSISTENT_PROPERTY
4356
0
                                    || aPropertyName == "URL"
4357
0
                                    || aPropertyName == "RepairPackage"
4358
0
                                    || aPropertyName == ENCRYPTION_GPG_PROPERTIES) )
4359
0
           || aPropertyName == "IsRoot"
4360
0
           || aPropertyName == MEDIATYPE_FALLBACK_USED_PROPERTY )
4361
0
            throw beans::PropertyVetoException();
4362
0
        else
4363
0
            throw beans::UnknownPropertyException( aPropertyName );
4364
120k
    }
4365
0
    else if ( m_nStorageType == embed::StorageFormats::OFOPXML )
4366
0
    {
4367
0
        if ( aPropertyName == "RelationsInfoStream" )
4368
0
        {
4369
0
            uno::Reference< io::XInputStream > xInRelStream;
4370
0
            if ( !( aValue >>= xInRelStream ) || !xInRelStream.is() )
4371
0
                throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
4372
4373
0
            uno::Reference< io::XSeekable > xSeek( xInRelStream, uno::UNO_QUERY );
4374
0
            if ( !xSeek.is() )
4375
0
            {
4376
                // currently this is an internal property that is used for optimization
4377
                // and the stream must support XSeekable interface
4378
                // TODO/LATER: in future it can be changed if property is used from outside
4379
0
                throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
4380
0
            }
4381
4382
0
            m_pImpl->m_xNewRelInfoStream = std::move(xInRelStream);
4383
0
            m_pImpl->m_aRelInfo = uno::Sequence< uno::Sequence< beans::StringPair > >();
4384
0
            m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED_STREAM;
4385
0
            m_pImpl->m_bBroadcastModified = true;
4386
0
            m_pImpl->m_bIsModified = true;
4387
0
        }
4388
0
        else if ( aPropertyName == "RelationsInfo" )
4389
0
        {
4390
0
            if ( !(aValue >>= m_pImpl->m_aRelInfo) )
4391
0
                throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
4392
4393
0
            m_pImpl->m_xNewRelInfoStream.clear();
4394
0
            m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4395
0
            m_pImpl->m_bBroadcastModified = true;
4396
0
            m_pImpl->m_bIsModified = true;
4397
0
        }
4398
0
        else if ( ( m_pImpl->m_bIsRoot && ( aPropertyName == "URL" || aPropertyName == "RepairPackage") )
4399
0
                 || aPropertyName == "IsRoot" )
4400
0
            throw beans::PropertyVetoException();
4401
0
        else
4402
0
            throw beans::UnknownPropertyException( aPropertyName );
4403
0
    }
4404
0
    else
4405
0
        throw beans::UnknownPropertyException( aPropertyName );
4406
4407
120k
    BroadcastModifiedIfNecessary();
4408
120k
}
4409
4410
uno::Any SAL_CALL OStorage::getPropertyValue( const OUString& aPropertyName )
4411
56.9k
{
4412
56.9k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4413
4414
56.9k
    if ( !m_pImpl )
4415
0
    {
4416
0
        SAL_INFO("package.xstor", "Disposed");
4417
0
        throw lang::DisposedException();
4418
0
    }
4419
4420
56.9k
    if ( m_nStorageType == embed::StorageFormats::PACKAGE
4421
56.9k
      && ( aPropertyName == "MediaType" || aPropertyName == MEDIATYPE_FALLBACK_USED_PROPERTY || aPropertyName == "Version" ) )
4422
42.8k
    {
4423
42.8k
        try
4424
42.8k
        {
4425
42.8k
            m_pImpl->ReadContents();
4426
42.8k
        }
4427
42.8k
        catch ( const uno::RuntimeException& )
4428
42.8k
        {
4429
0
            TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4430
0
            throw;
4431
0
        }
4432
42.8k
        catch ( const uno::Exception& )
4433
42.8k
        {
4434
0
            uno::Any aCaught( ::cppu::getCaughtException() );
4435
0
            SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4436
4437
0
            throw lang::WrappedTargetException(
4438
0
                                        u"Can't read contents!"_ustr,
4439
0
                                        getXWeak(),
4440
0
                                        aCaught );
4441
0
        }
4442
4443
42.8k
        if ( aPropertyName == "MediaType" )
4444
38.6k
            return uno::Any( m_pImpl->m_aMediaType );
4445
4.16k
        else if ( aPropertyName == "Version" )
4446
4.16k
            return uno::Any( m_pImpl->m_aVersion );
4447
0
        else
4448
0
            return uno::Any( m_pImpl->m_bMTFallbackUsed );
4449
42.8k
    }
4450
14.0k
    else if ( aPropertyName == "IsRoot" )
4451
0
    {
4452
0
        return uno::Any( m_pImpl->m_bIsRoot );
4453
0
    }
4454
14.0k
    else if ( aPropertyName == "OpenMode" )
4455
5.77k
    {
4456
5.77k
        return uno::Any( m_pImpl->m_nStorageMode );
4457
5.77k
    }
4458
8.32k
    else if ( m_pImpl->m_bIsRoot )
4459
8.32k
    {
4460
8.32k
        if ( aPropertyName == "URL"
4461
8.32k
          || aPropertyName == "RepairPackage" )
4462
0
        {
4463
0
            auto pProp = std::find_if(std::cbegin(m_pImpl->m_xProperties), std::cend(m_pImpl->m_xProperties),
4464
0
                [&aPropertyName](const css::beans::PropertyValue& rProp) { return rProp.Name == aPropertyName; });
4465
0
            if (pProp != std::cend(m_pImpl->m_xProperties))
4466
0
                return pProp->Value;
4467
4468
0
            if ( aPropertyName == "URL" )
4469
0
                return uno::Any( OUString() );
4470
4471
0
            return uno::Any( false ); // RepairPackage
4472
0
        }
4473
8.32k
        else if ( m_nStorageType == embed::StorageFormats::PACKAGE
4474
8.32k
          && ( aPropertyName == HAS_ENCRYPTED_ENTRIES_PROPERTY
4475
4.16k
            || aPropertyName == HAS_NONENCRYPTED_ENTRIES_PROPERTY
4476
0
            || aPropertyName == ENCRYPTION_GPG_PROPERTIES
4477
0
            || aPropertyName == IS_INCONSISTENT_PROPERTY ) )
4478
8.32k
        {
4479
8.32k
            try {
4480
8.32k
                m_pImpl->ReadContents();
4481
8.32k
                uno::Reference< beans::XPropertySet > xPackPropSet( m_pImpl->m_xPackage, uno::UNO_QUERY_THROW );
4482
8.32k
                return xPackPropSet->getPropertyValue( aPropertyName );
4483
8.32k
            }
4484
8.32k
            catch ( const uno::RuntimeException& )
4485
8.32k
            {
4486
0
                TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4487
0
                throw;
4488
0
            }
4489
8.32k
            catch ( const uno::Exception& )
4490
8.32k
            {
4491
0
                uno::Any aCaught( ::cppu::getCaughtException() );
4492
0
                SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4493
4494
0
                throw lang::WrappedTargetException( u"Can not open package!"_ustr,
4495
0
                                                    getXWeak(),
4496
0
                                                    aCaught );
4497
0
            }
4498
8.32k
        }
4499
8.32k
    }
4500
4501
0
    throw beans::UnknownPropertyException(aPropertyName);
4502
56.9k
}
4503
4504
void SAL_CALL OStorage::addPropertyChangeListener(
4505
    const OUString& /*aPropertyName*/,
4506
    const uno::Reference< beans::XPropertyChangeListener >& /*xListener*/ )
4507
0
{
4508
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4509
4510
0
    if ( !m_pImpl )
4511
0
    {
4512
0
        SAL_INFO("package.xstor", "Disposed");
4513
0
        throw lang::DisposedException();
4514
0
    }
4515
4516
    //TODO:
4517
0
}
4518
4519
void SAL_CALL OStorage::removePropertyChangeListener(
4520
    const OUString& /*aPropertyName*/,
4521
    const uno::Reference< beans::XPropertyChangeListener >& /*aListener*/ )
4522
0
{
4523
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4524
4525
0
    if ( !m_pImpl )
4526
0
    {
4527
0
        SAL_INFO("package.xstor", "Disposed");
4528
0
        throw lang::DisposedException();
4529
0
    }
4530
4531
    //TODO:
4532
0
}
4533
4534
void SAL_CALL OStorage::addVetoableChangeListener(
4535
    const OUString& /*PropertyName*/,
4536
    const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
4537
0
{
4538
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4539
4540
0
    if ( !m_pImpl )
4541
0
    {
4542
0
        SAL_INFO("package.xstor", "Disposed");
4543
0
        throw lang::DisposedException();
4544
0
    }
4545
4546
    //TODO:
4547
0
}
4548
4549
void SAL_CALL OStorage::removeVetoableChangeListener(
4550
    const OUString& /*PropertyName*/,
4551
    const uno::Reference< beans::XVetoableChangeListener >& /*aListener*/ )
4552
0
{
4553
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4554
4555
0
    if ( !m_pImpl )
4556
0
    {
4557
0
        SAL_INFO("package.xstor", "Disposed");
4558
0
        throw lang::DisposedException();
4559
0
    }
4560
4561
    //TODO:
4562
0
}
4563
4564
//  XRelationshipAccess
4565
4566
// TODO/LATER: the storage and stream implementations of this interface are very similar, they could use a helper class
4567
4568
sal_Bool SAL_CALL OStorage::hasByID(  const OUString& sID )
4569
0
{
4570
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4571
4572
0
    if ( !m_pImpl )
4573
0
    {
4574
0
        SAL_INFO("package.xstor", "Disposed");
4575
0
        throw lang::DisposedException();
4576
0
    }
4577
4578
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4579
0
        throw uno::RuntimeException();
4580
4581
0
    try
4582
0
    {
4583
0
        getRelationshipByID( sID );
4584
0
        return true;
4585
0
    }
4586
0
    catch( const container::NoSuchElementException& )
4587
0
    {
4588
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4589
0
    }
4590
4591
0
    return false;
4592
0
}
4593
4594
namespace
4595
{
4596
4597
const beans::StringPair* lcl_findPairByName(const uno::Sequence<beans::StringPair>& rSeq, const OUString& rName)
4598
135k
{
4599
271k
    return std::find_if(rSeq.begin(), rSeq.end(), [&rName](const beans::StringPair& rPair) { return rPair.First == rName; });
4600
135k
}
4601
4602
}
4603
4604
OUString SAL_CALL OStorage::getTargetByID(  const OUString& sID  )
4605
0
{
4606
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4607
4608
0
    if ( !m_pImpl )
4609
0
    {
4610
0
        SAL_INFO("package.xstor", "Disposed");
4611
0
        throw lang::DisposedException();
4612
0
    }
4613
4614
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4615
0
        throw uno::RuntimeException();
4616
4617
0
    const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
4618
0
    auto pRel = lcl_findPairByName(aSeq, u"Target"_ustr);
4619
0
    if (pRel != aSeq.end())
4620
0
        return pRel->Second;
4621
4622
0
    return OUString();
4623
0
}
4624
4625
OUString SAL_CALL OStorage::getTypeByID(  const OUString& sID  )
4626
0
{
4627
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4628
4629
0
    if ( !m_pImpl )
4630
0
    {
4631
0
        SAL_INFO("package.xstor", "Disposed");
4632
0
        throw lang::DisposedException();
4633
0
    }
4634
4635
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4636
0
        throw uno::RuntimeException();
4637
4638
0
    const uno::Sequence< beans::StringPair > aSeq = getRelationshipByID( sID );
4639
0
    auto pRel = lcl_findPairByName(aSeq, u"Type"_ustr);
4640
0
    if (pRel != aSeq.end())
4641
0
        return pRel->Second;
4642
4643
0
    return OUString();
4644
0
}
4645
4646
uno::Sequence< beans::StringPair > SAL_CALL OStorage::getRelationshipByID(  const OUString& sID  )
4647
0
{
4648
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4649
4650
0
    if ( !m_pImpl )
4651
0
    {
4652
0
        SAL_INFO("package.xstor", "Disposed");
4653
0
        throw lang::DisposedException();
4654
0
    }
4655
4656
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4657
0
        throw uno::RuntimeException();
4658
4659
    // TODO/LATER: in future the unification of the ID could be checked
4660
0
    const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4661
0
    const beans::StringPair aIDRel(u"Id"_ustr, sID);
4662
4663
0
    auto pRel = std::find_if(aSeq.begin(), aSeq.end(),
4664
0
        [&aIDRel](const uno::Sequence<beans::StringPair>& rRel) {
4665
0
            return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); });
4666
0
    if (pRel != aSeq.end())
4667
0
        return *pRel;
4668
4669
0
    throw container::NoSuchElementException();
4670
0
}
4671
4672
uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OStorage::getRelationshipsByType(  const OUString& sType  )
4673
51.0k
{
4674
51.0k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4675
4676
51.0k
    if ( !m_pImpl )
4677
0
    {
4678
0
        SAL_INFO("package.xstor", "Disposed");
4679
0
        throw lang::DisposedException();
4680
0
    }
4681
4682
51.0k
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4683
0
        throw uno::RuntimeException();
4684
4685
    // TODO/LATER: in future the unification of the ID could be checked
4686
51.0k
    const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4687
51.0k
    std::vector< uno::Sequence< beans::StringPair > > aResult;
4688
51.0k
    aResult.reserve(aSeq.getLength());
4689
4690
51.0k
    std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResult),
4691
135k
        [&sType](const uno::Sequence<beans::StringPair>& rRel) {
4692
135k
            auto pRel = lcl_findPairByName(rRel, u"Type"_ustr);
4693
135k
            return pRel != rRel.end()
4694
                // the type is usually a URL, so the check should be case insensitive
4695
135k
                && pRel->Second.equalsIgnoreAsciiCase( sType );
4696
135k
        });
4697
4698
51.0k
    return comphelper::containerToSequence(aResult);
4699
51.0k
}
4700
4701
uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OStorage::getAllRelationships()
4702
62.7k
{
4703
62.7k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4704
4705
62.7k
    if ( !m_pImpl )
4706
0
    {
4707
0
        SAL_INFO("package.xstor", "Disposed");
4708
0
        throw lang::DisposedException();
4709
0
    }
4710
4711
62.7k
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4712
0
        throw uno::RuntimeException();
4713
4714
62.7k
    uno::Sequence< uno::Sequence< beans::StringPair > > aRet;
4715
62.7k
    try
4716
62.7k
    {
4717
62.7k
        aRet = m_pImpl->GetAllRelationshipsIfAny();
4718
62.7k
    }
4719
62.7k
    catch (const io::IOException&)
4720
62.7k
    {
4721
1.61k
        throw;
4722
1.61k
    }
4723
62.7k
    catch (const uno::RuntimeException&)
4724
62.7k
    {
4725
74
        throw;
4726
74
    }
4727
62.7k
    catch (const uno::Exception &)
4728
62.7k
    {
4729
85
        uno::Any aCaught( ::cppu::getCaughtException() );
4730
85
        throw lang::WrappedTargetRuntimeException(u"Can't getAllRelationships!"_ustr,
4731
85
                                                 uno::Reference< uno::XInterface >(),
4732
85
                                                 aCaught);
4733
85
    }
4734
4735
60.9k
    return aRet;
4736
62.7k
}
4737
4738
void SAL_CALL OStorage::insertRelationshipByID(  const OUString& sID, const uno::Sequence< beans::StringPair >& aEntry, sal_Bool bReplace  )
4739
0
{
4740
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4741
4742
0
    if ( !m_pImpl )
4743
0
    {
4744
0
        SAL_INFO("package.xstor", "Disposed");
4745
0
        throw lang::DisposedException();
4746
0
    }
4747
4748
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4749
0
        throw uno::RuntimeException();
4750
4751
0
    const beans::StringPair aIDRel(u"Id"_ustr, sID);
4752
4753
0
    uno::Sequence<beans::StringPair>* pResult = nullptr;
4754
4755
    // TODO/LATER: in future the unification of the ID could be checked
4756
0
    uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4757
0
    for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
4758
0
    {
4759
0
        const auto& rRel = aSeq[nInd];
4760
0
        if (std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end())
4761
0
            pResult = &aSeq.getArray()[nInd];
4762
0
    }
4763
4764
0
    if ( pResult && !bReplace )
4765
0
        throw container::ElementExistException();
4766
4767
0
    if ( !pResult )
4768
0
    {
4769
0
        const sal_Int32 nIDInd = aSeq.getLength();
4770
0
        aSeq.realloc( nIDInd + 1 );
4771
0
        pResult = &aSeq.getArray()[nIDInd];
4772
0
    }
4773
4774
0
    std::vector<beans::StringPair> aResult;
4775
0
    aResult.reserve(aEntry.getLength() + 1);
4776
4777
0
    aResult.push_back(aIDRel);
4778
0
    std::copy_if(aEntry.begin(), aEntry.end(), std::back_inserter(aResult),
4779
0
        [](const beans::StringPair& rPair) { return rPair.First != "Id"; });
4780
4781
0
    *pResult = comphelper::containerToSequence(aResult);
4782
4783
0
    m_pImpl->m_aRelInfo = std::move(aSeq);
4784
0
    m_pImpl->m_xNewRelInfoStream.clear();
4785
0
    m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4786
0
}
4787
4788
void SAL_CALL OStorage::removeRelationshipByID(  const OUString& sID  )
4789
0
{
4790
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4791
4792
0
    if ( !m_pImpl )
4793
0
    {
4794
0
        SAL_INFO("package.xstor", "Disposed");
4795
0
        throw lang::DisposedException();
4796
0
    }
4797
4798
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4799
0
        throw uno::RuntimeException();
4800
4801
0
    uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4802
0
    const beans::StringPair aIDRel(u"Id"_ustr, sID);
4803
0
    auto pRel = std::find_if(std::cbegin(aSeq), std::cend(aSeq),
4804
0
        [&aIDRel](const uno::Sequence< beans::StringPair >& rRel) {
4805
0
            return std::find(rRel.begin(), rRel.end(), aIDRel) != rRel.end(); });
4806
0
    if (pRel != std::cend(aSeq))
4807
0
    {
4808
0
        auto nInd = static_cast<sal_Int32>(std::distance(std::cbegin(aSeq), pRel));
4809
0
        comphelper::removeElementAt(aSeq, nInd);
4810
4811
0
        m_pImpl->m_aRelInfo = std::move(aSeq);
4812
0
        m_pImpl->m_xNewRelInfoStream.clear();
4813
0
        m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4814
4815
        // TODO/LATER: in future the unification of the ID could be checked
4816
0
        return;
4817
0
    }
4818
4819
0
    throw container::NoSuchElementException();
4820
0
}
4821
4822
void SAL_CALL OStorage::insertRelationships(  const uno::Sequence< uno::Sequence< beans::StringPair > >& aEntries, sal_Bool bReplace  )
4823
0
{
4824
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4825
4826
0
    if ( !m_pImpl )
4827
0
    {
4828
0
        SAL_INFO("package.xstor", "Disposed");
4829
0
        throw lang::DisposedException();
4830
0
    }
4831
4832
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4833
0
        throw uno::RuntimeException();
4834
4835
0
    OUString aIDTag( u"Id"_ustr );
4836
0
    const uno::Sequence< uno::Sequence< beans::StringPair > > aSeq = getAllRelationships();
4837
0
    std::vector< uno::Sequence<beans::StringPair> > aResultVec;
4838
0
    aResultVec.reserve(aSeq.getLength() + aEntries.getLength());
4839
4840
0
    std::copy_if(aSeq.begin(), aSeq.end(), std::back_inserter(aResultVec),
4841
0
        [&aIDTag, &aEntries, bReplace](const uno::Sequence<beans::StringPair>& rTargetRel) {
4842
0
            auto pTargetPair = lcl_findPairByName(rTargetRel, aIDTag);
4843
0
            if (pTargetPair == rTargetRel.end())
4844
0
                return false;
4845
4846
0
            bool bIsSourceSame = std::any_of(aEntries.begin(), aEntries.end(),
4847
0
                [&pTargetPair](const uno::Sequence<beans::StringPair>& rSourceEntry) {
4848
0
                    return std::find(rSourceEntry.begin(), rSourceEntry.end(), *pTargetPair) != rSourceEntry.end(); });
4849
4850
0
            if ( bIsSourceSame && !bReplace )
4851
0
                throw container::ElementExistException();
4852
4853
            // if no such element in the provided sequence
4854
0
            return !bIsSourceSame;
4855
0
        });
4856
4857
0
    std::transform(aEntries.begin(), aEntries.end(), std::back_inserter(aResultVec),
4858
0
        [&aIDTag](const uno::Sequence<beans::StringPair>& rEntry) -> uno::Sequence<beans::StringPair> {
4859
0
            auto pPair = lcl_findPairByName(rEntry, aIDTag);
4860
0
            if (pPair == rEntry.end())
4861
0
                throw io::IOException(); // TODO: illegal relation ( no ID )
4862
4863
0
            auto aResult = comphelper::sequenceToContainer<std::vector<beans::StringPair>>(rEntry);
4864
0
            auto nIDInd = std::distance(rEntry.begin(), pPair);
4865
0
            std::rotate(aResult.begin(), std::next(aResult.begin(), nIDInd), std::next(aResult.begin(), nIDInd + 1));
4866
4867
0
            return comphelper::containerToSequence(aResult);
4868
0
        });
4869
4870
0
    m_pImpl->m_aRelInfo = comphelper::containerToSequence(aResultVec);
4871
0
    m_pImpl->m_xNewRelInfoStream.clear();
4872
0
    m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4873
0
}
4874
4875
void SAL_CALL OStorage::clearRelationships()
4876
0
{
4877
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4878
4879
0
    if ( !m_pImpl )
4880
0
    {
4881
0
        SAL_INFO("package.xstor", "Disposed");
4882
0
        throw lang::DisposedException();
4883
0
    }
4884
4885
0
    if ( m_nStorageType != embed::StorageFormats::OFOPXML )
4886
0
        throw uno::RuntimeException();
4887
4888
0
    m_pImpl->m_aRelInfo.realloc( 0 );
4889
0
    m_pImpl->m_xNewRelInfoStream.clear();
4890
0
    m_pImpl->m_nRelInfoStatus = RELINFO_CHANGED;
4891
0
}
4892
4893
//  XOptimizedStorage
4894
void SAL_CALL OStorage::insertRawNonEncrStreamElementDirect(
4895
            const OUString& /*sStreamName*/,
4896
            const uno::Reference< io::XInputStream >& /*xInStream*/ )
4897
0
{
4898
    // not implemented currently because there is still no demand
4899
    // might need to be implemented if direct copying of compressed streams is used
4900
0
    throw io::IOException();
4901
0
}
4902
4903
void SAL_CALL OStorage::insertStreamElementDirect(
4904
            const OUString& aStreamName,
4905
            const uno::Reference< io::XInputStream >& xInStream,
4906
            const uno::Sequence< beans::PropertyValue >& aProps )
4907
0
{
4908
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4909
4910
0
    if ( !m_pImpl )
4911
0
    {
4912
0
        SAL_INFO("package.xstor", "Disposed");
4913
0
        throw lang::DisposedException();
4914
0
    }
4915
4916
0
    if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
4917
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
4918
4919
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
4920
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable storage name
4921
4922
0
    if ( m_bReadOnlyWrap )
4923
0
        throw io::IOException(); // TODO: access denied
4924
4925
0
    try
4926
0
    {
4927
0
        SotElement_Impl* pElement = m_pImpl->FindElement( aStreamName );
4928
4929
0
        if ( pElement )
4930
0
            throw container::ElementExistException();
4931
4932
0
        pElement = OpenStreamElement_Impl( aStreamName, embed::ElementModes::READWRITE, false );
4933
0
        assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
4934
4935
0
        pElement->m_xStream->InsertStreamDirectly(xInStream, aProps);
4936
0
    }
4937
0
    catch( const embed::InvalidStorageException& )
4938
0
    {
4939
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4940
0
        throw;
4941
0
    }
4942
0
    catch( const lang::IllegalArgumentException& )
4943
0
    {
4944
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4945
0
        throw;
4946
0
    }
4947
0
    catch( const container::ElementExistException& )
4948
0
    {
4949
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4950
0
        throw;
4951
0
    }
4952
0
    catch( const embed::StorageWrappedTargetException& )
4953
0
    {
4954
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4955
0
        throw;
4956
0
    }
4957
0
    catch( const io::IOException& )
4958
0
    {
4959
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4960
0
        throw;
4961
0
    }
4962
0
    catch( const uno::RuntimeException& )
4963
0
    {
4964
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
4965
0
        throw;
4966
0
    }
4967
0
    catch( const uno::Exception& )
4968
0
    {
4969
0
        uno::Any aCaught( ::cppu::getCaughtException() );
4970
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
4971
4972
0
        throw embed::StorageWrappedTargetException( u"Can't insert stream directly!"_ustr,
4973
0
                                                 uno::Reference< io::XInputStream >(),
4974
0
                                                 aCaught );
4975
0
    }
4976
0
}
4977
4978
void SAL_CALL OStorage::copyElementDirectlyTo(
4979
            const OUString& aElementName,
4980
            const uno::Reference< embed::XOptimizedStorage >& xDest,
4981
            const OUString& aNewName )
4982
0
{
4983
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
4984
4985
0
    if ( !m_pImpl )
4986
0
    {
4987
0
        SAL_INFO("package.xstor", "Disposed");
4988
0
        throw lang::DisposedException();
4989
0
    }
4990
4991
0
    if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false )
4992
0
      || aNewName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aNewName, false ) )
4993
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
4994
4995
0
    if ( !xDest.is() || xDest == getXWeak() )
4996
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 2 );
4997
4998
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && ( aElementName == "_rels" || aNewName == "_rels" ) )
4999
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 ); // unacceptable name
5000
5001
0
    try
5002
0
    {
5003
0
        SotElement_Impl* pElement = m_pImpl->FindElement( aElementName );
5004
0
        if ( !pElement )
5005
0
            throw container::NoSuchElementException();
5006
5007
0
        uno::Reference< XNameAccess > xNameAccess( xDest, uno::UNO_QUERY_THROW );
5008
0
        if ( xNameAccess->hasByName( aNewName ) )
5009
0
            throw container::ElementExistException();
5010
5011
        // let the element be copied directly
5012
0
        uno::Reference< embed::XStorage > xStorDest( xDest, uno::UNO_QUERY_THROW );
5013
0
        m_pImpl->CopyStorageElement( pElement, xStorDest, aNewName, true );
5014
0
    }
5015
0
    catch( const embed::InvalidStorageException& )
5016
0
    {
5017
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5018
0
        throw;
5019
0
    }
5020
0
    catch( const lang::IllegalArgumentException& )
5021
0
    {
5022
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5023
0
        throw;
5024
0
    }
5025
0
    catch( const container::NoSuchElementException& )
5026
0
    {
5027
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5028
0
        throw;
5029
0
    }
5030
0
    catch( const container::ElementExistException& )
5031
0
    {
5032
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5033
0
        throw;
5034
0
    }
5035
0
    catch( const embed::StorageWrappedTargetException& )
5036
0
    {
5037
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5038
0
        throw;
5039
0
    }
5040
0
    catch( const io::IOException& )
5041
0
    {
5042
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5043
0
        throw;
5044
0
    }
5045
0
    catch( const uno::RuntimeException& )
5046
0
    {
5047
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5048
0
        throw;
5049
0
    }
5050
0
    catch( const uno::Exception& )
5051
0
    {
5052
0
        uno::Any aCaught( ::cppu::getCaughtException() );
5053
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5054
5055
0
        throw embed::StorageWrappedTargetException( u"Can't copy element directly!"_ustr,
5056
0
                                                 uno::Reference< io::XInputStream >(),
5057
0
                                                 aCaught );
5058
0
    }
5059
0
}
5060
5061
void SAL_CALL OStorage::writeAndAttachToStream( const uno::Reference< io::XStream >& xStream )
5062
0
{
5063
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5064
5065
0
    if ( !m_pImpl )
5066
0
    {
5067
0
        SAL_INFO("package.xstor", "Disposed");
5068
0
        throw lang::DisposedException();
5069
0
    }
5070
5071
0
    if ( !m_pImpl->m_bIsRoot )
5072
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
5073
5074
0
    if ( !m_pImpl->m_pSwitchStream )
5075
0
        throw uno::RuntimeException();
5076
5077
0
    try
5078
0
    {
5079
0
        m_pImpl->m_pSwitchStream->CopyAndSwitchPersistenceTo( xStream );
5080
0
    }
5081
0
    catch( const embed::InvalidStorageException& )
5082
0
    {
5083
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5084
0
        throw;
5085
0
    }
5086
0
    catch( const lang::IllegalArgumentException& )
5087
0
    {
5088
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5089
0
        throw;
5090
0
    }
5091
0
    catch( const embed::StorageWrappedTargetException& )
5092
0
    {
5093
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5094
0
        throw;
5095
0
    }
5096
0
    catch( const io::IOException& )
5097
0
    {
5098
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:" );
5099
0
        throw;
5100
0
    }
5101
0
    catch( const uno::RuntimeException& )
5102
0
    {
5103
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5104
0
        throw;
5105
0
    }
5106
0
    catch( const uno::Exception& )
5107
0
    {
5108
0
        uno::Any aCaught( ::cppu::getCaughtException() );
5109
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5110
5111
0
        throw embed::StorageWrappedTargetException( u"Can't write and attach to stream!"_ustr,
5112
0
                                                 uno::Reference< io::XInputStream >(),
5113
0
                                                 aCaught );
5114
0
    }
5115
5116
0
}
5117
5118
void SAL_CALL OStorage::attachToURL( const OUString& sURL,
5119
                                    sal_Bool bReadOnly )
5120
0
{
5121
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5122
5123
0
    if ( !m_pImpl )
5124
0
    {
5125
0
        SAL_INFO("package.xstor", "Disposed");
5126
0
        throw lang::DisposedException();
5127
0
    }
5128
5129
0
    if ( !m_pImpl->m_bIsRoot )
5130
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 0 );
5131
5132
0
    if ( !m_pImpl->m_pSwitchStream )
5133
0
        throw uno::RuntimeException();
5134
5135
0
    uno::Reference < ucb::XSimpleFileAccess3 > xAccess(
5136
0
        ucb::SimpleFileAccess::create( m_pImpl->m_xContext ) );
5137
5138
0
    try
5139
0
    {
5140
0
        if ( bReadOnly )
5141
0
        {
5142
0
            uno::Reference< io::XInputStream > xInputStream = xAccess->openFileRead( sURL );
5143
0
            m_pImpl->m_pSwitchStream->SwitchPersistenceTo( xInputStream );
5144
0
        }
5145
0
        else
5146
0
        {
5147
0
            uno::Reference< io::XStream > xStream = xAccess->openFileReadWrite( sURL );
5148
0
            m_pImpl->m_pSwitchStream->SwitchPersistenceTo( xStream );
5149
0
        }
5150
0
    }
5151
0
    catch( const embed::InvalidStorageException& )
5152
0
    {
5153
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5154
0
        throw;
5155
0
    }
5156
0
    catch( const lang::IllegalArgumentException& )
5157
0
    {
5158
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5159
0
        throw;
5160
0
    }
5161
0
    catch( const embed::StorageWrappedTargetException& )
5162
0
    {
5163
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5164
0
        throw;
5165
0
    }
5166
0
    catch( const io::IOException& )
5167
0
    {
5168
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5169
0
        throw;
5170
0
    }
5171
0
    catch( const uno::RuntimeException& )
5172
0
    {
5173
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5174
0
        throw;
5175
0
    }
5176
0
    catch( const uno::Exception& )
5177
0
    {
5178
0
        uno::Any aCaught( ::cppu::getCaughtException() );
5179
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5180
5181
0
        throw embed::StorageWrappedTargetException( u"Can't attach to URL!"_ustr,
5182
0
                                                 uno::Reference< io::XInputStream >(),
5183
0
                                                 aCaught );
5184
0
    }
5185
0
}
5186
5187
uno::Any SAL_CALL OStorage::getElementPropertyValue( const OUString& aElementName, const OUString& aPropertyName )
5188
0
{
5189
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5190
5191
0
    if ( !m_pImpl )
5192
0
    {
5193
0
        SAL_INFO("package.xstor", "Disposed");
5194
0
        throw lang::DisposedException();
5195
0
    }
5196
5197
0
    if ( aElementName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aElementName, false ) )
5198
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
5199
5200
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aElementName == "_rels" )
5201
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // TODO: unacceptable name
5202
5203
0
    try
5204
0
    {
5205
0
        SotElement_Impl *pElement = m_pImpl->FindElement( aElementName );
5206
0
        if ( !pElement )
5207
0
            throw container::NoSuchElementException();
5208
5209
        // TODO/LATER: Currently it is only implemented for MediaType property of substorages, might be changed in future
5210
0
        if ( !pElement->m_bIsStorage || m_nStorageType != embed::StorageFormats::PACKAGE || aPropertyName != "MediaType" )
5211
0
            throw beans::PropertyVetoException();
5212
5213
0
        if (!pElement->m_xStorage)
5214
0
            m_pImpl->OpenSubStorage( pElement, embed::ElementModes::READ );
5215
5216
0
        if (!pElement->m_xStorage)
5217
0
            throw io::IOException(); // TODO: general_error
5218
5219
0
        pElement->m_xStorage->ReadContents();
5220
0
        return uno::Any(pElement->m_xStorage->m_aMediaType);
5221
0
    }
5222
0
    catch( const embed::InvalidStorageException& )
5223
0
    {
5224
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5225
0
        throw;
5226
0
    }
5227
0
    catch( const lang::IllegalArgumentException& )
5228
0
    {
5229
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5230
0
        throw;
5231
0
    }
5232
0
    catch( const container::NoSuchElementException& )
5233
0
    {
5234
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5235
0
        throw;
5236
0
    }
5237
0
    catch( const beans::UnknownPropertyException& )
5238
0
    {
5239
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5240
0
        throw;
5241
0
    }
5242
0
    catch( const beans::PropertyVetoException& )
5243
0
    {
5244
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5245
0
        throw;
5246
0
    }
5247
0
    catch( const embed::StorageWrappedTargetException& )
5248
0
    {
5249
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5250
0
        throw;
5251
0
    }
5252
0
    catch( const io::IOException& )
5253
0
    {
5254
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5255
0
        throw;
5256
0
    }
5257
0
    catch( const uno::RuntimeException& )
5258
0
    {
5259
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5260
0
        throw;
5261
0
    }
5262
0
    catch( const uno::Exception& )
5263
0
    {
5264
0
        uno::Any aCaught( ::cppu::getCaughtException() );
5265
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5266
5267
0
        throw embed::StorageWrappedTargetException( u"Can't get element property!"_ustr,
5268
0
                                                 uno::Reference< io::XInputStream >(),
5269
0
                                                 aCaught );
5270
0
    }
5271
0
}
5272
5273
void SAL_CALL OStorage::copyStreamElementData( const OUString& aStreamName, const uno::Reference< io::XStream >& xTargetStream )
5274
0
{
5275
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5276
5277
0
    if ( !m_pImpl )
5278
0
    {
5279
0
        SAL_INFO("package.xstor", "Disposed");
5280
0
        throw lang::DisposedException();
5281
0
    }
5282
5283
0
    if ( aStreamName.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamName, false ) )
5284
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
5285
5286
0
    if ( m_nStorageType == embed::StorageFormats::OFOPXML && aStreamName == "_rels" )
5287
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 1 ); // unacceptable name
5288
5289
0
    if ( !xTargetStream.is() )
5290
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 2 );
5291
5292
0
    try
5293
0
    {
5294
0
        uno::Reference< io::XStream > xNonconstRef = xTargetStream;
5295
0
        m_pImpl->CloneStreamElement( aStreamName, false, ::comphelper::SequenceAsHashMap(), xNonconstRef );
5296
5297
0
        SAL_WARN_IF( xNonconstRef != xTargetStream, "package.xstor", "The provided stream reference seems not be filled in correctly!" );
5298
0
        if ( xNonconstRef != xTargetStream )
5299
0
            throw uno::RuntimeException(); // if the stream reference is set it must not be changed!
5300
0
    }
5301
0
    catch( const embed::InvalidStorageException& )
5302
0
    {
5303
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5304
0
        throw;
5305
0
    }
5306
0
    catch( const lang::IllegalArgumentException& )
5307
0
    {
5308
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5309
0
        throw;
5310
0
    }
5311
0
    catch( const packages::WrongPasswordException& )
5312
0
    {
5313
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5314
0
        throw;
5315
0
    }
5316
0
    catch( const io::IOException& )
5317
0
    {
5318
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5319
0
        throw;
5320
0
    }
5321
0
    catch( const embed::StorageWrappedTargetException& )
5322
0
    {
5323
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5324
0
        throw;
5325
0
    }
5326
0
    catch( const uno::RuntimeException& )
5327
0
    {
5328
0
        TOOLS_INFO_EXCEPTION("package.xstor", "Rethrow:");
5329
0
        throw;
5330
0
    }
5331
0
    catch( const uno::Exception& )
5332
0
    {
5333
0
        uno::Any aCaught( ::cppu::getCaughtException() );
5334
0
        SAL_INFO("package.xstor", "Rethrow: " << exceptionToString(aCaught));
5335
5336
0
        throw embed::StorageWrappedTargetException( u"Can't copy stream data!"_ustr,
5337
0
                                                 uno::Reference< io::XInputStream >(),
5338
0
                                                 aCaught );
5339
0
    }
5340
5341
0
}
5342
5343
// XHierarchicalStorageAccess
5344
uno::Reference< embed::XExtendedStorageStream > SAL_CALL OStorage::openStreamElementByHierarchicalName( const OUString& aStreamPath, ::sal_Int32 nOpenMode )
5345
78.0k
{
5346
78.0k
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5347
5348
78.0k
    if ( !m_pImpl )
5349
0
    {
5350
0
        SAL_INFO("package.xstor", "Disposed");
5351
0
        throw lang::DisposedException();
5352
0
    }
5353
5354
78.0k
    if ( aStreamPath.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamPath, true ) )
5355
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
5356
5357
78.0k
    if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
5358
78.0k
      && ( nOpenMode & embed::ElementModes::WRITE ) )
5359
0
        throw io::IOException(); // Access denied
5360
5361
78.0k
    std::vector<OUString> aListPath = OHierarchyHolder_Impl::GetListPathFromString( aStreamPath );
5362
78.0k
    OSL_ENSURE( aListPath.size(), "The result list must not be empty!" );
5363
5364
78.0k
    uno::Reference< embed::XExtendedStorageStream > xResult;
5365
78.0k
    if ( aListPath.size() == 1 )
5366
39.0k
    {
5367
39.0k
        try
5368
39.0k
        {
5369
            // that must be a direct request for a stream
5370
            // the transacted version of the stream should be opened
5371
5372
39.0k
            SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamPath, nOpenMode, false );
5373
39.0k
            assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
5374
5375
39.0k
            xResult.set(pElement->m_xStream->GetStream(nOpenMode, true),
5376
39.0k
                        uno::UNO_QUERY_THROW);
5377
39.0k
        }
5378
39.0k
        catch ( const container::NoSuchElementException & )
5379
39.0k
        {
5380
0
            throw io::IOException(); // file not found
5381
0
        }
5382
39.0k
    }
5383
39.0k
    else
5384
39.0k
    {
5385
        // there are still storages in between
5386
39.0k
        if (!m_pHierarchyHolder)
5387
10.4k
            m_pHierarchyHolder.reset(new OHierarchyHolder_Impl(this));
5388
5389
39.0k
        xResult = m_pHierarchyHolder->GetStreamHierarchically(
5390
39.0k
                                                ( m_pImpl->m_nStorageMode & embed::ElementModes::READWRITE ),
5391
39.0k
                                                aListPath,
5392
39.0k
                                                nOpenMode );
5393
39.0k
    }
5394
5395
64.4k
    if ( !xResult.is() )
5396
0
        throw uno::RuntimeException();
5397
5398
64.4k
    return xResult;
5399
64.4k
}
5400
5401
uno::Reference< embed::XExtendedStorageStream > SAL_CALL OStorage::openEncryptedStreamElementByHierarchicalName( const OUString& aStreamPath, ::sal_Int32 nOpenMode, const OUString& sPassword )
5402
0
{
5403
0
    return openEncryptedStreamByHierarchicalName( aStreamPath, nOpenMode, ::comphelper::OStorageHelper::CreatePackageEncryptionData( sPassword ) );
5404
0
}
5405
5406
void SAL_CALL OStorage::removeStreamElementByHierarchicalName( const OUString& aStreamPath )
5407
0
{
5408
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5409
5410
0
    if ( !m_pImpl )
5411
0
    {
5412
0
        SAL_INFO("package.xstor", "Disposed");
5413
0
        throw lang::DisposedException();
5414
0
    }
5415
5416
0
    if ( aStreamPath.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamPath, true ) )
5417
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
5418
5419
0
    if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE ) )
5420
0
        throw io::IOException(); // Access denied
5421
5422
0
    std::vector<OUString> aListPath = OHierarchyHolder_Impl::GetListPathFromString( aStreamPath );
5423
0
    OSL_ENSURE( aListPath.size(), "The result list must not be empty!" );
5424
5425
0
    if (!m_pHierarchyHolder)
5426
0
        m_pHierarchyHolder.reset(new OHierarchyHolder_Impl(this));
5427
5428
0
    m_pHierarchyHolder->RemoveStreamHierarchically(aListPath);
5429
0
}
5430
5431
// XHierarchicalStorageAccess2
5432
uno::Reference< embed::XExtendedStorageStream > SAL_CALL OStorage::openEncryptedStreamByHierarchicalName( const OUString& aStreamPath, ::sal_Int32 nOpenMode, const uno::Sequence< beans::NamedValue >& aEncryptionData )
5433
0
{
5434
0
    ::osl::MutexGuard aGuard( m_xSharedMutex->GetMutex() );
5435
5436
0
    if ( !m_pImpl )
5437
0
    {
5438
0
        SAL_INFO("package.xstor", "Disposed");
5439
0
        throw lang::DisposedException();
5440
0
    }
5441
5442
0
    if ( m_nStorageType != embed::StorageFormats::PACKAGE )
5443
0
        throw packages::NoEncryptionException();
5444
5445
0
    if ( aStreamPath.isEmpty() || !::comphelper::OStorageHelper::IsValidZipEntryFileName( aStreamPath, true ) )
5446
0
        throw lang::IllegalArgumentException( u"Unexpected entry name syntax."_ustr, uno::Reference< uno::XInterface >(), 1 );
5447
5448
0
    if ( !aEncryptionData.hasElements() )
5449
0
        throw lang::IllegalArgumentException( u""_ustr, uno::Reference< uno::XInterface >(), 3 );
5450
5451
0
    if ( !( m_pImpl->m_nStorageMode & embed::ElementModes::WRITE )
5452
0
      && ( nOpenMode & embed::ElementModes::WRITE ) )
5453
0
        throw io::IOException(); // Access denied
5454
5455
0
    std::vector<OUString> aListPath = OHierarchyHolder_Impl::GetListPathFromString( aStreamPath );
5456
0
    OSL_ENSURE( aListPath.size(), "The result list must not be empty!" );
5457
5458
0
    uno::Reference< embed::XExtendedStorageStream > xResult;
5459
0
    if ( aListPath.size() == 1 )
5460
0
    {
5461
        // that must be a direct request for a stream
5462
        // the transacted version of the stream should be opened
5463
5464
0
        SotElement_Impl *pElement = OpenStreamElement_Impl( aStreamPath, nOpenMode, true );
5465
0
        assert(pElement && pElement->m_xStream && "In case element can not be created an exception must be thrown!");
5466
5467
0
        xResult.set(pElement->m_xStream->GetStream(nOpenMode, aEncryptionData, true),
5468
0
                    uno::UNO_QUERY_THROW);
5469
0
    }
5470
0
    else
5471
0
    {
5472
        // there are still storages in between
5473
0
        if (!m_pHierarchyHolder)
5474
0
            m_pHierarchyHolder.reset(new OHierarchyHolder_Impl(this));
5475
5476
0
        xResult = m_pHierarchyHolder->GetStreamHierarchically(
5477
0
                                                ( m_pImpl->m_nStorageMode & embed::ElementModes::READWRITE ),
5478
0
                                                aListPath,
5479
0
                                                nOpenMode,
5480
0
                                                aEncryptionData );
5481
0
    }
5482
5483
0
    if ( !xResult.is() )
5484
0
        throw uno::RuntimeException();
5485
5486
0
    return xResult;
5487
0
}
5488
5489
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */