1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: oleprops.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
34 #include "oleprops.hxx"
36 #include <comphelper/types.hxx>
37 #include <tools/debug.hxx>
38 #include <tools/datetime.hxx>
39 #include <rtl/tencinfo.h>
41 // ============================================================================
44 // ============================================================================
47 #define STREAM_BUFFER_SIZE 2048
50 using ::rtl::OUString
;
51 using ::com::sun::star::uno::Any
;
52 using ::com::sun::star::uno::makeAny
;
54 using namespace ::com::sun::star
;
56 #define TIMESTAMP_INVALID_DATETIME ( DateTime ( Date ( 1, 1, 1601 ), Time ( 0, 0, 0 ) ) ) /// Invalid value for date and time to create invalid instance of TimeStamp.
57 #define TIMESTAMP_INVALID_UTILDATETIME ( util::DateTime ( 0, 0, 0, 0, 1, 1, 1601 ) ) /// Invalid value for date and time to create invalid instance of TimeStamp.
60 bool operator==(const util::DateTime
&i_rLeft
, const util::DateTime
&i_rRight
)
62 return i_rLeft
.Year
== i_rRight
.Year
63 && i_rLeft
.Month
== i_rRight
.Month
64 && i_rLeft
.Day
== i_rRight
.Day
65 && i_rLeft
.Hours
== i_rRight
.Hours
66 && i_rLeft
.Minutes
== i_rRight
.Minutes
67 && i_rLeft
.Seconds
== i_rRight
.Seconds
68 && i_rLeft
.HundredthSeconds
== i_rRight
.HundredthSeconds
;
71 // ============================================================================
73 /** Property representing a signed 32-bit integer value. */
74 class SfxOleInt32Property
: public SfxOlePropertyBase
77 explicit SfxOleInt32Property( sal_Int32 nPropId
, sal_Int32 nValue
= 0 );
79 inline sal_Int32
GetValue() const { return mnValue
; }
80 inline void SetValue( sal_Int32 nValue
) { mnValue
= nValue
; }
83 virtual void ImplLoad( SvStream
& rStrm
);
84 virtual void ImplSave( SvStream
& rStrm
);
90 // ============================================================================
92 /** Property representing a floating-point value. */
93 class SfxOleDoubleProperty
: public SfxOlePropertyBase
96 explicit SfxOleDoubleProperty( sal_Int32 nPropId
, double fValue
= 0.0 );
98 inline double GetValue() const { return mfValue
; }
99 inline void SetValue( double fValue
) { mfValue
= fValue
; }
102 virtual void ImplLoad( SvStream
& rStrm
);
103 virtual void ImplSave( SvStream
& rStrm
);
109 // ============================================================================
111 /** Property representing a boolean value. */
112 class SfxOleBoolProperty
: public SfxOlePropertyBase
115 explicit SfxOleBoolProperty( sal_Int32 nPropId
, bool bValue
= false );
117 inline bool GetValue() const { return mbValue
; }
118 inline void SetValue( bool bValue
) { mbValue
= bValue
; }
121 virtual void ImplLoad( SvStream
& rStrm
);
122 virtual void ImplSave( SvStream
& rStrm
);
128 // ============================================================================
130 /** Base class for properties that contain a single string value. */
131 class SfxOleStringPropertyBase
: public SfxOlePropertyBase
, public SfxOleStringHelper
134 explicit SfxOleStringPropertyBase(
135 sal_Int32 nPropId
, sal_Int32 nPropType
,
136 const SfxOleTextEncoding
& rTextEnc
);
137 explicit SfxOleStringPropertyBase(
138 sal_Int32 nPropId
, sal_Int32 nPropType
,
139 const SfxOleTextEncoding
& rTextEnc
, const String
& rValue
);
140 explicit SfxOleStringPropertyBase(
141 sal_Int32 nPropId
, sal_Int32 nPropType
,
142 rtl_TextEncoding eTextEnc
);
143 explicit SfxOleStringPropertyBase(
144 sal_Int32 nPropId
, sal_Int32 nPropType
,
145 rtl_TextEncoding eTextEnc
, const String
& rValue
);
147 inline const String
& GetValue() const { return maValue
; }
148 inline void SetValue( const String
& rValue
) { maValue
= rValue
; }
154 // ============================================================================
156 /** Property representing a bytestring value. */
157 class SfxOleString8Property
: public SfxOleStringPropertyBase
160 explicit SfxOleString8Property(
161 sal_Int32 nPropId
, const SfxOleTextEncoding
& rTextEnc
);
162 explicit SfxOleString8Property(
163 sal_Int32 nPropId
, const SfxOleTextEncoding
& rTextEnc
,
164 const String
& rValue
);
167 virtual void ImplLoad( SvStream
& rStrm
);
168 virtual void ImplSave( SvStream
& rStrm
);
171 // ============================================================================
173 /** Property representing a Unicode string value. */
174 class SfxOleString16Property
: public SfxOleStringPropertyBase
177 explicit SfxOleString16Property( sal_Int32 nPropId
);
178 explicit SfxOleString16Property( sal_Int32 nPropId
, const String
& rValue
);
181 virtual void ImplLoad( SvStream
& rStrm
);
182 virtual void ImplSave( SvStream
& rStrm
);
185 // ============================================================================
187 /** Property representing a filetime value as defined by the Windows API. */
188 class SfxOleFileTimeProperty
: public SfxOlePropertyBase
191 explicit SfxOleFileTimeProperty( sal_Int32 nPropId
);
192 /** @param rDateTime Date and time as LOCAL time. */
193 explicit SfxOleFileTimeProperty( sal_Int32 nPropId
, const util::DateTime
& rDateTime
);
195 /** Returns the time value as LOCAL time. */
196 inline const util::DateTime
& GetValue() const { return maDateTime
; }
197 /** @param rDateTime Date and time as LOCAL time. */
198 inline void SetValue( const util::DateTime
& rDateTime
) { maDateTime
= rDateTime
; }
201 virtual void ImplLoad( SvStream
& rStrm
);
202 virtual void ImplSave( SvStream
& rStrm
);
205 util::DateTime maDateTime
;
208 // ============================================================================
210 /** Property representing a thumbnail picture.
212 Currently, only saving this property is implemented.
214 class SfxOleThumbnailProperty
: public SfxOlePropertyBase
217 explicit SfxOleThumbnailProperty( sal_Int32 nPropId
,
218 const uno::Sequence
<sal_uInt8
> & i_rData
);
220 inline bool IsValid() const { return mData
.getLength() > 0; }
223 virtual void ImplLoad( SvStream
& rStrm
);
224 virtual void ImplSave( SvStream
& rStrm
);
227 uno::Sequence
<sal_uInt8
> mData
;
230 // ============================================================================
232 /** Property representing a BLOB (which presumably stands for binary large
235 Currently, only saving this property is implemented.
237 class SfxOleBlobProperty
: public SfxOlePropertyBase
240 explicit SfxOleBlobProperty( sal_Int32 nPropId
,
241 const uno::Sequence
<sal_uInt8
> & i_rData
);
242 inline bool IsValid() const { return mData
.getLength() > 0; }
245 virtual void ImplLoad( SvStream
& rStrm
);
246 virtual void ImplSave( SvStream
& rStrm
);
249 uno::Sequence
<sal_uInt8
> mData
;
252 // ============================================================================
254 sal_uInt16
SfxOleTextEncoding::GetCodePage() const
256 sal_uInt16 nCodePage
= IsUnicode() ? CODEPAGE_UNICODE
:
257 static_cast< sal_uInt16
>( rtl_getWindowsCodePageFromTextEncoding( *mxTextEnc
) );
258 return (nCodePage
== CODEPAGE_UNKNOWN
) ? CODEPAGE_UTF8
: nCodePage
;
261 void SfxOleTextEncoding::SetCodePage( sal_uInt16 nCodePage
)
263 if( nCodePage
== CODEPAGE_UNICODE
)
267 rtl_TextEncoding eTextEnc
= rtl_getTextEncodingFromWindowsCodePage( nCodePage
);
268 if( eTextEnc
!= RTL_TEXTENCODING_DONTKNOW
)
269 *mxTextEnc
= eTextEnc
;
273 // ----------------------------------------------------------------------------
275 String
SfxOleStringHelper::LoadString8( SvStream
& rStrm
) const
277 return IsUnicode() ? ImplLoadString16( rStrm
) : ImplLoadString8( rStrm
);
280 void SfxOleStringHelper::SaveString8( SvStream
& rStrm
, const String
& rValue
) const
283 ImplSaveString16( rStrm
, rValue
);
285 ImplSaveString8( rStrm
, rValue
);
288 String
SfxOleStringHelper::LoadString16( SvStream
& rStrm
) const
290 return ImplLoadString16( rStrm
);
293 void SfxOleStringHelper::SaveString16( SvStream
& rStrm
, const String
& rValue
) const
295 ImplSaveString16( rStrm
, rValue
);
298 String
SfxOleStringHelper::ImplLoadString8( SvStream
& rStrm
) const
301 // read size field (signed 32-bit)
304 // size field includes trailing NUL character
305 DBG_ASSERT( (0 < nSize
) && (nSize
<= 0xFFFF), "SfxOleStringHelper::ImplLoadString8 - invalid string" );
306 if( (0 < nSize
) && (nSize
<= 0xFFFF) )
308 // load character buffer
309 ::std::vector
< sal_Char
> aBuffer( static_cast< size_t >( nSize
+ 1 ), 0 );
310 rStrm
.Read( &aBuffer
.front(), static_cast< sal_Size
>( nSize
) );
311 // create string from encoded character array
312 aValue
= String( &aBuffer
.front(), GetTextEncoding() );
317 String
SfxOleStringHelper::ImplLoadString16( SvStream
& rStrm
) const
320 // read size field (signed 32-bit), may be buffer size or character count
323 DBG_ASSERT( (0 < nSize
) && (nSize
<= 0xFFFF), "SfxOleStringHelper::ImplLoadString16 - invalid string" );
324 // size field includes trailing NUL character
325 if( (0 < nSize
) && (nSize
<= 0xFFFF) )
327 // load character buffer
328 ::std::vector
< sal_Unicode
> aBuffer
;
329 aBuffer
.reserve( static_cast< size_t >( nSize
+ 1 ) );
331 for( sal_Int32 nIdx
= 0; nIdx
< nSize
; ++nIdx
)
334 aBuffer
.push_back( static_cast< sal_Unicode
>( cChar
) );
336 // stream is always padded to 32-bit boundary, skip 2 bytes on odd character count
337 if( (nSize
& 1) == 1 )
339 // create string from character array
340 aBuffer
.push_back( 0 );
341 aValue
= String( &aBuffer
.front() );
346 void SfxOleStringHelper::ImplSaveString8( SvStream
& rStrm
, const String
& rValue
) const
348 // encode to byte string
349 ByteString
aEncoded( rValue
, GetTextEncoding() );
350 // write size field (including trailing NUL character)
351 sal_Int32 nSize
= static_cast< sal_Int32
>( aEncoded
.Len() + 1 );
353 // write character array with trailing NUL character
354 rStrm
.Write( aEncoded
.GetBuffer(), aEncoded
.Len() );
355 rStrm
<< sal_uInt8( 0 );
358 void SfxOleStringHelper::ImplSaveString16( SvStream
& rStrm
, const String
& rValue
) const
360 // write size field (including trailing NUL character)
361 sal_Int32 nSize
= static_cast< sal_Int32
>( rValue
.Len() + 1 );
363 // write character array with trailing NUL character
364 for( xub_StrLen nIdx
= 0; nIdx
< rValue
.Len(); ++nIdx
)
365 rStrm
<< static_cast< sal_uInt16
>( rValue
.GetChar( nIdx
) );
366 rStrm
<< sal_uInt16( 0 );
367 // stream is always padded to 32-bit boundary, add 2 bytes on odd character count
368 if( (nSize
& 1) == 1 )
369 rStrm
<< sal_uInt16( 0 );
372 // ----------------------------------------------------------------------------
374 SfxOleObjectBase::~SfxOleObjectBase()
378 ErrCode
SfxOleObjectBase::Load( SvStream
& rStrm
)
380 mnErrCode
= ERRCODE_NONE
;
382 SetError( rStrm
.GetErrorCode() );
386 ErrCode
SfxOleObjectBase::Save( SvStream
& rStrm
)
388 mnErrCode
= ERRCODE_NONE
;
390 SetError( rStrm
.GetErrorCode() );
394 void SfxOleObjectBase::LoadObject( SvStream
& rStrm
, SfxOleObjectBase
& rObj
)
396 SetError( rObj
.Load( rStrm
) );
399 void SfxOleObjectBase::SaveObject( SvStream
& rStrm
, SfxOleObjectBase
& rObj
)
401 SetError( rObj
.Save( rStrm
) );
404 // ----------------------------------------------------------------------------
406 SfxOleCodePageProperty::SfxOleCodePageProperty() :
407 SfxOlePropertyBase( PROPID_CODEPAGE
, PROPTYPE_INT16
)
411 void SfxOleCodePageProperty::ImplLoad( SvStream
& rStrm
)
413 // property type is signed int16, but we use always unsigned int16 for codepages
414 sal_uInt16 nCodePage
;
416 SetCodePage( nCodePage
);
419 void SfxOleCodePageProperty::ImplSave( SvStream
& rStrm
)
421 // property type is signed int16, but we use always unsigned int16 for codepages
422 rStrm
<< GetCodePage();
425 // ----------------------------------------------------------------------------
427 SfxOleInt32Property::SfxOleInt32Property( sal_Int32 nPropId
, sal_Int32 nValue
) :
428 SfxOlePropertyBase( nPropId
, PROPTYPE_INT32
),
433 void SfxOleInt32Property::ImplLoad( SvStream
& rStrm
)
438 void SfxOleInt32Property::ImplSave( SvStream
& rStrm
)
443 // ----------------------------------------------------------------------------
445 SfxOleDoubleProperty::SfxOleDoubleProperty( sal_Int32 nPropId
, double fValue
) :
446 SfxOlePropertyBase( nPropId
, PROPTYPE_DOUBLE
),
451 void SfxOleDoubleProperty::ImplLoad( SvStream
& rStrm
)
456 void SfxOleDoubleProperty::ImplSave( SvStream
& rStrm
)
461 // ----------------------------------------------------------------------------
463 SfxOleBoolProperty::SfxOleBoolProperty( sal_Int32 nPropId
, bool bValue
) :
464 SfxOlePropertyBase( nPropId
, PROPTYPE_BOOL
),
469 void SfxOleBoolProperty::ImplLoad( SvStream
& rStrm
)
473 mbValue
= nValue
!= 0;
476 void SfxOleBoolProperty::ImplSave( SvStream
& rStrm
)
478 rStrm
<< static_cast< sal_Int16
>( mbValue
? -1 : 0 );
481 // ----------------------------------------------------------------------------
483 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
484 sal_Int32 nPropId
, sal_Int32 nPropType
, const SfxOleTextEncoding
& rTextEnc
) :
485 SfxOlePropertyBase( nPropId
, nPropType
),
486 SfxOleStringHelper( rTextEnc
)
490 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
491 sal_Int32 nPropId
, sal_Int32 nPropType
, const SfxOleTextEncoding
& rTextEnc
, const String
& rValue
) :
492 SfxOlePropertyBase( nPropId
, nPropType
),
493 SfxOleStringHelper( rTextEnc
),
498 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
499 sal_Int32 nPropId
, sal_Int32 nPropType
, rtl_TextEncoding eTextEnc
) :
500 SfxOlePropertyBase( nPropId
, nPropType
),
501 SfxOleStringHelper( eTextEnc
)
505 SfxOleStringPropertyBase::SfxOleStringPropertyBase(
506 sal_Int32 nPropId
, sal_Int32 nPropType
, rtl_TextEncoding eTextEnc
, const String
& rValue
) :
507 SfxOlePropertyBase( nPropId
, nPropType
),
508 SfxOleStringHelper( eTextEnc
),
513 // ----------------------------------------------------------------------------
515 SfxOleString8Property::SfxOleString8Property(
516 sal_Int32 nPropId
, const SfxOleTextEncoding
& rTextEnc
) :
517 SfxOleStringPropertyBase( nPropId
, PROPTYPE_STRING8
, rTextEnc
)
521 SfxOleString8Property::SfxOleString8Property(
522 sal_Int32 nPropId
, const SfxOleTextEncoding
& rTextEnc
, const String
& rValue
) :
523 SfxOleStringPropertyBase( nPropId
, PROPTYPE_STRING8
, rTextEnc
, rValue
)
527 void SfxOleString8Property::ImplLoad( SvStream
& rStrm
)
529 SetValue( LoadString8( rStrm
) );
532 void SfxOleString8Property::ImplSave( SvStream
& rStrm
)
534 SaveString8( rStrm
, GetValue() );
537 // ----------------------------------------------------------------------------
539 SfxOleString16Property::SfxOleString16Property( sal_Int32 nPropId
) :
540 SfxOleStringPropertyBase( nPropId
, PROPTYPE_STRING16
, RTL_TEXTENCODING_UCS2
)
544 SfxOleString16Property::SfxOleString16Property( sal_Int32 nPropId
, const String
& rValue
) :
545 SfxOleStringPropertyBase( nPropId
, PROPTYPE_STRING16
, RTL_TEXTENCODING_UCS2
, rValue
)
549 void SfxOleString16Property::ImplLoad( SvStream
& rStrm
)
551 SetValue( LoadString16( rStrm
) );
554 void SfxOleString16Property::ImplSave( SvStream
& rStrm
)
556 SaveString16( rStrm
, GetValue() );
559 // ----------------------------------------------------------------------------
561 SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId
) :
562 SfxOlePropertyBase( nPropId
, PROPTYPE_FILETIME
)
566 SfxOleFileTimeProperty::SfxOleFileTimeProperty( sal_Int32 nPropId
, const util::DateTime
& rDateTime
) :
567 SfxOlePropertyBase( nPropId
, PROPTYPE_FILETIME
),
568 maDateTime( rDateTime
)
572 void SfxOleFileTimeProperty::ImplLoad( SvStream
& rStrm
)
574 sal_uInt32 nLower
, nUpper
;
575 rStrm
>> nLower
>> nUpper
;
576 ::DateTime aDateTime
= DateTime::CreateFromWin32FileDateTime( nLower
, nUpper
);
577 // note: editing duration is stored as offset to TIMESTAMP_INVALID_DATETIME
578 // of course we should not convert the time zone of a duration!
579 // heuristic to detect editing durations (which we assume to be < 1 year):
580 // check only the year, not the entire date
581 if ( aDateTime
.GetYear() != TIMESTAMP_INVALID_DATETIME
.GetYear() )
582 aDateTime
.ConvertToLocalTime();
583 maDateTime
.Year
= aDateTime
.GetYear();
584 maDateTime
.Month
= aDateTime
.GetMonth();
585 maDateTime
.Day
= aDateTime
.GetDay();
586 maDateTime
.Hours
= aDateTime
.GetHour();
587 maDateTime
.Minutes
= aDateTime
.GetMin();
588 maDateTime
.Seconds
= aDateTime
.GetSec();
589 maDateTime
.HundredthSeconds
= aDateTime
.Get100Sec();
592 void SfxOleFileTimeProperty::ImplSave( SvStream
& rStrm
)
594 DateTime
aDateTimeUtc(
596 static_cast< USHORT
>( maDateTime
.Day
),
597 static_cast< USHORT
>( maDateTime
.Month
),
598 static_cast< USHORT
>( maDateTime
.Year
) ),
600 static_cast< ULONG
>( maDateTime
.Hours
),
601 static_cast< ULONG
>( maDateTime
.Minutes
),
602 static_cast< ULONG
>( maDateTime
.Seconds
),
603 static_cast< ULONG
>( maDateTime
.HundredthSeconds
) ) );
604 // invalid time stamp is not converted to UTC
605 // heuristic to detect editing durations (which we assume to be < 1 year):
606 // check only the year, not the entire date
607 if( aDateTimeUtc
.IsValid()
608 && aDateTimeUtc
.GetYear() != TIMESTAMP_INVALID_DATETIME
.GetYear() ) {
609 aDateTimeUtc
.ConvertToUTC();
611 sal_uInt32 nLower
, nUpper
;
612 aDateTimeUtc
.GetWin32FileDateTime( nLower
, nUpper
);
613 rStrm
<< nLower
<< nUpper
;
616 // ----------------------------------------------------------------------------
618 SfxOleThumbnailProperty::SfxOleThumbnailProperty(
619 sal_Int32 nPropId
, const uno::Sequence
<sal_uInt8
> & i_rData
) :
620 SfxOlePropertyBase( nPropId
, PROPTYPE_CLIPFMT
),
625 void SfxOleThumbnailProperty::ImplLoad( SvStream
& )
627 DBG_ERRORFILE( "SfxOleThumbnailProperty::ImplLoad - not implemented" );
628 SetError( SVSTREAM_INVALID_ACCESS
);
631 void SfxOleThumbnailProperty::ImplSave( SvStream
& rStrm
)
634 -----------------------------------------------------------------------
635 int32 size of following data
636 int32 clipboard format tag (see below)
637 byte[] clipboard data (see below)
639 Clipboard format tag:
640 -1 = Windows clipboard format
641 -2 = Macintosh clipboard format
642 -3 = GUID that contains a format identifier (FMTID)
643 >0 = custom clipboard format name plus data (see msdn site below)
647 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/propvariant.asp
648 http://jakarta.apache.org/poi/hpsf/thumbnails.html
649 http://linux.com.hk/docs/poi/org/apache/poi/hpsf/Thumbnail.html
650 http://sparks.discreet.com/knowledgebase/public/solutions/ExtractThumbnailImg.htm
654 // clipboard size: clip_format_tag + data_format_tag + bitmap_len
655 sal_Int32 nClipSize
= static_cast< sal_Int32
>( 4 + 4 + mData
.getLength() );
656 rStrm
<< nClipSize
<< CLIPFMT_WIN
<< CLIPDATAFMT_DIB
;
657 rStrm
.Write( mData
.getConstArray(), mData
.getLength() );
661 DBG_ERRORFILE( "SfxOleThumbnailProperty::ImplSave - invalid thumbnail property" );
662 SetError( SVSTREAM_INVALID_ACCESS
);
666 // ----------------------------------------------------------------------------
668 SfxOleBlobProperty::SfxOleBlobProperty( sal_Int32 nPropId
,
669 const uno::Sequence
<sal_uInt8
> & i_rData
) :
670 SfxOlePropertyBase( nPropId
, PROPTYPE_BLOB
),
675 void SfxOleBlobProperty::ImplLoad( SvStream
& )
677 DBG_ERRORFILE( "SfxOleBlobProperty::ImplLoad - not implemented" );
678 SetError( SVSTREAM_INVALID_ACCESS
);
681 void SfxOleBlobProperty::ImplSave( SvStream
& rStrm
)
684 rStrm
.Write( mData
.getConstArray(), mData
.getLength() );
686 DBG_ERRORFILE( "SfxOleBlobProperty::ImplSave - invalid BLOB property" );
687 SetError( SVSTREAM_INVALID_ACCESS
);
691 // ----------------------------------------------------------------------------
693 SfxOleDictionaryProperty::SfxOleDictionaryProperty( const SfxOleTextEncoding
& rTextEnc
) :
694 SfxOlePropertyBase( PROPID_DICTIONARY
, 0 ),
695 SfxOleStringHelper( rTextEnc
)
699 const String
& SfxOleDictionaryProperty::GetPropertyName( sal_Int32 nPropId
) const
701 SfxOlePropNameMap::const_iterator aIt
= maPropNameMap
.find( nPropId
);
702 return (aIt
== maPropNameMap
.end()) ? String::EmptyString() : aIt
->second
;
705 void SfxOleDictionaryProperty::SetPropertyName( sal_Int32 nPropId
, const String
& rPropName
)
707 maPropNameMap
[ nPropId
] = rPropName
;
708 // dictionary property contains number of pairs in property type field
709 SetPropType( static_cast< sal_Int32
>( maPropNameMap
.size() ) );
712 void SfxOleDictionaryProperty::ImplLoad( SvStream
& rStrm
)
714 // dictionary property contains number of pairs in property type field
715 sal_Int32 nNameCount
= GetPropType();
716 // read property ID/name pairs
717 maPropNameMap
.clear();
718 for( sal_Int32 nIdx
= 0; (nIdx
< nNameCount
) && (rStrm
.GetErrorCode() == SVSTREAM_OK
) && !rStrm
.IsEof(); ++nIdx
)
722 // name always stored as byte string
723 maPropNameMap
[ nPropId
] = LoadString8( rStrm
);
727 void SfxOleDictionaryProperty::ImplSave( SvStream
& rStrm
)
729 // write property ID/name pairs
730 for( SfxOlePropNameMap::const_iterator aIt
= maPropNameMap
.begin(), aEnd
= maPropNameMap
.end(); aIt
!= aEnd
; ++aIt
)
733 // name always stored as byte string
734 SaveString8( rStrm
, aIt
->second
);
738 // ----------------------------------------------------------------------------
740 SfxOleSection::SfxOleSection( bool bSupportsDict
) :
741 maDictProp( maCodePageProp
),
743 mbSupportsDict( bSupportsDict
)
747 SfxOlePropertyRef
SfxOleSection::GetProperty( sal_Int32 nPropId
) const
749 SfxOlePropertyRef xProp
;
750 SfxOlePropMap::const_iterator aIt
= maPropMap
.find( nPropId
);
751 if( aIt
!= maPropMap
.end() )
756 bool SfxOleSection::GetInt32Value( sal_Int32
& rnValue
, sal_Int32 nPropId
) const
758 SfxOlePropertyRef xProp
= GetProperty( nPropId
);
759 const SfxOleInt32Property
* pProp
=
760 dynamic_cast< const SfxOleInt32Property
* >( xProp
.get() );
762 rnValue
= pProp
->GetValue();
766 bool SfxOleSection::GetDoubleValue( double& rfValue
, sal_Int32 nPropId
) const
768 SfxOlePropertyRef xProp
= GetProperty( nPropId
);
769 const SfxOleDoubleProperty
* pProp
=
770 dynamic_cast< const SfxOleDoubleProperty
* >( xProp
.get() );
772 rfValue
= pProp
->GetValue();
776 bool SfxOleSection::GetBoolValue( bool& rbValue
, sal_Int32 nPropId
) const
778 SfxOlePropertyRef xProp
= GetProperty( nPropId
);
779 const SfxOleBoolProperty
* pProp
=
780 dynamic_cast< const SfxOleBoolProperty
* >( xProp
.get() );
782 rbValue
= pProp
->GetValue();
786 bool SfxOleSection::GetStringValue( String
& rValue
, sal_Int32 nPropId
) const
788 SfxOlePropertyRef xProp
= GetProperty( nPropId
);
789 const SfxOleStringPropertyBase
* pProp
=
790 dynamic_cast< const SfxOleStringPropertyBase
* >( xProp
.get() );
792 rValue
= pProp
->GetValue();
796 bool SfxOleSection::GetFileTimeValue( util::DateTime
& rValue
, sal_Int32 nPropId
) const
798 SfxOlePropertyRef xProp
= GetProperty( nPropId
);
799 const SfxOleFileTimeProperty
* pProp
=
800 dynamic_cast< const SfxOleFileTimeProperty
* >( xProp
.get() );
803 if ( pProp
->GetValue() == TIMESTAMP_INVALID_UTILDATETIME
)
804 rValue
= util::DateTime();
806 rValue
= pProp
->GetValue();
811 void SfxOleSection::SetProperty( SfxOlePropertyRef xProp
)
814 maPropMap
[ xProp
->GetPropId() ] = xProp
;
817 void SfxOleSection::SetInt32Value( sal_Int32 nPropId
, sal_Int32 nValue
)
819 SetProperty( SfxOlePropertyRef( new SfxOleInt32Property( nPropId
, nValue
) ) );
822 void SfxOleSection::SetDoubleValue( sal_Int32 nPropId
, double fValue
)
824 SetProperty( SfxOlePropertyRef( new SfxOleDoubleProperty( nPropId
, fValue
) ) );
827 void SfxOleSection::SetBoolValue( sal_Int32 nPropId
, bool bValue
)
829 SetProperty( SfxOlePropertyRef( new SfxOleBoolProperty( nPropId
, bValue
) ) );
832 bool SfxOleSection::SetStringValue( sal_Int32 nPropId
, const String
& rValue
, bool bSkipEmpty
)
834 bool bInserted
= !bSkipEmpty
|| (rValue
.Len() > 0);
836 SetProperty( SfxOlePropertyRef( new SfxOleString8Property( nPropId
, maCodePageProp
, rValue
) ) );
840 void SfxOleSection::SetFileTimeValue( sal_Int32 nPropId
, const util::DateTime
& rValue
)
842 if ( rValue
.Year
== 0 || rValue
.Month
== 0 || rValue
.Day
== 0 )
843 SetProperty( SfxOlePropertyRef( new SfxOleFileTimeProperty( nPropId
, TIMESTAMP_INVALID_UTILDATETIME
) ) );
845 SetProperty( SfxOlePropertyRef( new SfxOleFileTimeProperty( nPropId
, rValue
) ) );
848 void SfxOleSection::SetThumbnailValue( sal_Int32 nPropId
,
849 const uno::Sequence
<sal_uInt8
> & i_rData
)
851 SfxOleThumbnailProperty
* pThumbnail
= new SfxOleThumbnailProperty( nPropId
, i_rData
);
852 SfxOlePropertyRef
xProp( pThumbnail
); // take ownership
853 if( pThumbnail
->IsValid() )
854 SetProperty( xProp
);
857 void SfxOleSection::SetBlobValue( sal_Int32 nPropId
,
858 const uno::Sequence
<sal_uInt8
> & i_rData
)
860 SfxOleBlobProperty
* pBlob( new SfxOleBlobProperty( nPropId
, i_rData
) );
861 SfxOlePropertyRef
xProp( pBlob
);
862 if( pBlob
->IsValid() ) {
863 SetProperty( xProp
);
867 Any
SfxOleSection::GetAnyValue( sal_Int32 nPropId
) const
870 sal_Int32 nInt32
= 0;
871 double fDouble
= 0.0;
874 ::com::sun::star::util::DateTime aApiDateTime
;
876 if( GetInt32Value( nInt32
, nPropId
) )
878 else if( GetDoubleValue( fDouble
, nPropId
) )
880 else if( GetBoolValue( bBool
, nPropId
) )
881 ::comphelper::setBOOL( aValue
, bBool
? sal_True
: sal_False
);
882 else if( GetStringValue( aString
, nPropId
) )
883 aValue
<<= OUString( aString
);
884 else if( GetFileTimeValue( aApiDateTime
, nPropId
) )
886 aValue
<<= aApiDateTime
;
891 bool SfxOleSection::SetAnyValue( sal_Int32 nPropId
, const Any
& rValue
)
893 bool bInserted
= true;
894 sal_Int32 nInt32
= 0;
895 double fDouble
= 0.0;
897 ::com::sun::star::util::DateTime aApiDateTime
;
899 if( rValue
.getValueType() == ::getBooleanCppuType() )
900 SetBoolValue( nPropId
, ::comphelper::getBOOL( rValue
) == sal_True
);
901 else if( rValue
>>= nInt32
)
902 SetInt32Value( nPropId
, nInt32
);
903 else if( rValue
>>= fDouble
)
904 SetDoubleValue( nPropId
, fDouble
);
905 else if( rValue
>>= aString
)
906 bInserted
= SetStringValue( nPropId
, aString
);
907 else if( rValue
>>= aApiDateTime
)
909 SetFileTimeValue( nPropId
, aApiDateTime
);
916 const String
& SfxOleSection::GetPropertyName( sal_Int32 nPropId
) const
918 return maDictProp
.GetPropertyName( nPropId
);
921 void SfxOleSection::SetPropertyName( sal_Int32 nPropId
, const String
& rPropName
)
923 maDictProp
.SetPropertyName( nPropId
, rPropName
);
926 void SfxOleSection::GetPropertyIds( ::std::vector
< sal_Int32
>& rPropIds
) const
929 for( SfxOlePropMap::const_iterator aIt
= maPropMap
.begin(), aEnd
= maPropMap
.end(); aIt
!= aEnd
; ++aIt
)
930 rPropIds
.push_back( aIt
->first
);
933 sal_Int32
SfxOleSection::GetFreePropertyId() const
935 return maPropMap
.empty() ? PROPID_FIRSTCUSTOM
: (maPropMap
.rbegin()->first
+ 1);
938 void SfxOleSection::ImplLoad( SvStream
& rStrm
)
940 // read section header
941 mnStartPos
= rStrm
.Tell();
943 sal_Int32 nPropCount
;
944 rStrm
>> nSize
>> nPropCount
;
946 // read property ID/position pairs
947 typedef ::std::map
< sal_Int32
, sal_uInt32
> SfxOlePropPosMap
;
948 SfxOlePropPosMap aPropPosMap
;
949 for( sal_Int32 nPropIdx
= 0; (nPropIdx
< nPropCount
) && (rStrm
.GetErrorCode() == SVSTREAM_OK
) && !rStrm
.IsEof(); ++nPropIdx
)
953 rStrm
>> nPropId
>> nPropPos
;
954 aPropPosMap
[ nPropId
] = nPropPos
;
957 // read codepage property
958 SfxOlePropPosMap::iterator aCodePageIt
= aPropPosMap
.find( PROPID_CODEPAGE
);
959 if( (aCodePageIt
!= aPropPosMap
.end()) && SeekToPropertyPos( rStrm
, aCodePageIt
->second
) )
961 // codepage property must be of type signed int-16
964 if( nPropType
== PROPTYPE_INT16
)
965 LoadObject( rStrm
, maCodePageProp
);
966 // remove property position
967 aPropPosMap
.erase( aCodePageIt
);
970 // read dictionary property
971 SfxOlePropPosMap::iterator aDictIt
= aPropPosMap
.find( PROPID_DICTIONARY
);
972 if( (aDictIt
!= aPropPosMap
.end()) && SeekToPropertyPos( rStrm
, aDictIt
->second
) )
974 // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
977 // dictionary property contains number of pairs in property type field
978 sal_Int32 nNameCount
;
980 maDictProp
.SetNameCount( nNameCount
);
981 LoadObject( rStrm
, maDictProp
);
983 // always remove position of dictionary property (do not try to read it again below)
984 aPropPosMap
.erase( aDictIt
);
987 // read other properties
989 for( SfxOlePropPosMap::const_iterator aIt
= aPropPosMap
.begin(), aEnd
= aPropPosMap
.end(); aIt
!= aEnd
; ++aIt
)
990 if( SeekToPropertyPos( rStrm
, aIt
->second
) )
991 LoadProperty( rStrm
, aIt
->first
);
994 void SfxOleSection::ImplSave( SvStream
& rStrm
)
996 /* Always export with UTF-8 encoding. All dependent properties (bytestring
997 and dictionary) will be updated automatically. */
998 maCodePageProp
.SetTextEncoding( RTL_TEXTENCODING_UTF8
);
1000 // write section header
1001 mnStartPos
= rStrm
.Tell();
1002 sal_Int32 nPropCount
= static_cast< sal_Int32
>( maPropMap
.size() + 1 );
1003 if( maDictProp
.HasPropertyNames() )
1005 rStrm
<< sal_uInt32( 0 ) << nPropCount
;
1007 // write placeholders for property ID/position pairs
1008 sal_Size nPropPosPos
= rStrm
.Tell();
1009 rStrm
.SeekRel( static_cast< sal_sSize
>( 8 * nPropCount
) );
1011 // write dictionary property
1012 if( maDictProp
.HasPropertyNames() )
1013 SaveProperty( rStrm
, maDictProp
, nPropPosPos
);
1014 // write codepage property
1015 SaveProperty( rStrm
, maCodePageProp
, nPropPosPos
);
1016 // write other properties
1017 for( SfxOlePropMap::const_iterator aIt
= maPropMap
.begin(), aEnd
= maPropMap
.end(); aIt
!= aEnd
; ++aIt
)
1018 SaveProperty( rStrm
, *aIt
->second
, nPropPosPos
);
1020 // write section size (first field in section header)
1021 rStrm
.Seek( STREAM_SEEK_TO_END
);
1022 sal_uInt32 nSectSize
= static_cast< sal_uInt32
>( rStrm
.Tell() - mnStartPos
);
1023 rStrm
.Seek( mnStartPos
);
1027 bool SfxOleSection::SeekToPropertyPos( SvStream
& rStrm
, sal_uInt32 nPropPos
) const
1029 rStrm
.Seek( static_cast< sal_Size
>( mnStartPos
+ nPropPos
) );
1030 return rStrm
.GetErrorCode() == SVSTREAM_OK
;
1033 void SfxOleSection::LoadProperty( SvStream
& rStrm
, sal_Int32 nPropId
)
1035 // property data type
1036 sal_Int32 nPropType
;
1038 // create empty property object
1039 SfxOlePropertyRef xProp
;
1042 case PROPTYPE_INT32
:
1043 xProp
.reset( new SfxOleInt32Property( nPropId
) );
1045 case PROPTYPE_DOUBLE
:
1046 xProp
.reset( new SfxOleDoubleProperty( nPropId
) );
1049 xProp
.reset( new SfxOleBoolProperty( nPropId
) );
1051 case PROPTYPE_STRING8
:
1052 xProp
.reset( new SfxOleString8Property( nPropId
, maCodePageProp
) );
1054 case PROPTYPE_STRING16
:
1055 xProp
.reset( new SfxOleString16Property( nPropId
) );
1057 case PROPTYPE_FILETIME
:
1058 xProp
.reset( new SfxOleFileTimeProperty( nPropId
) );
1061 // load property contents
1064 SetError( xProp
->Load( rStrm
) );
1065 maPropMap
[ nPropId
] = xProp
;
1069 void SfxOleSection::SaveProperty( SvStream
& rStrm
, SfxOlePropertyBase
& rProp
, sal_Size
& rnPropPosPos
)
1071 rStrm
.Seek( STREAM_SEEK_TO_END
);
1072 sal_uInt32 nPropPos
= static_cast< sal_uInt32
>( rStrm
.Tell() - mnStartPos
);
1073 // property data type
1074 rStrm
<< rProp
.GetPropType();
1075 // write property contents
1076 SaveObject( rStrm
, rProp
);
1078 while( (rStrm
.Tell() & 3) != 0 )
1079 rStrm
<< sal_uInt8( 0 );
1080 // write property ID/position pair
1081 rStrm
.Seek( rnPropPosPos
);
1082 rStrm
<< rProp
.GetPropId() << nPropPos
;
1083 rnPropPosPos
= rStrm
.Tell();
1086 // ----------------------------------------------------------------------------
1088 ErrCode
SfxOlePropertySet::LoadPropertySet( SotStorage
* pStrg
, const String
& rStrmName
)
1092 SotStorageStreamRef xStrm
= pStrg
->OpenSotStream( rStrmName
, STREAM_STD_READ
);
1093 if( xStrm
.Is() && (xStrm
->GetError() == SVSTREAM_OK
) )
1095 xStrm
->SetBufferSize( STREAM_BUFFER_SIZE
);
1099 SetError( ERRCODE_IO_ACCESSDENIED
);
1102 SetError( ERRCODE_IO_ACCESSDENIED
);
1106 ErrCode
SfxOlePropertySet::SavePropertySet( SotStorage
* pStrg
, const String
& rStrmName
)
1110 SotStorageStreamRef xStrm
= pStrg
->OpenSotStream( rStrmName
, STREAM_TRUNC
| STREAM_STD_WRITE
);
1114 SetError( ERRCODE_IO_ACCESSDENIED
);
1117 SetError( ERRCODE_IO_ACCESSDENIED
);
1121 SfxOleSectionRef
SfxOlePropertySet::GetSection( SfxOleSectionType eSection
) const
1123 return GetSection( GetSectionGuid( eSection
) );
1126 SfxOleSectionRef
SfxOlePropertySet::GetSection( const SvGlobalName
& rSectionGuid
) const
1128 SfxOleSectionRef xSection
;
1129 SfxOleSectionMap::const_iterator aIt
= maSectionMap
.find( rSectionGuid
);
1130 if( aIt
!= maSectionMap
.end() )
1131 xSection
= aIt
->second
;
1135 SfxOleSection
& SfxOlePropertySet::AddSection( SfxOleSectionType eSection
)
1137 return AddSection( GetSectionGuid( eSection
) );
1140 SfxOleSection
& SfxOlePropertySet::AddSection( const SvGlobalName
& rSectionGuid
)
1142 SfxOleSectionRef xSection
= GetSection( rSectionGuid
);
1145 // #i66214# #i66428# applications may write broken dictionary properties in wrong sections
1146 bool bSupportsDict
= rSectionGuid
== GetSectionGuid( SECTION_CUSTOM
);
1147 xSection
.reset( new SfxOleSection( bSupportsDict
) );
1148 maSectionMap
[ rSectionGuid
] = xSection
;
1153 void SfxOlePropertySet::ImplLoad( SvStream
& rStrm
)
1155 // read property set header
1156 sal_uInt16 nByteOrder
;
1157 sal_uInt16 nVersion
;
1158 sal_uInt16 nOsMinor
;
1161 sal_Int32 nSectCount
;
1162 rStrm
>> nByteOrder
>> nVersion
>> nOsMinor
>> nOsType
>> aGuid
>> nSectCount
;
1165 sal_Size nSectPosPos
= rStrm
.Tell();
1166 for( sal_Int32 nSectIdx
= 0; (nSectIdx
< nSectCount
) && (rStrm
.GetErrorCode() == SVSTREAM_OK
) && !rStrm
.IsEof(); ++nSectIdx
)
1168 // read section guid/position pair
1169 rStrm
.Seek( nSectPosPos
);
1170 SvGlobalName aSectGuid
;
1171 sal_uInt32 nSectPos
;
1172 rStrm
>> aSectGuid
>> nSectPos
;
1173 nSectPosPos
= rStrm
.Tell();
1175 rStrm
.Seek( static_cast< sal_Size
>( nSectPos
) );
1176 if( rStrm
.GetErrorCode() == SVSTREAM_OK
)
1177 LoadObject( rStrm
, AddSection( aSectGuid
) );
1181 void SfxOlePropertySet::ImplSave( SvStream
& rStrm
)
1183 // write property set header
1185 sal_Int32 nSectCount
= static_cast< sal_Int32
>( maSectionMap
.size() );
1186 rStrm
<< sal_uInt16( 0xFFFE ) // byte order
1187 << sal_uInt16( 0 ) // version
1188 << sal_uInt16( 1 ) // OS minor version
1189 << sal_uInt16( 2 ) // OS type always windows for text encoding
1190 << aGuid
// unused guid
1191 << nSectCount
; // number of sections
1193 // write placeholders for section guid/position pairs
1194 sal_Size nSectPosPos
= rStrm
.Tell();
1195 rStrm
.SeekRel( static_cast< sal_sSize
>( 20 * nSectCount
) );
1198 for( SfxOleSectionMap::const_iterator aIt
= maSectionMap
.begin(), aEnd
= maSectionMap
.end(); aIt
!= aEnd
; ++aIt
)
1200 SfxOleSection
& rSection
= *aIt
->second
;
1201 rStrm
.Seek( STREAM_SEEK_TO_END
);
1202 sal_uInt32 nSectPos
= static_cast< sal_uInt32
>( rStrm
.Tell() );
1203 // write the section
1204 SaveObject( rStrm
, rSection
);
1205 // write section guid/position pair
1206 rStrm
.Seek( nSectPosPos
);
1207 rStrm
<< aIt
->first
<< nSectPos
;
1208 nSectPosPos
= rStrm
.Tell();
1212 const SvGlobalName
& SfxOlePropertySet::GetSectionGuid( SfxOleSectionType eSection
)
1214 static const SvGlobalName
saGlobalGuid( 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 );
1215 static const SvGlobalName
saBuiltInGuid( 0xD5CDD502, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1216 static const SvGlobalName
saCustomGuid( 0xD5CDD505, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE );
1217 static const SvGlobalName saEmptyGuid
;
1220 case SECTION_GLOBAL
: return saGlobalGuid
;
1221 case SECTION_BUILTIN
: return saBuiltInGuid
;
1222 case SECTION_CUSTOM
: return saCustomGuid
;
1223 default: DBG_ERRORFILE( "SfxOlePropertySet::GetSectionGuid - unknown section type" );
1228 // ============================================================================