/* * pGetSectionInfo - get the section information */ const section_block_type * pGetSectionInfo(const section_block_type *pOld, ULONG ulCharPos) { const section_mem_type *pCurr; if (pOld == NULL || ulCharPos == 0) { if (pAnchor == NULL) { /* There are no records, make one */ vDefault2SectionInfoList(0); fail(pAnchor == NULL); } /* The first record */ NO_DBG_MSG("First record"); return &pAnchor->tInfo; } NO_DBG_HEX(ulCharPos); for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { NO_DBG_HEX(pCurr->ulCharPos); if (ulCharPos == pCurr->ulCharPos || ulCharPos + 1 == pCurr->ulCharPos) { NO_DBG_HEX(pCurr->ulCharPos); return &pCurr->tInfo; } } return pOld; } /* end of pGetSectionInfo */
/* * tFiletime - get a filetime property */ static time_t tFiletime(ULONG ulOffset, const UCHAR *aucBuffer) { double dHi, dLo, dTmp; ULONG ulHi, ulLo; time_t tResult; ulLo = ulGetLong(ulOffset + 4, aucBuffer); ulHi = ulGetLong(ulOffset + 8, aucBuffer); NO_DBG_HEX(ulHi); NO_DBG_HEX(ulLo); /* Move the starting point from 01 Jan 1601 to 01 Jan 1970 */ dHi = (double)ulHi - (double)TIME_OFFSET_HI; dLo = (double)ulLo - (double)TIME_OFFSET_LO; NO_DBG_FLT(dHi); NO_DBG_FLT(dLo); /* Combine the values and divide by 10^7 to get seconds */ dTmp = dLo / 10000000.0; /* 10^7 */ dTmp += dHi * 429.4967926; /* 2^32 / 10^7 */ NO_DBG_FLT(dTmp); /* Make a time_t */ if (dTmp - 0.5 < TIME_T_MIN || dTmp + 0.5 > TIME_T_MAX) { return (time_t)-1; } tResult = dTmp < 0.0 ? (time_t)(dTmp - 0.5) : (time_t)(dTmp + 0.5); NO_DBG_MSG(ctime(&tResult)); return tResult; } /* end of tFiletime */
/* * 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 */
/* * bAdd2TextBlockList - add an element to the text block list * * returns: TRUE when successful, otherwise FALSE */ BOOL bAdd2TextBlockList(const text_block_type *pTextBlock) { list_mem_type *pListMember; fail(pTextBlock == NULL); fail(pTextBlock->ulFileOffset == FC_INVALID); fail(pTextBlock->ulCharPos == CP_INVALID); fail(pTextBlock->ulLength == 0); fail(pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength)); NO_DBG_MSG("bAdd2TextBlockList"); NO_DBG_HEX(pTextBlock->ulFileOffset); NO_DBG_HEX(pTextBlock->ulCharPos); NO_DBG_HEX(pTextBlock->ulLength); NO_DBG_DEC(pTextBlock->bUsesUnicode); NO_DBG_DEC(pTextBlock->usPropMod); if (pTextBlock->ulFileOffset == FC_INVALID || pTextBlock->ulCharPos == CP_INVALID || pTextBlock->ulLength == 0 || (pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength))) { werr(0, "Software (textblock) error"); return FALSE; } /* * Check for continuous blocks of the same character size and * the same properties modifier */ if (pBlockLast != NULL && pBlockLast->tInfo.ulFileOffset + pBlockLast->tInfo.ulLength == pTextBlock->ulFileOffset && pBlockLast->tInfo.ulCharPos + pBlockLast->tInfo.ulLength == pTextBlock->ulCharPos && pBlockLast->tInfo.bUsesUnicode == pTextBlock->bUsesUnicode && pBlockLast->tInfo.usPropMod == pTextBlock->usPropMod) { /* These are continous blocks */ pBlockLast->tInfo.ulLength += pTextBlock->ulLength; return TRUE; } /* Make a new block */ pListMember = xmalloc(sizeof(list_mem_type)); /* Add the block to the list */ pListMember->tInfo = *pTextBlock; pListMember->pNext = NULL; if (pTextAnchor == NULL) { pTextAnchor = pListMember; } else { fail(pBlockLast == NULL); pBlockLast->pNext = pListMember; } pBlockLast = pListMember; return TRUE; } /* end of bAdd2TextBlockList */
/* * 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 Header/Footer Information for Word 8/9/10/11 files */ void vGet8HdrFtrInfo(FILE *pFile, const pps_type *pTable, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader) { ULONG *aulCharPos; UCHAR *aucBuffer; ULONG ulHdrFtrOffset, ulBeginHdrFtrInfo; size_t tHdrFtrInfoLen, tIndex, tOffset, tLen; fail(pFile == NULL || pTable == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginHdrFtrInfo = ulGetLong(0xf2, aucHeader); /* fcPlcfhdd */ NO_DBG_HEX(ulBeginHdrFtrInfo); tHdrFtrInfoLen = (size_t)ulGetLong(0xf6, aucHeader); /* lcbPlcfhdd */ NO_DBG_DEC(tHdrFtrInfoLen); if (tHdrFtrInfoLen < 8) { DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen); return; } aucBuffer = aucFillInfoBuffer(pFile, pTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginHdrFtrInfo, tHdrFtrInfoLen); if (aucBuffer == NULL) { return; } NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen); tLen = tHdrFtrInfoLen / 4 - 1; DBG_DEC_C(tLen % 12 != 1 && tLen % 12 != 7, tLen); /* Save the header/footer offsets */ aulCharPos = xcalloc(tLen, sizeof(ULONG)); for (tIndex = 0, tOffset = 0; tIndex < tLen; tIndex++, tOffset += 4) { ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer); NO_DBG_HEX(ulHdrFtrOffset); aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset); NO_DBG_HEX(aulCharPos[tIndex]); } vCreat8HdrFtrInfoList(aulCharPos, tLen); /* Clean up and leave */ aulCharPos = xfree(aulCharPos); aucBuffer = xfree(aucBuffer); } /* end of vGet8HdrFtrInfo */
/* * vBuildLfoList - build the LFO list (pllfo) */ void vBuildLfoList(const UCHAR *aucBuffer, size_t tBufLen) { size_t tRecords; int iIndex; fail(aucBuffer == NULL); if (tBufLen < 4) { return; } tRecords = (size_t)ulGetLong(0, aucBuffer); NO_DBG_DEC(tRecords); if (4 + 16 * tRecords > tBufLen || tRecords >= 0x7fff) { /* Just a sanity check */ DBG_DEC(tRecords); DBG_DEC(4 + 16 * tRecords); DBG_DEC(tBufLen); return; } aulLfoList = xcalloc(tRecords, sizeof(ULONG)); for (iIndex = 0; iIndex < (int)tRecords; iIndex++) { aulLfoList[iIndex] = ulGetLong(4 + 16 * iIndex, aucBuffer); NO_DBG_HEX(aulLfoList[iIndex]); } usLfoLen = (USHORT)tRecords; } /* end of vBuildLfoList */
/* * vAnalyseDocumentSummaryInfo - analyse the document summary information */ static void vAnalyseDocumentSummaryInfo(const UCHAR *aucBuffer) { ULONG ulOffset; size_t tIndex, tCount, tPropID, tPropType; tCount = (size_t)ulGetLong(4, aucBuffer); DBG_DEC(tCount); for (tIndex = 0; tIndex < tCount; tIndex++) { tPropID = (size_t)ulGetLong(8 + tIndex * 8, aucBuffer); ulOffset = ulGetLong(12 + tIndex * 8, aucBuffer); NO_DBG_DEC(tPropID); NO_DBG_HEX(ulOffset); tPropType = (size_t)ulGetLong(ulOffset, aucBuffer); NO_DBG_DEC(tPropType); switch (tPropID) { case PIDD_MANAGER: if (tPropType == VT_LPSTR && szManager == NULL) { szManager = szLpstr(ulOffset, aucBuffer); } break; case PIDD_COMPANY: if (tPropType == VT_LPSTR && szCompany == NULL) { szCompany = szLpstr(ulOffset, aucBuffer); } break; default: break; } } } /* end of vAnalyseDocumentSummaryInfo */
/* * vUpdateWriteable - update a writeable icon with a string */ void vUpdateWriteable(window_handle tWindow, icon_handle tIconNumber, const char *szString) { icon_block tIcon; caret_block tCaret; int iLen; fail(szString == NULL); NO_DBG_DEC(tIconNumber); NO_DBG_MSG(szString); Error_CheckFatal(Wimp_GetIconState(tWindow, tIconNumber, &tIcon)); NO_DBG_HEX(tIcon.flags); if (!tIcon.flags.data.text || !tIcon.flags.data.indirected) { werr(1, "Icon %d must be indirected text", (int)tIconNumber); return; } strncpy(tIcon.data.indirecttext.buffer, szString, tIcon.data.indirecttext.bufflen - 1); /* Ensure the caret is behind the last character of the text */ Error_CheckFatal(Wimp_GetCaretPosition(&tCaret)); if (tCaret.window == tWindow && tCaret.icon == tIconNumber) { iLen = strlen(tIcon.data.indirecttext.buffer); if (tCaret.index != iLen) { tCaret.index = iLen; Error_CheckFatal(Wimp_SetCaretPosition(&tCaret)); } } Error_CheckFatal(Wimp_SetIconState(tWindow, tIconNumber, 0, 0)); vUpdateIcon(tWindow, &tIcon); } /* end of vUpdateWriteable */
/* * vAdd2RowInfoList - Add an element to the Row Information List */ void vAdd2RowInfoList(const row_block_type *pRowBlock) { row_desc_type *pListMember; short *psTmp; int iIndex; fail(pRowBlock == NULL); if (pRowBlock->ulFileOffsetStart == FC_INVALID || pRowBlock->ulFileOffsetEnd == FC_INVALID || pRowBlock->ulFileOffsetStart == pRowBlock->ulFileOffsetEnd) { DBG_HEX_C(pRowBlock->ulFileOffsetStart != FC_INVALID, pRowBlock->ulFileOffsetStart); DBG_HEX_C(pRowBlock->ulFileOffsetEnd != FC_INVALID, pRowBlock->ulFileOffsetEnd); return; } NO_DBG_HEX(pRowBlock->ulFileOffsetStart); NO_DBG_HEX(pRowBlock->ulFileOffsetEnd); NO_DBG_DEC(pRowBlock->ucNumberOfColumns); /* Create the new list member */ pListMember = xmalloc(sizeof(row_desc_type)); /* Fill the new list member */ pListMember->tInfo = *pRowBlock; pListMember->pNext = NULL; /* Correct the values where needed */ for (iIndex = 0, psTmp = pListMember->tInfo.asColumnWidth; iIndex < (int)pListMember->tInfo.ucNumberOfColumns; iIndex++, psTmp++) { if (*psTmp < 0) { *psTmp = 0; DBG_MSG("The column width was negative"); } } /* Add the new member to the list */ if (pAnchor == NULL) { pAnchor = pListMember; pRowCurrent = pListMember; } else { fail(pRowLast == NULL); pRowLast->pNext = pListMember; } pRowLast = pListMember; } /* end of vAdd2RowInfoList */
/* * Build the list with Header/Footer Information for Word 6/7 files */ void vGet6HdrFtrInfo(FILE *pFile, ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader) { ULONG *aulCharPos; UCHAR *aucBuffer; ULONG ulHdrFtrOffset, ulBeginHdrFtrInfo; size_t tHdrFtrInfoLen, tIndex, tOffset, tLen; fail(pFile == NULL || aucHeader == NULL); fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN); fail(aulBBD == NULL); ulBeginHdrFtrInfo = ulGetLong(0xb0, aucHeader); /* fcPlcfhdd */ NO_DBG_HEX(ulBeginHdrFtrInfo); tHdrFtrInfoLen = (size_t)ulGetLong(0xb4, aucHeader); /* lcbPlcfhdd */ NO_DBG_DEC(tHdrFtrInfoLen); if (tHdrFtrInfoLen < 8) { DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen); return; } aucBuffer = xmalloc(tHdrFtrInfoLen); if (!bReadBuffer(pFile, ulStartBlock, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucBuffer, ulBeginHdrFtrInfo, tHdrFtrInfoLen)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen); tLen = tHdrFtrInfoLen / 4 - 1; /* Save the header/footer offsets */ aulCharPos = xcalloc(tLen, sizeof(ULONG)); for (tIndex = 0, tOffset = 0; tIndex < tLen; tIndex++, tOffset += 4) { ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer); NO_DBG_HEX(ulHdrFtrOffset); aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset); NO_DBG_HEX(aulCharPos[tIndex]); } vCreat6HdrFtrInfoList(aulCharPos, tLen); aulCharPos = xfree(aulCharPos); aucBuffer = xfree(aucBuffer); } /* end of vGet6HdrFtrInfo */
/* * bAdd2DataBlockList - add an element to the data block list * * Returns TRUE when successful, otherwise FALSE */ BOOL bAdd2DataBlockList(const data_block_type *pDataBlock) { data_mem_type *pListMember; fail(pDataBlock == NULL); fail(pDataBlock->ulFileOffset == FC_INVALID); fail(pDataBlock->ulDataPos == CP_INVALID); fail(pDataBlock->ulLength == 0); NO_DBG_MSG("bAdd2DataBlockList"); NO_DBG_HEX(pDataBlock->ulFileOffset); NO_DBG_HEX(pDataBlock->ulDataPos); NO_DBG_HEX(pDataBlock->ulLength); if (pDataBlock->ulFileOffset == FC_INVALID || pDataBlock->ulDataPos == CP_INVALID || pDataBlock->ulLength == 0) { werr(0, "Software (datablock) error"); return FALSE; } /* Check for continuous blocks */ if (pBlockLast != NULL && pBlockLast->tInfo.ulFileOffset + pBlockLast->tInfo.ulLength == pDataBlock->ulFileOffset && pBlockLast->tInfo.ulDataPos + pBlockLast->tInfo.ulLength == pDataBlock->ulDataPos) { /* These are continous blocks */ pBlockLast->tInfo.ulLength += pDataBlock->ulLength; return TRUE; } /* Make a new block */ pListMember = xmalloc(sizeof(data_mem_type)); /* Add the block to the data list */ pListMember->tInfo = *pDataBlock; pListMember->pNext = NULL; if (pAnchor == NULL) { pAnchor = pListMember; } else { fail(pBlockLast == NULL); pBlockLast->pNext = pListMember; } pBlockLast = pListMember; return TRUE; } /* end of bAdd2DataBlockList */
/* * tOpenFont - make the specified font the current font * * Returns the font reference number for use in a draw file */ drawfile_fontref tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize) { os_error *e; const char *szOurFontname; font_handle tFont; int iFontnumber; NO_DBG_MSG("tOpenFont"); NO_DBG_DEC(ucWordFontNumber); NO_DBG_HEX(usFontStyle); NO_DBG_DEC(usWordFontSize); /* Keep the relevant bits */ usFontStyle &= FONT_BOLD|FONT_ITALIC; NO_DBG_HEX(usFontStyle); iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle); szOurFontname = szGetOurFontname(iFontnumber); if (szOurFontname == NULL || szOurFontname[0] == '\0') { tFontCurr = (font_handle)-1; return (byte)0; } NO_DBG_MSG(szOurFontname); e = Font_FindFont(&tFont, (char *)szOurFontname, (int)usWordFontSize * 8, (int)usWordFontSize * 8, 0, 0); if (e != NULL) { switch (e->errnum) { case 523: werr(0, "%s", e->errmess); break; default: werr(0, "Open font error %d: %s", e->errnum, e->errmess); break; } tFontCurr = (font_handle)-1; return (drawfile_fontref)0; } tFontCurr = tFont; NO_DBG_DEC(tFontCurr); return (drawfile_fontref)(iFontnumber + 1); } /* end of tOpenFont */
/* * tOpenFont - make the specified font the current font * * Returns the font reference number */ drawfile_fontref tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize) { options_type tOptions; const char *szOurFontname; size_t tIndex; int iFontnumber; NO_DBG_MSG("tOpenFont"); NO_DBG_DEC(ucWordFontNumber); NO_DBG_HEX(usFontStyle); NO_DBG_DEC(usWordFontSize); /* Keep the relevant bits */ usFontStyle &= FONT_BOLD|FONT_ITALIC; NO_DBG_HEX(usFontStyle); vGetOptions(&tOptions); eEncoding = tOptions.eEncoding; bUsePlainText = tOptions.eConversionType != conversion_draw && tOptions.eConversionType != conversion_ps && tOptions.eConversionType != conversion_pdf; if (bUsePlainText) { /* Plain text, no fonts */ return (drawfile_fontref)0; } iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle); szOurFontname = szGetOurFontname(iFontnumber); if (szOurFontname == NULL || szOurFontname[0] == '\0') { DBG_DEC(iFontnumber); return (drawfile_fontref)0; } NO_DBG_MSG(szOurFontname); for (tIndex = 0; tIndex < elementsof(szFontnames); tIndex++) { if (STREQ(szFontnames[tIndex], szOurFontname)) { NO_DBG_DEC(tIndex); return (drawfile_fontref)tIndex; } } return (drawfile_fontref)0; } /* end of tOpenFont */
/* * vAdd2PictInfoList - Add an element to the Picture Information List */ void vAdd2PictInfoList(const picture_block_type *pPictureBlock) { picture_mem_type *pListMember; fail(pPictureBlock == NULL); NO_DBG_MSG("bAdd2PictInfoList"); if (pPictureBlock->ulFileOffset == FC_INVALID) { /* * This offset is really past the end of the file, * so don't waste any memory by storing it. */ return; } if (pPictureBlock->ulFileOffsetPicture == FC_INVALID) { /* * The place where this picture is supposed to be stored * doesn't exist. */ return; } NO_DBG_HEX(pPictureBlock->ulFileOffset); NO_DBG_HEX(pPictureBlock->ulFileOffsetPicture); NO_DBG_HEX(pPictureBlock->ulPictureOffset); /* Create list member */ pListMember = xmalloc(sizeof(picture_mem_type)); /* Fill the list member */ pListMember->tInfo = *pPictureBlock; pListMember->pNext = NULL; /* Add the new member to the list */ if (pAnchor == NULL) { pAnchor = pListMember; } else { fail(pPictureLast == NULL); pPictureLast->pNext = pListMember; } pPictureLast = pListMember; } /* end of vAdd2PictInfoList */
/* * vAdd2FontInfoList - Add an element to the Font Information List */ void vAdd2FontInfoList(const font_block_type *pFontBlock) { font_mem_type *pListMember; fail(pFontBlock == NULL); NO_DBG_MSG("bAdd2FontInfoList"); if (pFontBlock->ulFileOffset == FC_INVALID) { /* * This offset is really past the end of the file, * so don't waste any memory by storing it. */ return; } NO_DBG_HEX(pFontBlock->ulFileOffset); NO_DBG_DEC_C(pFontBlock->ucFontNumber != 0, pFontBlock->ucFontNumber); NO_DBG_DEC_C(pFontBlock->usFontSize != DEFAULT_FONT_SIZE, pFontBlock->usFontSize); NO_DBG_DEC_C(pFontBlock->ucFontColor != 0, pFontBlock->ucFontColor); NO_DBG_HEX_C(pFontBlock->usFontStyle != 0x00, pFontBlock->usFontStyle); if (pFontLast != NULL && pFontLast->tInfo.ulFileOffset == pFontBlock->ulFileOffset) { /* * If two consecutive fonts share the same * offset, remember only the last font */ fail(pFontLast->pNext != NULL); pFontLast->tInfo = *pFontBlock; return; } /* Create list member */ pListMember = xmalloc(sizeof(font_mem_type)); /* Fill the list member */ pListMember->tInfo = *pFontBlock; pListMember->pNext = NULL; /* Correct the values where needed */ vCorrectFontValues(&pListMember->tInfo); /* Add the new member to the list */ if (pAnchor == NULL) { pAnchor = pListMember; } else { fail(pFontLast == NULL); pFontLast->pNext = pListMember; } pFontLast = pListMember; } /* end of vAdd2FontInfoList */
/* * Build the list with Header/Footer Information for WinWord 1/2 files */ void vGet2HdrFtrInfo(FILE *pFile, const UCHAR *aucHeader) { ULONG *aulCharPos; UCHAR *aucBuffer; ULONG ulHdrFtrOffset, ulBeginHdrFtrInfo; size_t tHdrFtrInfoLen, tIndex, tOffset, tLen; fail(pFile == NULL || aucHeader == NULL); ulBeginHdrFtrInfo = ulGetLong(0x9a, aucHeader); /* fcPlcfhdd */ NO_DBG_HEX(ulBeginHdrFtrInfo); tHdrFtrInfoLen = (size_t)usGetWord(0x9e, aucHeader); /* cbPlcfhdd */ NO_DBG_DEC(tHdrFtrInfoLen); if (tHdrFtrInfoLen < 8) { DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen); return; } aucBuffer = xmalloc(tHdrFtrInfoLen); if (!bReadBytes(aucBuffer, tHdrFtrInfoLen, ulBeginHdrFtrInfo, pFile)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen); tLen = tHdrFtrInfoLen / 4 - 1; /* Save the header/footer offsets */ aulCharPos = xcalloc(tLen, sizeof(ULONG)); for (tIndex = 0, tOffset = 0; tIndex < tLen; tIndex++, tOffset += 4) { ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer); NO_DBG_HEX(ulHdrFtrOffset); aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset); NO_DBG_HEX(aulCharPos[tIndex]); } vCreat2HdrFtrInfoList(aulCharPos, tLen); aulCharPos = xfree(aulCharPos); aucBuffer = xfree(aucBuffer); } /* end of vGet2HdrFtrInfo */
/* * vAnalyseSummaryInfo - analyse the summary information */ static void vAnalyseSummaryInfo(const UCHAR *aucBuffer) { ULONG ulOffset; size_t tIndex, tCount, tPropID, tPropType; tCount = (size_t)ulGetLong(4, aucBuffer); DBG_DEC(tCount); for (tIndex = 0; tIndex < tCount; tIndex++) { tPropID = (size_t)ulGetLong(8 + tIndex * 8, aucBuffer); ulOffset = ulGetLong(12 + tIndex * 8, aucBuffer); NO_DBG_DEC(tPropID); NO_DBG_HEX(ulOffset); tPropType = (size_t)ulGetLong(ulOffset, aucBuffer); NO_DBG_DEC(tPropType); switch (tPropID) { case PID_TITLE: if (tPropType == VT_LPSTR && szTitle == NULL) { szTitle = szLpstr(ulOffset, aucBuffer); } break; case PID_SUBJECT: if (tPropType == VT_LPSTR && szSubject == NULL) { szSubject = szLpstr(ulOffset, aucBuffer); } break; case PID_AUTHOR: if (tPropType == VT_LPSTR && szAuthor == NULL) { szAuthor = szLpstr(ulOffset, aucBuffer); } break; case PID_CREATE_DTM: if (tPropType == VT_FILETIME && tCreateDtm == (time_t)-1) { tCreateDtm = tFiletime(ulOffset, aucBuffer); } break; case PID_LASTSAVE_DTM: if (tPropType == VT_FILETIME && tLastSaveDtm == (time_t)-1) { tLastSaveDtm = tFiletime(ulOffset, aucBuffer); } break; case PID_APPNAME: if (tPropType == VT_LPSTR && szAppName == NULL) { szAppName = szLpstr(ulOffset, aucBuffer); } break; default: break; } } } /* end of vAnalyseSummaryInfo */
/* * vAdd2ListInfoList - add an element to the List Information list */ void vAdd2ListInfoList(ULONG ulListID, USHORT usIstd, UCHAR ucListLevel, const list_block_type *pListBlock) { list_desc_type *pListMember; fail(pListBlock == NULL); NO_DBG_HEX(ulListID); NO_DBG_DEC(usIstd); NO_DBG_DEC(ucListLevel); NO_DBG_DEC(pListBlock->ulStartAt); NO_DBG_DEC(pListBlock->bNoRestart); NO_DBG_DEC(pListBlock->sLeftIndent); NO_DBG_HEX(pListBlock->ucNFC); NO_DBG_HEX(pListBlock->usListChar); /* Create list member */ pListMember = xmalloc(sizeof(list_desc_type)); /* Fill the list member */ pListMember->tInfo = *pListBlock; pListMember->ulListID = ulListID; pListMember->usIstd = usIstd; pListMember->ucListLevel = ucListLevel; pListMember->pNext = NULL; /* Correct the values where needed */ if (pListMember->tInfo.ulStartAt > 0xffff) { DBG_DEC(pListMember->tInfo.ulStartAt); pListMember->tInfo.ulStartAt = 1; } /* Add the new member to the list */ if (pAnchor == NULL) { pAnchor = pListMember; } else { fail(pBlockLast == NULL); pBlockLast->pNext = pListMember; } pBlockLast = pListMember; } /* end of vAdd2ListInfoList */
/* * usGetIstd - get the istd that belongs to the given file offset */ USHORT usGetIstd(ULONG ulFileOffset) { const style_mem_type *pCurr, *pBest, *pStart; ULONG ulSeq, ulBest; ulSeq = ulGetSeqNumber(ulFileOffset); if (ulSeq == FC_INVALID) { return ISTD_NORMAL; } NO_DBG_HEX(ulFileOffset); NO_DBG_DEC(ulSeq); if (bInSequence && pMidPtr != NULL && ulSeq > pMidPtr->ulSequenceNumber) { /* The istd is in the second half of the chained list */ pStart = pMidPtr; } else { pStart = pAnchor; } pBest = NULL; ulBest = 0; for (pCurr = pStart; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr->ulSequenceNumber != FC_INVALID && (pBest == NULL || pCurr->ulSequenceNumber > ulBest) && pCurr->ulSequenceNumber <= ulSeq) { pBest = pCurr; ulBest = pCurr->ulSequenceNumber; } if (bInSequence && pCurr->ulSequenceNumber > ulSeq) { break; } } NO_DBG_DEC(ulBest); if (pBest == NULL) { return ISTD_NORMAL; } NO_DBG_DEC(pBest->tInfo.usIstd); return pBest->tInfo.usIstd; } /* end of usGetIstd */
/* * Build the lists with Document Property Information for Word 8/9/10/11 files */ void vGet8DopInfo(FILE *pFile, const pps_type *pTable, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader) { document_block_type tDocument; UCHAR *aucBuffer; ULONG ulBeginDocpInfo, ulTmp; size_t tDocpInfoLen; USHORT usTmp; fail(pFile == NULL || pTable == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */ NO_DBG_HEX(ulBeginSectInfo); tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */ NO_DBG_DEC(tSectInfoLen); if (tDocpInfoLen < 28) { DBG_MSG("No Document information"); return; } aucBuffer = aucFillInfoBuffer(pFile, pTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginDocpInfo, tDocpInfoLen); if (aucBuffer == NULL) { return; } usTmp = usGetWord(0x00, aucBuffer); tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */ tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */ ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */ tDocument.tCreateDate = tConvertDTTM(ulTmp); ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */ tDocument.tRevisedDate = tConvertDTTM(ulTmp); vCreateDocumentInfoList(&tDocument); aucBuffer = xfree(aucBuffer); } /* end of vGet8DopInfo */
/* * aucFillInfoBuffer - fill the information buffer * * Returns the information buffer when successful, otherwise NULL */ static UCHAR * aucFillInfoBuffer(FILE *pFile, const pps_type *pTable, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, ULONG ulBeginInfo, size_t tInfoLen) { const ULONG *aulBlockDepot; UCHAR *aucBuffer; size_t tBlockDepotLen, tBlockSize; fail(pFile == NULL || pTable == NULL); fail(aulBBD == NULL || aulSBD == NULL); fail(tInfoLen == 0); NO_DBG_DEC(pTable->ulSB); NO_DBG_HEX(pTable->ulSize); if (pTable->ulSize == 0) { DBG_MSG("No information"); return NULL; } if (pTable->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(tInfoLen); if (!bReadBuffer(pFile, pTable->ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucBuffer, ulBeginInfo, tInfoLen)) { aucBuffer = xfree(aucBuffer); return NULL; } return aucBuffer; } /* end of aucFillInfoBuffer */
/* * Get a matching record from the List Information List * * Returns NULL if no matching records is found */ const list_block_type * pGetListInfo(USHORT usListIndex, UCHAR ucListLevel) { list_desc_type *pCurr; list_block_type *pNearMatch; ULONG ulListID; if (usListIndex == 0) { return NULL; } if (usListIndex - 1 >= usLfoLen || ucListLevel > 8) { DBG_DEC(usListIndex); DBG_DEC(ucListLevel); return NULL; } fail(aulLfoList == NULL); ulListID = aulLfoList[usListIndex - 1]; NO_DBG_HEX(ulListID); pNearMatch = NULL; for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr->ulListID != ulListID) { /* No match */ continue; } if (pCurr->ucListLevel == ucListLevel) { /* Exact match */ return &pCurr->tInfo; } if (pCurr->ucListLevel == 0) { /* Near match */ pNearMatch = &pCurr->tInfo; } } /* No exact match, use a near match if any */ return pNearMatch; } /* end of pGetListInfo */
/* * pucAnalyseSummaryInfoHeader- */ static UCHAR * pucAnalyseSummaryInfoHeader(FILE *pFile, ULONG ulStartBlock, ULONG ulSize, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen) { const ULONG *aulBlockDepot; UCHAR *aucBuffer; size_t tBlockDepotLen, tBlockSize, tSectionCount, tLength; ULONG ulTmp, ulOffset; USHORT usLittleEndian, usEmpty, usOS, usVersion; UCHAR aucHdr[P_HEADER_SZ], aucSecLst[P_SECTION_MAX_SZ]; if (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; } if (tBlockDepotLen == 0) { DBG_MSG("The Block Depot length is zero"); return NULL; } /* Read the Summery Information header */ if (!bReadBuffer(pFile, ulStartBlock, aulBlockDepot, tBlockDepotLen, tBlockSize, aucHdr, 0, P_HEADER_SZ)) { return NULL; } NO_DBG_PRINT_BLOCK(aucHdr, P_HEADER_SZ); /* Analyse the Summery Information header */ usLittleEndian = usGetWord(0, aucHdr); if (usLittleEndian != 0xfffe) { DBG_HEX(usLittleEndian); DBG_MSG_C(usLittleEndian == 0xfeff, "Big endian"); return NULL; } usEmpty = usGetWord(2, aucHdr); if (usEmpty != 0x0000) { DBG_DEC(usEmpty); return NULL; } ulTmp = ulGetLong(4, aucHdr); DBG_HEX(ulTmp); usOS = (USHORT)(ulTmp >> 16); usVersion = (USHORT)(ulTmp & 0xffff); switch (usOS) { case 0: DBG_MSG("Win16"); DBG_HEX(usVersion); break; case 1: DBG_MSG("MacOS"); DBG_HEX(usVersion); break; case 2: DBG_MSG("Win32"); DBG_HEX(usVersion); break; default: DBG_DEC(usOS); DBG_HEX(usVersion); break; } tSectionCount = (size_t)ulGetLong(24, aucHdr); DBG_DEC_C(tSectionCount != 1 && tSectionCount != 2, tSectionCount); if (tSectionCount != 1 && tSectionCount != 2) { return NULL; } /* Read the Summery Information Section Lists */ if (!bReadBuffer(pFile, ulStartBlock, aulBlockDepot, tBlockDepotLen, tBlockSize, aucSecLst, P_HEADER_SZ, P_SECTION_SZ(tSectionCount))) { return NULL; } NO_DBG_PRINT_BLOCK(aucSecLst, P_SECTION_SZ(tSectionCount)); ulTmp = ulGetLong(0, aucSecLst); DBG_HEX(ulTmp); ulTmp = ulGetLong(4, aucSecLst); DBG_HEX(ulTmp); ulTmp = ulGetLong(8, aucSecLst); DBG_HEX(ulTmp); ulTmp = ulGetLong(12, aucSecLst); DBG_HEX(ulTmp); ulOffset = ulGetLong(16, aucSecLst); DBG_DEC_C(ulOffset != P_HEADER_SZ + P_SECTIONLIST_SZ && ulOffset != P_HEADER_SZ + 2 * P_SECTIONLIST_SZ, ulOffset); fail(ulOffset != P_HEADER_SZ + P_SECTIONLIST_SZ && ulOffset != P_HEADER_SZ + 2 * P_SECTIONLIST_SZ); tLength = (size_t)ulGetLong(tSectionCount * P_SECTIONLIST_SZ, aucSecLst); NO_DBG_HEX(tLength); fail(ulOffset + tLength > ulSize); /* Read the Summery Information */ aucBuffer = xmalloc(tLength); if (!bReadBuffer(pFile, ulStartBlock, aulBlockDepot, tBlockDepotLen, tBlockSize, aucBuffer, ulOffset, tLength)) { aucBuffer = xfree(aucBuffer); return NULL; } NO_DBG_PRINT_BLOCK(aucBuffer, tLength); return aucBuffer; } /* end of pucAnalyseSummaryInfoHeader */
/* * pSplitList - split the specified list in a printable part and a leftover part * * returns the pointer to the leftover part */ output_type * pSplitList(output_type *pAnchor) { output_type *pCurr, *pLeftOver; int iIndex; fail(pAnchor == NULL); for (pCurr = pAnchor; pCurr->pNext != NULL; pCurr = pCurr->pNext) ; /* EMPTY */ iIndex = -1; for (; pCurr != NULL; pCurr = pCurr->pPrev) { iIndex = iFindSplit(pCurr->szStorage, pCurr->tNextFree); if (iIndex >= 0) { break; } } if (pCurr == NULL || iIndex < 0) { /* No split, no leftover */ return NULL; } /* Split over the iIndex-th character */ NO_DBG_MSG("pLeftOver"); pLeftOver = xmalloc(sizeof(*pLeftOver)); fail(pCurr->tNextFree < (size_t)iIndex); pLeftOver->tStorageSize = pCurr->tNextFree - (size_t)iIndex; pLeftOver->szStorage = xmalloc(pLeftOver->tStorageSize); pLeftOver->tNextFree = pCurr->tNextFree - (size_t)iIndex - 1; (void)strncpy(pLeftOver->szStorage, pCurr->szStorage + iIndex + 1, pLeftOver->tNextFree); pLeftOver->szStorage[pLeftOver->tNextFree] = '\0'; NO_DBG_MSG(pLeftOver->szStorage); pLeftOver->ucFontColor = pCurr->ucFontColor; pLeftOver->usFontStyle = pCurr->usFontStyle; pLeftOver->tFontRef = pCurr->tFontRef; pLeftOver->usFontSize = pCurr->usFontSize; pLeftOver->lStringWidth = lComputeStringWidth( pLeftOver->szStorage, pLeftOver->tNextFree, pLeftOver->tFontRef, pLeftOver->usFontSize); pLeftOver->pPrev = NULL; pLeftOver->pNext = pCurr->pNext; if (pLeftOver->pNext != NULL) { pLeftOver->pNext->pPrev = pLeftOver; } fail(!bCheckDoubleLinkedList(pLeftOver)); NO_DBG_MSG("pAnchor"); NO_DBG_HEX(pCurr->szStorage[iIndex]); while (iIndex >= 0 && isspace((int)(UCHAR)pCurr->szStorage[iIndex])) { iIndex--; } pCurr->tNextFree = (size_t)iIndex + 1; pCurr->szStorage[pCurr->tNextFree] = '\0'; NO_DBG_MSG(pCurr->szStorage); pCurr->lStringWidth = lComputeStringWidth( pCurr->szStorage, pCurr->tNextFree, pCurr->tFontRef, pCurr->usFontSize); pCurr->pNext = NULL; fail(!bCheckDoubleLinkedList(pAnchor)); return pLeftOver; } /* end of pSplitList */
/* * 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 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 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 lists with Paragraph Information for WinWord 1/2 files */ void vGet2PapInfo(FILE *pFile, const UCHAR *aucHeader) { row_block_type tRow; style_block_type tStyle; USHORT *ausParfPage; UCHAR *aucBuffer; ULONG ulCharPos, ulCharPosFirst, ulCharPosLast; ULONG ulBeginParfInfo; size_t tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen; int iIndex, iIndex2, iRun, iFodo, iLen; row_info_enum eRowInfo; USHORT usParfFirstPage, usCount, usIstd; UCHAR ucStc; UCHAR aucFpage[BIG_BLOCK_SIZE]; fail(pFile == NULL || aucHeader == NULL); ulBeginParfInfo = ulGetLong(0xa6, aucHeader); /* fcPlcfbtePapx */ NO_DBG_HEX(ulBeginParfInfo); tParfInfoLen = (size_t)usGetWord(0xaa, aucHeader); /* cbPlcfbtePapx */ NO_DBG_DEC(tParfInfoLen); if (tParfInfoLen < 4) { DBG_DEC(tParfInfoLen); return; } aucBuffer = xmalloc(tParfInfoLen); if (!bReadBytes(aucBuffer, tParfInfoLen, ulBeginParfInfo, pFile)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen); tLen = (tParfInfoLen - 4) / 6; ausParfPage = xcalloc(tLen, sizeof(USHORT)); for (iIndex = 0, tOffset = (tLen + 1) * 4; iIndex < (int)tLen; iIndex++, tOffset += 2) { ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer); NO_DBG_DEC(ausParfPage[iIndex]); } DBG_HEX(ulGetLong(0, aucBuffer)); aucBuffer = xfree(aucBuffer); tParfPageNum = (size_t)usGetWord(0x144, aucHeader); /* cpnBtePap */ DBG_DEC(tParfPageNum); if (tLen < tParfPageNum) { /* Replace ParfPage by a longer version */ tLenOld = tLen; usParfFirstPage = usGetWord(0x140, aucHeader); /* pnPapFirst */ DBG_DEC(usParfFirstPage); tLen += tParfPageNum - 1; tSize = tLen * sizeof(USHORT); ausParfPage = xrealloc(ausParfPage, tSize); /* Add new values */ usCount = usParfFirstPage + 1; for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) { ausParfPage[iIndex] = usCount; NO_DBG_DEC(ausParfPage[iIndex]); usCount++; } } (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; for (iIndex = 0; iIndex < (int)tLen; iIndex++) { if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE, (ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE, pFile)) { break; } NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE); iRun = (int)ucGetByte(0x1ff, aucFpage); NO_DBG_DEC(iRun); for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) { if ((iRun + 1) * 4 + iIndex2 * 1 >= BIG_BLOCK_SIZE) { break; } NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage)); iFodo = 2 * (int)ucGetByte( (iRun + 1) * 4 + iIndex2 * 1, aucFpage); if (iFodo <= 0) { continue; } iLen = 2 * (int)ucGetByte(iFodo, aucFpage); ucStc = ucGetByte(iFodo + 1, aucFpage); usIstd = usStc2istd(ucStc); vFillStyleFromStylesheet(usIstd, &tStyle); vGet2StyleInfo(iFodo, aucFpage + 8, iLen - 8, &tStyle); ulCharPos = ulGetLong(iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPos); tStyle.ulFileOffset = ulCharPos; vAdd2StyleInfoList(&tStyle); eRowInfo = eGet2RowInfo(iFodo, aucFpage + 8, iLen - 8, &tRow); switch(eRowInfo) { case found_a_cell: if (ulCharPosFirst != CP_INVALID) { break; } ulCharPosFirst = ulGetLong( iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosFirst); tRow.ulCharPosStart = ulCharPosFirst; tRow.ulFileOffsetStart = ulCharPosFirst; break; case found_end_of_row: ulCharPosLast = ulGetLong( iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosLast); tRow.ulCharPosEnd = ulCharPosLast; /* Add 1 for compatiblity with Word 6 and up */ tRow.ulFileOffsetEnd = ulCharPosLast + 1; vAdd2RowInfoList(&tRow); (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; break; case found_nothing: break; default: DBG_DEC(eRowInfo); break; } } } ausParfPage = xfree(ausParfPage); } /* end of vGet2PapInfo */
/* * 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 */