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