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