update dev300-m58
[ooovba.git] / sfx2 / source / doc / oleprops.cxx
blobc0424c22607ad19f968bcb2d020a144beb1881bb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: oleprops.cxx,v $
10 * $Revision: 1.5 $
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 // ============================================================================
46 #define VERSION 11
47 #define STREAM_BUFFER_SIZE 2048
49 // usings
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.
59 static
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
76 public:
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; }
82 private:
83 virtual void ImplLoad( SvStream& rStrm );
84 virtual void ImplSave( SvStream& rStrm );
86 private:
87 sal_Int32 mnValue;
90 // ============================================================================
92 /** Property representing a floating-point value. */
93 class SfxOleDoubleProperty : public SfxOlePropertyBase
95 public:
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; }
101 private:
102 virtual void ImplLoad( SvStream& rStrm );
103 virtual void ImplSave( SvStream& rStrm );
105 private:
106 double mfValue;
109 // ============================================================================
111 /** Property representing a boolean value. */
112 class SfxOleBoolProperty : public SfxOlePropertyBase
114 public:
115 explicit SfxOleBoolProperty( sal_Int32 nPropId, bool bValue = false );
117 inline bool GetValue() const { return mbValue; }
118 inline void SetValue( bool bValue ) { mbValue = bValue; }
120 private:
121 virtual void ImplLoad( SvStream& rStrm );
122 virtual void ImplSave( SvStream& rStrm );
124 private:
125 bool mbValue;
128 // ============================================================================
130 /** Base class for properties that contain a single string value. */
131 class SfxOleStringPropertyBase : public SfxOlePropertyBase, public SfxOleStringHelper
133 public:
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; }
150 private:
151 String maValue;
154 // ============================================================================
156 /** Property representing a bytestring value. */
157 class SfxOleString8Property : public SfxOleStringPropertyBase
159 public:
160 explicit SfxOleString8Property(
161 sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc );
162 explicit SfxOleString8Property(
163 sal_Int32 nPropId, const SfxOleTextEncoding& rTextEnc,
164 const String& rValue );
166 private:
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
176 public:
177 explicit SfxOleString16Property( sal_Int32 nPropId );
178 explicit SfxOleString16Property( sal_Int32 nPropId, const String& rValue );
180 private:
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
190 public:
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; }
200 private:
201 virtual void ImplLoad( SvStream& rStrm );
202 virtual void ImplSave( SvStream& rStrm );
204 private:
205 util::DateTime maDateTime;
208 // ============================================================================
210 /** Property representing a thumbnail picture.
212 Currently, only saving this property is implemented.
214 class SfxOleThumbnailProperty : public SfxOlePropertyBase
216 public:
217 explicit SfxOleThumbnailProperty( sal_Int32 nPropId,
218 const uno::Sequence<sal_uInt8> & i_rData);
220 inline bool IsValid() const { return mData.getLength() > 0; }
222 private:
223 virtual void ImplLoad( SvStream& rStrm );
224 virtual void ImplSave( SvStream& rStrm );
226 private:
227 uno::Sequence<sal_uInt8> mData;
230 // ============================================================================
232 /** Property representing a BLOB (which presumably stands for binary large
233 object).
235 Currently, only saving this property is implemented.
237 class SfxOleBlobProperty : public SfxOlePropertyBase
239 public:
240 explicit SfxOleBlobProperty( sal_Int32 nPropId,
241 const uno::Sequence<sal_uInt8> & i_rData);
242 inline bool IsValid() const { return mData.getLength() > 0; }
244 private:
245 virtual void ImplLoad( SvStream& rStrm );
246 virtual void ImplSave( SvStream& rStrm );
248 private:
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 )
264 SetUnicode();
265 else
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
282 if( IsUnicode() )
283 ImplSaveString16( rStrm, rValue );
284 else
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
300 String aValue;
301 // read size field (signed 32-bit)
302 sal_Int32 nSize;
303 rStrm >> nSize;
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() );
314 return aValue;
317 String SfxOleStringHelper::ImplLoadString16( SvStream& rStrm ) const
319 String aValue;
320 // read size field (signed 32-bit), may be buffer size or character count
321 sal_Int32 nSize;
322 rStrm >> nSize;
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 ) );
330 sal_uInt16 cChar;
331 for( sal_Int32 nIdx = 0; nIdx < nSize; ++nIdx )
333 rStrm >> cChar;
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 )
338 rStrm.SeekRel( 2 );
339 // create string from character array
340 aBuffer.push_back( 0 );
341 aValue = String( &aBuffer.front() );
343 return aValue;
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 );
352 rStrm << nSize;
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 );
362 rStrm << nSize;
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;
381 ImplLoad( rStrm );
382 SetError( rStrm.GetErrorCode() );
383 return GetError();
386 ErrCode SfxOleObjectBase::Save( SvStream& rStrm )
388 mnErrCode = ERRCODE_NONE;
389 ImplSave( rStrm );
390 SetError( rStrm.GetErrorCode() );
391 return GetError();
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;
415 rStrm >> 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 ),
429 mnValue( nValue )
433 void SfxOleInt32Property::ImplLoad( SvStream& rStrm )
435 rStrm >> mnValue;
438 void SfxOleInt32Property::ImplSave( SvStream& rStrm )
440 rStrm << mnValue;
443 // ----------------------------------------------------------------------------
445 SfxOleDoubleProperty::SfxOleDoubleProperty( sal_Int32 nPropId, double fValue ) :
446 SfxOlePropertyBase( nPropId, PROPTYPE_DOUBLE ),
447 mfValue( fValue )
451 void SfxOleDoubleProperty::ImplLoad( SvStream& rStrm )
453 rStrm >> mfValue;
456 void SfxOleDoubleProperty::ImplSave( SvStream& rStrm )
458 rStrm << mfValue;
461 // ----------------------------------------------------------------------------
463 SfxOleBoolProperty::SfxOleBoolProperty( sal_Int32 nPropId, bool bValue ) :
464 SfxOlePropertyBase( nPropId, PROPTYPE_BOOL ),
465 mbValue( bValue )
469 void SfxOleBoolProperty::ImplLoad( SvStream& rStrm )
471 sal_Int16 nValue;
472 rStrm >> nValue;
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 ),
494 maValue( rValue )
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 ),
509 maValue( rValue )
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(
595 Date(
596 static_cast< USHORT >( maDateTime.Day ),
597 static_cast< USHORT >( maDateTime.Month ),
598 static_cast< USHORT >( maDateTime.Year ) ),
599 Time(
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 ),
621 mData(i_rData)
625 void SfxOleThumbnailProperty::ImplLoad( SvStream& )
627 DBG_ERRORFILE( "SfxOleThumbnailProperty::ImplLoad - not implemented" );
628 SetError( SVSTREAM_INVALID_ACCESS );
631 void SfxOleThumbnailProperty::ImplSave( SvStream& rStrm )
633 /* Type Contents
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)
644 0 = no data
646 References:
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
652 if( IsValid() )
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() );
659 else
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 ),
671 mData(i_rData)
675 void SfxOleBlobProperty::ImplLoad( SvStream& )
677 DBG_ERRORFILE( "SfxOleBlobProperty::ImplLoad - not implemented" );
678 SetError( SVSTREAM_INVALID_ACCESS );
681 void SfxOleBlobProperty::ImplSave( SvStream& rStrm )
683 if (IsValid()) {
684 rStrm.Write( mData.getConstArray(), mData.getLength() );
685 } else {
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 )
720 sal_Int32 nPropId;
721 rStrm >> nPropId;
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 )
732 rStrm << aIt->first;
733 // name always stored as byte string
734 SaveString8( rStrm, aIt->second );
738 // ----------------------------------------------------------------------------
740 SfxOleSection::SfxOleSection( bool bSupportsDict ) :
741 maDictProp( maCodePageProp ),
742 mnStartPos( 0 ),
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() )
752 xProp = aIt->second;
753 return xProp;
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() );
761 if( pProp )
762 rnValue = pProp->GetValue();
763 return pProp != 0;
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() );
771 if( pProp )
772 rfValue = pProp->GetValue();
773 return pProp != 0;
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() );
781 if( pProp )
782 rbValue = pProp->GetValue();
783 return pProp != 0;
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() );
791 if( pProp )
792 rValue = pProp->GetValue();
793 return pProp != 0;
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() );
801 if( pProp )
803 if ( pProp->GetValue() == TIMESTAMP_INVALID_UTILDATETIME )
804 rValue = util::DateTime();
805 else
806 rValue = pProp->GetValue();
808 return pProp != 0;
811 void SfxOleSection::SetProperty( SfxOlePropertyRef xProp )
813 if( xProp.get() )
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);
835 if( bInserted )
836 SetProperty( SfxOlePropertyRef( new SfxOleString8Property( nPropId, maCodePageProp, rValue ) ) );
837 return bInserted;
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 ) ) );
844 else
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
869 Any aValue;
870 sal_Int32 nInt32 = 0;
871 double fDouble = 0.0;
872 bool bBool = false;
873 String aString;
874 ::com::sun::star::util::DateTime aApiDateTime;
876 if( GetInt32Value( nInt32, nPropId ) )
877 aValue <<= nInt32;
878 else if( GetDoubleValue( fDouble, nPropId ) )
879 aValue <<= fDouble;
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;
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 ::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 );
911 else
912 bInserted = false;
913 return bInserted;
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
928 rPropIds.clear();
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();
942 sal_uInt32 nSize;
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 )
951 sal_Int32 nPropId;
952 sal_uInt32 nPropPos;
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
962 sal_Int32 nPropType;
963 rStrm >> nPropType;
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
975 if( mbSupportsDict )
977 // dictionary property contains number of pairs in property type field
978 sal_Int32 nNameCount;
979 rStrm >> 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
988 maPropMap.clear();
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() )
1004 ++nPropCount;
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 );
1024 rStrm << nSectSize;
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;
1037 rStrm >> nPropType;
1038 // create empty property object
1039 SfxOlePropertyRef xProp;
1040 switch( nPropType )
1042 case PROPTYPE_INT32:
1043 xProp.reset( new SfxOleInt32Property( nPropId ) );
1044 break;
1045 case PROPTYPE_DOUBLE:
1046 xProp.reset( new SfxOleDoubleProperty( nPropId ) );
1047 break;
1048 case PROPTYPE_BOOL:
1049 xProp.reset( new SfxOleBoolProperty( nPropId ) );
1050 break;
1051 case PROPTYPE_STRING8:
1052 xProp.reset( new SfxOleString8Property( nPropId, maCodePageProp ) );
1053 break;
1054 case PROPTYPE_STRING16:
1055 xProp.reset( new SfxOleString16Property( nPropId ) );
1056 break;
1057 case PROPTYPE_FILETIME:
1058 xProp.reset( new SfxOleFileTimeProperty( nPropId ) );
1059 break;
1061 // load property contents
1062 if( xProp.get() )
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 );
1077 // align to 32-bit
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 )
1090 if( pStrg )
1092 SotStorageStreamRef xStrm = pStrg->OpenSotStream( rStrmName, STREAM_STD_READ );
1093 if( xStrm.Is() && (xStrm->GetError() == SVSTREAM_OK) )
1095 xStrm->SetBufferSize( STREAM_BUFFER_SIZE );
1096 Load( *xStrm );
1098 else
1099 SetError( ERRCODE_IO_ACCESSDENIED );
1101 else
1102 SetError( ERRCODE_IO_ACCESSDENIED );
1103 return GetError();
1106 ErrCode SfxOlePropertySet::SavePropertySet( SotStorage* pStrg, const String& rStrmName )
1108 if( pStrg )
1110 SotStorageStreamRef xStrm = pStrg->OpenSotStream( rStrmName, STREAM_TRUNC | STREAM_STD_WRITE );
1111 if( xStrm.Is() )
1112 Save( *xStrm );
1113 else
1114 SetError( ERRCODE_IO_ACCESSDENIED );
1116 else
1117 SetError( ERRCODE_IO_ACCESSDENIED );
1118 return GetError();
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;
1132 return xSection;
1135 SfxOleSection& SfxOlePropertySet::AddSection( SfxOleSectionType eSection )
1137 return AddSection( GetSectionGuid( eSection ) );
1140 SfxOleSection& SfxOlePropertySet::AddSection( const SvGlobalName& rSectionGuid )
1142 SfxOleSectionRef xSection = GetSection( rSectionGuid );
1143 if( !xSection )
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;
1150 return *xSection;
1153 void SfxOlePropertySet::ImplLoad( SvStream& rStrm )
1155 // read property set header
1156 sal_uInt16 nByteOrder;
1157 sal_uInt16 nVersion;
1158 sal_uInt16 nOsMinor;
1159 sal_uInt16 nOsType;
1160 SvGlobalName aGuid;
1161 sal_Int32 nSectCount;
1162 rStrm >> nByteOrder >> nVersion >> nOsMinor >> nOsType >> aGuid >> nSectCount;
1164 // read sections
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();
1174 // read section
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
1184 SvGlobalName aGuid;
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 ) );
1197 // write sections
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;
1218 switch( eSection )
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" );
1225 return saEmptyGuid;
1228 // ============================================================================
1230 //} // namespace