Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sfx2/source/doc/oleprops.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
21
#include "oleprops.hxx"
22
23
#include <comphelper/types.hxx>
24
#include <o3tl/safeint.hxx>
25
#include <tools/datetime.hxx>
26
#include <tools/globname.hxx>
27
#include <rtl/ref.hxx>
28
#include <rtl/tencinfo.h>
29
#include <sal/log.hxx>
30
#include <utility>
31
32
#include <com/sun/star/uno/Sequence.hxx>
33
34
35
17.2k
#define STREAM_BUFFER_SIZE 2048
36
37
// usings
38
using ::com::sun::star::uno::Any;
39
40
using namespace ::com::sun::star;
41
42
23.1k
#define TIMESTAMP_INVALID_DATETIME      ( DateTime ( Date ( 1, 1, 1601 ), tools::Time ( 0, 0, 0 ) ) )  /// Invalid value for date and time to create invalid instance of TimeStamp.
43
/// Invalid value for date and time to create invalid instance of TimeStamp.
44
19.0k
#define TIMESTAMP_INVALID_UTILDATETIME  (util::DateTime(0, 0, 0, 0, 1, 1, 1601, false))
45
/// Invalid value for date to create invalid instance of TimeStamp.
46
16
#define TIMESTAMP_INVALID_UTILDATE  (util::Date(1, 1, 1601))
47
48
namespace {
49
50
/** Property representing a signed 32-bit integer value. */
51
class SfxOleInt32Property : public SfxOlePropertyBase
52
{
53
public:
54
    explicit            SfxOleInt32Property( sal_Int32 nPropId, sal_Int32 nValue = 0 );
55
56
474
    sal_Int32    GetValue() const { return mnValue; }
57
58
private:
59
    virtual void        ImplLoad( SvStream& rStrm ) override;
60
    virtual void        ImplSave( SvStream& rStrm ) override;
61
62
private:
63
    sal_Int32           mnValue;
64
};
65
66
67
/** Property representing a floating-point value. */
68
class SfxOleDoubleProperty : public SfxOlePropertyBase
69
{
70
public:
71
    explicit            SfxOleDoubleProperty( sal_Int32 nPropId, double fValue = 0.0 );
72
73
78
    double       GetValue() const { return mfValue; }
74
75
private:
76
    virtual void        ImplLoad( SvStream& rStrm ) override;
77
    virtual void        ImplSave( SvStream& rStrm ) override;
78
79
private:
80
    double              mfValue;
81
};
82
83
84
/** Property representing a boolean value. */
85
class SfxOleBoolProperty : public SfxOlePropertyBase
86
{
87
public:
88
    explicit            SfxOleBoolProperty( sal_Int32 nPropId, bool bValue = false );
89
90
208
    bool         GetValue() const { return mbValue; }
91
92
private:
93
    virtual void        ImplLoad( SvStream& rStrm ) override;
94
    virtual void        ImplSave( SvStream& rStrm ) override;
95
96
private:
97
    bool                mbValue;
98
};
99
100
101
/** Base class for properties that contain a single string value. */
102
class SfxOleStringPropertyBase : public SfxOlePropertyBase, public SfxOleStringHelper
103
{
104
public:
105
    explicit            SfxOleStringPropertyBase(
106
                            sal_Int32 nPropId, sal_Int32 nPropType,
107
                            const SfxOleTextEncoding& rTextEnc );
108
    explicit            SfxOleStringPropertyBase(
109
                            sal_Int32 nPropId, sal_Int32 nPropType,
110
                            const SfxOleTextEncoding& rTextEnc, OUString aValue );
111
    explicit            SfxOleStringPropertyBase(
112
                            sal_Int32 nPropId, sal_Int32 nPropType,
113
                            rtl_TextEncoding eTextEnc );
114
115
30.1k
    const OUString& GetValue() const { return maValue; }
116
42.0k
    void            SetValue( const OUString& rValue ) { maValue = rValue; }
117
118
private:
119
    OUString            maValue;
120
};
121
122
123
/** Property representing a bytestring value. */
124
class SfxOleString8Property : public SfxOleStringPropertyBase
125
{
126
public:
127
    explicit            SfxOleString8Property(
128
                            sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc );
129
    explicit            SfxOleString8Property(
130
                            sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc,
131
                            const OUString& rValue );
132
133
private:
134
    virtual void        ImplLoad( SvStream& rStrm ) override;
135
    virtual void        ImplSave( SvStream& rStrm ) override;
136
};
137
138
139
/** Property representing a Unicode string value. */
140
class SfxOleString16Property : public SfxOleStringPropertyBase
141
{
142
public:
143
    explicit            SfxOleString16Property( sal_Int32 nPropId );
144
145
private:
146
    virtual void        ImplLoad( SvStream& rStrm ) override;
147
    virtual void        ImplSave( SvStream& rStrm ) override;
148
};
149
150
151
/** Property representing a filetime value as defined by the Windows API. */
152
class SfxOleFileTimeProperty : public SfxOlePropertyBase
153
{
154
public:
155
    explicit            SfxOleFileTimeProperty( sal_Int32 nPropId );
156
    /** @param rDateTime  Date and time as LOCAL time. */
157
    explicit            SfxOleFileTimeProperty( sal_Int32 nPropId, const util::DateTime& rDateTime );
158
159
    /** Returns the time value as LOCAL time. */
160
35.1k
    const util::DateTime& GetValue() const { return maDateTime; }
161
162
private:
163
    virtual void        ImplLoad( SvStream& rStrm ) override;
164
    virtual void        ImplSave( SvStream& rStrm ) override;
165
166
private:
167
    util::DateTime      maDateTime;
168
};
169
170
/** Property representing a filetime value as defined by the Windows API. */
171
class SfxOleDateProperty : public SfxOlePropertyBase
172
{
173
public:
174
    explicit            SfxOleDateProperty( sal_Int32 nPropId );
175
176
    /** Returns the date value as LOCAL time. */
177
32
    const util::Date& GetValue() const { return maDate; }
178
179
private:
180
    virtual void        ImplLoad( SvStream& rStrm ) override;
181
    virtual void        ImplSave( SvStream& rStrm ) override;
182
183
private:
184
    util::Date      maDate;
185
};
186
187
188
/** Property representing a thumbnail picture.
189
190
    Currently, only saving this property is implemented.
191
 */
192
class SfxOleThumbnailProperty : public SfxOlePropertyBase
193
{
194
public:
195
    explicit            SfxOleThumbnailProperty( sal_Int32 nPropId,
196
                            const uno::Sequence<sal_Int8> & i_rData);
197
198
0
    bool         IsValid() const { return mData.hasElements(); }
199
200
private:
201
    virtual void        ImplLoad( SvStream& rStrm ) override;
202
    virtual void        ImplSave( SvStream& rStrm ) override;
203
204
private:
205
    uno::Sequence<sal_Int8>    mData;
206
};
207
208
209
/** Property representing a BLOB (which presumably stands for binary large
210
    object).
211
212
    Currently, only saving this property is implemented.
213
 */
214
class SfxOleBlobProperty : public SfxOlePropertyBase
215
{
216
public:
217
    explicit            SfxOleBlobProperty( sal_Int32 nPropId,
218
                            const uno::Sequence<sal_Int8> & i_rData);
219
0
    bool         IsValid() const { return mData.hasElements(); }
220
221
private:
222
    virtual void        ImplLoad( SvStream& rStrm ) override;
223
    virtual void        ImplSave( SvStream& rStrm ) override;
224
225
private:
226
    uno::Sequence<sal_Int8>    mData;
227
};
228
229
}
230
231
sal_uInt16 SfxOleTextEncoding::GetCodePage() const
232
0
{
233
0
    sal_uInt16 nCodePage = IsUnicode() ? CODEPAGE_UNICODE :
234
0
        static_cast< sal_uInt16 >( rtl_getWindowsCodePageFromTextEncoding( *mxTextEnc ) );
235
0
    return (nCodePage == CODEPAGE_UNKNOWN) ? CODEPAGE_UTF8 : nCodePage;
236
0
}
237
238
void SfxOleTextEncoding::SetCodePage( sal_uInt16 nCodePage )
239
11.8k
{
240
11.8k
    if( nCodePage == CODEPAGE_UNICODE )
241
175
        SetUnicode();
242
11.7k
    else
243
11.7k
    {
244
11.7k
        rtl_TextEncoding eTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage );
245
11.7k
        if( eTextEnc != RTL_TEXTENCODING_DONTKNOW )
246
11.1k
            *mxTextEnc = eTextEnc;
247
11.7k
    }
248
11.8k
}
249
250
251
OUString SfxOleStringHelper::LoadString8( SvStream& rStrm ) const
252
55.3k
{
253
55.3k
    return IsUnicode() ? ImplLoadString16( rStrm ) : ImplLoadString8( rStrm );
254
55.3k
}
255
256
void SfxOleStringHelper::SaveString8( SvStream& rStrm, std::u16string_view rValue ) const
257
0
{
258
0
    if( IsUnicode() )
259
0
        ImplSaveString16( rStrm, rValue );
260
0
    else
261
0
        ImplSaveString8( rStrm, rValue );
262
0
}
263
264
OUString SfxOleStringHelper::LoadString16( SvStream& rStrm )
265
1.83k
{
266
1.83k
    return ImplLoadString16( rStrm );
267
1.83k
}
268
269
void SfxOleStringHelper::SaveString16( SvStream& rStrm, std::u16string_view rValue )
270
0
{
271
0
    ImplSaveString16( rStrm, rValue );
272
0
}
273
274
OUString SfxOleStringHelper::ImplLoadString8( SvStream& rStrm ) const
275
55.2k
{
276
    // read size field (signed 32-bit)
277
55.2k
    sal_Int32 nSize(0);
278
55.2k
    rStrm.ReadInt32( nSize );
279
    // size field includes trailing NUL character
280
55.2k
    SAL_WARN_IF(nSize < 1 || nSize > 0xFFFF, "sfx.doc", "SfxOleStringHelper::ImplLoadString8 - invalid string of len " << nSize);
281
55.2k
    if (nSize < 1 || nSize > 0xFFFF)
282
13.3k
        return OUString();
283
    // load character buffer
284
41.9k
    OString sValue(read_uInt8s_ToOString(rStrm, nSize - 1));
285
41.9k
    if (rStrm.good() && rStrm.remainingSize())
286
40.9k
        rStrm.SeekRel(1);  // skip null-byte at end
287
41.9k
    return OStringToOUString(sValue, GetTextEncoding());
288
55.2k
}
289
290
OUString SfxOleStringHelper::ImplLoadString16( SvStream& rStrm )
291
1.99k
{
292
    // read size field (signed 32-bit), may be buffer size or character count
293
1.99k
    sal_Int32 nSize(0);
294
1.99k
    rStrm.ReadInt32(nSize);
295
1.99k
    SAL_WARN_IF(nSize < 1 || nSize > 0xFFFF, "sfx.doc", "SfxOleStringHelper::ImplLoadString16 - invalid string of len " << nSize);
296
    // size field includes trailing NUL character
297
1.99k
    if (nSize < 1 || nSize > 0xFFFF)
298
276
        return OUString();
299
    // load character buffer
300
1.71k
    OUString aValue = read_uInt16s_ToOUString(rStrm, nSize - 1);
301
1.71k
    sal_Int32 nSkip(2); // skip null-byte at end
302
    // stream is always padded to 32-bit boundary, skip 2 bytes on odd character count
303
1.71k
    if ((nSize & 1) == 1)
304
691
        nSkip += 2;
305
1.71k
    nSkip = std::min<sal_uInt32>(nSkip, rStrm.remainingSize());
306
1.71k
    if (rStrm.good() && nSkip)
307
1.66k
        rStrm.SeekRel(nSkip);
308
1.71k
    return aValue;
309
1.99k
}
310
311
void SfxOleStringHelper::ImplSaveString8( SvStream& rStrm, std::u16string_view rValue ) const
312
0
{
313
    // encode to byte string
314
0
    OString aEncoded(OUStringToOString(rValue, GetTextEncoding()));
315
    // write size field (including trailing NUL character)
316
0
    sal_Int32 nSize = aEncoded.getLength() + 1;
317
0
    rStrm.WriteInt32( nSize );
318
    // write character array with trailing NUL character
319
0
    rStrm.WriteBytes(aEncoded.getStr(), aEncoded.getLength());
320
0
    rStrm.WriteUChar( 0 );
321
0
}
322
323
void SfxOleStringHelper::ImplSaveString16( SvStream& rStrm, std::u16string_view rValue )
324
0
{
325
    // write size field (including trailing NUL character)
326
0
    sal_Int32 nSize = static_cast< sal_Int32 >( rValue.size() + 1 );
327
0
    rStrm.WriteInt32( nSize );
328
    // write character array with trailing NUL character
329
0
    for( char16_t c : rValue )
330
0
        rStrm.WriteUInt16( c );
331
0
    rStrm.WriteUInt16( 0 );
332
    // stream is always padded to 32-bit boundary, add 2 bytes on odd character count
333
0
    if( (nSize & 1) == 1 )
334
0
        rStrm.WriteUInt16( 0 );
335
0
}
336
337
338
SfxOleObjectBase::~SfxOleObjectBase()
339
243k
{
340
243k
}
341
342
ErrCode const & SfxOleObjectBase::Load( SvStream& rStrm )
343
179k
{
344
179k
    mnErrCode = ERRCODE_NONE;
345
179k
    ImplLoad( rStrm );
346
179k
    SetError( rStrm.GetErrorCode() );
347
179k
    return GetError();
348
179k
}
349
350
ErrCode const & SfxOleObjectBase::Save( SvStream& rStrm )
351
0
{
352
0
    mnErrCode = ERRCODE_NONE;
353
0
    ImplSave( rStrm );
354
0
    SetError( rStrm.GetErrorCode() );
355
0
    return GetError();
356
0
}
357
358
void SfxOleObjectBase::LoadObject( SvStream& rStrm, SfxOleObjectBase& rObj )
359
54.6k
{
360
54.6k
    SetError( rObj.Load( rStrm ) );
361
54.6k
}
362
363
void SfxOleObjectBase::SaveObject( SvStream& rStrm, SfxOleObjectBase& rObj )
364
0
{
365
0
    SetError( rObj.Save( rStrm ) );
366
0
}
367
368
369
SfxOleCodePageProperty::SfxOleCodePageProperty() :
370
27.1k
    SfxOlePropertyBase( PROPID_CODEPAGE, PROPTYPE_INT16 )
371
27.1k
{
372
27.1k
}
373
374
void SfxOleCodePageProperty::ImplLoad(SvStream& rStrm)
375
11.8k
{
376
    // property type is signed int16, but we use always unsigned int16 for codepages
377
11.8k
    sal_uInt16 nCodePage(0);
378
11.8k
    rStrm.ReadUInt16(nCodePage);
379
11.8k
    SetCodePage(nCodePage);
380
11.8k
}
381
382
void SfxOleCodePageProperty::ImplSave( SvStream& rStrm )
383
0
{
384
    // property type is signed int16, but we use always unsigned int16 for codepages
385
0
    rStrm.WriteUInt16( GetCodePage() );
386
0
}
387
388
389
SfxOleInt32Property::SfxOleInt32Property( sal_Int32 nPropId, sal_Int32 nValue ) :
390
24.4k
    SfxOlePropertyBase( nPropId, PROPTYPE_INT32 ),
391
24.4k
    mnValue( nValue )
392
24.4k
{
393
24.4k
}
394
395
void SfxOleInt32Property::ImplLoad( SvStream& rStrm )
396
24.4k
{
397
24.4k
    rStrm.ReadInt32( mnValue );
398
24.4k
}
399
400
void SfxOleInt32Property::ImplSave( SvStream& rStrm )
401
0
{
402
0
    rStrm.WriteInt32( mnValue );
403
0
}
404
405
406
SfxOleDoubleProperty::SfxOleDoubleProperty( sal_Int32 nPropId, double fValue ) :
407
1.19k
    SfxOlePropertyBase( nPropId, PROPTYPE_DOUBLE ),
408
1.19k
    mfValue( fValue )
409
1.19k
{
410
1.19k
}
411
412
void SfxOleDoubleProperty::ImplLoad( SvStream& rStrm )
413
1.19k
{
414
1.19k
    rStrm.ReadDouble( mfValue );
415
1.19k
}
416
417
void SfxOleDoubleProperty::ImplSave( SvStream& rStrm )
418
0
{
419
0
    rStrm.WriteDouble( mfValue );
420
0
}
421
422
423
SfxOleBoolProperty::SfxOleBoolProperty( sal_Int32 nPropId, bool bValue ) :
424
12.6k
    SfxOlePropertyBase( nPropId, PROPTYPE_BOOL ),
425
12.6k
    mbValue( bValue )
426
12.6k
{
427
12.6k
}
428
429
void SfxOleBoolProperty::ImplLoad( SvStream& rStrm )
430
12.6k
{
431
12.6k
    sal_Int16 nValue(0);
432
12.6k
    rStrm.ReadInt16( nValue );
433
12.6k
    mbValue = nValue != 0;
434
12.6k
}
435
436
void SfxOleBoolProperty::ImplSave( SvStream& rStrm )
437
0
{
438
0
    rStrm.WriteInt16( mbValue ? -1 : 0 );
439
0
}
440
441
442
SfxOleStringPropertyBase::SfxOleStringPropertyBase(
443
        sal_Int32 nPropId, sal_Int32 nPropType, const SfxOleTextEncoding& rTextEnc ) :
444
40.1k
    SfxOlePropertyBase( nPropId, nPropType ),
445
40.1k
    SfxOleStringHelper( rTextEnc )
446
40.1k
{
447
40.1k
}
448
449
SfxOleStringPropertyBase::SfxOleStringPropertyBase(
450
        sal_Int32 nPropId, sal_Int32 nPropType, const SfxOleTextEncoding& rTextEnc, OUString aValue ) :
451
0
    SfxOlePropertyBase( nPropId, nPropType ),
452
0
    SfxOleStringHelper( rTextEnc ),
453
0
    maValue(std::move( aValue ))
454
0
{
455
0
}
456
457
SfxOleStringPropertyBase::SfxOleStringPropertyBase(
458
        sal_Int32 nPropId, sal_Int32 nPropType, rtl_TextEncoding eTextEnc ) :
459
1.83k
    SfxOlePropertyBase( nPropId, nPropType ),
460
1.83k
    SfxOleStringHelper( eTextEnc )
461
1.83k
{
462
1.83k
}
463
464
465
SfxOleString8Property::SfxOleString8Property(
466
        sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc ) :
467
40.1k
    SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING8, rTextEnc )
468
40.1k
{
469
40.1k
}
470
471
SfxOleString8Property::SfxOleString8Property(
472
        sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc, const OUString& rValue ) :
473
0
    SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING8, rTextEnc, rValue )
474
0
{
475
0
}
476
477
void SfxOleString8Property::ImplLoad( SvStream& rStrm )
478
40.1k
{
479
40.1k
    SetValue( LoadString8( rStrm ) );
480
40.1k
}
481
482
void SfxOleString8Property::ImplSave( SvStream& rStrm )
483
0
{
484
0
    SaveString8( rStrm, GetValue() );
485
0
}
486
487
488
SfxOleString16Property::SfxOleString16Property( sal_Int32 nPropId ) :
489
1.83k
    SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING16, RTL_TEXTENCODING_UCS2 )
490
1.83k
{
491
1.83k
}
492
493
void SfxOleString16Property::ImplLoad( SvStream& rStrm )
494
1.83k
{
495
1.83k
    SetValue( LoadString16( rStrm ) );
496
1.83k
}
497
498
void SfxOleString16Property::ImplSave( SvStream& rStrm )
499
0
{
500
0
    SaveString16( rStrm, GetValue() );
501
0
}
502
503
504
SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId ) :
505
23.1k
    SfxOlePropertyBase( nPropId, PROPTYPE_FILETIME )
506
23.1k
{
507
23.1k
}
508
509
SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId, const util::DateTime& rDateTime ) :
510
0
    SfxOlePropertyBase( nPropId, PROPTYPE_FILETIME ),
511
0
    maDateTime( rDateTime )
512
0
{
513
0
}
514
515
void SfxOleFileTimeProperty::ImplLoad( SvStream& rStrm )
516
23.1k
{
517
23.1k
    sal_uInt32 nLower(0), nUpper(0);
518
23.1k
    rStrm.ReadUInt32( nLower ).ReadUInt32( nUpper );
519
23.1k
    ::DateTime aDateTime = DateTime::CreateFromWin32FileDateTime( nLower, nUpper );
520
    // note: editing duration is stored as offset to TIMESTAMP_INVALID_DATETIME
521
    //       of course we should not convert the time zone of a duration!
522
    // heuristic to detect editing durations (which we assume to be < 1 year):
523
    // check only the year, not the entire date
524
23.1k
    if ( aDateTime.GetYear() != TIMESTAMP_INVALID_DATETIME.GetYear() )
525
14.0k
        aDateTime.ConvertToLocalTime();
526
23.1k
    maDateTime.Year    = aDateTime.GetYear();
527
23.1k
    maDateTime.Month   = aDateTime.GetMonth();
528
23.1k
    maDateTime.Day     = aDateTime.GetDay();
529
23.1k
    maDateTime.Hours   = aDateTime.GetHour();
530
23.1k
    maDateTime.Minutes = aDateTime.GetMin();
531
23.1k
    maDateTime.Seconds = aDateTime.GetSec();
532
23.1k
    maDateTime.NanoSeconds = aDateTime.GetNanoSec();
533
23.1k
    maDateTime.IsUTC   = false;
534
23.1k
}
535
536
void SfxOleFileTimeProperty::ImplSave( SvStream& rStrm )
537
0
{
538
0
    DateTime aDateTimeUtc(
539
0
            Date(
540
0
                maDateTime.Day,
541
0
                maDateTime.Month,
542
0
                static_cast< sal_uInt16 >( maDateTime.Year ) ),
543
0
            tools::Time(
544
0
                maDateTime.Hours,
545
0
                maDateTime.Minutes,
546
0
                maDateTime.Seconds,
547
0
                maDateTime.NanoSeconds ) );
548
    // invalid time stamp is not converted to UTC
549
    // heuristic to detect editing durations (which we assume to be < 1 year):
550
    // check only the year, not the entire date
551
0
    if( aDateTimeUtc.IsValidAndGregorian()
552
0
        && aDateTimeUtc.GetYear() != TIMESTAMP_INVALID_DATETIME.GetYear() ) {
553
0
            aDateTimeUtc.ConvertToUTC();
554
0
    }
555
0
    sal_uInt32 nLower, nUpper;
556
0
    aDateTimeUtc.GetWin32FileDateTime( nLower, nUpper );
557
0
    rStrm.WriteUInt32( nLower ).WriteUInt32( nUpper );
558
0
}
559
560
SfxOleDateProperty::SfxOleDateProperty( sal_Int32 nPropId ) :
561
3.69k
    SfxOlePropertyBase( nPropId, PROPTYPE_DATE )
562
3.69k
{
563
3.69k
}
564
565
void SfxOleDateProperty::ImplLoad( SvStream& rStrm )
566
3.69k
{
567
3.69k
    double fValue(0.0);
568
3.69k
    rStrm.ReadDouble( fValue );
569
    //stored as number of days (not seconds) since December 31, 1899
570
3.69k
    sal_Int32 nDays = fValue;
571
3.69k
    sal_Int32 nStartDays = ::Date::DateToDays(31, 12, 1899);
572
3.69k
    if (o3tl::checked_add(nStartDays, nDays, nStartDays))
573
3.69k
        SAL_WARN("sfx.doc", "SfxOleDateProperty::ImplLoad bad date, ignored");
574
3.69k
    else
575
3.69k
    {
576
3.69k
        ::Date aDate(31, 12, 1899);
577
3.69k
        aDate.AddDays(nDays);
578
3.69k
        maDate.Day = aDate.GetDay();
579
3.69k
        maDate.Month = aDate.GetMonth();
580
3.69k
        maDate.Year = aDate.GetYear();
581
3.69k
    }
582
3.69k
}
583
584
void SfxOleDateProperty::ImplSave( SvStream& rStrm )
585
0
{
586
0
    sal_Int32 nDays = ::Date::DateToDays(maDate.Day, maDate.Month, maDate.Year);
587
    //number of days (not seconds) since December 31, 1899
588
0
    sal_Int32 nStartDays = ::Date::DateToDays(31, 12, 1899);
589
0
    double fValue = nDays-nStartDays;
590
0
    rStrm.WriteDouble( fValue );
591
0
}
592
593
594
SfxOleThumbnailProperty::SfxOleThumbnailProperty(
595
        sal_Int32 nPropId, const uno::Sequence<sal_Int8> & i_rData) :
596
0
    SfxOlePropertyBase( nPropId, PROPTYPE_CLIPFMT ),
597
0
    mData(i_rData)
598
0
{
599
0
}
600
601
void SfxOleThumbnailProperty::ImplLoad( SvStream& )
602
0
{
603
0
    SAL_WARN( "sfx.doc", "SfxOleThumbnailProperty::ImplLoad - not implemented" );
604
0
    SetError( SVSTREAM_INVALID_ACCESS );
605
0
}
606
607
void SfxOleThumbnailProperty::ImplSave( SvStream& rStrm )
608
0
{
609
    /*  Type        Contents
610
        -----------------------------------------------------------------------
611
        int32       size of following data
612
        int32       clipboard format tag (see below)
613
        byte[]      clipboard data (see below)
614
615
        Clipboard format tag:
616
            -1 = Windows clipboard format
617
            -2 = Macintosh clipboard format
618
            -3 = GUID that contains a format identifier (FMTID)
619
            >0 = custom clipboard format name plus data (see msdn site below)
620
            0  = no data
621
622
        References:
623
        http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/propvariant.asp
624
        http://jakarta.apache.org/poi/hpsf/thumbnails.html
625
        http://linux.com.hk/docs/poi/org/apache/poi/hpsf/Thumbnail.html
626
        https://web.archive.org/web/20060126202945/http://sparks.discreet.com/knowledgebase/public/solutions/ExtractThumbnailImg.htm
627
     */
628
0
    if( IsValid() )
629
0
    {
630
        // clipboard size: clip_format_tag + data_format_tag + bitmap_len
631
0
        sal_Int32 nClipSize = static_cast< sal_Int32 >( 4 + 4 + mData.getLength() );
632
0
        rStrm.WriteInt32( nClipSize ).WriteInt32( CLIPFMT_WIN ).WriteInt32( CLIPDATAFMT_DIB );
633
0
        rStrm.WriteBytes(mData.getConstArray(), mData.getLength());
634
0
    }
635
0
    else
636
0
    {
637
0
        SAL_WARN( "sfx.doc", "SfxOleThumbnailProperty::ImplSave - invalid thumbnail property" );
638
0
        SetError( SVSTREAM_INVALID_ACCESS );
639
0
    }
640
0
}
641
642
643
SfxOleBlobProperty::SfxOleBlobProperty( sal_Int32 nPropId,
644
        const uno::Sequence<sal_Int8> & i_rData) :
645
0
    SfxOlePropertyBase( nPropId, PROPTYPE_BLOB ),
646
0
    mData(i_rData)
647
0
{
648
0
}
649
650
void SfxOleBlobProperty::ImplLoad( SvStream& )
651
0
{
652
0
    SAL_WARN( "sfx.doc", "SfxOleBlobProperty::ImplLoad - not implemented" );
653
0
    SetError( SVSTREAM_INVALID_ACCESS );
654
0
}
655
656
void SfxOleBlobProperty::ImplSave( SvStream& rStrm )
657
0
{
658
0
    if (IsValid()) {
659
0
        rStrm.WriteBytes(mData.getConstArray(), mData.getLength());
660
0
    } else {
661
0
        SAL_WARN( "sfx.doc", "SfxOleBlobProperty::ImplSave - invalid BLOB property" );
662
0
        SetError( SVSTREAM_INVALID_ACCESS );
663
0
    }
664
0
}
665
666
667
SfxOleDictionaryProperty::SfxOleDictionaryProperty( const SfxOleTextEncoding& rTextEnc ) :
668
27.1k
    SfxOlePropertyBase( PROPID_DICTIONARY, 0 ),
669
27.1k
    SfxOleStringHelper( rTextEnc )
670
27.1k
{
671
27.1k
}
672
673
OUString SfxOleDictionaryProperty::GetPropertyName( sal_Int32 nPropId ) const
674
2.15k
{
675
2.15k
    SfxOlePropNameMap::const_iterator aIt = maPropNameMap.find( nPropId );
676
2.15k
    return (aIt == maPropNameMap.end()) ? OUString() : aIt->second;
677
2.15k
}
678
679
void SfxOleDictionaryProperty::SetPropertyName( sal_Int32 nPropId, const OUString& rPropName )
680
0
{
681
0
    maPropNameMap[ nPropId ] = rPropName;
682
    // dictionary property contains number of pairs in property type field
683
0
    SetPropType( static_cast< sal_Int32 >( maPropNameMap.size() ) );
684
0
}
685
686
void SfxOleDictionaryProperty::ImplLoad( SvStream& rStrm )
687
1.19k
{
688
    // dictionary property contains number of pairs in property type field
689
1.19k
    sal_Int32 nNameCount = GetPropType();
690
    // read property ID/name pairs
691
1.19k
    maPropNameMap.clear();
692
16.3k
    for (sal_Int32 nIdx = 0; nIdx < nNameCount && rStrm.good() && rStrm.remainingSize() >= 4; ++nIdx)
693
15.1k
    {
694
15.1k
        sal_Int32 nPropId(0);
695
15.1k
        rStrm.ReadInt32(nPropId);
696
        // name always stored as byte string
697
15.1k
        maPropNameMap[nPropId] = LoadString8(rStrm);
698
15.1k
    }
699
1.19k
}
700
701
void SfxOleDictionaryProperty::ImplSave( SvStream& rStrm )
702
0
{
703
    // write property ID/name pairs
704
0
    for (auto const& propName : maPropNameMap)
705
0
    {
706
0
        rStrm.WriteInt32( propName.first );
707
        // name always stored as byte string
708
0
        SaveString8( rStrm, propName.second );
709
0
    }
710
0
}
711
712
713
SfxOleSection::SfxOleSection( bool bSupportsDict ) :
714
27.1k
    maDictProp( maCodePageProp ),
715
27.1k
    mnStartPos( 0 ),
716
27.1k
    mbSupportsDict( bSupportsDict )
717
27.1k
{
718
27.1k
}
719
720
SfxOlePropertyRef SfxOleSection::GetProperty( sal_Int32 nPropId ) const
721
81.7k
{
722
81.7k
    SfxOlePropertyRef xProp;
723
81.7k
    SfxOlePropMap::const_iterator aIt = maPropMap.find( nPropId );
724
81.7k
    if( aIt != maPropMap.end() )
725
55.1k
        xProp = aIt->second;
726
81.7k
    return xProp;
727
81.7k
}
728
729
bool SfxOleSection::GetInt32Value( sal_Int32& rnValue, sal_Int32 nPropId ) const
730
2.15k
{
731
2.15k
    SfxOlePropertyRef xProp = GetProperty( nPropId );
732
2.15k
    const SfxOleInt32Property* pProp =
733
2.15k
        dynamic_cast< const SfxOleInt32Property* >( xProp.get() );
734
2.15k
    if( pProp )
735
474
        rnValue = pProp->GetValue();
736
2.15k
    return pProp != nullptr;
737
2.15k
}
738
739
bool SfxOleSection::GetDoubleValue( double& rfValue, sal_Int32 nPropId ) const
740
1.68k
{
741
1.68k
    SfxOlePropertyRef xProp = GetProperty( nPropId );
742
1.68k
    const SfxOleDoubleProperty* pProp =
743
1.68k
        dynamic_cast< const SfxOleDoubleProperty* >( xProp.get() );
744
1.68k
    if( pProp )
745
78
        rfValue = pProp->GetValue();
746
1.68k
    return pProp != nullptr;
747
1.68k
}
748
749
bool SfxOleSection::GetBoolValue( bool& rbValue, sal_Int32 nPropId ) const
750
1.60k
{
751
1.60k
    SfxOlePropertyRef xProp = GetProperty( nPropId );
752
1.60k
    const SfxOleBoolProperty* pProp =
753
1.60k
        dynamic_cast< const SfxOleBoolProperty* >( xProp.get() );
754
1.60k
    if( pProp )
755
208
        rbValue = pProp->GetValue();
756
1.60k
    return pProp != nullptr;
757
1.60k
}
758
759
bool SfxOleSection::GetStringValue( OUString& rValue, sal_Int32 nPropId ) const
760
50.9k
{
761
50.9k
    SfxOlePropertyRef xProp = GetProperty( nPropId );
762
50.9k
    const SfxOleStringPropertyBase* pProp =
763
50.9k
        dynamic_cast< const SfxOleStringPropertyBase* >( xProp.get() );
764
50.9k
    if( pProp )
765
30.1k
        rValue = pProp->GetValue();
766
50.9k
    return pProp != nullptr;
767
50.9k
}
768
769
bool SfxOleSection::GetFileTimeValue( util::DateTime& rValue, sal_Int32 nPropId ) const
770
25.3k
{
771
25.3k
    SfxOlePropertyRef xProp = GetProperty( nPropId );
772
25.3k
    const SfxOleFileTimeProperty* pProp =
773
25.3k
        dynamic_cast< const SfxOleFileTimeProperty* >( xProp.get() );
774
25.3k
    if( pProp )
775
19.0k
    {
776
19.0k
        if ( pProp->GetValue() == TIMESTAMP_INVALID_UTILDATETIME )
777
2.94k
            rValue = util::DateTime();
778
16.0k
        else
779
16.0k
            rValue = pProp->GetValue();
780
19.0k
    }
781
25.3k
    return pProp != nullptr;
782
25.3k
}
783
784
bool SfxOleSection::GetDateValue( util::Date& rValue, sal_Int32 nPropId ) const
785
16
{
786
16
    SfxOlePropertyRef xProp = GetProperty( nPropId );
787
16
    const SfxOleDateProperty* pProp =
788
16
        dynamic_cast< const SfxOleDateProperty* >( xProp.get() );
789
16
    if( pProp )
790
16
    {
791
16
        if ( pProp->GetValue() == TIMESTAMP_INVALID_UTILDATE )
792
0
            rValue = util::Date();
793
16
        else
794
16
            rValue = pProp->GetValue();
795
16
    }
796
16
    return pProp != nullptr;
797
16
}
798
799
void SfxOleSection::SetProperty( const SfxOlePropertyRef& xProp )
800
0
{
801
0
    if( xProp )
802
0
        maPropMap[ xProp->GetPropId() ] = xProp;
803
0
}
804
805
void SfxOleSection::SetInt32Value( sal_Int32 nPropId, sal_Int32 nValue )
806
0
{
807
0
    SetProperty( std::make_shared<SfxOleInt32Property>( nPropId, nValue ) );
808
0
}
809
810
void SfxOleSection::SetDoubleValue( sal_Int32 nPropId, double fValue )
811
0
{
812
0
    SetProperty( std::make_shared<SfxOleDoubleProperty>( nPropId, fValue ) );
813
0
}
814
815
void SfxOleSection::SetBoolValue( sal_Int32 nPropId, bool bValue )
816
0
{
817
0
    SetProperty( std::make_shared<SfxOleBoolProperty>( nPropId, bValue ) );
818
0
}
819
820
bool SfxOleSection::SetStringValue( sal_Int32 nPropId, const OUString& rValue )
821
0
{
822
0
    bool bInserted = !rValue.isEmpty();
823
0
    if( bInserted )
824
0
        SetProperty( std::make_shared<SfxOleString8Property>( nPropId, maCodePageProp, rValue ) );
825
0
    return bInserted;
826
0
}
827
828
void SfxOleSection::SetFileTimeValue( sal_Int32 nPropId, const util::DateTime& rValue )
829
0
{
830
0
    if ( rValue.Year == 0 || rValue.Month == 0 || rValue.Day == 0 )
831
0
        SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, TIMESTAMP_INVALID_UTILDATETIME ) );
832
0
    else
833
0
        SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, rValue ) );
834
0
}
835
836
void SfxOleSection::SetDateValue( sal_Int32 nPropId, const util::Date& rValue )
837
0
{
838
    //Annoyingly MS2010 considers VT_DATE apparently as an invalid possibility, so here we use VT_FILETIME
839
    //instead :-(
840
0
    if ( rValue.Year == 0 || rValue.Month == 0 || rValue.Day == 0 )
841
0
        SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, TIMESTAMP_INVALID_UTILDATETIME ) );
842
0
    else
843
0
    {
844
0
        const util::DateTime aValue(0, 0, 0, 0, rValue.Day, rValue.Month,
845
0
                rValue.Year, false );
846
0
        SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, aValue ) );
847
0
    }
848
0
}
849
850
void SfxOleSection::SetThumbnailValue( sal_Int32 nPropId,
851
    const uno::Sequence<sal_Int8> & i_rData)
852
0
{
853
0
    auto pThumbnail = std::make_shared<SfxOleThumbnailProperty>( nPropId, i_rData );
854
0
    if( pThumbnail->IsValid() )
855
0
        SetProperty( pThumbnail );
856
0
}
857
858
void SfxOleSection::SetBlobValue( sal_Int32 nPropId,
859
    const uno::Sequence<sal_Int8> & i_rData)
860
0
{
861
0
    auto pBlob = std::make_shared<SfxOleBlobProperty>( nPropId, i_rData );
862
0
    if( pBlob->IsValid() )
863
0
        SetProperty( pBlob );
864
0
}
865
866
Any SfxOleSection::GetAnyValue( sal_Int32 nPropId ) const
867
2.15k
{
868
2.15k
    Any aValue;
869
2.15k
    sal_Int32 nInt32 = 0;
870
2.15k
    double fDouble = 0.0;
871
2.15k
    bool bBool = false;
872
2.15k
    OUString aString;
873
2.15k
    css::util::DateTime aApiDateTime;
874
2.15k
    css::util::Date aApiDate;
875
876
2.15k
    if( GetInt32Value( nInt32, nPropId ) )
877
474
        aValue <<= nInt32;
878
1.68k
    else if( GetDoubleValue( fDouble, nPropId ) )
879
78
        aValue <<= fDouble;
880
1.60k
    else if( GetBoolValue( bBool, nPropId ) )
881
208
        aValue <<= bBool;
882
1.39k
    else if( GetStringValue( aString, nPropId ) )
883
879
        aValue <<= aString;
884
518
    else if( GetFileTimeValue( aApiDateTime, nPropId ) )
885
502
    {
886
502
        aValue <<= aApiDateTime;
887
502
    }
888
16
    else if( GetDateValue( aApiDate, nPropId ) )
889
16
    {
890
16
        aValue <<= aApiDate;
891
16
    }
892
2.15k
    return aValue;
893
2.15k
}
894
895
bool SfxOleSection::SetAnyValue( sal_Int32 nPropId, const Any& rValue )
896
0
{
897
0
    bool bInserted = true;
898
0
    sal_Int32 nInt32 = 0;
899
0
    double fDouble = 0.0;
900
0
    OUString aString;
901
0
    css::util::DateTime aApiDateTime;
902
0
    css::util::Date aApiDate;
903
904
0
    if( rValue.getValueType() == cppu::UnoType<bool>::get() )
905
0
        SetBoolValue( nPropId, ::comphelper::getBOOL( rValue ) );
906
0
    else if( rValue >>= nInt32 )
907
0
        SetInt32Value( nPropId, nInt32 );
908
0
    else if( rValue >>= fDouble )
909
0
        SetDoubleValue( nPropId, fDouble );
910
0
    else if( rValue >>= aString )
911
0
        bInserted = SetStringValue( nPropId, aString );
912
0
    else if( rValue >>= aApiDateTime )
913
0
        SetFileTimeValue( nPropId, aApiDateTime );
914
0
    else if( rValue >>= aApiDate )
915
0
        SetDateValue( nPropId, aApiDate );
916
0
    else
917
0
        bInserted = false;
918
0
    return bInserted;
919
0
}
920
921
OUString SfxOleSection::GetPropertyName( sal_Int32 nPropId ) const
922
2.15k
{
923
2.15k
    return maDictProp.GetPropertyName( nPropId );
924
2.15k
}
925
926
void SfxOleSection::SetPropertyName( sal_Int32 nPropId, const OUString& rPropName )
927
0
{
928
0
    maDictProp.SetPropertyName( nPropId, rPropName );
929
0
}
930
931
void SfxOleSection::GetPropertyIds( ::std::vector< sal_Int32 >& rPropIds ) const
932
2.25k
{
933
2.25k
    rPropIds.clear();
934
2.25k
    for (auto const& prop : maPropMap)
935
2.15k
        rPropIds.push_back(prop.first);
936
2.25k
}
937
938
sal_Int32 SfxOleSection::GetFreePropertyId() const
939
0
{
940
0
    return maPropMap.empty() ? PROPID_FIRSTCUSTOM : (maPropMap.rbegin()->first + 1);
941
0
}
942
943
void SfxOleSection::ImplLoad( SvStream& rStrm )
944
41.6k
{
945
    // read section header
946
41.6k
    mnStartPos = rStrm.Tell();
947
41.6k
    sal_uInt32 nSize(0);
948
41.6k
    sal_Int32 nPropCount(0);
949
41.6k
    rStrm.ReadUInt32( nSize ).ReadInt32( nPropCount );
950
951
    // read property ID/position pairs
952
41.6k
    typedef ::std::map< sal_Int32, sal_uInt32 > SfxOlePropPosMap;
953
41.6k
    SfxOlePropPosMap aPropPosMap;
954
17.3M
    for (sal_Int32 nPropIdx = 0; nPropIdx < nPropCount && rStrm.good(); ++nPropIdx)
955
17.3M
    {
956
17.3M
        sal_Int32 nPropId(0);
957
17.3M
        sal_uInt32 nPropPos(0);
958
17.3M
        rStrm.ReadInt32( nPropId ).ReadUInt32( nPropPos );
959
17.3M
        aPropPosMap[ nPropId ] = nPropPos;
960
17.3M
    }
961
962
    // read codepage property
963
41.6k
    SfxOlePropPosMap::iterator aCodePageIt = aPropPosMap.find( PROPID_CODEPAGE );
964
41.6k
    if( (aCodePageIt != aPropPosMap.end()) && SeekToPropertyPos( rStrm, aCodePageIt->second ) )
965
20.9k
    {
966
        // codepage property must be of type signed int-16
967
20.9k
        sal_Int32 nPropType(0);
968
20.9k
        rStrm.ReadInt32( nPropType );
969
20.9k
        if( nPropType == PROPTYPE_INT16 )
970
11.8k
            LoadObject( rStrm, maCodePageProp );
971
        // remove property position
972
20.9k
        aPropPosMap.erase( aCodePageIt );
973
20.9k
    }
974
975
    // read dictionary property
976
41.6k
    SfxOlePropPosMap::iterator aDictIt = aPropPosMap.find( PROPID_DICTIONARY );
977
41.6k
    if( (aDictIt != aPropPosMap.end()) && SeekToPropertyPos( rStrm, aDictIt->second ) )
978
19.9k
    {
979
        // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
980
19.9k
        if( mbSupportsDict )
981
1.19k
        {
982
            // dictionary property contains number of pairs in property type field
983
1.19k
            sal_Int32 nNameCount(0);
984
1.19k
            rStrm.ReadInt32( nNameCount );
985
1.19k
            maDictProp.SetNameCount( nNameCount );
986
1.19k
            LoadObject( rStrm, maDictProp );
987
1.19k
        }
988
        // always remove position of dictionary property (do not try to read it again below)
989
19.9k
        aPropPosMap.erase( aDictIt );
990
19.9k
    }
991
992
    // read other properties
993
41.6k
    maPropMap.clear();
994
41.6k
    for (auto const& propPos : aPropPosMap)
995
5.03M
        if( SeekToPropertyPos( rStrm, propPos.second ) )
996
1.07M
            LoadProperty( rStrm, propPos.first );
997
41.6k
}
998
999
void SfxOleSection::ImplSave( SvStream& rStrm )
1000
0
{
1001
    /*  Always export with UTF-8 encoding. All dependent properties (bytestring
1002
        and dictionary) will be updated automatically. */
1003
0
    maCodePageProp.SetTextEncoding( RTL_TEXTENCODING_UTF8 );
1004
1005
    // write section header
1006
0
    mnStartPos = rStrm.Tell();
1007
0
    sal_Int32 nPropCount = static_cast< sal_Int32 >( maPropMap.size() + 1 );
1008
0
    if( maDictProp.HasPropertyNames() )
1009
0
        ++nPropCount;
1010
0
    rStrm.WriteUInt32( 0 ).WriteInt32( nPropCount );
1011
1012
    // write placeholders for property ID/position pairs
1013
0
    sal_uInt64 nPropPosPos = rStrm.Tell();
1014
0
    rStrm.SeekRel( static_cast< sal_sSize >(nPropCount) * 8 );
1015
1016
    // write dictionary property
1017
0
    if( maDictProp.HasPropertyNames() )
1018
0
        SaveProperty( rStrm, maDictProp, nPropPosPos );
1019
    // write codepage property
1020
0
    SaveProperty( rStrm, maCodePageProp, nPropPosPos );
1021
    // write other properties
1022
0
    for (auto const& prop : maPropMap)
1023
0
        SaveProperty( rStrm, *prop.second, nPropPosPos );
1024
1025
    // write section size (first field in section header)
1026
0
    sal_uInt32 nSectSize = static_cast< sal_uInt32 >( rStrm.TellEnd() - mnStartPos );
1027
0
    rStrm.Seek( mnStartPos );
1028
0
    rStrm.WriteUInt32( nSectSize );
1029
0
}
1030
1031
bool SfxOleSection::SeekToPropertyPos( SvStream& rStrm, sal_uInt32 nPropPos ) const
1032
5.08M
{
1033
5.08M
    return checkSeek(rStrm, static_cast<std::size_t>(mnStartPos + nPropPos)) &&
1034
1.13M
           rStrm.GetErrorCode() == ERRCODE_NONE;
1035
5.08M
}
1036
1037
void SfxOleSection::LoadProperty( SvStream& rStrm, sal_Int32 nPropId )
1038
1.07M
{
1039
    // property data type
1040
1.07M
    sal_Int32 nPropType(0);
1041
1.07M
    rStrm.ReadInt32( nPropType );
1042
    // create empty property object
1043
1.07M
    SfxOlePropertyRef xProp;
1044
1.07M
    switch( nPropType )
1045
1.07M
    {
1046
24.4k
        case PROPTYPE_INT32:
1047
24.4k
            xProp = std::make_shared<SfxOleInt32Property>( nPropId );
1048
24.4k
        break;
1049
1.19k
        case PROPTYPE_DOUBLE:
1050
1.19k
            xProp = std::make_shared<SfxOleDoubleProperty>( nPropId );
1051
1.19k
        break;
1052
12.6k
        case PROPTYPE_BOOL:
1053
12.6k
            xProp = std::make_shared<SfxOleBoolProperty>( nPropId );
1054
12.6k
        break;
1055
40.1k
        case PROPTYPE_STRING8:
1056
40.1k
            xProp = std::make_shared<SfxOleString8Property>( nPropId, maCodePageProp );
1057
40.1k
        break;
1058
1.83k
        case PROPTYPE_STRING16:
1059
1.83k
            xProp = std::make_shared<SfxOleString16Property>( nPropId );
1060
1.83k
        break;
1061
23.1k
        case PROPTYPE_FILETIME:
1062
23.1k
            xProp = std::make_shared<SfxOleFileTimeProperty>( nPropId );
1063
23.1k
        break;
1064
3.69k
        case PROPTYPE_DATE:
1065
3.69k
            xProp = std::make_shared<SfxOleDateProperty>( nPropId );
1066
3.69k
        break;
1067
1.07M
    }
1068
    // load property contents
1069
1.07M
    if( xProp )
1070
107k
    {
1071
107k
        SetError( xProp->Load( rStrm ) );
1072
107k
        maPropMap[ nPropId ] = std::move(xProp);
1073
107k
    }
1074
1.07M
}
1075
1076
void SfxOleSection::SaveProperty( SvStream& rStrm, SfxOlePropertyBase& rProp, sal_uInt64 & rnPropPosPos )
1077
0
{
1078
0
    rStrm.Seek( STREAM_SEEK_TO_END );
1079
0
    sal_uInt32 nPropPos = static_cast< sal_uInt32 >( rStrm.Tell() - mnStartPos );
1080
    // property data type
1081
0
    rStrm.WriteInt32( rProp.GetPropType() );
1082
    // write property contents
1083
0
    SaveObject( rStrm, rProp );
1084
    // align to 32-bit
1085
0
    while( (rStrm.Tell() & 3) != 0 )
1086
0
        rStrm.WriteUChar( 0 );
1087
    // write property ID/position pair
1088
0
    rStrm.Seek( rnPropPosPos );
1089
0
    rStrm.WriteInt32( rProp.GetPropId() ).WriteUInt32( nPropPos );
1090
0
    rnPropPosPos = rStrm.Tell();
1091
0
}
1092
1093
1094
ErrCode const & SfxOlePropertySet::LoadPropertySet( SotStorage* pStrg, const OUString& rStrmName )
1095
55.4k
{
1096
55.4k
    if( pStrg )
1097
55.4k
    {
1098
55.4k
        rtl::Reference<SotStorageStream> xStrm = pStrg->OpenSotStream( rStrmName, StreamMode::STD_READ );
1099
55.4k
        if( xStrm.is() && (xStrm->GetError() == ERRCODE_NONE) )
1100
17.2k
        {
1101
17.2k
            xStrm->SetBufferSize( STREAM_BUFFER_SIZE );
1102
17.2k
            Load( *xStrm );
1103
17.2k
        }
1104
38.1k
        else
1105
38.1k
            SetError( ERRCODE_IO_ACCESSDENIED );
1106
55.4k
    }
1107
0
    else
1108
0
        SetError( ERRCODE_IO_ACCESSDENIED );
1109
55.4k
    return GetError();
1110
55.4k
}
1111
1112
ErrCode const & SfxOlePropertySet::SavePropertySet( SotStorage* pStrg, const OUString& rStrmName )
1113
0
{
1114
0
    if( pStrg )
1115
0
    {
1116
0
        rtl::Reference<SotStorageStream> xStrm = pStrg->OpenSotStream( rStrmName, StreamMode::TRUNC | StreamMode::STD_WRITE );
1117
0
        if (xStrm.is() && xStrm->IsWritable())
1118
0
            Save( *xStrm );
1119
0
        else
1120
0
            SetError( ERRCODE_IO_ACCESSDENIED );
1121
0
    }
1122
0
    else
1123
0
        SetError( ERRCODE_IO_ACCESSDENIED );
1124
0
    return GetError();
1125
0
}
1126
1127
SfxOleSectionRef SfxOlePropertySet::GetSection( SfxOleSectionType eSection ) const
1128
55.4k
{
1129
55.4k
    return GetSection( GetSectionGuid( eSection ) );
1130
55.4k
}
1131
1132
SfxOleSectionRef SfxOlePropertySet::GetSection( const SvGlobalName& rSectionGuid ) const
1133
97.0k
{
1134
97.0k
    SfxOleSectionRef xSection;
1135
97.0k
    SfxOleSectionMap::const_iterator aIt = maSectionMap.find( rSectionGuid );
1136
97.0k
    if( aIt != maSectionMap.end() )
1137
22.9k
        xSection = aIt->second;
1138
97.0k
    return xSection;
1139
97.0k
}
1140
1141
SfxOleSection& SfxOlePropertySet::AddSection( SfxOleSectionType eSection )
1142
0
{
1143
0
    return AddSection( GetSectionGuid( eSection ) );
1144
0
}
1145
1146
SfxOleSection& SfxOlePropertySet::AddSection( const SvGlobalName& rSectionGuid )
1147
41.6k
{
1148
41.6k
    SfxOleSectionRef xSection = GetSection( rSectionGuid );
1149
41.6k
    if( !xSection )
1150
27.1k
    {
1151
        // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
1152
27.1k
        bool bSupportsDict = rSectionGuid == GetSectionGuid( SECTION_CUSTOM );
1153
27.1k
        xSection = std::make_shared<SfxOleSection>( bSupportsDict );
1154
27.1k
        maSectionMap[ rSectionGuid ] = xSection;
1155
27.1k
    }
1156
41.6k
    return *xSection;
1157
41.6k
}
1158
1159
void SfxOlePropertySet::ImplLoad( SvStream& rStrm )
1160
17.2k
{
1161
    // read property set header
1162
17.2k
    sal_uInt16 nByteOrder;
1163
17.2k
    sal_uInt16 nVersion;
1164
17.2k
    sal_uInt16 nOsMinor;
1165
17.2k
    sal_uInt16 nOsType;
1166
17.2k
    SvGlobalName aGuid;
1167
17.2k
    sal_Int32 nSectCount(0);
1168
17.2k
    rStrm.ReadUInt16( nByteOrder ).ReadUInt16( nVersion ).ReadUInt16( nOsMinor ).ReadUInt16( nOsType );
1169
17.2k
    rStrm >> aGuid;
1170
17.2k
    rStrm.ReadInt32( nSectCount );
1171
1172
    // read sections
1173
17.2k
    sal_uInt64 nSectPosPos = rStrm.Tell();
1174
58.4k
    for (sal_Int32 nSectIdx = 0; nSectIdx < nSectCount; ++nSectIdx)
1175
43.8k
    {
1176
        // read section guid/position pair
1177
43.8k
        rStrm.Seek(nSectPosPos);
1178
43.8k
        SvGlobalName aSectGuid;
1179
43.8k
        rStrm >> aSectGuid;
1180
43.8k
        sal_uInt32 nSectPos(0);
1181
43.8k
        rStrm.ReadUInt32(nSectPos);
1182
43.8k
        if (!rStrm.good())
1183
102
            break;
1184
43.7k
        nSectPosPos = rStrm.Tell();
1185
        // read section
1186
43.7k
        if (!checkSeek(rStrm, nSectPos))
1187
2.18k
            break;
1188
41.6k
        LoadObject(rStrm, AddSection(aSectGuid));
1189
41.6k
        if (!rStrm.good())
1190
405
            break;
1191
41.6k
    }
1192
17.2k
}
1193
1194
void SfxOlePropertySet::ImplSave( SvStream& rStrm )
1195
0
{
1196
    // write property set header
1197
0
    SvGlobalName aGuid;
1198
0
    sal_Int32 nSectCount = static_cast< sal_Int32 >( maSectionMap.size() );
1199
0
    rStrm  .WriteUInt16( 0xFFFE )     // byte order
1200
0
           .WriteUInt16( 0 )          // version
1201
0
           .WriteUInt16( 1 )          // OS minor version
1202
0
           .WriteUInt16( 2 );         // OS type always windows for text encoding
1203
0
    WriteSvGlobalName( rStrm, aGuid );                    // unused guid
1204
0
    rStrm  .WriteInt32( nSectCount );              // number of sections
1205
1206
    // write placeholders for section guid/position pairs
1207
0
    sal_uInt64 nSectPosPos = rStrm.Tell();
1208
0
    rStrm.SeekRel( static_cast< sal_sSize >(nSectCount) * 20 );
1209
1210
    // write sections
1211
0
    for (auto const& section : maSectionMap)
1212
0
    {
1213
0
        SfxOleSection& rSection = *section.second;
1214
0
        rStrm.Seek( STREAM_SEEK_TO_END );
1215
0
        sal_uInt32 nSectPos = static_cast< sal_uInt32 >( rStrm.Tell() );
1216
        // write the section
1217
0
        SaveObject( rStrm, rSection );
1218
        // write section guid/position pair
1219
0
        rStrm.Seek( nSectPosPos );
1220
0
        WriteSvGlobalName( rStrm, section.first );
1221
0
        rStrm.WriteUInt32( nSectPos );
1222
0
        nSectPosPos = rStrm.Tell();
1223
0
    }
1224
0
}
1225
1226
const SvGlobalName& SfxOlePropertySet::GetSectionGuid( SfxOleSectionType eSection )
1227
82.5k
{
1228
82.5k
    static const SvGlobalName saGlobalGuid(  0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 );
1229
82.5k
    static const SvGlobalName saBuiltInGuid( 0xD5CDD502, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1230
82.5k
    static const SvGlobalName saCustomGuid(  0xD5CDD505, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1231
82.5k
    static const SvGlobalName saEmptyGuid;
1232
82.5k
    switch( eSection )
1233
82.5k
    {
1234
27.7k
        case SECTION_GLOBAL:    return saGlobalGuid;
1235
0
        case SECTION_BUILTIN:   return saBuiltInGuid;
1236
54.8k
        case SECTION_CUSTOM:    return saCustomGuid;
1237
0
        default:    SAL_WARN( "sfx.doc", "SfxOlePropertySet::GetSectionGuid - unknown section type" );
1238
82.5k
    }
1239
0
    return saEmptyGuid;
1240
82.5k
}
1241
1242
1243
//} // namespace
1244
1245
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */