tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / sfx2 / source / doc / oleprops.cxx
blob8ba709111fcee580808fc2defa54bd7254756f9b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "oleprops.hxx"
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>
31 #define STREAM_BUFFER_SIZE 2048
33 // usings
34 using ::com::sun::star::uno::Any;
36 using namespace ::com::sun::star;
38 #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 #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 #define TIMESTAMP_INVALID_UTILDATE (util::Date(1, 1, 1601))
44 namespace {
46 /** Property representing a signed 32-bit integer value. */
47 class SfxOleInt32Property : public SfxOlePropertyBase
49 public:
50 explicit SfxOleInt32Property( sal_Int32 nPropId, sal_Int32 nValue = 0 );
52 sal_Int32 GetValue() const { return mnValue; }
54 private:
55 virtual void ImplLoad( SvStream& rStrm ) override;
56 virtual void ImplSave( SvStream& rStrm ) override;
58 private:
59 sal_Int32 mnValue;
63 /** Property representing a floating-point value. */
64 class SfxOleDoubleProperty : public SfxOlePropertyBase
66 public:
67 explicit SfxOleDoubleProperty( sal_Int32 nPropId, double fValue = 0.0 );
69 double GetValue() const { return mfValue; }
71 private:
72 virtual void ImplLoad( SvStream& rStrm ) override;
73 virtual void ImplSave( SvStream& rStrm ) override;
75 private:
76 double mfValue;
80 /** Property representing a boolean value. */
81 class SfxOleBoolProperty : public SfxOlePropertyBase
83 public:
84 explicit SfxOleBoolProperty( sal_Int32 nPropId, bool bValue = false );
86 bool GetValue() const { return mbValue; }
88 private:
89 virtual void ImplLoad( SvStream& rStrm ) override;
90 virtual void ImplSave( SvStream& rStrm ) override;
92 private:
93 bool mbValue;
97 /** Base class for properties that contain a single string value. */
98 class SfxOleStringPropertyBase : public SfxOlePropertyBase, public SfxOleStringHelper
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 );
111 const OUString& GetValue() const { return maValue; }
112 void SetValue( const OUString& rValue ) { maValue = rValue; }
114 private:
115 OUString maValue;
119 /** Property representing a bytestring value. */
120 class SfxOleString8Property : public SfxOleStringPropertyBase
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 );
129 private:
130 virtual void ImplLoad( SvStream& rStrm ) override;
131 virtual void ImplSave( SvStream& rStrm ) override;
135 /** Property representing a Unicode string value. */
136 class SfxOleString16Property : public SfxOleStringPropertyBase
138 public:
139 explicit SfxOleString16Property( sal_Int32 nPropId );
141 private:
142 virtual void ImplLoad( SvStream& rStrm ) override;
143 virtual void ImplSave( SvStream& rStrm ) override;
147 /** Property representing a filetime value as defined by the Windows API. */
148 class SfxOleFileTimeProperty : public SfxOlePropertyBase
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 );
155 /** Returns the time value as LOCAL time. */
156 const util::DateTime& GetValue() const { return maDateTime; }
158 private:
159 virtual void ImplLoad( SvStream& rStrm ) override;
160 virtual void ImplSave( SvStream& rStrm ) override;
162 private:
163 util::DateTime maDateTime;
166 /** Property representing a filetime value as defined by the Windows API. */
167 class SfxOleDateProperty : public SfxOlePropertyBase
169 public:
170 explicit SfxOleDateProperty( sal_Int32 nPropId );
172 /** Returns the date value as LOCAL time. */
173 const util::Date& GetValue() const { return maDate; }
175 private:
176 virtual void ImplLoad( SvStream& rStrm ) override;
177 virtual void ImplSave( SvStream& rStrm ) override;
179 private:
180 util::Date maDate;
184 /** Property representing a thumbnail picture.
186 Currently, only saving this property is implemented.
188 class SfxOleThumbnailProperty : public SfxOlePropertyBase
190 public:
191 explicit SfxOleThumbnailProperty( sal_Int32 nPropId,
192 const uno::Sequence<sal_Int8> & i_rData);
194 bool IsValid() const { return mData.hasElements(); }
196 private:
197 virtual void ImplLoad( SvStream& rStrm ) override;
198 virtual void ImplSave( SvStream& rStrm ) override;
200 private:
201 uno::Sequence<sal_Int8> mData;
205 /** Property representing a BLOB (which presumably stands for binary large
206 object).
208 Currently, only saving this property is implemented.
210 class SfxOleBlobProperty : public SfxOlePropertyBase
212 public:
213 explicit SfxOleBlobProperty( sal_Int32 nPropId,
214 const uno::Sequence<sal_Int8> & i_rData);
215 bool IsValid() const { return mData.hasElements(); }
217 private:
218 virtual void ImplLoad( SvStream& rStrm ) override;
219 virtual void ImplSave( SvStream& rStrm ) override;
221 private:
222 uno::Sequence<sal_Int8> mData;
227 sal_uInt16 SfxOleTextEncoding::GetCodePage() const
229 sal_uInt16 nCodePage = IsUnicode() ? CODEPAGE_UNICODE :
230 static_cast< sal_uInt16 >( rtl_getWindowsCodePageFromTextEncoding( *mxTextEnc ) );
231 return (nCodePage == CODEPAGE_UNKNOWN) ? CODEPAGE_UTF8 : nCodePage;
234 void SfxOleTextEncoding::SetCodePage( sal_uInt16 nCodePage )
236 if( nCodePage == CODEPAGE_UNICODE )
237 SetUnicode();
238 else
240 rtl_TextEncoding eTextEnc = rtl_getTextEncodingFromWindowsCodePage( nCodePage );
241 if( eTextEnc != RTL_TEXTENCODING_DONTKNOW )
242 *mxTextEnc = eTextEnc;
247 OUString SfxOleStringHelper::LoadString8( SvStream& rStrm ) const
249 return IsUnicode() ? ImplLoadString16( rStrm ) : ImplLoadString8( rStrm );
252 void SfxOleStringHelper::SaveString8( SvStream& rStrm, std::u16string_view rValue ) const
254 if( IsUnicode() )
255 ImplSaveString16( rStrm, rValue );
256 else
257 ImplSaveString8( rStrm, rValue );
260 OUString SfxOleStringHelper::LoadString16( SvStream& rStrm )
262 return ImplLoadString16( rStrm );
265 void SfxOleStringHelper::SaveString16( SvStream& rStrm, std::u16string_view rValue )
267 ImplSaveString16( rStrm, rValue );
270 OUString SfxOleStringHelper::ImplLoadString8( SvStream& rStrm ) const
272 // read size field (signed 32-bit)
273 sal_Int32 nSize(0);
274 rStrm.ReadInt32( nSize );
275 // size field includes trailing NUL character
276 SAL_WARN_IF(nSize < 1 || nSize > 0xFFFF, "sfx.doc", "SfxOleStringHelper::ImplLoadString8 - invalid string of len " << nSize);
277 if (nSize < 1 || nSize > 0xFFFF)
278 return OUString();
279 // load character buffer
280 OString sValue(read_uInt8s_ToOString(rStrm, nSize - 1));
281 if (rStrm.good() && rStrm.remainingSize())
282 rStrm.SeekRel(1); // skip null-byte at end
283 return OStringToOUString(sValue, GetTextEncoding());
286 OUString SfxOleStringHelper::ImplLoadString16( SvStream& rStrm )
288 // read size field (signed 32-bit), may be buffer size or character count
289 sal_Int32 nSize(0);
290 rStrm.ReadInt32(nSize);
291 SAL_WARN_IF(nSize < 1 || nSize > 0xFFFF, "sfx.doc", "SfxOleStringHelper::ImplLoadString16 - invalid string of len " << nSize);
292 // size field includes trailing NUL character
293 if (nSize < 1 || nSize > 0xFFFF)
294 return OUString();
295 // load character buffer
296 OUString aValue = read_uInt16s_ToOUString(rStrm, nSize - 1);
297 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 if ((nSize & 1) == 1)
300 nSkip += 2;
301 nSkip = std::min<sal_uInt32>(nSkip, rStrm.remainingSize());
302 if (rStrm.good() && nSkip)
303 rStrm.SeekRel(nSkip);
304 return aValue;
307 void SfxOleStringHelper::ImplSaveString8( SvStream& rStrm, std::u16string_view rValue ) const
309 // encode to byte string
310 OString aEncoded(OUStringToOString(rValue, GetTextEncoding()));
311 // write size field (including trailing NUL character)
312 sal_Int32 nSize = aEncoded.getLength() + 1;
313 rStrm.WriteInt32( nSize );
314 // write character array with trailing NUL character
315 rStrm.WriteBytes(aEncoded.getStr(), aEncoded.getLength());
316 rStrm.WriteUChar( 0 );
319 void SfxOleStringHelper::ImplSaveString16( SvStream& rStrm, std::u16string_view rValue )
321 // write size field (including trailing NUL character)
322 sal_Int32 nSize = static_cast< sal_Int32 >( rValue.size() + 1 );
323 rStrm.WriteInt32( nSize );
324 // write character array with trailing NUL character
325 for( size_t nIdx = 0; nIdx < rValue.size(); ++nIdx )
326 rStrm.WriteUInt16( rValue[ nIdx ] );
327 rStrm.WriteUInt16( 0 );
328 // stream is always padded to 32-bit boundary, add 2 bytes on odd character count
329 if( (nSize & 1) == 1 )
330 rStrm.WriteUInt16( 0 );
334 SfxOleObjectBase::~SfxOleObjectBase()
338 ErrCode const & SfxOleObjectBase::Load( SvStream& rStrm )
340 mnErrCode = ERRCODE_NONE;
341 ImplLoad( rStrm );
342 SetError( rStrm.GetErrorCode() );
343 return GetError();
346 ErrCode const & SfxOleObjectBase::Save( SvStream& rStrm )
348 mnErrCode = ERRCODE_NONE;
349 ImplSave( rStrm );
350 SetError( rStrm.GetErrorCode() );
351 return GetError();
354 void SfxOleObjectBase::LoadObject( SvStream& rStrm, SfxOleObjectBase& rObj )
356 SetError( rObj.Load( rStrm ) );
359 void SfxOleObjectBase::SaveObject( SvStream& rStrm, SfxOleObjectBase& rObj )
361 SetError( rObj.Save( rStrm ) );
365 SfxOleCodePageProperty::SfxOleCodePageProperty() :
366 SfxOlePropertyBase( PROPID_CODEPAGE, PROPTYPE_INT16 )
370 void SfxOleCodePageProperty::ImplLoad(SvStream& rStrm)
372 // property type is signed int16, but we use always unsigned int16 for codepages
373 sal_uInt16 nCodePage(0);
374 rStrm.ReadUInt16(nCodePage);
375 SetCodePage(nCodePage);
378 void SfxOleCodePageProperty::ImplSave( SvStream& rStrm )
380 // property type is signed int16, but we use always unsigned int16 for codepages
381 rStrm.WriteUInt16( GetCodePage() );
385 SfxOleInt32Property::SfxOleInt32Property( sal_Int32 nPropId, sal_Int32 nValue ) :
386 SfxOlePropertyBase( nPropId, PROPTYPE_INT32 ),
387 mnValue( nValue )
391 void SfxOleInt32Property::ImplLoad( SvStream& rStrm )
393 rStrm.ReadInt32( mnValue );
396 void SfxOleInt32Property::ImplSave( SvStream& rStrm )
398 rStrm.WriteInt32( mnValue );
402 SfxOleDoubleProperty::SfxOleDoubleProperty( sal_Int32 nPropId, double fValue ) :
403 SfxOlePropertyBase( nPropId, PROPTYPE_DOUBLE ),
404 mfValue( fValue )
408 void SfxOleDoubleProperty::ImplLoad( SvStream& rStrm )
410 rStrm.ReadDouble( mfValue );
413 void SfxOleDoubleProperty::ImplSave( SvStream& rStrm )
415 rStrm.WriteDouble( mfValue );
419 SfxOleBoolProperty::SfxOleBoolProperty( sal_Int32 nPropId, bool bValue ) :
420 SfxOlePropertyBase( nPropId, PROPTYPE_BOOL ),
421 mbValue( bValue )
425 void SfxOleBoolProperty::ImplLoad( SvStream& rStrm )
427 sal_Int16 nValue(0);
428 rStrm.ReadInt16( nValue );
429 mbValue = nValue != 0;
432 void SfxOleBoolProperty::ImplSave( SvStream& rStrm )
434 rStrm.WriteInt16( mbValue ? -1 : 0 );
438 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
439 sal_Int32 nPropId, sal_Int32 nPropType, const SfxOleTextEncoding& rTextEnc ) :
440 SfxOlePropertyBase( nPropId, nPropType ),
441 SfxOleStringHelper( rTextEnc )
445 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
446 sal_Int32 nPropId, sal_Int32 nPropType, const SfxOleTextEncoding& rTextEnc, OUString aValue ) :
447 SfxOlePropertyBase( nPropId, nPropType ),
448 SfxOleStringHelper( rTextEnc ),
449 maValue(std::move( aValue ))
453 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
454 sal_Int32 nPropId, sal_Int32 nPropType, rtl_TextEncoding eTextEnc ) :
455 SfxOlePropertyBase( nPropId, nPropType ),
456 SfxOleStringHelper( eTextEnc )
461 SfxOleString8Property::SfxOleString8Property(
462 sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc ) :
463 SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING8, rTextEnc )
467 SfxOleString8Property::SfxOleString8Property(
468 sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc, const OUString& rValue ) :
469 SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING8, rTextEnc, rValue )
473 void SfxOleString8Property::ImplLoad( SvStream& rStrm )
475 SetValue( LoadString8( rStrm ) );
478 void SfxOleString8Property::ImplSave( SvStream& rStrm )
480 SaveString8( rStrm, GetValue() );
484 SfxOleString16Property::SfxOleString16Property( sal_Int32 nPropId ) :
485 SfxOleStringPropertyBase( nPropId, PROPTYPE_STRING16, RTL_TEXTENCODING_UCS2 )
489 void SfxOleString16Property::ImplLoad( SvStream& rStrm )
491 SetValue( LoadString16( rStrm ) );
494 void SfxOleString16Property::ImplSave( SvStream& rStrm )
496 SaveString16( rStrm, GetValue() );
500 SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId ) :
501 SfxOlePropertyBase( nPropId, PROPTYPE_FILETIME )
505 SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId, const util::DateTime& rDateTime ) :
506 SfxOlePropertyBase( nPropId, PROPTYPE_FILETIME ),
507 maDateTime( rDateTime )
511 void SfxOleFileTimeProperty::ImplLoad( SvStream& rStrm )
513 sal_uInt32 nLower(0), nUpper(0);
514 rStrm.ReadUInt32( nLower ).ReadUInt32( nUpper );
515 ::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 if ( aDateTime.GetYear() != TIMESTAMP_INVALID_DATETIME.GetYear() )
521 aDateTime.ConvertToLocalTime();
522 maDateTime.Year = aDateTime.GetYear();
523 maDateTime.Month = aDateTime.GetMonth();
524 maDateTime.Day = aDateTime.GetDay();
525 maDateTime.Hours = aDateTime.GetHour();
526 maDateTime.Minutes = aDateTime.GetMin();
527 maDateTime.Seconds = aDateTime.GetSec();
528 maDateTime.NanoSeconds = aDateTime.GetNanoSec();
529 maDateTime.IsUTC = false;
532 void SfxOleFileTimeProperty::ImplSave( SvStream& rStrm )
534 DateTime aDateTimeUtc(
535 Date(
536 maDateTime.Day,
537 maDateTime.Month,
538 static_cast< sal_uInt16 >( maDateTime.Year ) ),
539 tools::Time(
540 maDateTime.Hours,
541 maDateTime.Minutes,
542 maDateTime.Seconds,
543 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 if( aDateTimeUtc.IsValidAndGregorian()
548 && aDateTimeUtc.GetYear() != TIMESTAMP_INVALID_DATETIME.GetYear() ) {
549 aDateTimeUtc.ConvertToUTC();
551 sal_uInt32 nLower, nUpper;
552 aDateTimeUtc.GetWin32FileDateTime( nLower, nUpper );
553 rStrm.WriteUInt32( nLower ).WriteUInt32( nUpper );
556 SfxOleDateProperty::SfxOleDateProperty( sal_Int32 nPropId ) :
557 SfxOlePropertyBase( nPropId, PROPTYPE_DATE )
561 void SfxOleDateProperty::ImplLoad( SvStream& rStrm )
563 double fValue(0.0);
564 rStrm.ReadDouble( fValue );
565 //stored as number of days (not seconds) since December 31, 1899
566 sal_Int32 nDays = fValue;
567 sal_Int32 nStartDays = ::Date::DateToDays(31, 12, 1899);
568 if (o3tl::checked_add(nStartDays, nDays, nStartDays))
569 SAL_WARN("sfx.doc", "SfxOleDateProperty::ImplLoad bad date, ignored");
570 else
572 ::Date aDate(31, 12, 1899);
573 aDate.AddDays(nDays);
574 maDate.Day = aDate.GetDay();
575 maDate.Month = aDate.GetMonth();
576 maDate.Year = aDate.GetYear();
580 void SfxOleDateProperty::ImplSave( SvStream& rStrm )
582 sal_Int32 nDays = ::Date::DateToDays(maDate.Day, maDate.Month, maDate.Year);
583 //number of days (not seconds) since December 31, 1899
584 sal_Int32 nStartDays = ::Date::DateToDays(31, 12, 1899);
585 double fValue = nDays-nStartDays;
586 rStrm.WriteDouble( fValue );
590 SfxOleThumbnailProperty::SfxOleThumbnailProperty(
591 sal_Int32 nPropId, const uno::Sequence<sal_Int8> & i_rData) :
592 SfxOlePropertyBase( nPropId, PROPTYPE_CLIPFMT ),
593 mData(i_rData)
597 void SfxOleThumbnailProperty::ImplLoad( SvStream& )
599 SAL_WARN( "sfx.doc", "SfxOleThumbnailProperty::ImplLoad - not implemented" );
600 SetError( SVSTREAM_INVALID_ACCESS );
603 void SfxOleThumbnailProperty::ImplSave( SvStream& rStrm )
605 /* Type Contents
606 -----------------------------------------------------------------------
607 int32 size of following data
608 int32 clipboard format tag (see below)
609 byte[] clipboard data (see below)
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
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
624 if( IsValid() )
626 // clipboard size: clip_format_tag + data_format_tag + bitmap_len
627 sal_Int32 nClipSize = static_cast< sal_Int32 >( 4 + 4 + mData.getLength() );
628 rStrm.WriteInt32( nClipSize ).WriteInt32( CLIPFMT_WIN ).WriteInt32( CLIPDATAFMT_DIB );
629 rStrm.WriteBytes(mData.getConstArray(), mData.getLength());
631 else
633 SAL_WARN( "sfx.doc", "SfxOleThumbnailProperty::ImplSave - invalid thumbnail property" );
634 SetError( SVSTREAM_INVALID_ACCESS );
639 SfxOleBlobProperty::SfxOleBlobProperty( sal_Int32 nPropId,
640 const uno::Sequence<sal_Int8> & i_rData) :
641 SfxOlePropertyBase( nPropId, PROPTYPE_BLOB ),
642 mData(i_rData)
646 void SfxOleBlobProperty::ImplLoad( SvStream& )
648 SAL_WARN( "sfx.doc", "SfxOleBlobProperty::ImplLoad - not implemented" );
649 SetError( SVSTREAM_INVALID_ACCESS );
652 void SfxOleBlobProperty::ImplSave( SvStream& rStrm )
654 if (IsValid()) {
655 rStrm.WriteBytes(mData.getConstArray(), mData.getLength());
656 } else {
657 SAL_WARN( "sfx.doc", "SfxOleBlobProperty::ImplSave - invalid BLOB property" );
658 SetError( SVSTREAM_INVALID_ACCESS );
663 SfxOleDictionaryProperty::SfxOleDictionaryProperty( const SfxOleTextEncoding& rTextEnc ) :
664 SfxOlePropertyBase( PROPID_DICTIONARY, 0 ),
665 SfxOleStringHelper( rTextEnc )
669 OUString SfxOleDictionaryProperty::GetPropertyName( sal_Int32 nPropId ) const
671 SfxOlePropNameMap::const_iterator aIt = maPropNameMap.find( nPropId );
672 return (aIt == maPropNameMap.end()) ? OUString() : aIt->second;
675 void SfxOleDictionaryProperty::SetPropertyName( sal_Int32 nPropId, const OUString& rPropName )
677 maPropNameMap[ nPropId ] = rPropName;
678 // dictionary property contains number of pairs in property type field
679 SetPropType( static_cast< sal_Int32 >( maPropNameMap.size() ) );
682 void SfxOleDictionaryProperty::ImplLoad( SvStream& rStrm )
684 // dictionary property contains number of pairs in property type field
685 sal_Int32 nNameCount = GetPropType();
686 // read property ID/name pairs
687 maPropNameMap.clear();
688 for (sal_Int32 nIdx = 0; nIdx < nNameCount && rStrm.good() && rStrm.remainingSize() >= 4; ++nIdx)
690 sal_Int32 nPropId(0);
691 rStrm.ReadInt32(nPropId);
692 // name always stored as byte string
693 maPropNameMap[nPropId] = LoadString8(rStrm);
697 void SfxOleDictionaryProperty::ImplSave( SvStream& rStrm )
699 // write property ID/name pairs
700 for (auto const& propName : maPropNameMap)
702 rStrm.WriteInt32( propName.first );
703 // name always stored as byte string
704 SaveString8( rStrm, propName.second );
709 SfxOleSection::SfxOleSection( bool bSupportsDict ) :
710 maDictProp( maCodePageProp ),
711 mnStartPos( 0 ),
712 mbSupportsDict( bSupportsDict )
716 SfxOlePropertyRef SfxOleSection::GetProperty( sal_Int32 nPropId ) const
718 SfxOlePropertyRef xProp;
719 SfxOlePropMap::const_iterator aIt = maPropMap.find( nPropId );
720 if( aIt != maPropMap.end() )
721 xProp = aIt->second;
722 return xProp;
725 bool SfxOleSection::GetInt32Value( sal_Int32& rnValue, sal_Int32 nPropId ) const
727 SfxOlePropertyRef xProp = GetProperty( nPropId );
728 const SfxOleInt32Property* pProp =
729 dynamic_cast< const SfxOleInt32Property* >( xProp.get() );
730 if( pProp )
731 rnValue = pProp->GetValue();
732 return pProp != nullptr;
735 bool SfxOleSection::GetDoubleValue( double& rfValue, sal_Int32 nPropId ) const
737 SfxOlePropertyRef xProp = GetProperty( nPropId );
738 const SfxOleDoubleProperty* pProp =
739 dynamic_cast< const SfxOleDoubleProperty* >( xProp.get() );
740 if( pProp )
741 rfValue = pProp->GetValue();
742 return pProp != nullptr;
745 bool SfxOleSection::GetBoolValue( bool& rbValue, sal_Int32 nPropId ) const
747 SfxOlePropertyRef xProp = GetProperty( nPropId );
748 const SfxOleBoolProperty* pProp =
749 dynamic_cast< const SfxOleBoolProperty* >( xProp.get() );
750 if( pProp )
751 rbValue = pProp->GetValue();
752 return pProp != nullptr;
755 bool SfxOleSection::GetStringValue( OUString& rValue, sal_Int32 nPropId ) const
757 SfxOlePropertyRef xProp = GetProperty( nPropId );
758 const SfxOleStringPropertyBase* pProp =
759 dynamic_cast< const SfxOleStringPropertyBase* >( xProp.get() );
760 if( pProp )
761 rValue = pProp->GetValue();
762 return pProp != nullptr;
765 bool SfxOleSection::GetFileTimeValue( util::DateTime& rValue, sal_Int32 nPropId ) const
767 SfxOlePropertyRef xProp = GetProperty( nPropId );
768 const SfxOleFileTimeProperty* pProp =
769 dynamic_cast< const SfxOleFileTimeProperty* >( xProp.get() );
770 if( pProp )
772 if ( pProp->GetValue() == TIMESTAMP_INVALID_UTILDATETIME )
773 rValue = util::DateTime();
774 else
775 rValue = pProp->GetValue();
777 return pProp != nullptr;
780 bool SfxOleSection::GetDateValue( util::Date& rValue, sal_Int32 nPropId ) const
782 SfxOlePropertyRef xProp = GetProperty( nPropId );
783 const SfxOleDateProperty* pProp =
784 dynamic_cast< const SfxOleDateProperty* >( xProp.get() );
785 if( pProp )
787 if ( pProp->GetValue() == TIMESTAMP_INVALID_UTILDATE )
788 rValue = util::Date();
789 else
790 rValue = pProp->GetValue();
792 return pProp != nullptr;
795 void SfxOleSection::SetProperty( const SfxOlePropertyRef& xProp )
797 if( xProp )
798 maPropMap[ xProp->GetPropId() ] = xProp;
801 void SfxOleSection::SetInt32Value( sal_Int32 nPropId, sal_Int32 nValue )
803 SetProperty( std::make_shared<SfxOleInt32Property>( nPropId, nValue ) );
806 void SfxOleSection::SetDoubleValue( sal_Int32 nPropId, double fValue )
808 SetProperty( std::make_shared<SfxOleDoubleProperty>( nPropId, fValue ) );
811 void SfxOleSection::SetBoolValue( sal_Int32 nPropId, bool bValue )
813 SetProperty( std::make_shared<SfxOleBoolProperty>( nPropId, bValue ) );
816 bool SfxOleSection::SetStringValue( sal_Int32 nPropId, const OUString& rValue )
818 bool bInserted = !rValue.isEmpty();
819 if( bInserted )
820 SetProperty( std::make_shared<SfxOleString8Property>( nPropId, maCodePageProp, rValue ) );
821 return bInserted;
824 void SfxOleSection::SetFileTimeValue( sal_Int32 nPropId, const util::DateTime& rValue )
826 if ( rValue.Year == 0 || rValue.Month == 0 || rValue.Day == 0 )
827 SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, TIMESTAMP_INVALID_UTILDATETIME ) );
828 else
829 SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, rValue ) );
832 void SfxOleSection::SetDateValue( sal_Int32 nPropId, const util::Date& rValue )
834 //Annoyingly MS2010 considers VT_DATE apparently as an invalid possibility, so here we use VT_FILETIME
835 //instead :-(
836 if ( rValue.Year == 0 || rValue.Month == 0 || rValue.Day == 0 )
837 SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, TIMESTAMP_INVALID_UTILDATETIME ) );
838 else
840 const util::DateTime aValue(0, 0, 0, 0, rValue.Day, rValue.Month,
841 rValue.Year, false );
842 SetProperty( std::make_shared<SfxOleFileTimeProperty>( nPropId, aValue ) );
846 void SfxOleSection::SetThumbnailValue( sal_Int32 nPropId,
847 const uno::Sequence<sal_Int8> & i_rData)
849 auto pThumbnail = std::make_shared<SfxOleThumbnailProperty>( nPropId, i_rData );
850 if( pThumbnail->IsValid() )
851 SetProperty( pThumbnail );
854 void SfxOleSection::SetBlobValue( sal_Int32 nPropId,
855 const uno::Sequence<sal_Int8> & i_rData)
857 auto pBlob = std::make_shared<SfxOleBlobProperty>( nPropId, i_rData );
858 if( pBlob->IsValid() )
859 SetProperty( pBlob );
862 Any SfxOleSection::GetAnyValue( sal_Int32 nPropId ) const
864 Any aValue;
865 sal_Int32 nInt32 = 0;
866 double fDouble = 0.0;
867 bool bBool = false;
868 OUString aString;
869 css::util::DateTime aApiDateTime;
870 css::util::Date aApiDate;
872 if( GetInt32Value( nInt32, nPropId ) )
873 aValue <<= nInt32;
874 else if( GetDoubleValue( fDouble, nPropId ) )
875 aValue <<= fDouble;
876 else if( GetBoolValue( bBool, nPropId ) )
877 aValue <<= bBool;
878 else if( GetStringValue( aString, nPropId ) )
879 aValue <<= aString;
880 else if( GetFileTimeValue( aApiDateTime, nPropId ) )
882 aValue <<= aApiDateTime;
884 else if( GetDateValue( aApiDate, nPropId ) )
886 aValue <<= aApiDate;
888 return aValue;
891 bool SfxOleSection::SetAnyValue( sal_Int32 nPropId, const Any& rValue )
893 bool bInserted = true;
894 sal_Int32 nInt32 = 0;
895 double fDouble = 0.0;
896 OUString aString;
897 css::util::DateTime aApiDateTime;
898 css::util::Date aApiDate;
900 if( rValue.getValueType() == cppu::UnoType<bool>::get() )
901 SetBoolValue( nPropId, ::comphelper::getBOOL( rValue ) );
902 else if( rValue >>= nInt32 )
903 SetInt32Value( nPropId, nInt32 );
904 else if( rValue >>= fDouble )
905 SetDoubleValue( nPropId, fDouble );
906 else if( rValue >>= aString )
907 bInserted = SetStringValue( nPropId, aString );
908 else if( rValue >>= aApiDateTime )
909 SetFileTimeValue( nPropId, aApiDateTime );
910 else if( rValue >>= aApiDate )
911 SetDateValue( nPropId, aApiDate );
912 else
913 bInserted = false;
914 return bInserted;
917 OUString SfxOleSection::GetPropertyName( sal_Int32 nPropId ) const
919 return maDictProp.GetPropertyName( nPropId );
922 void SfxOleSection::SetPropertyName( sal_Int32 nPropId, const OUString& rPropName )
924 maDictProp.SetPropertyName( nPropId, rPropName );
927 void SfxOleSection::GetPropertyIds( ::std::vector< sal_Int32 >& rPropIds ) const
929 rPropIds.clear();
930 for (auto const& prop : maPropMap)
931 rPropIds.push_back(prop.first);
934 sal_Int32 SfxOleSection::GetFreePropertyId() const
936 return maPropMap.empty() ? PROPID_FIRSTCUSTOM : (maPropMap.rbegin()->first + 1);
939 void SfxOleSection::ImplLoad( SvStream& rStrm )
941 // read section header
942 mnStartPos = rStrm.Tell();
943 sal_uInt32 nSize(0);
944 sal_Int32 nPropCount(0);
945 rStrm.ReadUInt32( nSize ).ReadInt32( nPropCount );
947 // read property ID/position pairs
948 typedef ::std::map< sal_Int32, sal_uInt32 > SfxOlePropPosMap;
949 SfxOlePropPosMap aPropPosMap;
950 for (sal_Int32 nPropIdx = 0; nPropIdx < nPropCount && rStrm.good(); ++nPropIdx)
952 sal_Int32 nPropId(0);
953 sal_uInt32 nPropPos(0);
954 rStrm.ReadInt32( nPropId ).ReadUInt32( nPropPos );
955 aPropPosMap[ nPropId ] = nPropPos;
958 // read codepage property
959 SfxOlePropPosMap::iterator aCodePageIt = aPropPosMap.find( PROPID_CODEPAGE );
960 if( (aCodePageIt != aPropPosMap.end()) && SeekToPropertyPos( rStrm, aCodePageIt->second ) )
962 // codepage property must be of type signed int-16
963 sal_Int32 nPropType(0);
964 rStrm.ReadInt32( nPropType );
965 if( nPropType == PROPTYPE_INT16 )
966 LoadObject( rStrm, maCodePageProp );
967 // remove property position
968 aPropPosMap.erase( aCodePageIt );
971 // read dictionary property
972 SfxOlePropPosMap::iterator aDictIt = aPropPosMap.find( PROPID_DICTIONARY );
973 if( (aDictIt != aPropPosMap.end()) && SeekToPropertyPos( rStrm, aDictIt->second ) )
975 // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
976 if( mbSupportsDict )
978 // dictionary property contains number of pairs in property type field
979 sal_Int32 nNameCount(0);
980 rStrm.ReadInt32( nNameCount );
981 maDictProp.SetNameCount( nNameCount );
982 LoadObject( rStrm, maDictProp );
984 // always remove position of dictionary property (do not try to read it again below)
985 aPropPosMap.erase( aDictIt );
988 // read other properties
989 maPropMap.clear();
990 for (auto const& propPos : aPropPosMap)
991 if( SeekToPropertyPos( rStrm, propPos.second ) )
992 LoadProperty( rStrm, propPos.first );
995 void SfxOleSection::ImplSave( SvStream& rStrm )
997 /* Always export with UTF-8 encoding. All dependent properties (bytestring
998 and dictionary) will be updated automatically. */
999 maCodePageProp.SetTextEncoding( RTL_TEXTENCODING_UTF8 );
1001 // write section header
1002 mnStartPos = rStrm.Tell();
1003 sal_Int32 nPropCount = static_cast< sal_Int32 >( maPropMap.size() + 1 );
1004 if( maDictProp.HasPropertyNames() )
1005 ++nPropCount;
1006 rStrm.WriteUInt32( 0 ).WriteInt32( nPropCount );
1008 // write placeholders for property ID/position pairs
1009 sal_uInt64 nPropPosPos = rStrm.Tell();
1010 rStrm.SeekRel( static_cast< sal_sSize >( 8 * nPropCount ) );
1012 // write dictionary property
1013 if( maDictProp.HasPropertyNames() )
1014 SaveProperty( rStrm, maDictProp, nPropPosPos );
1015 // write codepage property
1016 SaveProperty( rStrm, maCodePageProp, nPropPosPos );
1017 // write other properties
1018 for (auto const& prop : maPropMap)
1019 SaveProperty( rStrm, *prop.second, nPropPosPos );
1021 // write section size (first field in section header)
1022 sal_uInt32 nSectSize = static_cast< sal_uInt32 >( rStrm.TellEnd() - mnStartPos );
1023 rStrm.Seek( mnStartPos );
1024 rStrm.WriteUInt32( nSectSize );
1027 bool SfxOleSection::SeekToPropertyPos( SvStream& rStrm, sal_uInt32 nPropPos ) const
1029 return checkSeek(rStrm, static_cast<std::size_t>(mnStartPos + nPropPos)) &&
1030 rStrm.GetErrorCode() == ERRCODE_NONE;
1033 void SfxOleSection::LoadProperty( SvStream& rStrm, sal_Int32 nPropId )
1035 // property data type
1036 sal_Int32 nPropType(0);
1037 rStrm.ReadInt32( nPropType );
1038 // create empty property object
1039 SfxOlePropertyRef xProp;
1040 switch( nPropType )
1042 case PROPTYPE_INT32:
1043 xProp = std::make_shared<SfxOleInt32Property>( nPropId );
1044 break;
1045 case PROPTYPE_DOUBLE:
1046 xProp = std::make_shared<SfxOleDoubleProperty>( nPropId );
1047 break;
1048 case PROPTYPE_BOOL:
1049 xProp = std::make_shared<SfxOleBoolProperty>( nPropId );
1050 break;
1051 case PROPTYPE_STRING8:
1052 xProp = std::make_shared<SfxOleString8Property>( nPropId, maCodePageProp );
1053 break;
1054 case PROPTYPE_STRING16:
1055 xProp = std::make_shared<SfxOleString16Property>( nPropId );
1056 break;
1057 case PROPTYPE_FILETIME:
1058 xProp = std::make_shared<SfxOleFileTimeProperty>( nPropId );
1059 break;
1060 case PROPTYPE_DATE:
1061 xProp = std::make_shared<SfxOleDateProperty>( nPropId );
1062 break;
1064 // load property contents
1065 if( xProp )
1067 SetError( xProp->Load( rStrm ) );
1068 maPropMap[ nPropId ] = std::move(xProp);
1072 void SfxOleSection::SaveProperty( SvStream& rStrm, SfxOlePropertyBase& rProp, sal_uInt64 & rnPropPosPos )
1074 rStrm.Seek( STREAM_SEEK_TO_END );
1075 sal_uInt32 nPropPos = static_cast< sal_uInt32 >( rStrm.Tell() - mnStartPos );
1076 // property data type
1077 rStrm.WriteInt32( rProp.GetPropType() );
1078 // write property contents
1079 SaveObject( rStrm, rProp );
1080 // align to 32-bit
1081 while( (rStrm.Tell() & 3) != 0 )
1082 rStrm.WriteUChar( 0 );
1083 // write property ID/position pair
1084 rStrm.Seek( rnPropPosPos );
1085 rStrm.WriteInt32( rProp.GetPropId() ).WriteUInt32( nPropPos );
1086 rnPropPosPos = rStrm.Tell();
1090 ErrCode const & SfxOlePropertySet::LoadPropertySet( SotStorage* pStrg, const OUString& rStrmName )
1092 if( pStrg )
1094 rtl::Reference<SotStorageStream> xStrm = pStrg->OpenSotStream( rStrmName, StreamMode::STD_READ );
1095 if( xStrm.is() && (xStrm->GetError() == ERRCODE_NONE) )
1097 xStrm->SetBufferSize( STREAM_BUFFER_SIZE );
1098 Load( *xStrm );
1100 else
1101 SetError( ERRCODE_IO_ACCESSDENIED );
1103 else
1104 SetError( ERRCODE_IO_ACCESSDENIED );
1105 return GetError();
1108 ErrCode const & SfxOlePropertySet::SavePropertySet( SotStorage* pStrg, const OUString& rStrmName )
1110 if( pStrg )
1112 rtl::Reference<SotStorageStream> xStrm = pStrg->OpenSotStream( rStrmName, StreamMode::TRUNC | StreamMode::STD_WRITE );
1113 if (xStrm.is() && xStrm->IsWritable())
1114 Save( *xStrm );
1115 else
1116 SetError( ERRCODE_IO_ACCESSDENIED );
1118 else
1119 SetError( ERRCODE_IO_ACCESSDENIED );
1120 return GetError();
1123 SfxOleSectionRef SfxOlePropertySet::GetSection( SfxOleSectionType eSection ) const
1125 return GetSection( GetSectionGuid( eSection ) );
1128 SfxOleSectionRef SfxOlePropertySet::GetSection( const SvGlobalName& rSectionGuid ) const
1130 SfxOleSectionRef xSection;
1131 SfxOleSectionMap::const_iterator aIt = maSectionMap.find( rSectionGuid );
1132 if( aIt != maSectionMap.end() )
1133 xSection = aIt->second;
1134 return xSection;
1137 SfxOleSection& SfxOlePropertySet::AddSection( SfxOleSectionType eSection )
1139 return AddSection( GetSectionGuid( eSection ) );
1142 SfxOleSection& SfxOlePropertySet::AddSection( const SvGlobalName& rSectionGuid )
1144 SfxOleSectionRef xSection = GetSection( rSectionGuid );
1145 if( !xSection )
1147 // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
1148 bool bSupportsDict = rSectionGuid == GetSectionGuid( SECTION_CUSTOM );
1149 xSection = std::make_shared<SfxOleSection>( bSupportsDict );
1150 maSectionMap[ rSectionGuid ] = xSection;
1152 return *xSection;
1155 void SfxOlePropertySet::ImplLoad( SvStream& rStrm )
1157 // read property set header
1158 sal_uInt16 nByteOrder;
1159 sal_uInt16 nVersion;
1160 sal_uInt16 nOsMinor;
1161 sal_uInt16 nOsType;
1162 SvGlobalName aGuid;
1163 sal_Int32 nSectCount(0);
1164 rStrm.ReadUInt16( nByteOrder ).ReadUInt16( nVersion ).ReadUInt16( nOsMinor ).ReadUInt16( nOsType );
1165 rStrm >> aGuid;
1166 rStrm.ReadInt32( nSectCount );
1168 // read sections
1169 sal_uInt64 nSectPosPos = rStrm.Tell();
1170 for (sal_Int32 nSectIdx = 0; nSectIdx < nSectCount; ++nSectIdx)
1172 // read section guid/position pair
1173 rStrm.Seek(nSectPosPos);
1174 SvGlobalName aSectGuid;
1175 rStrm >> aSectGuid;
1176 sal_uInt32 nSectPos(0);
1177 rStrm.ReadUInt32(nSectPos);
1178 if (!rStrm.good())
1179 break;
1180 nSectPosPos = rStrm.Tell();
1181 // read section
1182 if (!checkSeek(rStrm, nSectPos))
1183 break;
1184 LoadObject(rStrm, AddSection(aSectGuid));
1185 if (!rStrm.good())
1186 break;
1190 void SfxOlePropertySet::ImplSave( SvStream& rStrm )
1192 // write property set header
1193 SvGlobalName aGuid;
1194 sal_Int32 nSectCount = static_cast< sal_Int32 >( maSectionMap.size() );
1195 rStrm .WriteUInt16( 0xFFFE ) // byte order
1196 .WriteUInt16( 0 ) // version
1197 .WriteUInt16( 1 ) // OS minor version
1198 .WriteUInt16( 2 ); // OS type always windows for text encoding
1199 WriteSvGlobalName( rStrm, aGuid ); // unused guid
1200 rStrm .WriteInt32( nSectCount ); // number of sections
1202 // write placeholders for section guid/position pairs
1203 sal_uInt64 nSectPosPos = rStrm.Tell();
1204 rStrm.SeekRel( static_cast< sal_sSize >( 20 * nSectCount ) );
1206 // write sections
1207 for (auto const& section : maSectionMap)
1209 SfxOleSection& rSection = *section.second;
1210 rStrm.Seek( STREAM_SEEK_TO_END );
1211 sal_uInt32 nSectPos = static_cast< sal_uInt32 >( rStrm.Tell() );
1212 // write the section
1213 SaveObject( rStrm, rSection );
1214 // write section guid/position pair
1215 rStrm.Seek( nSectPosPos );
1216 WriteSvGlobalName( rStrm, section.first );
1217 rStrm.WriteUInt32( nSectPos );
1218 nSectPosPos = rStrm.Tell();
1222 const SvGlobalName& SfxOlePropertySet::GetSectionGuid( SfxOleSectionType eSection )
1224 static const SvGlobalName saGlobalGuid( 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 );
1225 static const SvGlobalName saBuiltInGuid( 0xD5CDD502, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1226 static const SvGlobalName saCustomGuid( 0xD5CDD505, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1227 static const SvGlobalName saEmptyGuid;
1228 switch( eSection )
1230 case SECTION_GLOBAL: return saGlobalGuid;
1231 case SECTION_BUILTIN: return saBuiltInGuid;
1232 case SECTION_CUSTOM: return saCustomGuid;
1233 default: SAL_WARN( "sfx.doc", "SfxOlePropertySet::GetSectionGuid - unknown section type" );
1235 return saEmptyGuid;
1239 //} // namespace
1241 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */