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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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