mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
877 lines
24 KiB
C
877 lines
24 KiB
C
/*
|
|
* notes.c
|
|
* Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
|
|
*
|
|
* Description:
|
|
* Functions to tell the difference between footnotes and endnotes
|
|
*/
|
|
|
|
#include "antiword.h"
|
|
|
|
/*
|
|
* Private structures to hide the way the information
|
|
* is stored from the rest of the program
|
|
*/
|
|
typedef struct footnote_local_tag {
|
|
footnote_block_type tInfo;
|
|
ULONG ulCharPosStart;
|
|
ULONG ulCharPosNext;
|
|
BOOL bUseful;
|
|
} footnote_local_type;
|
|
|
|
/* Variables needed to write the Footnote and Endnote information */
|
|
static ULONG *aulFootnoteList = NULL;
|
|
static size_t tFootnoteListLength = 0;
|
|
static ULONG *aulEndnoteList = NULL;
|
|
static size_t tEndnoteListLength = 0;
|
|
/* Variables needed to write the Footnote Text */
|
|
static footnote_local_type *pFootnoteText = NULL;
|
|
static size_t tFootnoteTextLength = 0;
|
|
|
|
|
|
/*
|
|
* Destroy the lists with footnote and endnote information
|
|
*/
|
|
void
|
|
vDestroyNotesInfoLists(void)
|
|
{
|
|
footnote_local_type *pRecord;
|
|
size_t tFootnote;
|
|
|
|
TRACE_MSG("vDestroyNotesInfoLists");
|
|
|
|
/* Free the lists and reset all control variables */
|
|
aulEndnoteList = xfree(aulEndnoteList);
|
|
aulFootnoteList = xfree(aulFootnoteList);
|
|
tEndnoteListLength = 0;
|
|
tFootnoteListLength = 0;
|
|
for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
|
|
pRecord = pFootnoteText + tFootnote;
|
|
pRecord->tInfo.szText = xfree(pRecord->tInfo.szText);
|
|
}
|
|
pFootnoteText = xfree(pFootnoteText);
|
|
tFootnoteTextLength = 0;
|
|
} /* end of vDestroyNotesInfoLists */
|
|
|
|
/*
|
|
* Build the list with footnote information for Word for DOS files
|
|
*/
|
|
static void
|
|
vGet0FootnotesInfoAndText(FILE *pFile, const UCHAR *aucHeader)
|
|
{
|
|
footnote_local_type *pCurr;
|
|
UCHAR *aucBuffer;
|
|
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
|
|
ULONG ulCharPos, ulBeginNextBlock;
|
|
size_t tFootnotes, tFootnoteInfoLen;
|
|
size_t tIndex;
|
|
UCHAR aucTmp[2];
|
|
|
|
TRACE_MSG("vGet0FootnotesInfoAndText");
|
|
|
|
fail(pFile == NULL || aucHeader == NULL);
|
|
|
|
ulBeginOfText = 128;
|
|
NO_DBG_HEX(ulBeginOfText);
|
|
ulBeginFootnoteInfo = 128 * (ULONG)usGetWord(0x14, aucHeader);
|
|
DBG_HEX(ulBeginFootnoteInfo);
|
|
ulBeginNextBlock = 128 * (ULONG)usGetWord(0x16, aucHeader);
|
|
DBG_HEX(ulBeginNextBlock);
|
|
|
|
if (ulBeginFootnoteInfo == ulBeginNextBlock) {
|
|
DBG_MSG("No Footnotes in this document");
|
|
return;
|
|
}
|
|
|
|
/* Read the the number of footnotes + 1 */
|
|
if (!bReadBytes(aucTmp, 2, ulBeginFootnoteInfo, pFile)) {
|
|
return;
|
|
}
|
|
tFootnotes = (size_t)usGetWord(0, aucTmp);
|
|
if (tFootnotes < 2) {
|
|
DBG_MSG("No Footnotes in this document (2)");
|
|
}
|
|
DBG_DEC(tFootnotes);
|
|
tFootnoteInfoLen = 8 * tFootnotes;
|
|
|
|
aucBuffer = xmalloc(tFootnoteInfoLen);
|
|
if (!bReadBytes(aucBuffer,
|
|
tFootnoteInfoLen, ulBeginFootnoteInfo + 4, pFile)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
|
|
|
|
/* Get footnote information */
|
|
fail(tFootnoteListLength != 0);
|
|
tFootnoteListLength = tFootnotes - 1;
|
|
fail(tFootnoteListLength == 0);
|
|
|
|
fail(aulFootnoteList != NULL);
|
|
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
|
|
ulOffset = ulGetLong(tIndex * 8, aucBuffer);
|
|
DBG_HEX(ulOffset);
|
|
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
|
|
DBG_HEX(ulFileOffset);
|
|
aulFootnoteList[tIndex] = ulFileOffset;
|
|
}
|
|
|
|
/* Get footnote text */
|
|
fail(tFootnoteTextLength != 0);
|
|
tFootnoteTextLength = tFootnotes - 1;
|
|
fail(tFootnoteTextLength == 0);
|
|
|
|
fail(pFootnoteText != NULL);
|
|
pFootnoteText = xcalloc(tFootnoteTextLength,
|
|
sizeof(footnote_local_type));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
|
|
pCurr = pFootnoteText + tIndex;
|
|
pCurr->tInfo.szText = NULL;
|
|
ulOffset = ulGetLong(tIndex * 8 + 4, aucBuffer);
|
|
DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfText + ulOffset;
|
|
DBG_HEX(ulCharPos);
|
|
DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosStart = ulCharPos;
|
|
ulOffset = ulGetLong((tIndex + 1) * 8 + 4, aucBuffer);
|
|
DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfText + ulOffset;
|
|
DBG_HEX(ulCharPos);
|
|
DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosNext = ulCharPos;
|
|
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet0FootnotesInfoAndText */
|
|
|
|
/*
|
|
* Build the lists note information for Word for DOS files
|
|
*/
|
|
static void
|
|
vGet0NotesInfo(FILE *pFile, const UCHAR *aucHeader)
|
|
{
|
|
TRACE_MSG("vGet0NotesInfo");
|
|
|
|
vGet0FootnotesInfoAndText(pFile, aucHeader);
|
|
/* There are no endnotes in a Word for DOS file */
|
|
} /* end of vGet0NotesInfo */
|
|
|
|
/*
|
|
* Build the list with footnote information for WinWord 1/2 files
|
|
*/
|
|
static void
|
|
vGet2FootnotesInfo(FILE *pFile, const UCHAR *aucHeader)
|
|
{
|
|
UCHAR *aucBuffer;
|
|
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
|
|
size_t tFootnoteInfoLen;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet2FootnotesInfo");
|
|
|
|
fail(pFile == NULL || aucHeader == NULL);
|
|
|
|
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
NO_DBG_HEX(ulBeginOfText);
|
|
ulBeginFootnoteInfo = ulGetLong(0x64, aucHeader); /* fcPlcffndRef */
|
|
NO_DBG_HEX(ulBeginFootnoteInfo);
|
|
tFootnoteInfoLen = (size_t)usGetWord(0x68, aucHeader); /* cbPlcffndRef */
|
|
NO_DBG_DEC(tFootnoteInfoLen);
|
|
|
|
if (tFootnoteInfoLen < 10) {
|
|
DBG_MSG("No Footnotes in this document");
|
|
return;
|
|
}
|
|
|
|
aucBuffer = xmalloc(tFootnoteInfoLen);
|
|
if (!bReadBytes(aucBuffer,
|
|
tFootnoteInfoLen, ulBeginFootnoteInfo, pFile)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
|
|
|
|
fail(tFootnoteListLength != 0);
|
|
tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
|
|
fail(tFootnoteListLength == 0);
|
|
|
|
fail(aulFootnoteList != NULL);
|
|
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
|
|
NO_DBG_HEX(ulFileOffset);
|
|
aulFootnoteList[tIndex] = ulFileOffset;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet2FootnotesInfo */
|
|
|
|
/*
|
|
* Build the list with footnote text information for WinWord 1/2 files
|
|
*/
|
|
static void
|
|
vGet2FootnotesText(FILE *pFile, const UCHAR *aucHeader)
|
|
{
|
|
footnote_local_type *pCurr;
|
|
UCHAR *aucBuffer;
|
|
ULONG ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
|
|
size_t tFootnoteTextLen;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet2FootnotesText");
|
|
|
|
fail(pFile == NULL || aucHeader == NULL);
|
|
|
|
ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
|
|
NO_DBG_HEX(ulBeginOfFootnotes);
|
|
|
|
ulBeginFootnoteText = ulGetLong(0x6a, aucHeader); /* fcPlcffndTxt */
|
|
NO_DBG_HEX(ulBeginFootnoteText);
|
|
tFootnoteTextLen =
|
|
(size_t)usGetWord(0x6e, aucHeader); /* cbPlcffndTxt */
|
|
NO_DBG_DEC(tFootnoteTextLen);
|
|
|
|
if (tFootnoteTextLen < 12) {
|
|
DBG_MSG("No Footnote text in this document");
|
|
return;
|
|
}
|
|
|
|
aucBuffer = xmalloc(tFootnoteTextLen);
|
|
if (!bReadBytes(aucBuffer,
|
|
tFootnoteTextLen, ulBeginFootnoteText, pFile)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
|
|
|
|
fail(tFootnoteTextLength != 0);
|
|
tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
|
|
fail(tFootnoteTextLength == 0);
|
|
|
|
fail(pFootnoteText != NULL);
|
|
pFootnoteText = xcalloc(tFootnoteTextLength,
|
|
sizeof(footnote_local_type));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
|
|
pCurr = pFootnoteText + tIndex;
|
|
pCurr->tInfo.szText = NULL;
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfFootnotes + ulOffset;
|
|
NO_DBG_HEX(ulCharPos);
|
|
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosStart = ulCharPos;
|
|
ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfFootnotes + ulOffset;
|
|
NO_DBG_HEX(ulCharPos);
|
|
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosNext = ulCharPos;
|
|
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet2FootnotesText */
|
|
|
|
/*
|
|
* Build the lists note information for WinWord 1/2 files
|
|
*/
|
|
static void
|
|
vGet2NotesInfo(FILE *pFile, const UCHAR *aucHeader)
|
|
{
|
|
TRACE_MSG("vGet2NotesInfo");
|
|
|
|
vGet2FootnotesInfo(pFile, aucHeader);
|
|
vGet2FootnotesText(pFile, aucHeader);
|
|
/* There are no endnotes in a WinWord 1/2 file */
|
|
} /* end of vGet2NotesInfo */
|
|
|
|
/*
|
|
* Build the list with footnote information for Word 6/7 files
|
|
*/
|
|
static void
|
|
vGet6FootnotesInfo(FILE *pFile, ULONG ulStartBlock,
|
|
const ULONG *aulBBD, size_t tBBDLen,
|
|
const UCHAR *aucHeader)
|
|
{
|
|
UCHAR *aucBuffer;
|
|
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
|
|
size_t tFootnoteInfoLen;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet6FootnotesInfo");
|
|
|
|
fail(pFile == NULL || aucHeader == NULL);
|
|
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
|
|
fail(aulBBD == NULL);
|
|
|
|
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
NO_DBG_HEX(ulBeginOfText);
|
|
ulBeginFootnoteInfo = ulGetLong(0x68, aucHeader); /* fcPlcffndRef */
|
|
NO_DBG_HEX(ulBeginFootnoteInfo);
|
|
tFootnoteInfoLen =
|
|
(size_t)ulGetLong(0x6c, aucHeader); /* lcbPlcffndRef */
|
|
NO_DBG_DEC(tFootnoteInfoLen);
|
|
|
|
if (tFootnoteInfoLen < 10) {
|
|
DBG_MSG("No Footnotes in this document");
|
|
return;
|
|
}
|
|
|
|
aucBuffer = xmalloc(tFootnoteInfoLen);
|
|
if (!bReadBuffer(pFile, ulStartBlock,
|
|
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
|
|
aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
|
|
|
|
fail(tFootnoteListLength != 0);
|
|
tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
|
|
fail(tFootnoteListLength == 0);
|
|
|
|
fail(aulFootnoteList != NULL);
|
|
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
|
|
NO_DBG_HEX(ulFileOffset);
|
|
aulFootnoteList[tIndex] = ulFileOffset;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet6FootnotesInfo */
|
|
|
|
/*
|
|
* Build the list with footnote text information for Word 6/7 files
|
|
*/
|
|
static void
|
|
vGet6FootnotesText(FILE *pFile, ULONG ulStartBlock,
|
|
const ULONG *aulBBD, size_t tBBDLen,
|
|
const UCHAR *aucHeader)
|
|
{
|
|
footnote_local_type *pCurr;
|
|
UCHAR *aucBuffer;
|
|
ULONG ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
|
|
size_t tFootnoteTextLen;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet6FootnotesText");
|
|
|
|
fail(pFile == NULL || aucHeader == NULL);
|
|
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
|
|
fail(aulBBD == NULL);
|
|
|
|
ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
|
|
NO_DBG_HEX(ulBeginOfFootnotes);
|
|
|
|
ulBeginFootnoteText = ulGetLong(0x70, aucHeader); /* fcPlcffndTxt */
|
|
NO_DBG_HEX(ulBeginFootnoteText);
|
|
tFootnoteTextLen =
|
|
(size_t)ulGetLong(0x74, aucHeader); /* lcbPlcffndTxt */
|
|
NO_DBG_DEC(tFootnoteTextLen);
|
|
|
|
if (tFootnoteTextLen < 12) {
|
|
DBG_MSG("No Footnote text in this document");
|
|
return;
|
|
}
|
|
|
|
aucBuffer = xmalloc(tFootnoteTextLen);
|
|
if (!bReadBuffer(pFile, ulStartBlock,
|
|
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
|
|
aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
|
|
|
|
fail(tFootnoteTextLength != 0);
|
|
tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
|
|
fail(tFootnoteTextLength == 0);
|
|
|
|
fail(pFootnoteText != NULL);
|
|
pFootnoteText = xcalloc(tFootnoteTextLength,
|
|
sizeof(footnote_local_type));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
|
|
pCurr = pFootnoteText + tIndex;
|
|
pCurr->tInfo.szText = NULL;
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfFootnotes + ulOffset;
|
|
NO_DBG_HEX(ulCharPos);
|
|
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosStart = ulCharPos;
|
|
ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfFootnotes + ulOffset;
|
|
NO_DBG_HEX(ulCharPos);
|
|
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosNext = ulCharPos;
|
|
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet6FootnotesText */
|
|
|
|
/*
|
|
* Build the list with endnote information for Word 6/7 files
|
|
*/
|
|
static void
|
|
vGet6EndnotesInfo(FILE *pFile, ULONG ulStartBlock,
|
|
const ULONG *aulBBD, size_t tBBDLen,
|
|
const UCHAR *aucHeader)
|
|
{
|
|
UCHAR *aucBuffer;
|
|
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
|
|
size_t tEndnoteInfoLen;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet6EndnotesInfo");
|
|
|
|
fail(pFile == NULL || aucHeader == NULL);
|
|
fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
|
|
fail(aulBBD == NULL);
|
|
|
|
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
NO_DBG_HEX(ulBeginOfText);
|
|
ulBeginEndnoteInfo = ulGetLong(0x1d2, aucHeader); /* fcPlcfendRef */
|
|
NO_DBG_HEX(ulBeginEndnoteInfo);
|
|
tEndnoteInfoLen =
|
|
(size_t)ulGetLong(0x1d6, aucHeader); /* lcbPlcfendRef */
|
|
NO_DBG_DEC(tEndnoteInfoLen);
|
|
|
|
if (tEndnoteInfoLen < 10) {
|
|
DBG_MSG("No Endnotes in this document");
|
|
return;
|
|
}
|
|
|
|
aucBuffer = xmalloc(tEndnoteInfoLen);
|
|
if (!bReadBuffer(pFile, ulStartBlock,
|
|
aulBBD, tBBDLen, BIG_BLOCK_SIZE,
|
|
aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
|
|
|
|
fail(tEndnoteListLength != 0);
|
|
tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
|
|
fail(tEndnoteListLength == 0);
|
|
|
|
fail(aulEndnoteList != NULL);
|
|
aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
|
|
|
|
for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
|
|
NO_DBG_HEX(ulFileOffset);
|
|
aulEndnoteList[tIndex] = ulFileOffset;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet6EndnotesInfo */
|
|
|
|
/*
|
|
* Build the lists note information for Word 6/7 files
|
|
*/
|
|
static void
|
|
vGet6NotesInfo(FILE *pFile, ULONG ulStartBlock,
|
|
const ULONG *aulBBD, size_t tBBDLen,
|
|
const UCHAR *aucHeader)
|
|
{
|
|
TRACE_MSG("vGet6NotesInfo");
|
|
|
|
vGet6FootnotesInfo(pFile, ulStartBlock,
|
|
aulBBD, tBBDLen, aucHeader);
|
|
vGet6FootnotesText(pFile, ulStartBlock,
|
|
aulBBD, tBBDLen, aucHeader);
|
|
vGet6EndnotesInfo(pFile, ulStartBlock,
|
|
aulBBD, tBBDLen, aucHeader);
|
|
} /* end of vGet6NotesInfo */
|
|
|
|
/*
|
|
* Build the list with footnote information for Word 8/9/10 files
|
|
*/
|
|
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)
|
|
{
|
|
const ULONG *aulBlockDepot;
|
|
UCHAR *aucBuffer;
|
|
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
|
|
size_t tFootnoteInfoLen, tBlockDepotLen, tBlockSize;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet8FootnotesInfo");
|
|
|
|
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
NO_DBG_HEX(ulBeginOfText);
|
|
ulBeginFootnoteInfo = ulGetLong(0xaa, aucHeader); /* fcPlcffndRef */
|
|
NO_DBG_HEX(ulBeginFootnoteInfo);
|
|
tFootnoteInfoLen =
|
|
(size_t)ulGetLong(0xae, aucHeader); /* lcbPlcffndRef */
|
|
NO_DBG_DEC(tFootnoteInfoLen);
|
|
|
|
if (tFootnoteInfoLen < 10) {
|
|
DBG_MSG("No Footnotes in this document");
|
|
return;
|
|
}
|
|
|
|
NO_DBG_DEC(pPPS->tTable.ulSB);
|
|
NO_DBG_HEX(pPPS->tTable.ulSize);
|
|
if (pPPS->tTable.ulSize == 0) {
|
|
DBG_MSG("No footnotes information");
|
|
return;
|
|
}
|
|
|
|
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
|
|
/* Use the Small Block Depot */
|
|
aulBlockDepot = aulSBD;
|
|
tBlockDepotLen = tSBDLen;
|
|
tBlockSize = SMALL_BLOCK_SIZE;
|
|
} else {
|
|
/* Use the Big Block Depot */
|
|
aulBlockDepot = aulBBD;
|
|
tBlockDepotLen = tBBDLen;
|
|
tBlockSize = BIG_BLOCK_SIZE;
|
|
}
|
|
aucBuffer = xmalloc(tFootnoteInfoLen);
|
|
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
|
|
aulBlockDepot, tBlockDepotLen, tBlockSize,
|
|
aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
|
|
|
|
fail(tFootnoteListLength != 0);
|
|
tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
|
|
fail(tFootnoteListLength == 0);
|
|
|
|
fail(aulFootnoteList != NULL);
|
|
aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
|
|
NO_DBG_HEX(ulFileOffset);
|
|
aulFootnoteList[tIndex] = ulFileOffset;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet8FootnotesInfo */
|
|
|
|
/*
|
|
* Build the list with footnote text information for Word 8/9/10 files
|
|
*/
|
|
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)
|
|
{
|
|
footnote_local_type *pCurr;
|
|
const ULONG *aulBlockDepot;
|
|
UCHAR *aucBuffer;
|
|
ULONG ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
|
|
size_t tFootnoteTextLen, tBlockDepotLen, tBlockSize;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet8FootnotesText");
|
|
|
|
ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
ulBeginOfFootnotes += ulGetLong(0x4c, aucHeader); /* ccpText */
|
|
NO_DBG_HEX(ulBeginOfFootnotes);
|
|
|
|
ulBeginFootnoteText = ulGetLong(0xb2, aucHeader); /* fcPlcffndTxt */
|
|
NO_DBG_HEX(ulBeginFootnoteText);
|
|
tFootnoteTextLen =
|
|
(size_t)ulGetLong(0xb6, aucHeader); /* lcbPlcffndTxt */
|
|
NO_DBG_DEC(tFootnoteTextLen);
|
|
|
|
if (tFootnoteTextLen < 12) {
|
|
DBG_MSG("No Footnote text in this document");
|
|
return;
|
|
}
|
|
|
|
NO_DBG_DEC(pPPS->tTable.ulSB);
|
|
NO_DBG_HEX(pPPS->tTable.ulSize);
|
|
if (pPPS->tTable.ulSize == 0) {
|
|
DBG_MSG("No footnote text information");
|
|
return;
|
|
}
|
|
|
|
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
|
|
/* Use the Small Block Depot */
|
|
aulBlockDepot = aulSBD;
|
|
tBlockDepotLen = tSBDLen;
|
|
tBlockSize = SMALL_BLOCK_SIZE;
|
|
} else {
|
|
/* Use the Big Block Depot */
|
|
aulBlockDepot = aulBBD;
|
|
tBlockDepotLen = tBBDLen;
|
|
tBlockSize = BIG_BLOCK_SIZE;
|
|
}
|
|
aucBuffer = xmalloc(tFootnoteTextLen);
|
|
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
|
|
aulBlockDepot, tBlockDepotLen, tBlockSize,
|
|
aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
|
|
|
|
fail(tFootnoteTextLength != 0);
|
|
tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
|
|
fail(tFootnoteTextLength == 0);
|
|
|
|
fail(pFootnoteText != NULL);
|
|
pFootnoteText = xcalloc(tFootnoteTextLength,
|
|
sizeof(footnote_local_type));
|
|
|
|
for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
|
|
pCurr = pFootnoteText + tIndex;
|
|
pCurr->tInfo.szText = NULL;
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfFootnotes + ulOffset;
|
|
NO_DBG_HEX(ulCharPos);
|
|
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosStart = ulCharPos;
|
|
ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulCharPos = ulBeginOfFootnotes + ulOffset;
|
|
NO_DBG_HEX(ulCharPos);
|
|
NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
|
|
pCurr->ulCharPosNext = ulCharPos;
|
|
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet8FootnotesText */
|
|
|
|
/*
|
|
* Build the list with endnote information for Word 8/9/10 files
|
|
*/
|
|
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)
|
|
{
|
|
const ULONG *aulBlockDepot;
|
|
UCHAR *aucBuffer;
|
|
ULONG ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
|
|
size_t tEndnoteInfoLen, tBlockDepotLen, tBlockSize;
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("vGet8EndnotesInfo");
|
|
|
|
ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
|
|
NO_DBG_HEX(ulBeginOfText);
|
|
ulBeginEndnoteInfo = ulGetLong(0x20a, aucHeader); /* fcPlcfendRef */
|
|
NO_DBG_HEX(ulBeginEndnoteInfo);
|
|
tEndnoteInfoLen = (size_t)ulGetLong(0x20e, aucHeader); /* lcbPlcfendRef */
|
|
NO_DBG_DEC(tEndnoteInfoLen);
|
|
|
|
if (tEndnoteInfoLen < 10) {
|
|
DBG_MSG("No endnotes in this document");
|
|
return;
|
|
}
|
|
|
|
NO_DBG_DEC(pPPS->tTable.ulSB);
|
|
NO_DBG_HEX(pPPS->tTable.ulSize);
|
|
if (pPPS->tTable.ulSize == 0) {
|
|
DBG_MSG("No endnotes information");
|
|
return;
|
|
}
|
|
|
|
if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
|
|
/* Use the Small Block Depot */
|
|
aulBlockDepot = aulSBD;
|
|
tBlockDepotLen = tSBDLen;
|
|
tBlockSize = SMALL_BLOCK_SIZE;
|
|
} else {
|
|
/* Use the Big Block Depot */
|
|
aulBlockDepot = aulBBD;
|
|
tBlockDepotLen = tBBDLen;
|
|
tBlockSize = BIG_BLOCK_SIZE;
|
|
}
|
|
aucBuffer = xmalloc(tEndnoteInfoLen);
|
|
if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
|
|
aulBlockDepot, tBlockDepotLen, tBlockSize,
|
|
aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
|
|
aucBuffer = xfree(aucBuffer);
|
|
return;
|
|
}
|
|
NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
|
|
|
|
fail(tEndnoteListLength != 0);
|
|
tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
|
|
fail(tEndnoteListLength == 0);
|
|
|
|
fail(aulEndnoteList != NULL);
|
|
aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
|
|
|
|
for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
|
|
ulOffset = ulGetLong(tIndex * 4, aucBuffer);
|
|
NO_DBG_HEX(ulOffset);
|
|
ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
|
|
NO_DBG_HEX(ulFileOffset);
|
|
aulEndnoteList[tIndex] = ulFileOffset;
|
|
}
|
|
aucBuffer = xfree(aucBuffer);
|
|
} /* end of vGet8EndnotesInfo */
|
|
|
|
/*
|
|
* Build the lists with footnote and endnote information for Word 8/9/10 files
|
|
*/
|
|
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)
|
|
{
|
|
TRACE_MSG("vGet8NotesInfo");
|
|
|
|
vGet8FootnotesInfo(pFile, pPPS,
|
|
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
|
|
vGet8FootnotesText(pFile, pPPS,
|
|
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
|
|
vGet8EndnotesInfo(pFile, pPPS,
|
|
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
|
|
} /* end of vGet8NotesInfo */
|
|
|
|
/*
|
|
* Build the lists with footnote and endnote information
|
|
*/
|
|
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)
|
|
{
|
|
TRACE_MSG("vGetNotesInfo");
|
|
|
|
fail(pFile == NULL);
|
|
fail(pPPS == NULL && iWordVersion >= 6);
|
|
fail(aulBBD == NULL && tBBDLen != 0);
|
|
fail(aulSBD == NULL && tSBDLen != 0);
|
|
fail(aucHeader == NULL);
|
|
|
|
switch (iWordVersion) {
|
|
case 0:
|
|
vGet0NotesInfo(pFile, aucHeader);
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
vGet2NotesInfo(pFile, aucHeader);
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
vGet6NotesInfo(pFile, pPPS->tWordDocument.ulSB,
|
|
aulBBD, tBBDLen, aucHeader);
|
|
break;
|
|
case 8:
|
|
vGet8NotesInfo(pFile, pPPS,
|
|
aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
|
|
break;
|
|
default:
|
|
werr(0, "Sorry, no notes information");
|
|
break;
|
|
}
|
|
} /* end of vGetNotesInfo */
|
|
|
|
/*
|
|
* vPrepareFootnoteText - prepare the footnote text
|
|
*/
|
|
void
|
|
vPrepareFootnoteText(FILE *pFile)
|
|
{
|
|
footnote_local_type *pCurr;
|
|
size_t tFootnote;
|
|
|
|
fail(pFile == NULL);
|
|
fail(pFootnoteText == NULL && tFootnoteTextLength != 0);
|
|
|
|
if (pFootnoteText == NULL || tFootnoteTextLength == 0) {
|
|
/* No information */
|
|
return;
|
|
}
|
|
|
|
/* Fill text and useful-ness */
|
|
for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
|
|
pCurr = pFootnoteText + tFootnote;
|
|
pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
|
|
if (pCurr->bUseful) {
|
|
pCurr->tInfo.szText = szFootnoteDecryptor(pFile,
|
|
pCurr->ulCharPosStart,
|
|
pCurr->ulCharPosNext);
|
|
} else {
|
|
pCurr->tInfo.szText = NULL;
|
|
}
|
|
}
|
|
} /* end of vPrepareFootnoteText */
|
|
|
|
/*
|
|
* szGetFootnootText - get the text of the spefified footnote
|
|
*/
|
|
const char *
|
|
szGetFootnootText(UINT uiFootnoteIndex)
|
|
{
|
|
if ((size_t)uiFootnoteIndex >= tFootnoteTextLength) {
|
|
return NULL;
|
|
}
|
|
return pFootnoteText[uiFootnoteIndex].tInfo.szText;
|
|
} /* end of szGetFootnootText */
|
|
|
|
/*
|
|
* Get the notetype of the note at the given fileoffset
|
|
*/
|
|
notetype_enum
|
|
eGetNotetype(ULONG ulFileOffset)
|
|
{
|
|
size_t tIndex;
|
|
|
|
TRACE_MSG("eGetNotetype");
|
|
|
|
fail(aulFootnoteList == NULL && tFootnoteListLength != 0);
|
|
fail(aulEndnoteList == NULL && tEndnoteListLength != 0);
|
|
|
|
/* Go for the easy answers first */
|
|
if (tFootnoteListLength == 0 && tEndnoteListLength == 0) {
|
|
return notetype_is_unknown;
|
|
}
|
|
if (tEndnoteListLength == 0) {
|
|
return notetype_is_footnote;
|
|
}
|
|
if (tFootnoteListLength == 0) {
|
|
return notetype_is_endnote;
|
|
}
|
|
/* No easy answer, so we search */
|
|
for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
|
|
if (aulFootnoteList[tIndex] == ulFileOffset) {
|
|
return notetype_is_footnote;
|
|
}
|
|
}
|
|
for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
|
|
if (aulEndnoteList[tIndex] == ulFileOffset) {
|
|
return notetype_is_endnote;
|
|
}
|
|
}
|
|
/* Not found */
|
|
return notetype_is_unknown;
|
|
} /* end of eGetNotetype */
|