1 /*
2 * finddata.c
3 * Copyright (C) 2000-2002 A.J. van Os; Released under GPL
4 *
5 * Description:
6 * Find the blocks that contain the data of MS Word files
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include "antiword.h"
12
13
14 /*
15 * bAddDataBlocks - Add the blocks to the data block list
16 *
17 * Returns TRUE when successful, otherwise FALSE
18 */
19 BOOL
bAddDataBlocks(ULONG ulDataPosFirst,ULONG ulTotalLength,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen)20 bAddDataBlocks(ULONG ulDataPosFirst, ULONG ulTotalLength,
21 ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen)
22 {
23 data_block_type tDataBlock;
24 ULONG ulDataPos, ulOffset, ulIndex;
25 long lToGo;
26 BOOL bSuccess;
27
28 fail(ulTotalLength > (ULONG)LONG_MAX);
29 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
30 fail(aulBBD == NULL);
31
32 NO_DBG_HEX(ulDataPosFirst);
33 NO_DBG_DEC(ulTotalLength);
34
35 lToGo = (long)ulTotalLength;
36
37 ulDataPos = ulDataPosFirst;
38 ulOffset = ulDataPosFirst;
39 for (ulIndex = ulStartBlock;
40 ulIndex != END_OF_CHAIN && lToGo > 0;
41 ulIndex = aulBBD[ulIndex]) {
42 if (ulIndex == UNUSED_BLOCK || ulIndex >= (ULONG)tBBDLen) {
43 DBG_DEC(ulIndex);
44 DBG_DEC(tBBDLen);
45 return FALSE;
46 }
47 if (ulOffset >= BIG_BLOCK_SIZE) {
48 ulOffset -= BIG_BLOCK_SIZE;
49 continue;
50 }
51 tDataBlock.ulFileOffset =
52 (ulIndex + 1) * BIG_BLOCK_SIZE + ulOffset;
53 tDataBlock.ulDataPos = ulDataPos;
54 tDataBlock.ulLength = min(BIG_BLOCK_SIZE - ulOffset,
55 (ULONG)lToGo);
56 fail(tDataBlock.ulLength > BIG_BLOCK_SIZE);
57 ulOffset = 0;
58 if (!bAdd2DataBlockList(&tDataBlock)) {
59 DBG_HEX(tDataBlock.ulFileOffset);
60 DBG_HEX(tDataBlock.ulDataPos);
61 DBG_DEC(tDataBlock.ulLength);
62 return FALSE;
63 }
64 ulDataPos += tDataBlock.ulLength;
65 lToGo -= (long)tDataBlock.ulLength;
66 }
67 bSuccess = lToGo == 0 ||
68 (ulTotalLength == (ULONG)LONG_MAX && ulIndex == END_OF_CHAIN);
69 DBG_DEC_C(!bSuccess, lToGo);
70 DBG_DEC_C(!bSuccess, ulTotalLength);
71 DBG_DEC_C(!bSuccess, ulIndex);
72 return bSuccess;
73 } /* end of bAddDataBlocks */
74
75 /*
76 * bGet6DocumentData - make a list of the data blocks of Word 6/7 files
77 *
78 * Code for "fast saved" files.
79 *
80 * Returns TRUE when successful, otherwise FALSE
81 */
82 BOOL
bGet6DocumentData(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)83 bGet6DocumentData(FILE *pFile, ULONG ulStartBlock,
84 const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
85 {
86 UCHAR *aucBuffer;
87 ULONG ulBeginTextInfo, ulOffset, ulTotLength;
88 size_t tTextInfoLen;
89 int iIndex, iOff, iType, iLen, iPieces;
90
91 DBG_MSG("bGet6DocumentData");
92
93 fail(pFile == NULL);
94 fail(aulBBD == NULL);
95 fail(aucHeader == NULL);
96
97 ulBeginTextInfo = ulGetLong(0x160, aucHeader);
98 DBG_HEX(ulBeginTextInfo);
99 tTextInfoLen = (size_t)ulGetLong(0x164, aucHeader);
100 DBG_DEC(tTextInfoLen);
101
102 aucBuffer = xmalloc(tTextInfoLen);
103 if (!bReadBuffer(pFile, ulStartBlock,
104 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
105 aucBuffer, ulBeginTextInfo, tTextInfoLen)) {
106 aucBuffer = xfree(aucBuffer);
107 return FALSE;
108 }
109 NO_DBG_PRINT_BLOCK(aucBuffer, tTextInfoLen);
110
111 iOff = 0;
112 while (iOff < (int)tTextInfoLen) {
113 iType = (int)ucGetByte(iOff, aucBuffer);
114 iOff++;
115 if (iType == 0) {
116 iOff++;
117 continue;
118 }
119 iLen = (int)usGetWord(iOff, aucBuffer);
120 iOff += 2;
121 if (iType == 1) {
122 iOff += iLen;
123 continue;
124 }
125 if (iType != 2) {
126 werr(0, "Unknown type of 'fastsaved' format");
127 aucBuffer = xfree(aucBuffer);
128 return FALSE;
129 }
130 /* Type 2 */
131 NO_DBG_DEC(iLen);
132 iOff += 2;
133 iPieces = (iLen - 4) / 12;
134 DBG_DEC(iPieces);
135 for (iIndex = 0; iIndex < iPieces; iIndex++) {
136 ulOffset = ulGetLong(
137 iOff + (iPieces + 1) * 4 + iIndex * 8 + 2,
138 aucBuffer);
139 ulTotLength = ulGetLong(iOff + (iIndex + 1) * 4,
140 aucBuffer) -
141 ulGetLong(iOff + iIndex * 4,
142 aucBuffer);
143 if (!bAddDataBlocks(ulOffset, ulTotLength,
144 ulStartBlock,
145 aulBBD, tBBDLen)) {
146 aucBuffer = xfree(aucBuffer);
147 return FALSE;
148 }
149 }
150 break;
151 }
152 aucBuffer = xfree(aucBuffer);
153 return TRUE;
154 } /* end of bGet6DocumentData */
155