Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * finddata.c
 * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
 *
 * Description:
 * Find the blocks that contain the data of MS Word files
 */

#include <stdio.h>
#include <stdlib.h>
#include "antiword.h"


/*
 * bAddDataBlocks - Add the blocks to the data block list
 *
 * Returns TRUE when successful, otherwise FALSE
 */
BOOL
bAddDataBlocks(ULONG ulDataPosFirst, ULONG ulTotalLength,
        ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen)
{
        data_block_type tDataBlock;
        ULONG   ulDataPos, ulOffset, ulIndex;
        long    lToGo;
        BOOL    bSuccess;

        fail(ulTotalLength > (ULONG)LONG_MAX);
        fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
        fail(aulBBD == NULL);

        NO_DBG_HEX(ulDataPosFirst);
        NO_DBG_DEC(ulTotalLength);

        lToGo = (long)ulTotalLength;

        ulDataPos = ulDataPosFirst;
        ulOffset = ulDataPosFirst;
        for (ulIndex = ulStartBlock;
             ulIndex != END_OF_CHAIN && lToGo > 0;
             ulIndex = aulBBD[ulIndex]) {
                if (ulIndex == UNUSED_BLOCK || ulIndex >= (ULONG)tBBDLen) {
                        DBG_DEC(ulIndex);
                        DBG_DEC(tBBDLen);
                        return FALSE;
                }
                if (ulOffset >= BIG_BLOCK_SIZE) {
                        ulOffset -= BIG_BLOCK_SIZE;
                        continue;
                }
                tDataBlock.ulFileOffset =
                        (ulIndex + 1) * BIG_BLOCK_SIZE + ulOffset;
                tDataBlock.ulDataPos = ulDataPos;
                tDataBlock.ulLength = min(BIG_BLOCK_SIZE - ulOffset,
                                                (ULONG)lToGo);
                fail(tDataBlock.ulLength > BIG_BLOCK_SIZE);
                ulOffset = 0;
                if (!bAdd2DataBlockList(&tDataBlock)) {
                        DBG_HEX(tDataBlock.ulFileOffset);
                        DBG_HEX(tDataBlock.ulDataPos);
                        DBG_DEC(tDataBlock.ulLength);
                        return FALSE;
                }
                ulDataPos += tDataBlock.ulLength;
                lToGo -= (long)tDataBlock.ulLength;
        }
        bSuccess = lToGo == 0 ||
                (ulTotalLength == (ULONG)LONG_MAX && ulIndex == END_OF_CHAIN);
        DBG_DEC_C(!bSuccess, lToGo);
        DBG_DEC_C(!bSuccess, ulTotalLength);
        DBG_DEC_C(!bSuccess, ulIndex);
        return bSuccess;
} /* end of bAddDataBlocks */

/*
 * bGet6DocumentData - make a list of the data blocks of Word 6/7 files
 *
 * Code for "fast saved" files.
 *
 * Returns TRUE when successful, otherwise FALSE
 */
BOOL
bGet6DocumentData(FILE *pFile, ULONG ulStartBlock,
        const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
{
        UCHAR   *aucBuffer;
        ULONG   ulBeginTextInfo, ulOffset, ulTotLength;
        size_t  tTextInfoLen;
        int     iIndex, iOff, iType, iLen, iPieces;

        DBG_MSG("bGet6DocumentData");

        fail(pFile == NULL);
        fail(aulBBD == NULL);
        fail(aucHeader == NULL);

        ulBeginTextInfo = ulGetLong(0x160, aucHeader);
        DBG_HEX(ulBeginTextInfo);
        tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader);
        DBG_DEC(tTextInfoLen);

        aucBuffer = xmalloc(tTextInfoLen);
        if (!bReadBuffer(pFile, ulStartBlock,
                        aulBBD, tBBDLen, BIG_BLOCK_SIZE,
                        aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
                aucBuffer = xfree(aucBuffer);
                return FALSE;
        }
        NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);

        iOff = 0;
        while (iOff < (int)tTextInfoLen) {
                iType = (int)ucGetByte(iOff, aucBuffer);
                iOff++;
                if (iType == 0) {
                        iOff++;
                        continue;
                }
                iLen = (int)usGetWord(iOff, aucBuffer);
                iOff += 2;
                if (iType == 1) {
                        iOff += iLen;
                        continue;
                }
                if (iType != 2) {
                        werr(0, "Unknown type of 'fastsaved' format");
                        aucBuffer = xfree(aucBuffer);
                        return FALSE;
                }
                /* Type 2 */
                NO_DBG_DEC(iLen);
                iOff += 2;
                iPieces = (iLen - 4) / 12;
                DBG_DEC(iPieces);
                for (iIndex = 0; iIndex < iPieces; iIndex++) {
                        ulOffset = ulGetLong(
                                iOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
                                aucBuffer);
                        ulTotLength = ulGetLong(iOff + (iIndex + 1) * 4,
                                                aucBuffer) -
                                        ulGetLong(iOff + iIndex * 4,
                                                aucBuffer);
                        if (!bAddDataBlocks(ulOffset, ulTotLength,
                                        ulStartBlock,
                                        aulBBD, tBBDLen)) {
                                aucBuffer = xfree(aucBuffer);
                                return FALSE;
                        }
                }
                break;
        }
        aucBuffer = xfree(aucBuffer);
        return TRUE;
} /* end of bGet6DocumentData */