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: propread.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_sd.hxx"
33 #include <propread.hxx>
34 #include <tools/bigint.hxx>
35 #include "rtl/tencinfo.h"
36 #include "rtl/textenc.h"
38 // ------------------------------------------------------------------------
47 PropEntry( sal_uInt32 nId
, const sal_uInt8
* pBuf
, sal_uInt32 nBufSize
, sal_uInt16 nTextEnc
);
48 PropEntry( const PropEntry
& rProp
);
49 ~PropEntry() { delete[] mpBuf
; } ;
51 const PropEntry
& operator=(const PropEntry
& rPropEntry
);
54 PropEntry::PropEntry( sal_uInt32 nId
, const sal_uInt8
* pBuf
, sal_uInt32 nBufSize
, sal_uInt16 nTextEnc
) :
57 mnTextEnc ( nTextEnc
),
58 mpBuf ( new sal_uInt8
[ nBufSize
] )
60 memcpy( (void*)mpBuf
, (void*)pBuf
, nBufSize
);
63 PropEntry::PropEntry( const PropEntry
& rProp
) :
65 mnSize ( rProp
.mnSize
),
66 mnTextEnc ( rProp
.mnTextEnc
),
67 mpBuf ( new sal_uInt8
[ mnSize
] )
69 memcpy( (void*)mpBuf
, (void*)rProp
.mpBuf
, mnSize
);
72 const PropEntry
& PropEntry::operator=(const PropEntry
& rPropEntry
)
74 if ( this != &rPropEntry
)
77 mnId
= rPropEntry
.mnId
;
78 mnSize
= rPropEntry
.mnSize
;
79 mnTextEnc
= rPropEntry
.mnTextEnc
;
80 mpBuf
= new sal_uInt8
[ mnSize
];
81 memcpy( (void*)mpBuf
, (void*)rPropEntry
.mpBuf
, mnSize
);
86 // -----------------------------------------------------------------------
88 void PropItem::Clear()
90 Seek( STREAM_SEEK_TO_BEGIN
);
91 delete[] (sal_uInt8
*)SwitchBuffer();
94 // -----------------------------------------------------------------------
96 BOOL
PropItem::Read( String
& rString
, sal_uInt32 nStringType
, sal_Bool bAlign
)
98 sal_uInt32 i
, nItemSize
, nType
, nItemPos
;
99 sal_Bool bRetValue
= sal_False
;
103 if ( nStringType
== VT_EMPTY
)
106 nType
= nStringType
& VT_TYPEMASK
;
114 if ( (sal_uInt16
)nItemSize
)
116 sal_Char
* pString
= new sal_Char
[ (sal_uInt16
)nItemSize
];
117 if ( mnTextEnc
== RTL_TEXTENCODING_UCS2
)
120 if ( (sal_uInt16
)nItemSize
> 1 )
122 sal_Unicode
* pWString
= (sal_Unicode
*)pString
;
123 for ( i
= 0; i
< (sal_uInt16
)nItemSize
; i
++ )
124 *this >> pWString
[ i
];
125 rString
= String( pWString
, (sal_uInt16
)nItemSize
- 1 );
129 bRetValue
= sal_True
;
133 SvMemoryStream::Read( pString
, (sal_uInt16
)nItemSize
);
134 if ( pString
[ (sal_uInt16
)nItemSize
- 1 ] == 0 )
136 if ( (sal_uInt16
)nItemSize
> 1 )
137 rString
= String( ByteString( pString
), mnTextEnc
);
140 bRetValue
= sal_True
;
146 SeekRel( ( 4 - ( nItemSize
& 3 ) ) & 3 ); // dword align
154 sal_Unicode
* pString
= new sal_Unicode
[ (sal_uInt16
)nItemSize
];
155 for ( i
= 0; i
< (sal_uInt16
)nItemSize
; i
++ )
156 *this >> pString
[ i
];
157 if ( pString
[ i
- 1 ] == 0 )
159 if ( (sal_uInt16
)nItemSize
> 1 )
160 rString
= String( pString
, (sal_uInt16
)nItemSize
- 1 );
163 bRetValue
= sal_True
;
167 if ( bAlign
&& ( nItemSize
& 1 ) )
168 SeekRel( 2 ); // dword align
177 // -----------------------------------------------------------------------
179 PropItem
& PropItem::operator=( PropItem
& rPropItem
)
181 if ( this != &rPropItem
)
183 Seek( STREAM_SEEK_TO_BEGIN
);
184 delete[] (sal_uInt8
*)SwitchBuffer();
186 mnTextEnc
= rPropItem
.mnTextEnc
;
187 sal_uInt32 nItemPos
= rPropItem
.Tell();
188 rPropItem
.Seek( STREAM_SEEK_TO_END
);
189 SvMemoryStream::Write( rPropItem
.GetData(), rPropItem
.Tell() );
190 rPropItem
.Seek( nItemPos
);
195 // -----------------------------------------------------------------------
202 Dict( sal_uInt32 nId
, String rString
) { mnId
= nId
; aString
= rString
; };
205 // -----------------------------------------------------------------------
207 Dictionary::~Dictionary()
209 for ( void* pPtr
= First(); pPtr
; pPtr
= Next() )
213 // -----------------------------------------------------------------------
215 void Dictionary::AddProperty( sal_uInt32 nId
, const String
& rString
)
217 if ( rString
.Len() ) // eindeutige namen bei properties
219 // pruefen, ob es die Propertybeschreibung in der Dictionary schon gibt
220 for ( Dict
* pDict
= (Dict
*)First(); pDict
; pDict
= (Dict
*)Next() )
222 if ( pDict
->mnId
== nId
)
224 pDict
->aString
= rString
;
228 Insert( new Dict( nId
, rString
), LIST_APPEND
);
232 // -----------------------------------------------------------------------
234 UINT32
Dictionary::GetProperty( const String
& rString
)
236 for ( Dict
* pDict
= (Dict
*)First(); pDict
; pDict
= (Dict
*)Next() )
238 if ( pDict
->aString
== rString
)
244 // -----------------------------------------------------------------------
246 Dictionary
& Dictionary::operator=( Dictionary
& rDictionary
)
250 if ( this != &rDictionary
)
252 for ( pPtr
= First(); pPtr
; pPtr
= Next() )
255 for ( pPtr
= rDictionary
.First(); pPtr
; pPtr
= rDictionary
.Next() )
256 Insert( new Dict( ((Dict
*)pPtr
)->mnId
, ((Dict
*)pPtr
)->aString
), LIST_APPEND
);
261 // -----------------------------------------------------------------------
263 Section::Section( Section
& rSection
)
266 mnTextEnc
= rSection
.mnTextEnc
;
267 for ( int i
= 0; i
< 16; i
++ )
268 aFMTID
[ i
] = rSection
.aFMTID
[ i
];
269 for ( PropEntry
* pProp
= (PropEntry
*)rSection
.First(); pProp
; pProp
= (PropEntry
*)rSection
.Next() )
270 Insert( new PropEntry( *pProp
), LIST_APPEND
);
273 // -----------------------------------------------------------------------
275 Section::Section( const sal_uInt8
* pFMTID
)
277 mnTextEnc
= RTL_TEXTENCODING_MS_1252
;
278 for ( int i
= 0; i
< 16; i
++ )
279 aFMTID
[ i
] = pFMTID
[ i
];
282 // -----------------------------------------------------------------------
284 sal_Bool
Section::GetProperty( sal_uInt32 nId
, PropItem
& rPropItem
)
289 for ( pProp
= (PropEntry
*)First(); pProp
; pProp
= (PropEntry
*)Next() )
291 if ( pProp
->mnId
== nId
)
297 rPropItem
.SetTextEncoding( mnTextEnc
);
298 rPropItem
.Write( pProp
->mpBuf
, pProp
->mnSize
);
299 rPropItem
.Seek( STREAM_SEEK_TO_BEGIN
);
306 // -----------------------------------------------------------------------
308 void Section::AddProperty( sal_uInt32 nId
, const sal_uInt8
* pBuf
, sal_uInt32 nBufSize
)
314 if ( nId
== 0xffffffff )
317 // keine doppelten PropId's zulassen, sortieren
318 for ( sal_uInt32 i
= 0; i
< Count(); i
++ )
320 PropEntry
* pPropEntry
= (PropEntry
*)GetObject( i
);
321 if ( pPropEntry
->mnId
== nId
)
322 delete (PropEntry
*)Replace( new PropEntry( nId
, pBuf
, nBufSize
, mnTextEnc
), i
);
323 else if ( pPropEntry
->mnId
> nId
)
324 Insert( new PropEntry( nId
, pBuf
, nBufSize
, mnTextEnc
), i
);
329 Insert( new PropEntry( nId
, pBuf
, nBufSize
, mnTextEnc
), LIST_APPEND
);
332 // -----------------------------------------------------------------------
334 sal_Bool
Section::GetDictionary( Dictionary
& rDict
)
336 sal_Bool bRetValue
= sal_False
;
341 for ( pProp
= (PropEntry
*)First(); pProp
; pProp
= (PropEntry
*)Next() )
343 if ( pProp
->mnId
== 0 )
348 sal_uInt32 nDictCount
, nId
, nSize
, nPos
;
349 SvMemoryStream
aStream( (sal_Int8
*)pProp
->mpBuf
, pProp
->mnSize
, STREAM_READ
);
350 aStream
.Seek( STREAM_SEEK_TO_BEGIN
);
351 aStream
>> nDictCount
;
352 for ( sal_uInt32 i
= 0; i
< nDictCount
; i
++ )
354 aStream
>> nId
>> nSize
;
355 if ( (sal_uInt16
)nSize
)
358 nPos
= aStream
.Tell();
359 sal_Char
* pString
= new sal_Char
[ (sal_uInt16
)nSize
];
360 aStream
.Read( pString
, (sal_uInt16
)nSize
);
361 if ( mnTextEnc
== RTL_TEXTENCODING_UCS2
)
364 aStream
.Seek( nPos
);
365 sal_Unicode
* pWString
= (sal_Unicode
*)pString
;
366 for ( i
= 0; i
< (sal_uInt16
)nSize
; i
++ )
367 aStream
>> pWString
[ i
];
368 aString
= String( pWString
, (sal_uInt16
)nSize
- 1 );
371 aString
= String( ByteString( pString
, (sal_uInt16
)nSize
- 1 ), mnTextEnc
);
373 if ( !aString
.Len() )
375 aDict
.AddProperty( nId
, aString
);
377 bRetValue
= sal_True
;
384 // -----------------------------------------------------------------------
388 for ( PropEntry
* pProp
= (PropEntry
*)First(); pProp
; pProp
= (PropEntry
*)Next() )
392 // -----------------------------------------------------------------------
394 void Section::Read( SvStorageStream
*pStrm
)
396 sal_uInt32 i
, nSecOfs
, nSecSize
, nPropCount
, nPropId
, nPropOfs
, nPropType
, nPropSize
, nCurrent
, nVectorCount
, nTemp
, nStrmSize
;
397 nSecOfs
= pStrm
->Tell();
399 pStrm
->Seek( STREAM_SEEK_TO_END
);
400 nStrmSize
= pStrm
->Tell();
401 pStrm
->Seek( nSecOfs
);
403 mnTextEnc
= RTL_TEXTENCODING_MS_1252
;
404 *pStrm
>> nSecSize
>> nPropCount
;
405 while( nPropCount
-- && ( pStrm
->GetError() == ERRCODE_NONE
) )
407 *pStrm
>> nPropId
>> nPropOfs
;
408 nCurrent
= pStrm
->Tell();
409 pStrm
->Seek( nPropOfs
+ nSecOfs
);
410 if ( nPropId
) // dictionary wird nicht eingelesen
417 if ( nPropType
& VT_VECTOR
)
419 *pStrm
>> nVectorCount
;
420 nPropType
&=~VT_VECTOR
;
427 sal_Bool bVariant
= ( nPropType
== VT_VARIANT
);
429 for ( i
= 0; nPropSize
&& ( i
< nVectorCount
); i
++ )
466 nPropSize
+= ( nTemp
+ 4 );
471 nPropSize
+= ( nTemp
+ 4 );
476 nPropSize
+= ( nTemp
<< 1 ) + 4;
479 case VT_BLOB_OBJECT
:
483 nPropSize
+= ( nTemp
+ 4 );
489 case VT_STREAMED_OBJECT
:
490 case VT_STORED_OBJECT
:
498 if ( ( nVectorCount
- i
) > 1 )
499 pStrm
->Seek( nPropOfs
+ nSecOfs
+ nPropSize
);
506 pStrm
->Seek( nPropOfs
+ nSecOfs
);
507 sal_uInt8
* pBuf
= new sal_uInt8
[ nPropSize
];
508 pStrm
->Read( pBuf
, nPropSize
);
509 AddProperty( nPropId
, pBuf
, nPropSize
);
515 if ( GetProperty( 1, aPropItem
) )
517 sal_uInt16 nCodePage
;
518 aPropItem
>> nPropType
;
519 if ( nPropType
== VT_I2
)
521 aPropItem
>> nCodePage
;
523 if ( nCodePage
== 1200 )
525 mnTextEnc
= RTL_TEXTENCODING_UCS2
;
529 mnTextEnc
= rtl_getTextEncodingFromWindowsCodePage( nCodePage
);
530 if ( mnTextEnc
== RTL_TEXTENCODING_DONTKNOW
)
531 mnTextEnc
= RTL_TEXTENCODING_MS_1252
;
536 mnTextEnc
= RTL_TEXTENCODING_MS_1252
;
543 sal_uInt32 nDictCount
, nSize
;
544 *pStrm
>> nDictCount
;
545 for ( i
= 0; i
< nDictCount
; i
++ )
547 *pStrm
>> nSize
>> nSize
;
548 pStrm
->SeekRel( nSize
);
550 nSize
= pStrm
->Tell();
551 pStrm
->Seek( nPropOfs
+ nSecOfs
);
552 nSize
-= pStrm
->Tell();
553 if ( nSize
> nStrmSize
)
558 sal_uInt8
* pBuf
= new sal_uInt8
[ nSize
];
559 pStrm
->Read( pBuf
, nSize
);
560 AddProperty( 0xffffffff, pBuf
, nSize
);
563 pStrm
->Seek( nCurrent
);
565 pStrm
->Seek( nSecOfs
+ nSecSize
);
568 // -----------------------------------------------------------------------
570 Section
& Section::operator=( Section
& rSection
)
574 if ( this != &rSection
)
576 memcpy( (void*)aFMTID
, (void*)rSection
.aFMTID
, 16 );
577 for ( pProp
= (PropEntry
*)First(); pProp
; pProp
= (PropEntry
*)Next() )
580 for ( pProp
= (PropEntry
*)rSection
.First(); pProp
; pProp
= (PropEntry
*)rSection
.Next() )
581 Insert( new PropEntry( *pProp
), LIST_APPEND
);
586 // -----------------------------------------------------------------------
588 PropRead::PropRead( SvStorage
& rStorage
, const String
& rName
) :
589 mbStatus ( sal_False
),
590 mnByteOrder ( 0xfffe ),
595 if ( rStorage
.IsStream( rName
) )
597 mpSvStream
= rStorage
.OpenSotStream( rName
, STREAM_STD_READ
);
600 mpSvStream
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
601 memset( mApplicationCLSID
, 0, 16 );
607 // -----------------------------------------------------------------------
609 void PropRead::AddSection( Section
& rSection
)
611 Insert( new Section( rSection
), LIST_APPEND
);
614 // -----------------------------------------------------------------------
616 const Section
* PropRead::GetSection( const sal_uInt8
* pFMTID
)
620 for ( pSection
= (Section
*)First(); pSection
; pSection
= (Section
*)Next() )
622 if ( memcmp( pSection
->GetFMTID(), pFMTID
, 16 ) == 0 )
628 // -----------------------------------------------------------------------
630 PropRead::~PropRead()
632 for ( Section
* pSection
= (Section
*)First(); pSection
; pSection
= (Section
*)Next() )
636 // -----------------------------------------------------------------------
638 void PropRead::Read()
640 for ( Section
* pSection
= (Section
*)First(); pSection
; pSection
= (Section
*)Next() )
645 sal_uInt32 nSections
;
646 sal_uInt32 nSectionOfs
;
648 *mpSvStream
>> mnByteOrder
>> mnFormat
>> mnVersionLo
>> mnVersionHi
;
649 if ( mnByteOrder
== 0xfffe )
651 sal_uInt8
* pSectCLSID
= new sal_uInt8
[ 16 ];
652 mpSvStream
->Read( mApplicationCLSID
, 16 );
653 *mpSvStream
>> nSections
;
654 if ( nSections
> 2 ) // sj: PowerPoint documents are containing max 2 sections
656 mbStatus
= sal_False
;
658 else for ( sal_uInt32 i
= 0; i
< nSections
; i
++ )
660 mpSvStream
->Read( pSectCLSID
, 16 );
661 *mpSvStream
>> nSectionOfs
;
662 nCurrent
= mpSvStream
->Tell();
663 mpSvStream
->Seek( nSectionOfs
);
664 Section
aSection( pSectCLSID
);
665 aSection
.Read( mpSvStream
);
666 AddSection( aSection
);
667 mpSvStream
->Seek( nCurrent
);
674 // -----------------------------------------------------------------------
676 PropRead
& PropRead::operator=( PropRead
& rPropRead
)
680 if ( this != &rPropRead
)
682 mbStatus
= rPropRead
.mbStatus
;
683 mpSvStream
= rPropRead
.mpSvStream
;
685 mnByteOrder
= rPropRead
.mnByteOrder
;
686 mnFormat
= rPropRead
.mnFormat
;
687 mnVersionLo
= rPropRead
.mnVersionLo
;
688 mnVersionHi
= rPropRead
.mnVersionHi
;
689 memcpy( mApplicationCLSID
, rPropRead
.mApplicationCLSID
, 16 );
691 for ( pSection
= (Section
*)First(); pSection
; pSection
= (Section
*)Next() )
694 for ( pSection
= (Section
*)rPropRead
.First(); pSection
; pSection
= (Section
*)rPropRead
.Next() )
695 Insert( new Section( *pSection
), LIST_APPEND
);