LCOV - code coverage report
Current view: top level - libreoffice/sot/source/sdstor - stgelem.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 245 255 96.1 %
Date: 2012-12-17 Functions: 26 28 92.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <string.h> // memset(), memcpy()
      22             : #include <rtl/ustring.hxx>
      23             : #include <com/sun/star/lang/Locale.hpp>
      24             : #include <unotools/charclass.hxx>
      25             : #include "sot/stg.hxx"
      26             : #include "stgelem.hxx"
      27             : #include "stgcache.hxx"
      28             : #include "stgstrms.hxx"
      29             : #include "stgdir.hxx"
      30             : #include "stgio.hxx"
      31             : 
      32             : static const sal_uInt16 nMaxLegalStr = 31;
      33             : 
      34             : static sal_uInt8 cStgSignature[ 8 ] = { 0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1 };
      35             : 
      36             : ////////////////////////////// struct ClsId  /////////////////////////////
      37             : 
      38        3503 : SvStream& operator >>( SvStream& r, ClsId& rId )
      39             : {
      40        3503 :     r >> rId.n1
      41        7006 :       >> rId.n2
      42        7006 :       >> rId.n3
      43        7006 :       >> rId.n4
      44        7006 :       >> rId.n5
      45        7006 :       >> rId.n6
      46        7006 :       >> rId.n7
      47        7006 :       >> rId.n8
      48        7006 :       >> rId.n9
      49        7006 :       >> rId.n10
      50        7006 :       >> rId.n11;
      51        3503 :     return r;
      52             : }
      53             : 
      54        1098 : SvStream& operator <<( SvStream& r, const ClsId& rId )
      55             : {
      56             :     return
      57        1098 :        r  << (sal_Int32) rId.n1
      58        2196 :           << (sal_Int16) rId.n2
      59        2196 :           << (sal_Int16) rId.n3
      60        2196 :           << (sal_uInt8) rId.n4
      61        2196 :           << (sal_uInt8) rId.n5
      62        2196 :           << (sal_uInt8) rId.n6
      63        2196 :           << (sal_uInt8) rId.n7
      64        2196 :           << (sal_uInt8) rId.n8
      65        2196 :           << (sal_uInt8) rId.n9
      66        2196 :           << (sal_uInt8) rId.n10
      67        2196 :           << (sal_uInt8) rId.n11;
      68             : }
      69             : 
      70             : ///////////////////////////// class StgHeader ////////////////////////////
      71             : 
      72        1209 : StgHeader::StgHeader()
      73             : : nVersion( 0 )
      74             : , nByteOrder( 0 )
      75             : , nPageSize( 0 )
      76             : , nDataPageSize( 0 )
      77             : , bDirty( 0 )
      78             : , nFATSize( 0 )
      79             : , nTOCstrm( 0 )
      80             : , nReserved( 0 )
      81             : , nThreshold( 0 )
      82             : , nDataFAT( 0 )
      83             : , nDataFATSize( 0 )
      84             : , nMasterChain( 0 )
      85        1209 : , nMaster( 0 )
      86             : {
      87        1209 :     memset( cSignature, 0, sizeof( cSignature ) );
      88        1209 :     memset( &aClsId, 0, sizeof( ClsId ) );
      89        1209 :     memset( cReserved, 0, sizeof( cReserved ) );
      90        1209 :     memset( nMasterFAT, 0, sizeof( nMasterFAT ) );
      91        1209 : }
      92             : 
      93          56 : void StgHeader::Init()
      94             : {
      95          56 :     memcpy( cSignature, cStgSignature, 8 );
      96          56 :     memset( &aClsId, 0, sizeof( ClsId ) );
      97          56 :     nVersion      = 0x0003003B;
      98          56 :     nByteOrder    = 0xFFFE;
      99          56 :     nPageSize     = 9;          // 512 bytes
     100          56 :     nDataPageSize = 6;          // 64 bytes
     101          56 :     bDirty = 0;
     102          56 :     memset( cReserved, 0, sizeof( cReserved ) );
     103          56 :     nFATSize = 0;
     104          56 :     nTOCstrm = 0;
     105          56 :     nReserved = 0;
     106          56 :     nThreshold    = 4096;
     107          56 :     nDataFAT = 0;
     108          56 :     nDataFATSize  = 0;
     109          56 :     nMasterChain  = STG_EOF;
     110             : 
     111          56 :     SetTOCStart( STG_EOF );
     112          56 :     SetDataFATStart( STG_EOF );
     113        6160 :     for( short i = 0; i < 109; i++ )
     114        6104 :         SetFATPage( i, STG_FREE );
     115          56 : }
     116             : 
     117         224 : sal_Bool StgHeader::Load( StgIo& rIo )
     118             : {
     119         224 :     sal_Bool bResult = sal_False;
     120         224 :     if ( rIo.GetStrm() )
     121             :     {
     122         224 :         SvStream& r = *rIo.GetStrm();
     123         224 :         bResult = Load( r );
     124         224 :         bResult = ( bResult && rIo.Good() );
     125             :     }
     126             : 
     127         224 :     return bResult;
     128             : }
     129             : 
     130        1153 : sal_Bool StgHeader::Load( SvStream& r )
     131             : {
     132        1153 :     r.Seek( 0L );
     133        1153 :     r.Read( cSignature, 8 );
     134        1153 :     r >> aClsId                     // 08 Class ID
     135        2306 :       >> nVersion                   // 1A version number
     136        2306 :       >> nByteOrder                 // 1C Unicode byte order indicator
     137        2306 :       >> nPageSize                  // 1E 1 << nPageSize = block size
     138        2306 :       >> nDataPageSize;             // 20 1 << this size == data block size
     139        1153 :     r.SeekRel( 10 );
     140        1153 :     r >> nFATSize                   // 2C total number of FAT pages
     141        2306 :       >> nTOCstrm                   // 30 starting page for the TOC stream
     142        2306 :       >> nReserved                  // 34
     143        2306 :       >> nThreshold                 // 38 minimum file size for big data
     144        2306 :       >> nDataFAT                   // 3C page # of 1st data FAT block
     145        2306 :       >> nDataFATSize               // 40 # of data FATpages
     146        2306 :       >> nMasterChain               // 44 chain to the next master block
     147        2306 :       >> nMaster;                   // 48 # of additional master blocks
     148      126830 :     for( short i = 0; i < 109; i++ )
     149      125677 :         r >> nMasterFAT[ i ];
     150             : 
     151        1153 :     return ( r.GetErrorCode() == ERRCODE_NONE && Check() );
     152             : }
     153             : 
     154         112 : sal_Bool StgHeader::Store( StgIo& rIo )
     155             : {
     156         112 :     if( !bDirty )
     157           0 :         return sal_True;
     158         112 :     SvStream& r = *rIo.GetStrm();
     159         112 :     r.Seek( 0L );
     160         112 :     r.Write( cSignature, 8 + 16 );
     161         112 :     r << nVersion                   // 1A version number
     162         224 :       << nByteOrder                 // 1C Unicode byte order indicator
     163         224 :       << nPageSize                  // 1E 1 << nPageSize = block size
     164         224 :       << nDataPageSize              // 20 1 << this size == data block size
     165         112 :       << (sal_Int32) 0 << (sal_Int32) 0 << (sal_Int16) 0
     166         224 :       << nFATSize                   // 2C total number of FAT pages
     167         224 :       << nTOCstrm                   // 30 starting page for the TOC stream
     168         224 :       << nReserved                  // 34
     169         224 :       << nThreshold                 // 38 minimum file size for big data
     170         224 :       << nDataFAT                   // 3C page # of 1st data FAT block
     171         224 :       << nDataFATSize               // 40 # of data FAT pages
     172         224 :       << nMasterChain               // 44 chain to the next master block
     173         224 :       << nMaster;                   // 48 # of additional master blocks
     174       12320 :     for( short i = 0; i < 109; i++ )
     175       12208 :         r << nMasterFAT[ i ];
     176         112 :     bDirty = !rIo.Good();
     177         112 :     return sal_Bool( !bDirty );
     178             : }
     179             : 
     180        2456 : static bool lcl_wontoverflow(short shift)
     181             : {
     182        2456 :     return shift >= 0 && shift < (short)sizeof(short) * 8 - 1;
     183             : }
     184             : 
     185        2474 : static bool isKnownSpecial(sal_Int32 nLocation)
     186             : {
     187             :     return (nLocation == STG_FREE ||
     188             :             nLocation == STG_EOF ||
     189             :             nLocation == STG_FAT ||
     190        2474 :             nLocation == STG_MASTER);
     191             : }
     192             : 
     193             : // Perform thorough checks also on unknown variables
     194        1765 : sal_Bool StgHeader::Check()
     195             : {
     196        1765 :     return sal_Bool( memcmp( cSignature, cStgSignature, 8 ) == 0
     197             :             && (short) ( nVersion >> 16 ) == 3 )
     198             :             && nPageSize == 9
     199        1228 :             && lcl_wontoverflow(nPageSize)
     200        1228 :             && lcl_wontoverflow(nDataPageSize)
     201             :             && nFATSize > 0
     202             :             && nTOCstrm >= 0
     203             :             && nThreshold > 0
     204        1228 :             && ( isKnownSpecial(nDataFAT) || ( nDataFAT >= 0 && nDataFATSize > 0 ) )
     205        1228 :             && ( isKnownSpecial(nMasterChain) || nMasterChain >=0 )
     206        6677 :             && nMaster >= 0;
     207             : }
     208             : 
     209       67338 : sal_Int32 StgHeader::GetFATPage( short n ) const
     210             : {
     211       67338 :     if( n >= 0 && n < 109 )
     212       67338 :         return nMasterFAT[ n ];
     213             :     else
     214           0 :         return STG_EOF;
     215             : }
     216             : 
     217        6168 : void StgHeader::SetFATPage( short n, sal_Int32 nb )
     218             : {
     219        6168 :     if( n >= 0 && n < 109 )
     220             :     {
     221        6168 :         if( nMasterFAT[ n ] != nb )
     222        6168 :             bDirty = sal_True, nMasterFAT[ n ] = nb;
     223             :     }
     224        6168 : }
     225             : 
     226         286 : void StgHeader::SetTOCStart( sal_Int32 n )
     227             : {
     228         286 :     if( n != nTOCstrm ) bDirty = sal_True, nTOCstrm = n;
     229         286 : }
     230             : 
     231         168 : void StgHeader::SetDataFATStart( sal_Int32 n )
     232             : {
     233         168 :     if( n != nDataFAT ) bDirty = sal_True, nDataFAT = n;
     234         168 : }
     235             : 
     236         112 : void StgHeader::SetDataFATSize( sal_Int32 n )
     237             : {
     238         112 :     if( n != nDataFATSize ) bDirty = sal_True, nDataFATSize = n;
     239         112 : }
     240             : 
     241          64 : void StgHeader::SetFATSize( sal_Int32 n )
     242             : {
     243          64 :     if( n != nFATSize ) bDirty = sal_True, nFATSize = n;
     244          64 : }
     245             : 
     246           0 : void StgHeader::SetFATChain( sal_Int32 n )
     247             : {
     248           0 :     if( n != nMasterChain )
     249           0 :         bDirty = sal_True, nMasterChain = n;
     250           0 : }
     251             : 
     252           0 : void StgHeader::SetMasters( sal_Int32 n )
     253             : {
     254           0 :     if( n != nMaster ) bDirty = sal_True, nMaster = n;
     255           0 : }
     256             : 
     257             : ///////////////////////////// class StgEntry /////////////////////////////
     258             : 
     259        6258 : sal_Bool StgEntry::Init()
     260             : {
     261        6258 :     memset( nName, 0, sizeof( nName ) );
     262        6258 :     nNameLen = 0;
     263        6258 :     cType = 0;
     264        6258 :     cFlags = 0;
     265        6258 :     nLeft = 0;
     266        6258 :     nRight = 0;
     267        6258 :     nChild = 0;
     268        6258 :     memset( &aClsId, 0, sizeof( aClsId ) );
     269        6258 :     nFlags = 0;
     270        6258 :     nMtime[0] = 0; nMtime[1] = 0;
     271        6258 :     nAtime[0] = 0; nAtime[1] = 0;
     272        6258 :     nPage1 = 0;
     273        6258 :     nSize = 0;
     274        6258 :     nUnknown = 0;
     275             : 
     276        6258 :     SetLeaf( STG_LEFT,  STG_FREE );
     277        6258 :     SetLeaf( STG_RIGHT, STG_FREE );
     278        6258 :     SetLeaf( STG_CHILD, STG_FREE );
     279        6258 :     SetLeaf( STG_DATA,  STG_EOF );
     280        6258 :     return sal_True;
     281             : }
     282             : 
     283        8444 : static String ToUpperUnicode( const String & rStr )
     284             : {
     285             :     // I don't know the locale, so en_US is hopefully fine
     286        8444 :     static CharClass aCC( LanguageTag( com::sun::star::lang::Locale( "en", "US", "" )) );
     287        8444 :     return aCC.uppercase( rStr );
     288             : }
     289             : 
     290        6140 : sal_Bool StgEntry::SetName( const String& rName )
     291             : {
     292             :     // I don't know the locale, so en_US is hopefully fine
     293        6140 :     aName = ToUpperUnicode( rName );
     294        6140 :     aName.Erase( nMaxLegalStr );
     295             : 
     296             :     int i;
     297       60700 :     for( i = 0; i < aName.Len() && i < 32; i++ )
     298       54560 :         nName[ i ] = rName.GetChar( sal_uInt16( i ));
     299      154200 :     while( i < 32 )
     300      141920 :         nName[ i++ ] = 0;
     301        6140 :     nNameLen = ( aName.Len() + 1 ) << 1;
     302        6140 :     return sal_True;
     303             : }
     304             : 
     305       10656 : sal_Int32 StgEntry::GetLeaf( StgEntryRef eRef ) const
     306             : {
     307       10656 :     sal_Int32 n = -1;
     308       10656 :     switch( eRef )
     309             :     {
     310        2304 :         case STG_LEFT:  n = nLeft;  break;
     311        2304 :         case STG_RIGHT: n = nRight; break;
     312        3368 :         case STG_CHILD: n = nChild; break;
     313        2680 :         case STG_DATA:  n = nPage1; break;
     314             :     }
     315       10656 :     return n;
     316             : }
     317             : 
     318       29276 : void StgEntry::SetLeaf( StgEntryRef eRef, sal_Int32 nPage )
     319             : {
     320       29276 :     switch( eRef )
     321             :     {
     322        7108 :         case STG_LEFT:  nLeft  = nPage; break;
     323        7108 :         case STG_RIGHT: nRight = nPage; break;
     324        7108 :         case STG_CHILD: nChild = nPage; break;
     325        7952 :         case STG_DATA:  nPage1 = nPage; break;
     326             :     }
     327       29276 : }
     328             : 
     329          62 : void StgEntry::SetClassId( const ClsId& r )
     330             : {
     331          62 :     memcpy( &aClsId, &r, sizeof( ClsId ) );
     332          62 : }
     333             : 
     334        2406 : void StgEntry::GetName( String& rName ) const
     335             : {
     336        2406 :     sal_uInt16 n = nNameLen;
     337        2406 :     if( n )
     338        2404 :         n = ( n >> 1 ) - 1;
     339        2406 :     rName = rtl::OUString(nName, n);
     340        2406 : }
     341             : 
     342             : // Compare two entries. Do this case-insensitive.
     343             : 
     344       54272 : short StgEntry::Compare( const StgEntry& r ) const
     345             : {
     346             :     /*
     347             :     short nRes = r.nNameLen - nNameLen;
     348             :     if( !nRes ) return strcmp( r.aName, aName );
     349             :     else return nRes;
     350             :     */
     351       54272 :     sal_Int32 nRes = r.nNameLen - nNameLen;
     352       54272 :     if( !nRes )
     353       21496 :         nRes = r.aName.CompareTo( aName );
     354       54272 :     return (short)nRes;
     355             :     //return aName.CompareTo( r.aName );
     356             : }
     357             : 
     358             : // These load/store operations are a bit more complicated,
     359             : // since they have to copy their contents into a packed structure.
     360             : 
     361        2310 : sal_Bool StgEntry::Load( const void* pFrom, sal_uInt32 nBufSize )
     362             : {
     363        2310 :     if ( nBufSize < 128 )
     364           0 :         return sal_False;
     365             : 
     366        2310 :     SvMemoryStream r( (sal_Char*) pFrom, nBufSize, STREAM_READ );
     367       76230 :     for( short i = 0; i < 32; i++ )
     368       73920 :         r >> nName[ i ];            // 00 name as WCHAR
     369        2310 :     r >> nNameLen                   // 40 size of name in bytes including 00H
     370        4620 :       >> cType                      // 42 entry type
     371        4620 :       >> cFlags                     // 43 0 or 1 (tree balance?)
     372        4620 :       >> nLeft                      // 44 left node entry
     373        4620 :       >> nRight                     // 48 right node entry
     374        4620 :       >> nChild                     // 4C 1st child entry if storage
     375        4620 :       >> aClsId                     // 50 class ID (optional)
     376        4620 :       >> nFlags                     // 60 state flags(?)
     377        4620 :       >> nMtime[ 0 ]                // 64 modification time
     378        4620 :       >> nMtime[ 1 ]                // 64 modification time
     379        4620 :       >> nAtime[ 0 ]                // 6C creation and access time
     380        4620 :       >> nAtime[ 1 ]                // 6C creation and access time
     381        4620 :       >> nPage1                     // 74 starting block (either direct or translated)
     382        4620 :       >> nSize                      // 78 file size
     383        4620 :       >> nUnknown;                  // 7C unknown
     384             : 
     385        2310 :     sal_uInt16 n = nNameLen;
     386        2310 :     if( n )
     387        2306 :         n = ( n >> 1 ) - 1;
     388             : 
     389        2310 :     if (n > nMaxLegalStr)
     390           4 :         return sal_False;
     391             : 
     392        2306 :     if ((cType != STG_STORAGE) && ((nSize < 0) || (nPage1 < 0 && !isKnownSpecial(nPage1))))
     393             :     {
     394             :         // the size makes no sense 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
     396           2 :         return sal_False;
     397             :     }
     398             : 
     399        2304 :     aName = rtl::OUString( nName, n );
     400             :     // I don't know the locale, so en_US is hopefully fine
     401        2304 :     aName = ToUpperUnicode( aName );
     402        2304 :     aName.Erase( nMaxLegalStr );
     403             : 
     404        2304 :     return sal_True;
     405             : }
     406             : 
     407        1088 : void StgEntry::Store( void* pTo )
     408             : {
     409        1088 :     SvMemoryStream r( (sal_Char *)pTo, 128, STREAM_WRITE );
     410       35904 :     for( short i = 0; i < 32; i++ )
     411       34816 :         r << nName[ i ];            // 00 name as WCHAR
     412        1088 :     r << nNameLen                   // 40 size of name in bytes including 00H
     413        2176 :       << cType                      // 42 entry type
     414        2176 :       << cFlags                     // 43 0 or 1 (tree balance?)
     415        2176 :       << nLeft                      // 44 left node entry
     416        2176 :       << nRight                     // 48 right node entry
     417        2176 :       << nChild                     // 4C 1st child entry if storage;
     418        2176 :       << aClsId                     // 50 class ID (optional)
     419        2176 :       << nFlags                     // 60 state flags(?)
     420        2176 :       << nMtime[ 0 ]                // 64 modification time
     421        2176 :       << nMtime[ 1 ]                // 64 modification time
     422        2176 :       << nAtime[ 0 ]                // 6C creation and access time
     423        2176 :       << nAtime[ 1 ]                // 6C creation and access time
     424        2176 :       << nPage1                     // 74 starting block (either direct or translated)
     425        2176 :       << nSize                      // 78 file size
     426        2176 :       << nUnknown;                  // 7C unknown
     427        1088 : }
     428             : 
     429             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10