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