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