xref: /plan9/sys/src/cmd/aux/antiword/notes.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1 /*
2  * notes.c
3  * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
4  *
5  * Description:
6  * Functions to tell the difference between footnotes and endnotes
7  */
8 
9 #include "antiword.h"
10 
11 /*
12  * Private structures to hide the way the information
13  * is stored from the rest of the program
14  */
15 typedef struct footnote_local_tag {
16         footnote_block_type	tInfo;
17         ULONG			ulCharPosStart;
18         ULONG			ulCharPosNext;
19         BOOL			bUseful;
20 } footnote_local_type;
21 
22 /* Variables needed to write the Footnote and Endnote information */
23 static ULONG	*aulFootnoteList = NULL;
24 static size_t	tFootnoteListLength = 0;
25 static ULONG	*aulEndnoteList = NULL;
26 static size_t	tEndnoteListLength = 0;
27 /* Variables needed to write the Footnote Text */
28 static footnote_local_type	*pFootnoteText = NULL;
29 static size_t			tFootnoteTextLength = 0;
30 
31 
32 /*
33  * Destroy the lists with footnote and endnote information
34  */
35 void
vDestroyNotesInfoLists(void)36 vDestroyNotesInfoLists(void)
37 {
38 	footnote_local_type	*pRecord;
39 	size_t			tFootnote;
40 
41 	TRACE_MSG("vDestroyNotesInfoLists");
42 
43 	/* Free the lists and reset all control variables */
44 	aulEndnoteList = xfree(aulEndnoteList);
45 	aulFootnoteList = xfree(aulFootnoteList);
46 	tEndnoteListLength = 0;
47 	tFootnoteListLength = 0;
48 	for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
49 		pRecord = pFootnoteText + tFootnote;
50 		pRecord->tInfo.szText = xfree(pRecord->tInfo.szText);
51 	}
52 	pFootnoteText = xfree(pFootnoteText);
53 	tFootnoteTextLength = 0;
54 } /* end of vDestroyNotesInfoLists */
55 
56 /*
57  * Build the list with footnote information for Word for DOS files
58  */
59 static void
vGet0FootnotesInfoAndText(FILE * pFile,const UCHAR * aucHeader)60 vGet0FootnotesInfoAndText(FILE *pFile, const UCHAR *aucHeader)
61 {
62 	footnote_local_type	*pCurr;
63 	UCHAR	*aucBuffer;
64 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
65 	ULONG	ulCharPos, ulBeginNextBlock;
66 	size_t	tFootnotes, tFootnoteInfoLen;
67 	size_t	tIndex;
68 	UCHAR   aucTmp[2];
69 
70 	TRACE_MSG("vGet0FootnotesInfoAndText");
71 
72 	fail(pFile == NULL || aucHeader == NULL);
73 
74 	ulBeginOfText = 128;
75 	NO_DBG_HEX(ulBeginOfText);
76 	ulBeginFootnoteInfo =  128 * (ULONG)usGetWord(0x14, aucHeader);
77 	DBG_HEX(ulBeginFootnoteInfo);
78 	ulBeginNextBlock = 128 * (ULONG)usGetWord(0x16, aucHeader);
79 	DBG_HEX(ulBeginNextBlock);
80 
81 	if (ulBeginFootnoteInfo == ulBeginNextBlock) {
82 		DBG_MSG("No Footnotes in this document");
83 		return;
84 	}
85 
86 	/* Read the the number of footnotes + 1 */
87 	if (!bReadBytes(aucTmp, 2, ulBeginFootnoteInfo, pFile)) {
88 		return;
89 	}
90 	tFootnotes = (size_t)usGetWord(0, aucTmp);
91 	if (tFootnotes < 2) {
92 		DBG_MSG("No Footnotes in this document (2)");
93 	}
94 	DBG_DEC(tFootnotes);
95 	tFootnoteInfoLen =  8 * tFootnotes;
96 
97 	aucBuffer = xmalloc(tFootnoteInfoLen);
98 	if (!bReadBytes(aucBuffer,
99 			tFootnoteInfoLen, ulBeginFootnoteInfo + 4, pFile)) {
100 		aucBuffer = xfree(aucBuffer);
101 		return;
102 	}
103 	DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
104 
105 	/* Get footnote information */
106 	fail(tFootnoteListLength != 0);
107 	tFootnoteListLength = tFootnotes - 1;
108 	fail(tFootnoteListLength == 0);
109 
110 	fail(aulFootnoteList != NULL);
111 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
112 
113 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
114 		ulOffset = ulGetLong(tIndex * 8, aucBuffer);
115 		DBG_HEX(ulOffset);
116 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
117 		DBG_HEX(ulFileOffset);
118 		aulFootnoteList[tIndex] = ulFileOffset;
119 	}
120 
121 	/* Get footnote text */
122 	fail(tFootnoteTextLength != 0);
123 	tFootnoteTextLength = tFootnotes - 1;
124 	fail(tFootnoteTextLength == 0);
125 
126 	fail(pFootnoteText != NULL);
127 	pFootnoteText = xcalloc(tFootnoteTextLength,
128 				sizeof(footnote_local_type));
129 
130 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
131 		pCurr = pFootnoteText + tIndex;
132 		pCurr->tInfo.szText = NULL;
133 		ulOffset = ulGetLong(tIndex * 8 + 4, aucBuffer);
134 		DBG_HEX(ulOffset);
135 		ulCharPos = ulBeginOfText + ulOffset;
136 		DBG_HEX(ulCharPos);
137 		DBG_HEX(ulCharPos2FileOffset(ulCharPos));
138 		pCurr->ulCharPosStart = ulCharPos;
139 		ulOffset = ulGetLong((tIndex + 1) * 8 + 4, aucBuffer);
140 		DBG_HEX(ulOffset);
141 		ulCharPos = ulBeginOfText + ulOffset;
142 		DBG_HEX(ulCharPos);
143 		DBG_HEX(ulCharPos2FileOffset(ulCharPos));
144 		pCurr->ulCharPosNext = ulCharPos;
145 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
146 	}
147 	aucBuffer = xfree(aucBuffer);
148 } /* end of vGet0FootnotesInfoAndText */
149 
150 /*
151  * Build the lists note information for Word for DOS files
152  */
153 static void
vGet0NotesInfo(FILE * pFile,const UCHAR * aucHeader)154 vGet0NotesInfo(FILE *pFile, const UCHAR *aucHeader)
155 {
156 	TRACE_MSG("vGet0NotesInfo");
157 
158 	vGet0FootnotesInfoAndText(pFile, aucHeader);
159 	/* There are no endnotes in a Word for DOS file */
160 } /* end of vGet0NotesInfo */
161 
162 /*
163  * Build the list with footnote information for WinWord 1/2 files
164  */
165 static void
vGet2FootnotesInfo(FILE * pFile,const UCHAR * aucHeader)166 vGet2FootnotesInfo(FILE *pFile, const UCHAR *aucHeader)
167 {
168 	UCHAR	*aucBuffer;
169 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
170 	size_t	tFootnoteInfoLen;
171 	size_t	tIndex;
172 
173 	TRACE_MSG("vGet2FootnotesInfo");
174 
175 	fail(pFile == NULL || aucHeader == NULL);
176 
177 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
178 	NO_DBG_HEX(ulBeginOfText);
179 	ulBeginFootnoteInfo = ulGetLong(0x64, aucHeader); /* fcPlcffndRef */
180 	NO_DBG_HEX(ulBeginFootnoteInfo);
181 	tFootnoteInfoLen = (size_t)usGetWord(0x68, aucHeader); /* cbPlcffndRef */
182 	NO_DBG_DEC(tFootnoteInfoLen);
183 
184 	if (tFootnoteInfoLen < 10) {
185 		DBG_MSG("No Footnotes in this document");
186 		return;
187 	}
188 
189 	aucBuffer = xmalloc(tFootnoteInfoLen);
190 	if (!bReadBytes(aucBuffer,
191 			tFootnoteInfoLen, ulBeginFootnoteInfo, pFile)) {
192 		aucBuffer = xfree(aucBuffer);
193 		return;
194 	}
195 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
196 
197 	fail(tFootnoteListLength != 0);
198 	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
199 	fail(tFootnoteListLength == 0);
200 
201 	fail(aulFootnoteList != NULL);
202 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
203 
204 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
205 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
206 		NO_DBG_HEX(ulOffset);
207 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
208 		NO_DBG_HEX(ulFileOffset);
209 		aulFootnoteList[tIndex] = ulFileOffset;
210 	}
211 	aucBuffer = xfree(aucBuffer);
212 } /* end of vGet2FootnotesInfo */
213 
214 /*
215  * Build the list with footnote text information for WinWord 1/2 files
216  */
217 static void
vGet2FootnotesText(FILE * pFile,const UCHAR * aucHeader)218 vGet2FootnotesText(FILE *pFile, const UCHAR *aucHeader)
219 {
220 	footnote_local_type	*pCurr;
221 	UCHAR	*aucBuffer;
222 	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
223 	size_t	tFootnoteTextLen;
224 	size_t	tIndex;
225 
226 	TRACE_MSG("vGet2FootnotesText");
227 
228 	fail(pFile == NULL || aucHeader == NULL);
229 
230 	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
231 	ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
232 	NO_DBG_HEX(ulBeginOfFootnotes);
233 
234 	ulBeginFootnoteText = ulGetLong(0x6a, aucHeader); /* fcPlcffndTxt */
235 	NO_DBG_HEX(ulBeginFootnoteText);
236 	tFootnoteTextLen =
237 		(size_t)usGetWord(0x6e, aucHeader); /* cbPlcffndTxt */
238 	NO_DBG_DEC(tFootnoteTextLen);
239 
240 	if (tFootnoteTextLen < 12) {
241 		DBG_MSG("No Footnote text in this document");
242 		return;
243 	}
244 
245 	aucBuffer = xmalloc(tFootnoteTextLen);
246 	if (!bReadBytes(aucBuffer,
247 			tFootnoteTextLen, ulBeginFootnoteText, pFile)) {
248 		aucBuffer = xfree(aucBuffer);
249 		return;
250 	}
251 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
252 
253 	fail(tFootnoteTextLength != 0);
254 	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
255 	fail(tFootnoteTextLength == 0);
256 
257 	fail(pFootnoteText != NULL);
258 	pFootnoteText = xcalloc(tFootnoteTextLength,
259 				sizeof(footnote_local_type));
260 
261 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
262 		pCurr = pFootnoteText + tIndex;
263 		pCurr->tInfo.szText = NULL;
264 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
265 		NO_DBG_HEX(ulOffset);
266 		ulCharPos = ulBeginOfFootnotes + ulOffset;
267 		NO_DBG_HEX(ulCharPos);
268 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
269 		pCurr->ulCharPosStart = ulCharPos;
270 		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
271 		NO_DBG_HEX(ulOffset);
272 		ulCharPos = ulBeginOfFootnotes + ulOffset;
273 		NO_DBG_HEX(ulCharPos);
274 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
275 		pCurr->ulCharPosNext = ulCharPos;
276 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
277 	}
278 	aucBuffer = xfree(aucBuffer);
279 } /* end of vGet2FootnotesText */
280 
281 /*
282  * Build the lists note information for WinWord 1/2 files
283  */
284 static void
vGet2NotesInfo(FILE * pFile,const UCHAR * aucHeader)285 vGet2NotesInfo(FILE *pFile, const UCHAR *aucHeader)
286 {
287 	TRACE_MSG("vGet2NotesInfo");
288 
289 	vGet2FootnotesInfo(pFile, aucHeader);
290 	vGet2FootnotesText(pFile, aucHeader);
291 	/* There are no endnotes in a WinWord 1/2 file */
292 } /* end of vGet2NotesInfo */
293 
294 /*
295  * Build the list with footnote information for Word 6/7 files
296  */
297 static void
vGet6FootnotesInfo(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)298 vGet6FootnotesInfo(FILE *pFile, ULONG ulStartBlock,
299 	const ULONG *aulBBD, size_t tBBDLen,
300 	const UCHAR *aucHeader)
301 {
302 	UCHAR	*aucBuffer;
303 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
304 	size_t	tFootnoteInfoLen;
305 	size_t	tIndex;
306 
307 	TRACE_MSG("vGet6FootnotesInfo");
308 
309 	fail(pFile == NULL || aucHeader == NULL);
310 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
311 	fail(aulBBD == NULL);
312 
313 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
314 	NO_DBG_HEX(ulBeginOfText);
315 	ulBeginFootnoteInfo = ulGetLong(0x68, aucHeader); /* fcPlcffndRef */
316 	NO_DBG_HEX(ulBeginFootnoteInfo);
317 	tFootnoteInfoLen =
318 		(size_t)ulGetLong(0x6c, aucHeader); /* lcbPlcffndRef */
319 	NO_DBG_DEC(tFootnoteInfoLen);
320 
321 	if (tFootnoteInfoLen < 10) {
322 		DBG_MSG("No Footnotes in this document");
323 		return;
324 	}
325 
326 	aucBuffer = xmalloc(tFootnoteInfoLen);
327 	if (!bReadBuffer(pFile, ulStartBlock,
328 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
329 			aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
330 		aucBuffer = xfree(aucBuffer);
331 		return;
332 	}
333 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
334 
335 	fail(tFootnoteListLength != 0);
336 	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
337 	fail(tFootnoteListLength == 0);
338 
339 	fail(aulFootnoteList != NULL);
340 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
341 
342 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
343 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
344 		NO_DBG_HEX(ulOffset);
345 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
346 		NO_DBG_HEX(ulFileOffset);
347 		aulFootnoteList[tIndex] = ulFileOffset;
348 	}
349 	aucBuffer = xfree(aucBuffer);
350 } /* end of vGet6FootnotesInfo */
351 
352 /*
353  * Build the list with footnote text information for Word 6/7 files
354  */
355 static void
vGet6FootnotesText(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)356 vGet6FootnotesText(FILE *pFile, ULONG ulStartBlock,
357 	const ULONG *aulBBD, size_t tBBDLen,
358 	const UCHAR *aucHeader)
359 {
360 	footnote_local_type	*pCurr;
361 	UCHAR	*aucBuffer;
362 	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
363 	size_t	tFootnoteTextLen;
364 	size_t	tIndex;
365 
366 	TRACE_MSG("vGet6FootnotesText");
367 
368 	fail(pFile == NULL || aucHeader == NULL);
369 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
370 	fail(aulBBD == NULL);
371 
372 	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
373 	ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
374 	NO_DBG_HEX(ulBeginOfFootnotes);
375 
376 	ulBeginFootnoteText = ulGetLong(0x70, aucHeader); /* fcPlcffndTxt */
377 	NO_DBG_HEX(ulBeginFootnoteText);
378 	tFootnoteTextLen =
379 		(size_t)ulGetLong(0x74, aucHeader); /* lcbPlcffndTxt */
380 	NO_DBG_DEC(tFootnoteTextLen);
381 
382 	if (tFootnoteTextLen < 12) {
383 		DBG_MSG("No Footnote text in this document");
384 		return;
385 	}
386 
387 	aucBuffer = xmalloc(tFootnoteTextLen);
388 	if (!bReadBuffer(pFile, ulStartBlock,
389 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
390 			aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
391 		aucBuffer = xfree(aucBuffer);
392 		return;
393 	}
394 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
395 
396 	fail(tFootnoteTextLength != 0);
397 	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
398 	fail(tFootnoteTextLength == 0);
399 
400 	fail(pFootnoteText != NULL);
401 	pFootnoteText = xcalloc(tFootnoteTextLength,
402 				sizeof(footnote_local_type));
403 
404 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
405 		pCurr = pFootnoteText + tIndex;
406 		pCurr->tInfo.szText = NULL;
407 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
408 		NO_DBG_HEX(ulOffset);
409 		ulCharPos = ulBeginOfFootnotes + ulOffset;
410 		NO_DBG_HEX(ulCharPos);
411 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
412 		pCurr->ulCharPosStart = ulCharPos;
413 		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
414 		NO_DBG_HEX(ulOffset);
415 		ulCharPos = ulBeginOfFootnotes + ulOffset;
416 		NO_DBG_HEX(ulCharPos);
417 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
418 		pCurr->ulCharPosNext = ulCharPos;
419 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
420 	}
421 	aucBuffer = xfree(aucBuffer);
422 } /* end of vGet6FootnotesText */
423 
424 /*
425  * Build the list with endnote information for Word 6/7 files
426  */
427 static void
vGet6EndnotesInfo(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)428 vGet6EndnotesInfo(FILE *pFile, ULONG ulStartBlock,
429 	const ULONG *aulBBD, size_t tBBDLen,
430 	const UCHAR *aucHeader)
431 {
432 	UCHAR	*aucBuffer;
433 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
434 	size_t	tEndnoteInfoLen;
435 	size_t	tIndex;
436 
437 	TRACE_MSG("vGet6EndnotesInfo");
438 
439 	fail(pFile == NULL || aucHeader == NULL);
440 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
441 	fail(aulBBD == NULL);
442 
443 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
444 	NO_DBG_HEX(ulBeginOfText);
445 	ulBeginEndnoteInfo = ulGetLong(0x1d2, aucHeader); /* fcPlcfendRef */
446 	NO_DBG_HEX(ulBeginEndnoteInfo);
447 	tEndnoteInfoLen =
448 		(size_t)ulGetLong(0x1d6, aucHeader); /* lcbPlcfendRef */
449 	NO_DBG_DEC(tEndnoteInfoLen);
450 
451 	if (tEndnoteInfoLen < 10) {
452 		DBG_MSG("No Endnotes in this document");
453 		return;
454 	}
455 
456 	aucBuffer = xmalloc(tEndnoteInfoLen);
457 	if (!bReadBuffer(pFile, ulStartBlock,
458 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
459 			aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
460 		aucBuffer = xfree(aucBuffer);
461 		return;
462 	}
463 	NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
464 
465 	fail(tEndnoteListLength != 0);
466 	tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
467 	fail(tEndnoteListLength == 0);
468 
469 	fail(aulEndnoteList != NULL);
470 	aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
471 
472 	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
473 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
474 		NO_DBG_HEX(ulOffset);
475 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
476 		NO_DBG_HEX(ulFileOffset);
477 		aulEndnoteList[tIndex] = ulFileOffset;
478 	}
479 	aucBuffer = xfree(aucBuffer);
480 } /* end of vGet6EndnotesInfo */
481 
482 /*
483  * Build the lists note information for Word 6/7 files
484  */
485 static void
vGet6NotesInfo(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)486 vGet6NotesInfo(FILE *pFile, ULONG ulStartBlock,
487 	const ULONG *aulBBD, size_t tBBDLen,
488 	const UCHAR *aucHeader)
489 {
490 	TRACE_MSG("vGet6NotesInfo");
491 
492 	vGet6FootnotesInfo(pFile, ulStartBlock,
493 			aulBBD, tBBDLen, aucHeader);
494 	vGet6FootnotesText(pFile, ulStartBlock,
495 			aulBBD, tBBDLen, aucHeader);
496 	vGet6EndnotesInfo(pFile, ulStartBlock,
497 			aulBBD, tBBDLen, aucHeader);
498 } /* end of vGet6NotesInfo */
499 
500 /*
501  * Build the list with footnote information for Word 8/9/10 files
502  */
503 static void
vGet8FootnotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)504 vGet8FootnotesInfo(FILE *pFile, const pps_info_type *pPPS,
505 	const ULONG *aulBBD, size_t tBBDLen,
506 	const ULONG *aulSBD, size_t tSBDLen,
507 	const UCHAR *aucHeader)
508 {
509 	const ULONG	*aulBlockDepot;
510 	UCHAR	*aucBuffer;
511 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
512 	size_t	tFootnoteInfoLen, tBlockDepotLen, tBlockSize;
513 	size_t	tIndex;
514 
515 	TRACE_MSG("vGet8FootnotesInfo");
516 
517 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
518 	NO_DBG_HEX(ulBeginOfText);
519 	ulBeginFootnoteInfo = ulGetLong(0xaa, aucHeader); /* fcPlcffndRef */
520 	NO_DBG_HEX(ulBeginFootnoteInfo);
521 	tFootnoteInfoLen =
522 		(size_t)ulGetLong(0xae, aucHeader); /* lcbPlcffndRef */
523 	NO_DBG_DEC(tFootnoteInfoLen);
524 
525 	if (tFootnoteInfoLen < 10) {
526 		DBG_MSG("No Footnotes in this document");
527 		return;
528 	}
529 
530 	NO_DBG_DEC(pPPS->tTable.ulSB);
531 	NO_DBG_HEX(pPPS->tTable.ulSize);
532 	if (pPPS->tTable.ulSize == 0) {
533 		DBG_MSG("No footnotes information");
534 		return;
535 	}
536 
537 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
538 	  	/* Use the Small Block Depot */
539 		aulBlockDepot = aulSBD;
540 		tBlockDepotLen = tSBDLen;
541 		tBlockSize = SMALL_BLOCK_SIZE;
542 	} else {
543 	  	/* Use the Big Block Depot */
544 		aulBlockDepot = aulBBD;
545 		tBlockDepotLen = tBBDLen;
546 		tBlockSize = BIG_BLOCK_SIZE;
547 	}
548 	aucBuffer = xmalloc(tFootnoteInfoLen);
549 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
550 			aulBlockDepot, tBlockDepotLen, tBlockSize,
551 			aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
552 		aucBuffer = xfree(aucBuffer);
553 		return;
554 	}
555 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
556 
557 	fail(tFootnoteListLength != 0);
558 	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
559 	fail(tFootnoteListLength == 0);
560 
561 	fail(aulFootnoteList != NULL);
562 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
563 
564 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
565 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
566 		NO_DBG_HEX(ulOffset);
567 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
568 		NO_DBG_HEX(ulFileOffset);
569 		aulFootnoteList[tIndex] = ulFileOffset;
570 	}
571 	aucBuffer = xfree(aucBuffer);
572 } /* end of vGet8FootnotesInfo */
573 
574 /*
575  * Build the list with footnote text information for Word 8/9/10 files
576  */
577 static void
vGet8FootnotesText(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)578 vGet8FootnotesText(FILE *pFile, const pps_info_type *pPPS,
579 	const ULONG *aulBBD, size_t tBBDLen,
580 	const ULONG *aulSBD, size_t tSBDLen,
581 	const UCHAR *aucHeader)
582 {
583 	footnote_local_type	*pCurr;
584 	const ULONG	*aulBlockDepot;
585 	UCHAR	*aucBuffer;
586 	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
587 	size_t	tFootnoteTextLen, tBlockDepotLen, tBlockSize;
588 	size_t	tIndex;
589 
590 	TRACE_MSG("vGet8FootnotesText");
591 
592 	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
593 	ulBeginOfFootnotes += ulGetLong(0x4c, aucHeader); /* ccpText */
594 	NO_DBG_HEX(ulBeginOfFootnotes);
595 
596 	ulBeginFootnoteText = ulGetLong(0xb2, aucHeader); /* fcPlcffndTxt */
597 	NO_DBG_HEX(ulBeginFootnoteText);
598 	tFootnoteTextLen =
599 		(size_t)ulGetLong(0xb6, aucHeader); /* lcbPlcffndTxt */
600 	NO_DBG_DEC(tFootnoteTextLen);
601 
602 	if (tFootnoteTextLen < 12) {
603 		DBG_MSG("No Footnote text in this document");
604 		return;
605 	}
606 
607 	NO_DBG_DEC(pPPS->tTable.ulSB);
608 	NO_DBG_HEX(pPPS->tTable.ulSize);
609 	if (pPPS->tTable.ulSize == 0) {
610 		DBG_MSG("No footnote text information");
611 		return;
612 	}
613 
614 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
615 	  	/* Use the Small Block Depot */
616 		aulBlockDepot = aulSBD;
617 		tBlockDepotLen = tSBDLen;
618 		tBlockSize = SMALL_BLOCK_SIZE;
619 	} else {
620 	  	/* Use the Big Block Depot */
621 		aulBlockDepot = aulBBD;
622 		tBlockDepotLen = tBBDLen;
623 		tBlockSize = BIG_BLOCK_SIZE;
624 	}
625 	aucBuffer = xmalloc(tFootnoteTextLen);
626 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
627 			aulBlockDepot, tBlockDepotLen, tBlockSize,
628 			aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
629 		aucBuffer = xfree(aucBuffer);
630 		return;
631 	}
632 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
633 
634 	fail(tFootnoteTextLength != 0);
635 	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
636 	fail(tFootnoteTextLength == 0);
637 
638 	fail(pFootnoteText != NULL);
639 	pFootnoteText = xcalloc(tFootnoteTextLength,
640 				sizeof(footnote_local_type));
641 
642 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
643 		pCurr = pFootnoteText + tIndex;
644 		pCurr->tInfo.szText = NULL;
645 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
646 		NO_DBG_HEX(ulOffset);
647 		ulCharPos = ulBeginOfFootnotes + ulOffset;
648 		NO_DBG_HEX(ulCharPos);
649 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
650 		pCurr->ulCharPosStart = ulCharPos;
651 		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
652 		NO_DBG_HEX(ulOffset);
653 		ulCharPos = ulBeginOfFootnotes + ulOffset;
654 		NO_DBG_HEX(ulCharPos);
655 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
656 		pCurr->ulCharPosNext = ulCharPos;
657 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
658 	}
659 	aucBuffer = xfree(aucBuffer);
660 } /* end of vGet8FootnotesText */
661 
662 /*
663  * Build the list with endnote information for Word 8/9/10 files
664  */
665 static void
vGet8EndnotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)666 vGet8EndnotesInfo(FILE *pFile, const pps_info_type *pPPS,
667 	const ULONG *aulBBD, size_t tBBDLen,
668 	const ULONG *aulSBD, size_t tSBDLen,
669 	const UCHAR *aucHeader)
670 {
671 	const ULONG	*aulBlockDepot;
672 	UCHAR	*aucBuffer;
673 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
674 	size_t	tEndnoteInfoLen, tBlockDepotLen, tBlockSize;
675 	size_t	tIndex;
676 
677 	TRACE_MSG("vGet8EndnotesInfo");
678 
679 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
680 	NO_DBG_HEX(ulBeginOfText);
681 	ulBeginEndnoteInfo = ulGetLong(0x20a, aucHeader); /* fcPlcfendRef */
682 	NO_DBG_HEX(ulBeginEndnoteInfo);
683 	tEndnoteInfoLen = (size_t)ulGetLong(0x20e, aucHeader); /* lcbPlcfendRef */
684 	NO_DBG_DEC(tEndnoteInfoLen);
685 
686 	if (tEndnoteInfoLen < 10) {
687 		DBG_MSG("No endnotes in this document");
688 		return;
689 	}
690 
691 	NO_DBG_DEC(pPPS->tTable.ulSB);
692 	NO_DBG_HEX(pPPS->tTable.ulSize);
693 	if (pPPS->tTable.ulSize == 0) {
694 		DBG_MSG("No endnotes information");
695 		return;
696 	}
697 
698 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
699 	  	/* Use the Small Block Depot */
700 		aulBlockDepot = aulSBD;
701 		tBlockDepotLen = tSBDLen;
702 		tBlockSize = SMALL_BLOCK_SIZE;
703 	} else {
704 	  	/* Use the Big Block Depot */
705 		aulBlockDepot = aulBBD;
706 		tBlockDepotLen = tBBDLen;
707 		tBlockSize = BIG_BLOCK_SIZE;
708 	}
709 	aucBuffer = xmalloc(tEndnoteInfoLen);
710 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
711 			aulBlockDepot, tBlockDepotLen, tBlockSize,
712 			aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
713 		aucBuffer = xfree(aucBuffer);
714 		return;
715 	}
716 	NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
717 
718 	fail(tEndnoteListLength != 0);
719 	tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
720 	fail(tEndnoteListLength == 0);
721 
722 	fail(aulEndnoteList != NULL);
723 	aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
724 
725 	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
726 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
727 		NO_DBG_HEX(ulOffset);
728 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
729 		NO_DBG_HEX(ulFileOffset);
730 		aulEndnoteList[tIndex] = ulFileOffset;
731 	}
732 	aucBuffer = xfree(aucBuffer);
733 } /* end of vGet8EndnotesInfo */
734 
735 /*
736  * Build the lists with footnote and endnote information for Word 8/9/10 files
737  */
738 static void
vGet8NotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)739 vGet8NotesInfo(FILE *pFile, const pps_info_type *pPPS,
740 	const ULONG *aulBBD, size_t tBBDLen,
741 	const ULONG *aulSBD, size_t tSBDLen,
742 	const UCHAR *aucHeader)
743 {
744 	TRACE_MSG("vGet8NotesInfo");
745 
746 	vGet8FootnotesInfo(pFile, pPPS,
747 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
748 	vGet8FootnotesText(pFile, pPPS,
749 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
750 	vGet8EndnotesInfo(pFile, pPPS,
751 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
752 } /* end of vGet8NotesInfo */
753 
754 /*
755  * Build the lists with footnote and endnote information
756  */
757 void
vGetNotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader,int iWordVersion)758 vGetNotesInfo(FILE *pFile, const pps_info_type *pPPS,
759 	const ULONG *aulBBD, size_t tBBDLen,
760 	const ULONG *aulSBD, size_t tSBDLen,
761 	const UCHAR *aucHeader, int iWordVersion)
762 {
763 	TRACE_MSG("vGetNotesInfo");
764 
765 	fail(pFile == NULL);
766 	fail(pPPS == NULL && iWordVersion >= 6);
767 	fail(aulBBD == NULL && tBBDLen != 0);
768 	fail(aulSBD == NULL && tSBDLen != 0);
769 	fail(aucHeader == NULL);
770 
771 	switch (iWordVersion) {
772 	case 0:
773 		vGet0NotesInfo(pFile, aucHeader);
774 		break;
775 	case 1:
776 	case 2:
777 		vGet2NotesInfo(pFile, aucHeader);
778 		break;
779 	case 4:
780 	case 5:
781 		break;
782 	case 6:
783 	case 7:
784 		vGet6NotesInfo(pFile, pPPS->tWordDocument.ulSB,
785 			aulBBD, tBBDLen, aucHeader);
786 		break;
787 	case 8:
788 		vGet8NotesInfo(pFile, pPPS,
789 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
790 		break;
791 	default:
792 		werr(0, "Sorry, no notes information");
793 		break;
794 	}
795 } /* end of vGetNotesInfo */
796 
797 /*
798  *  vPrepareFootnoteText - prepare the footnote text
799  */
800 void
vPrepareFootnoteText(FILE * pFile)801 vPrepareFootnoteText(FILE *pFile)
802 {
803 	footnote_local_type	*pCurr;
804 	size_t		tFootnote;
805 
806 	fail(pFile == NULL);
807 	fail(pFootnoteText == NULL && tFootnoteTextLength != 0);
808 
809 	if (pFootnoteText == NULL || tFootnoteTextLength == 0) {
810 		/* No information */
811 		return;
812 	}
813 
814 	/* Fill text and useful-ness */
815 	for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
816 		pCurr = pFootnoteText + tFootnote;
817 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
818 		if (pCurr->bUseful) {
819 			pCurr->tInfo.szText = szFootnoteDecryptor(pFile,
820 							pCurr->ulCharPosStart,
821 							pCurr->ulCharPosNext);
822 		} else {
823 			pCurr->tInfo.szText = NULL;
824 		}
825 	}
826 } /* end of vPrepareFootnoteText */
827 
828 /*
829  * szGetFootnootText - get the text of the spefified footnote
830  */
831 const char *
szGetFootnootText(UINT uiFootnoteIndex)832 szGetFootnootText(UINT uiFootnoteIndex)
833 {
834 	if ((size_t)uiFootnoteIndex >= tFootnoteTextLength) {
835 		return NULL;
836 	}
837 	return pFootnoteText[uiFootnoteIndex].tInfo.szText;
838 } /* end of szGetFootnootText */
839 
840 /*
841  * Get the notetype of the note at the given fileoffset
842  */
843 notetype_enum
eGetNotetype(ULONG ulFileOffset)844 eGetNotetype(ULONG ulFileOffset)
845 {
846 	size_t	tIndex;
847 
848 	TRACE_MSG("eGetNotetype");
849 
850 	fail(aulFootnoteList == NULL && tFootnoteListLength != 0);
851 	fail(aulEndnoteList == NULL && tEndnoteListLength != 0);
852 
853 	/* Go for the easy answers first */
854 	if (tFootnoteListLength == 0 && tEndnoteListLength == 0) {
855 		return notetype_is_unknown;
856 	}
857 	if (tEndnoteListLength == 0) {
858 		return notetype_is_footnote;
859 	}
860 	if (tFootnoteListLength == 0) {
861 		return notetype_is_endnote;
862 	}
863 	/* No easy answer, so we search */
864 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
865 		if (aulFootnoteList[tIndex] == ulFileOffset) {
866 			return notetype_is_footnote;
867 		}
868 	}
869 	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
870 		if (aulEndnoteList[tIndex] == ulFileOffset) {
871 			return notetype_is_endnote;
872 		}
873 	}
874 	/* Not found */
875 	return notetype_is_unknown;
876 } /* end of eGetNotetype */
877