Coverage Report

Created: 2025-07-07 10:01

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