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: stgelem.cxx,v $
10 * $Revision: 1.12.6.1 $
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_sot.hxx"
34 #include <string.h> // memset(), memcpy()
35 #include <rtl/ustring.hxx>
36 #include <com/sun/star/lang/Locale.hpp>
37 #include <unotools/charclass.hxx>
39 #include "stgelem.hxx"
40 #include "stgcache.hxx"
41 #include "stgstrms.hxx"
45 static BYTE cStgSignature
[ 8 ] = { 0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1 };
47 ////////////////////////////// struct ClsId /////////////////////////////
49 SvStream
& operator >>( SvStream
& r
, ClsId
& rId
)
65 SvStream
& operator <<( SvStream
& r
, const ClsId
& rId
)
81 ///////////////////////////// class StgHeader ////////////////////////////
83 StgHeader::StgHeader()
85 memset( this, 0, sizeof( StgHeader
) );
88 void StgHeader::Init()
90 memset( this, 0, sizeof( StgHeader
) );
91 memcpy( cSignature
, cStgSignature
, 8 );
92 nVersion
= 0x0003003B;
94 nPageSize
= 9; // 512 bytes
95 nDataPageSize
= 6; // 64 bytes
98 nMasterChain
= STG_EOF
;
99 SetTOCStart( STG_EOF
);
100 SetDataFATStart( STG_EOF
);
101 for( short i
= 0; i
< 109; i
++ )
102 SetFATPage( i
, STG_FREE
);
105 BOOL
StgHeader::Load( StgIo
& rIo
)
107 SvStream
& r
= *rIo
.GetStrm();
112 BOOL
StgHeader::Load( SvStream
& r
)
115 r
.Read( cSignature
, 8 );
116 r
>> aClsId
// 08 Class ID
117 >> nVersion
// 1A version number
118 >> nByteOrder
// 1C Unicode byte order indicator
119 >> nPageSize
// 1E 1 << nPageSize = block size
120 >> nDataPageSize
; // 20 1 << this size == data block size
122 r
>> nFATSize
// 2C total number of FAT pages
123 >> nTOCstrm
// 30 starting page for the TOC stream
125 >> nThreshold
// 38 minimum file size for big data
126 >> nDataFAT
// 3C page # of 1st data FAT block
127 >> nDataFATSize
// 40 # of data FATpages
128 >> nMasterChain
// 44 chain to the next master block
129 >> nMaster
; // 48 # of additional master blocks
130 for( short i
= 0; i
< 109; i
++ )
131 r
>> nMasterFAT
[ i
];
132 return r
.GetErrorCode() == ERRCODE_NONE
;
135 BOOL
StgHeader::Store( StgIo
& rIo
)
139 SvStream
& r
= *rIo
.GetStrm();
141 r
.Write( cSignature
, 8 + 16 );
142 r
<< nVersion
// 1A version number
143 << nByteOrder
// 1C Unicode byte order indicator
144 << nPageSize
// 1E 1 << nPageSize = block size
145 << nDataPageSize
// 20 1 << this size == data block size
146 << (INT32
) 0 << (INT32
) 0 << (INT16
) 0
147 << nFATSize
// 2C total number of FAT pages
148 << nTOCstrm
// 30 starting page for the TOC stream
150 << nThreshold
// 38 minimum file size for big data
151 << nDataFAT
// 3C page # of 1st data FAT block
152 << nDataFATSize
// 40 # of data FAT pages
153 << nMasterChain
// 44 chain to the next master block
154 << nMaster
; // 48 # of additional master blocks
155 for( short i
= 0; i
< 109; i
++ )
156 r
<< nMasterFAT
[ i
];
157 bDirty
= !rIo
.Good();
158 return BOOL( !bDirty
);
161 static bool lcl_wontoverflow(short shift
)
163 return shift
>= 0 && shift
< (short)sizeof(short) * 8 - 1;
166 // Perform thorough checks also on unknown variables
167 BOOL
StgHeader::Check()
169 return BOOL( memcmp( cSignature
, cStgSignature
, 8 ) == 0
170 && (short) ( nVersion
>> 16 ) == 3 )
171 && lcl_wontoverflow(nPageSize
)
172 && lcl_wontoverflow(nDataPageSize
);
175 INT32
StgHeader::GetFATPage( short n
) const
177 if( n
>= 0 && n
< 109 )
178 return nMasterFAT
[ n
];
183 void StgHeader::SetFATPage( short n
, INT32 nb
)
185 if( n
>= 0 && n
< 109 )
187 if( nMasterFAT
[ n
] != nb
)
188 bDirty
= TRUE
, nMasterFAT
[ n
] = nb
;
192 void StgHeader::SetClassId( const ClsId
& r
)
194 if( memcmp( &aClsId
, &r
, sizeof( ClsId
) ) )
195 bDirty
= TRUE
, memcpy( &aClsId
, &r
, sizeof( ClsId
) );
198 void StgHeader::SetTOCStart( INT32 n
)
200 if( n
!= nTOCstrm
) bDirty
= TRUE
, nTOCstrm
= n
;
203 void StgHeader::SetDataFATStart( INT32 n
)
205 if( n
!= nDataFAT
) bDirty
= TRUE
, nDataFAT
= n
;
208 void StgHeader::SetDataFATSize( INT32 n
)
210 if( n
!= nDataFATSize
) bDirty
= TRUE
, nDataFATSize
= n
;
213 void StgHeader::SetFATSize( INT32 n
)
215 if( n
!= nFATSize
) bDirty
= TRUE
, nFATSize
= n
;
218 void StgHeader::SetFATChain( INT32 n
)
220 if( n
!= nMasterChain
)
221 bDirty
= TRUE
, nMasterChain
= n
;
224 void StgHeader::SetMasters( INT32 n
)
226 if( n
!= nMaster
) bDirty
= TRUE
, nMaster
= n
;
229 ///////////////////////////// class StgEntry /////////////////////////////
231 // This class is only a wrapper around teh dir entry structure
232 // which retrieves and sets data.
234 // The name must be smaller than 32 chars. Conversion into Unicode
235 // is easy, since the 1st 256 characters of the Windows ANSI set
236 // equal the 1st 256 Unicode characters.
238 void ToUnicode_Impl( String& rName )
241 rName.Convert( ::GetSystemCharSet(), CHARSET_ANSI );
243 BYTE* p = (BYTE*) rName.GetCharStr();
244 for( USHORT i = 0; i < rName.Len(); i++, p++ )
246 // check each character and substitute blanks for illegal ones
248 if( cChar == '!' || cChar == ':' || cChar == '\\' || cChar == '/' )
254 static void FromUnicode( String& rName )
256 rName.Convert( CHARSET_ANSI, ::GetSystemCharSet() );
259 BOOL
StgEntry::Init()
261 memset( this, 0, sizeof (StgEntry
) - sizeof( String
) );
262 SetLeaf( STG_LEFT
, STG_FREE
);
263 SetLeaf( STG_RIGHT
, STG_FREE
);
264 SetLeaf( STG_CHILD
, STG_FREE
);
265 SetLeaf( STG_DATA
, STG_EOF
);
269 static String
ToUpperUnicode( const String
& rStr
)
271 // I don't know the locale, so en_US is hopefully fine
273 com.sun.star.lang.Locale aLocale;
274 aLocale.Language = OUString::createFromAscii( "en" );
275 aLocale.Country = OUString::createFromAscii( "US" );
277 static rtl::OUString aEN
=rtl::OUString::createFromAscii( "en" );
278 static rtl::OUString aUS
=rtl::OUString::createFromAscii( "US" );
279 static CharClass
aCC( com::sun::star::lang::Locale( aEN
, aUS
, rtl::OUString() ) );
280 return aCC
.toUpper( rStr
, 0, rStr
.Len() );
284 BOOL
StgEntry::SetName( const String
& rName
)
286 // I don't know the locale, so en_US is hopefully fine
287 aName
= ToUpperUnicode( rName
);
291 for( i
= 0; i
< aName
.Len() && i
< 32; i
++ )
292 nName
[ i
] = rName
.GetChar( sal_uInt16( i
));
295 nNameLen
= ( aName
.Len() + 1 ) << 1;
299 INT32
StgEntry::GetLeaf( StgEntryRef eRef
) const
304 case STG_LEFT
: n
= nLeft
; break;
305 case STG_RIGHT
: n
= nRight
; break;
306 case STG_CHILD
: n
= nChild
; break;
307 case STG_DATA
: n
= nPage1
; break;
312 void StgEntry::SetLeaf( StgEntryRef eRef
, INT32 nPage
)
316 case STG_LEFT
: nLeft
= nPage
; break;
317 case STG_RIGHT
: nRight
= nPage
; break;
318 case STG_CHILD
: nChild
= nPage
; break;
319 case STG_DATA
: nPage1
= nPage
; break;
323 const INT32
* StgEntry::GetTime( StgEntryTime eTime
) const
325 return( eTime
== STG_MODIFIED
) ? nMtime
: nAtime
;
328 void StgEntry::SetTime( StgEntryTime eTime
, INT32
* pTime
)
330 if( eTime
== STG_MODIFIED
)
331 nMtime
[ 0 ] = *pTime
++, nMtime
[ 1 ] = *pTime
;
333 nAtime
[ 0 ] = *pTime
++, nAtime
[ 1 ] = *pTime
;
336 void StgEntry::SetClassId( const ClsId
& r
)
338 memcpy( &aClsId
, &r
, sizeof( ClsId
) );
341 void StgEntry::GetName( String
& rName
) const
346 rName
= String( nName
, n
);
349 // Compare two entries. Do this case-insensitive.
351 short StgEntry::Compare( const StgEntry
& r
) const
354 short nRes = r.nNameLen - nNameLen;
355 if( !nRes ) return strcmp( r.aName, aName );
358 sal_Int32 nRes
= r
.nNameLen
- nNameLen
;
360 nRes
= r
.aName
.CompareTo( aName
);
362 //return aName.CompareTo( r.aName );
365 // These load/store operations are a bit more complicated,
366 // since they have to copy their contents into a packed structure.
368 BOOL
StgEntry::Load( const void* pFrom
)
370 SvMemoryStream
r( (sal_Char
*) pFrom
, 128, STREAM_READ
);
371 for( short i
= 0; i
< 32; i
++ )
372 r
>> nName
[ i
]; // 00 name as WCHAR
373 r
>> nNameLen
// 40 size of name in bytes including 00H
374 >> cType
// 42 entry type
375 >> cFlags
// 43 0 or 1 (tree balance?)
376 >> nLeft
// 44 left node entry
377 >> nRight
// 48 right node entry
378 >> nChild
// 4C 1st child entry if storage
379 >> aClsId
// 50 class ID (optional)
380 >> nFlags
// 60 state flags(?)
381 >> nMtime
[ 0 ] // 64 modification time
382 >> nMtime
[ 1 ] // 64 modification time
383 >> nAtime
[ 0 ] // 6C creation and access time
384 >> nAtime
[ 1 ] // 6C creation and access time
385 >> nPage1
// 74 starting block (either direct or translated)
386 >> nSize
// 78 file size
387 >> nUnknown
; // 7C unknown
392 if( n
> 31 || (nSize
< 0 && cType
!= STG_STORAGE
) )
394 // the size makes no sence for the substorage
395 // TODO/LATER: actually the size should be an unsigned value, but in this case it would mean a stream of more than 2Gb
399 aName
= String( nName
, n
);
400 // I don't know the locale, so en_US is hopefully fine
401 aName
= ToUpperUnicode( aName
);
407 void StgEntry::Store( void* pTo
)
409 SvMemoryStream
r( (sal_Char
*)pTo
, 128, STREAM_WRITE
);
410 for( short i
= 0; i
< 32; i
++ )
411 r
<< nName
[ i
]; // 00 name as WCHAR
412 r
<< nNameLen
// 40 size of name in bytes including 00H
413 << cType
// 42 entry type
414 << cFlags
// 43 0 or 1 (tree balance?)
415 << nLeft
// 44 left node entry
416 << nRight
// 48 right node entry
417 << nChild
// 4C 1st child entry if storage;
418 << aClsId
// 50 class ID (optional)
419 << nFlags
// 60 state flags(?)
420 << nMtime
[ 0 ] // 64 modification time
421 << nMtime
[ 1 ] // 64 modification time
422 << nAtime
[ 0 ] // 6C creation and access time
423 << nAtime
[ 1 ] // 6C creation and access time
424 << nPage1
// 74 starting block (either direct or translated)
425 << nSize
// 78 file size
426 << nUnknown
; // 7C unknown