LCOV - code coverage report
Current view: top level - sot/source/sdstor - stgelem.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 253 265 95.5 %
Date: 2015-06-13 12:38:46 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>
      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 const sal_uInt8 cStgSignature[ 8 ] = { 0xD0,0xCF,0x11,0xE0,0xA1,0xB1,0x1A,0xE1 };
      35             : 
      36             : ////////////////////////////// struct ClsId
      37             : 
      38       15524 : SvStream& ReadClsId( SvStream& r, ClsId& rId )
      39             : {
      40       15524 :     r.ReadUInt32( rId.Data1 )
      41       31048 :      .ReadUInt16( rId.Data2 )
      42       31048 :      .ReadUInt16( rId.Data3 )
      43       31048 :      .ReadUChar( rId.Data4[0] )
      44       31048 :      .ReadUChar( rId.Data4[1] )
      45       31048 :      .ReadUChar( rId.Data4[2] )
      46       31048 :      .ReadUChar( rId.Data4[3] )
      47       31048 :      .ReadUChar( rId.Data4[4] )
      48       31048 :      .ReadUChar( rId.Data4[5] )
      49       31048 :      .ReadUChar( rId.Data4[6] )
      50       31048 :      .ReadUChar( rId.Data4[7] );
      51       15524 :     return r;
      52             : }
      53             : 
      54        4233 : SvStream& WriteClsId( SvStream& r, const ClsId& rId )
      55             : {
      56             :     return
      57        4233 :        r .WriteUInt32( rId.Data1 )
      58        8466 :          .WriteUInt16( rId.Data2 )
      59        8466 :          .WriteUInt16( rId.Data3 )
      60        8466 :          .WriteUChar( rId.Data4[0] )
      61        8466 :          .WriteUChar( rId.Data4[1] )
      62        8466 :          .WriteUChar( rId.Data4[2] )
      63        8466 :          .WriteUChar( rId.Data4[3] )
      64        8466 :          .WriteUChar( rId.Data4[4] )
      65        8466 :          .WriteUChar( rId.Data4[5] )
      66        8466 :          .WriteUChar( rId.Data4[6] )
      67        8466 :          .WriteUChar( rId.Data4[7] );
      68             : }
      69             : 
      70             : ///////////////////////////// class StgHeader
      71             : 
      72        9881 : StgHeader::StgHeader()
      73             : : nVersion( 0 )
      74             : , nByteOrder( 0 )
      75             : , nPageSize( 0 )
      76             : , nDataPageSize( 0 )
      77             : , bDirty( sal_uInt8(false) )
      78             : , nFATSize( 0 )
      79             : , nTOCstrm( 0 )
      80             : , nReserved( 0 )
      81             : , nThreshold( 0 )
      82             : , nDataFAT( 0 )
      83             : , nDataFATSize( 0 )
      84             : , nMasterChain( 0 )
      85        9881 : , nMaster( 0 )
      86             : {
      87        9881 :     memset( cSignature, 0, sizeof( cSignature ) );
      88        9881 :     memset( &aClsId, 0, sizeof( ClsId ) );
      89        9881 :     memset( cReserved, 0, sizeof( cReserved ) );
      90        9881 :     memset( nMasterFAT, 0, sizeof( nMasterFAT ) );
      91        9881 : }
      92             : 
      93         214 : void StgHeader::Init()
      94             : {
      95         214 :     memcpy( cSignature, cStgSignature, 8 );
      96         214 :     memset( &aClsId, 0, sizeof( ClsId ) );
      97         214 :     nVersion      = 0x0003003B;
      98         214 :     nByteOrder    = 0xFFFE;
      99         214 :     nPageSize     = 9;          // 512 bytes
     100         214 :     nDataPageSize = 6;          // 64 bytes
     101         214 :     bDirty = sal_uInt8(false);
     102         214 :     memset( cReserved, 0, sizeof( cReserved ) );
     103         214 :     nFATSize = 0;
     104         214 :     nTOCstrm = 0;
     105         214 :     nReserved = 0;
     106         214 :     nThreshold    = 4096;
     107         214 :     nDataFAT = 0;
     108         214 :     nDataFATSize  = 0;
     109         214 :     nMasterChain  = STG_EOF;
     110             : 
     111         214 :     SetTOCStart( STG_EOF );
     112         214 :     SetDataFATStart( STG_EOF );
     113       23540 :     for( short i = 0; i < cFATPagesInHeader; i++ )
     114       23326 :         SetFATPage( i, STG_FREE );
     115         214 : }
     116             : 
     117        3329 : bool StgHeader::Load( StgIo& rIo )
     118             : {
     119        3329 :     bool bResult = false;
     120        3329 :     if ( rIo.GetStrm() )
     121             :     {
     122        3329 :         SvStream& r = *rIo.GetStrm();
     123        3329 :         bResult = Load( r );
     124        3329 :         bResult = ( bResult && rIo.Good() );
     125             :     }
     126             : 
     127        3329 :     return bResult;
     128             : }
     129             : 
     130        9646 : bool StgHeader::Load( SvStream& r )
     131             : {
     132        9646 :     r.Seek( 0L );
     133        9646 :     r.Read( cSignature, 8 );
     134        9646 :     ReadClsId( r, aClsId );         // 08 Class ID
     135        9646 :     r.ReadInt32( nVersion )                   // 1A version number
     136       19292 :      .ReadUInt16( nByteOrder )                 // 1C Unicode byte order indicator
     137       19292 :      .ReadInt16( nPageSize )                  // 1E 1 << nPageSize = block size
     138       19292 :      .ReadInt16( nDataPageSize );             // 20 1 << this size == data block size
     139        9646 :     r.SeekRel( 10 );
     140        9646 :     r.ReadInt32( nFATSize )                   // 2C total number of FAT pages
     141       19292 :      .ReadInt32( nTOCstrm )                   // 30 starting page for the TOC stream
     142       19292 :      .ReadInt32( nReserved )                  // 34
     143       19292 :      .ReadInt32( nThreshold )                 // 38 minimum file size for big data
     144       19292 :      .ReadInt32( nDataFAT )                   // 3C page # of 1st data FAT block
     145       19292 :      .ReadInt32( nDataFATSize )               // 40 # of data FATpages
     146       19292 :      .ReadInt32( nMasterChain )               // 44 chain to the next master block
     147       19292 :      .ReadInt32( nMaster );                   // 48 # of additional master blocks
     148     1061060 :     for( short i = 0; i < cFATPagesInHeader; i++ )
     149     1051414 :         r.ReadInt32( nMasterFAT[ i ] );
     150             : 
     151        9646 :     return (r.GetErrorCode() == ERRCODE_NONE) && Check();
     152             : }
     153             : 
     154         436 : bool StgHeader::Store( StgIo& rIo )
     155             : {
     156         436 :     if( !bDirty )
     157           0 :         return true;
     158             : 
     159         436 :     SvStream& r = *rIo.GetStrm();
     160         436 :     r.Seek( 0L );
     161         436 :     r.Write( cSignature, 8 );
     162         436 :     WriteClsId( r, aClsId );                   // 08 Class ID
     163         436 :     r.WriteInt32( nVersion )                   // 1A version number
     164         872 :      .WriteUInt16( nByteOrder )                 // 1C Unicode byte order indicator
     165         872 :      .WriteInt16( nPageSize )                  // 1E 1 << nPageSize = block size
     166         872 :      .WriteInt16( nDataPageSize )              // 20 1 << this size == data block size
     167         436 :      .WriteInt32( 0 ).WriteInt32( 0 ).WriteInt16( 0 )
     168         872 :      .WriteInt32( nFATSize )                   // 2C total number of FAT pages
     169         872 :      .WriteInt32( nTOCstrm )                   // 30 starting page for the TOC stream
     170         872 :      .WriteInt32( nReserved )                  // 34
     171         872 :      .WriteInt32( nThreshold )                 // 38 minimum file size for big data
     172         872 :      .WriteInt32( nDataFAT )                   // 3C page # of 1st data FAT block
     173         872 :      .WriteInt32( nDataFATSize )               // 40 # of data FAT pages
     174         872 :      .WriteInt32( nMasterChain )               // 44 chain to the next master block
     175         872 :      .WriteInt32( nMaster );                   // 48 # of additional master blocks
     176       47960 :     for( short i = 0; i < cFATPagesInHeader; i++ )
     177       47524 :         r.WriteInt32( nMasterFAT[ i ] );
     178         436 :     bDirty = sal_uInt8(!rIo.Good());
     179         436 :     return !bDirty;
     180             : }
     181             : 
     182        4420 : static bool lcl_wontoverflow(short shift)
     183             : {
     184        4420 :     return shift >= 0 && shift < (short)sizeof(short) * 8 - 1;
     185             : }
     186             : 
     187        4529 : static bool isKnownSpecial(sal_Int32 nLocation)
     188             : {
     189        4527 :     return (nLocation == STG_FREE ||
     190        1980 :             nLocation == STG_EOF ||
     191        6509 :             nLocation == STG_FAT ||
     192        4529 :             nLocation == STG_MASTER);
     193             : }
     194             : 
     195             : // Perform thorough checks also on unknown variables
     196       10749 : bool StgHeader::Check()
     197             : {
     198       10749 :     return  memcmp( cSignature, cStgSignature, 8 ) == 0
     199        2210 :             && (short) ( nVersion >> 16 ) == 3
     200        2210 :             && nPageSize == 9
     201        2210 :             && lcl_wontoverflow(nPageSize)
     202        2210 :             && lcl_wontoverflow(nDataPageSize)
     203        2210 :             && nFATSize > 0
     204        2210 :             && nTOCstrm >= 0
     205        2210 :             && nThreshold > 0
     206        2210 :             && ( isKnownSpecial(nDataFAT) || ( nDataFAT >= 0 && nDataFATSize > 0 ) )
     207        2210 :             && ( isKnownSpecial(nMasterChain) || nMasterChain >=0 )
     208       12959 :             && nMaster >= 0;
     209             : }
     210             : 
     211      149996 : sal_Int32 StgHeader::GetFATPage( short n ) const
     212             : {
     213      149996 :     if( n >= 0 && n < cFATPagesInHeader )
     214      149996 :         return nMasterFAT[ n ];
     215             :     else
     216           0 :         return STG_EOF;
     217             : }
     218             : 
     219       23573 : void StgHeader::SetFATPage( short n, sal_Int32 nb )
     220             : {
     221       23573 :     if( n >= 0 && n < cFATPagesInHeader )
     222             :     {
     223       23573 :         if( nMasterFAT[ n ] != nb )
     224       23573 :             bDirty = sal_uInt8(true), nMasterFAT[ n ] = nb;
     225             :     }
     226       23573 : }
     227             : 
     228        1090 : void StgHeader::SetTOCStart( sal_Int32 n )
     229             : {
     230        1090 :     if( n != nTOCstrm ) bDirty = sal_uInt8(true), nTOCstrm = n;
     231        1090 : }
     232             : 
     233         650 : void StgHeader::SetDataFATStart( sal_Int32 n )
     234             : {
     235         650 :     if( n != nDataFAT ) bDirty = sal_uInt8(true), nDataFAT = n;
     236         650 : }
     237             : 
     238         436 : void StgHeader::SetDataFATSize( sal_Int32 n )
     239             : {
     240         436 :     if( n != nDataFATSize ) bDirty = sal_uInt8(true), nDataFATSize = n;
     241         436 : }
     242             : 
     243         235 : void StgHeader::SetFATSize( sal_Int32 n )
     244             : {
     245         235 :     if( n != nFATSize ) bDirty = sal_uInt8(true), nFATSize = n;
     246         235 : }
     247             : 
     248           0 : void StgHeader::SetFATChain( sal_Int32 n )
     249             : {
     250           0 :     if( n != nMasterChain )
     251           0 :         bDirty = sal_uInt8(true), nMasterChain = n;
     252           0 : }
     253             : 
     254           0 : void StgHeader::SetMasters( sal_Int32 n )
     255             : {
     256           0 :     if( n != nMaster ) bDirty = sal_uInt8(true), nMaster = n;
     257           0 : }
     258             : 
     259             : ///////////////////////////// class StgEntry
     260             : 
     261       18146 : bool StgEntry::Init()
     262             : {
     263       18146 :     memset( nName, 0, sizeof( nName ) );
     264       18146 :     nNameLen = 0;
     265       18146 :     cType = 0;
     266       18146 :     cFlags = 0;
     267       18146 :     nLeft = 0;
     268       18146 :     nRight = 0;
     269       18146 :     nChild = 0;
     270       18146 :     memset( &aClsId, 0, sizeof( aClsId ) );
     271       18146 :     nFlags = 0;
     272       18146 :     nMtime[0] = 0; nMtime[1] = 0;
     273       18146 :     nAtime[0] = 0; nAtime[1] = 0;
     274       18146 :     nPage1 = 0;
     275       18146 :     nSize = 0;
     276       18146 :     nUnknown = 0;
     277             : 
     278       18146 :     SetLeaf( STG_LEFT,  STG_FREE );
     279       18146 :     SetLeaf( STG_RIGHT, STG_FREE );
     280       18146 :     SetLeaf( STG_CHILD, STG_FREE );
     281       18146 :     SetLeaf( STG_DATA,  STG_EOF );
     282       18146 :     return true;
     283             : }
     284             : 
     285       23581 : static OUString ToUpperUnicode( const OUString & rStr )
     286             : {
     287             :     // I don't know the locale, so en_US is hopefully fine
     288       23581 :     static CharClass aCC( LanguageTag( com::sun::star::lang::Locale( "en", "US", "" )) );
     289       23581 :     return aCC.uppercase( rStr );
     290             : }
     291             : 
     292       17706 : bool StgEntry::SetName( const OUString& rName )
     293             : {
     294             :     // I don't know the locale, so en_US is hopefully fine
     295       17706 :     aName = ToUpperUnicode( rName );
     296       17706 :     if(aName.getLength() > nMaxLegalStr)
     297             :     {
     298           0 :         aName = aName.copy(0, nMaxLegalStr);
     299             :     }
     300             : 
     301             :     sal_uInt16 i;
     302      166829 :     for( i = 0; i < rName.getLength() && i <= nMaxLegalStr; i++ )
     303             :     {
     304      149123 :         nName[ i ] = rName[ i ];
     305             :     }
     306      452881 :     while (i <= nMaxLegalStr)
     307             :     {
     308      417469 :         nName[ i++ ] = 0;
     309             :     }
     310       17706 :     nNameLen = ( rName.getLength() + 1 ) << 1;
     311       17706 :     return true;
     312             : }
     313             : 
     314       27105 : sal_Int32 StgEntry::GetLeaf( StgEntryRef eRef ) const
     315             : {
     316       27105 :     sal_Int32 n = -1;
     317       27105 :     switch( eRef )
     318             :     {
     319        5875 :     case STG_LEFT:  n = nLeft;  break;
     320        5875 :     case STG_RIGHT: n = nRight; break;
     321        8421 :     case STG_CHILD: n = nChild; break;
     322        6934 :     case STG_DATA:  n = nPage1; break;
     323             :     }
     324       27105 :     return n;
     325             : }
     326             : 
     327       86336 : void StgEntry::SetLeaf( StgEntryRef eRef, sal_Int32 nPage )
     328             : {
     329       86336 :     switch( eRef )
     330             :     {
     331       20903 :     case STG_LEFT:  nLeft  = nPage; break;
     332       20903 :     case STG_RIGHT: nRight = nPage; break;
     333       20903 :     case STG_CHILD: nChild = nPage; break;
     334       23627 :     case STG_DATA:  nPage1 = nPage; break;
     335             :     }
     336       86336 : }
     337             : 
     338         202 : void StgEntry::SetClassId( const ClsId& r )
     339             : {
     340         202 :     memcpy( &aClsId, &r, sizeof( ClsId ) );
     341         202 : }
     342             : 
     343        5903 : void StgEntry::GetName( OUString& rName ) const
     344             : {
     345        5903 :     sal_uInt16 n = nNameLen;
     346        5903 :     if( n )
     347        5902 :         n = ( n >> 1 ) - 1;
     348        5903 :     rName = OUString(nName, n);
     349        5903 : }
     350             : 
     351             : // Compare two entries. Do this case-insensitive.
     352             : 
     353      121678 : sal_Int32 StgEntry::Compare( const StgEntry& r ) const
     354             : {
     355      121678 :     if (r.nNameLen != nNameLen)
     356       80073 :         return r.nNameLen > nNameLen ? 1 : -1;
     357             :     else
     358       41605 :         return r.aName.compareTo(aName);
     359             : }
     360             : 
     361             : // These load/store operations are a bit more complicated,
     362             : // since they have to copy their contents into a packed structure.
     363             : 
     364        5878 : bool StgEntry::Load( const void* pFrom, sal_uInt32 nBufSize )
     365             : {
     366        5878 :     if ( nBufSize < 128 )
     367           0 :         return false;
     368             : 
     369        5878 :     SvMemoryStream r( const_cast<void *>(pFrom), nBufSize, StreamMode::READ );
     370      193974 :     for( short i = 0; i < 32; i++ )
     371      188096 :         r.ReadUInt16( nName[ i ] );            // 00 name as WCHAR
     372        5878 :     r.ReadUInt16( nNameLen )                   // 40 size of name in bytes including 00H
     373       11756 :      .ReadUChar( cType )                      // 42 entry type
     374       11756 :      .ReadUChar( cFlags )                     // 43 0 or 1 (tree balance?)
     375       11756 :      .ReadInt32( nLeft )                      // 44 left node entry
     376       11756 :      .ReadInt32( nRight )                     // 48 right node entry
     377       11756 :      .ReadInt32( nChild );                    // 4C 1st child entry if storage
     378        5878 :     ReadClsId( r, aClsId );         // 50 class ID (optional)
     379        5878 :     r.ReadInt32( nFlags )                     // 60 state flags(?)
     380       11756 :      .ReadInt32( nMtime[ 0 ] )                // 64 modification time
     381       11756 :      .ReadInt32( nMtime[ 1 ] )                // 64 modification time
     382       11756 :      .ReadInt32( nAtime[ 0 ] )                // 6C creation and access time
     383       11756 :      .ReadInt32( nAtime[ 1 ] )                // 6C creation and access time
     384       11756 :      .ReadInt32( nPage1 )                     // 74 starting block (either direct or translated)
     385       11756 :      .ReadInt32( nSize )                      // 78 file size
     386       11756 :      .ReadInt32( nUnknown );                  // 7C unknown
     387             : 
     388        5878 :     sal_uInt16 n = nNameLen;
     389        5878 :     if( n )
     390        5876 :         n = ( n >> 1 ) - 1;
     391             : 
     392        5878 :     if (n > nMaxLegalStr)
     393           2 :         return false;
     394             : 
     395        5876 :     if ((cType != STG_STORAGE) && ((nSize < 0) || (nPage1 < 0 && !isKnownSpecial(nPage1))))
     396             :     {
     397             :         // the size makes no sense for the substorage
     398             :         // TODO/LATER: actually the size should be an unsigned value, but in this case it would mean a stream of more than 2Gb
     399           1 :         return false;
     400             :     }
     401             : 
     402        5875 :     aName = OUString(nName , n);
     403             :     // I don't know the locale, so en_US is hopefully fine
     404        5875 :     aName = ToUpperUnicode( aName );
     405        5875 :     if(aName.getLength() > nMaxLegalStr)
     406             :     {
     407           0 :         aName = aName.copy(0, nMaxLegalStr);
     408             :     }
     409             : 
     410        5875 :     return true;
     411             : }
     412             : 
     413        3744 : void StgEntry::Store( void* pTo )
     414             : {
     415        3744 :     SvMemoryStream r( pTo, 128, StreamMode::WRITE );
     416      123552 :     for( short i = 0; i < 32; i++ )
     417      119808 :         r.WriteUInt16( nName[ i ] );            // 00 name as WCHAR
     418        3744 :     r.WriteUInt16( nNameLen )                   // 40 size of name in bytes including 00H
     419        7488 :      .WriteUChar( cType )                      // 42 entry type
     420        7488 :      .WriteUChar( cFlags )                     // 43 0 or 1 (tree balance?)
     421        7488 :      .WriteInt32( nLeft )                      // 44 left node entry
     422        7488 :      .WriteInt32( nRight )                     // 48 right node entry
     423        7488 :      .WriteInt32( nChild );                    // 4C 1st child entry if storage;
     424        3744 :     WriteClsId( r, aClsId );                   // 50 class ID (optional)
     425        3744 :     r.WriteInt32( nFlags )                     // 60 state flags(?)
     426        7488 :      .WriteInt32( nMtime[ 0 ] )                // 64 modification time
     427        7488 :      .WriteInt32( nMtime[ 1 ] )                // 64 modification time
     428        7488 :      .WriteInt32( nAtime[ 0 ] )                // 6C creation and access time
     429        7488 :      .WriteInt32( nAtime[ 1 ] )                // 6C creation and access time
     430        7488 :      .WriteInt32( nPage1 )                     // 74 starting block (either direct or translated)
     431        7488 :      .WriteInt32( nSize )                      // 78 file size
     432        7488 :      .WriteInt32( nUnknown );                  // 7C unknown
     433        3744 : }
     434             : 
     435             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11