📄 summary.c
字号:
/* * summary.c * Copyright (C) 2002-2005 A.J. van Os; Released under GNU GPL * * Description: * Read the summary information of a Word document */#include <time.h>#include <string.h>#include "antiword.h"#define P_HEADER_SZ 28#define P_SECTIONLIST_SZ 20#define P_LENGTH_SZ 4#define P_SECTION_MAX_SZ (2 * P_SECTIONLIST_SZ + P_LENGTH_SZ)#define P_SECTION_SZ(x) ((x) * P_SECTIONLIST_SZ + P_LENGTH_SZ)#define PID_TITLE 2#define PID_SUBJECT 3#define PID_AUTHOR 4#define PID_CREATE_DTM 12#define PID_LASTSAVE_DTM 13#define PID_APPNAME 18#define PIDD_MANAGER 14#define PIDD_COMPANY 15#define VT_LPSTR 30#define VT_FILETIME 64#define TIME_OFFSET_HI 0x019db1de#define TIME_OFFSET_LO 0xd53e8000static char *szTitle = NULL;static char *szSubject = NULL;static char *szAuthor = NULL;static time_t tCreateDtm = (time_t)-1;static time_t tLastSaveDtm= (time_t)-1;static char *szAppName = NULL;static char *szManager = NULL;static char *szCompany = NULL;static USHORT usLid = (USHORT)-1;/* * vDestroySummaryInfo - destroy the summary information */voidvDestroySummaryInfo(void){ TRACE_MSG("vDestroySummaryInfo"); szTitle = xfree(szTitle); szSubject = xfree(szSubject); szAuthor = xfree(szAuthor); tCreateDtm = (time_t)-1; tLastSaveDtm = (time_t)-1; szAppName = xfree(szAppName); szManager = xfree(szManager); szCompany = xfree(szCompany); usLid = (USHORT)-1;} /* end of vDestroySummaryInfo *//* * tConvertDosDate - convert DOS date format * * returns Unix time_t or -1 */static time_ttConvertDosDate(const char *szDosDate){ struct tm tTime; const char *pcTmp; time_t tResult; memset(&tTime, 0, sizeof(tTime)); pcTmp = szDosDate; /* Get the month */ if (!isdigit(*pcTmp)) { return (time_t)-1; } tTime.tm_mon = (int)(*pcTmp - '0'); pcTmp++; if (isdigit(*pcTmp)) { tTime.tm_mon *= 10; tTime.tm_mon += (int)(*pcTmp - '0'); pcTmp++; } /* Get the first separater */ if (isalnum(*pcTmp)) { return (time_t)-1; } pcTmp++; /* Get the day */ if (!isdigit(*pcTmp)) { return (time_t)-1; } tTime.tm_mday = (int)(*pcTmp - '0'); pcTmp++; if (isdigit(*pcTmp)) { tTime.tm_mday *= 10; tTime.tm_mday += (int)(*pcTmp - '0'); pcTmp++; } /* Get the second separater */ if (isalnum(*pcTmp)) { return (time_t)-1; } pcTmp++; /* Get the year */ if (!isdigit(*pcTmp)) { return (time_t)-1; } tTime.tm_year = (int)(*pcTmp - '0'); pcTmp++; if (isdigit(*pcTmp)) { tTime.tm_year *= 10; tTime.tm_year += (int)(*pcTmp - '0'); pcTmp++; } /* Check the values */ if (tTime.tm_mon == 0 || tTime.tm_mday == 0 || tTime.tm_mday > 31) { return (time_t)-1; } /* Correct the values */ tTime.tm_mon--; /* From 01-12 to 00-11 */ if (tTime.tm_year < 80) { tTime.tm_year += 100; /* 00 means 2000 is 100 */ } tTime.tm_isdst = -1; tResult = mktime(&tTime); NO_DBG_MSG(ctime(&tResult)); return tResult;} /* end of tConvertDosDate *//* * szLpstr - get a zero terminate string property */static char *szLpstr(ULONG ulOffset, const UCHAR *aucBuffer){ char *szStart, *szResult, *szTmp; size_t tSize; tSize = (size_t)ulGetLong(ulOffset + 4, aucBuffer); NO_DBG_DEC(tSize); if (tSize == 0) { return NULL; } /* Remove white space from the start of the string */ szStart = (char *)aucBuffer + ulOffset + 8; NO_DBG_MSG(szStart); fail(strlen(szStart) >= tSize); while (isspace(*szStart)) { szStart++; } if (szStart[0] == '\0') { return NULL; } szResult = xstrdup(szStart); /* Remove white space from the end of the string */ szTmp = szResult + strlen(szResult) - 1; while (isspace(*szTmp)) { *szTmp = '\0'; szTmp--; } NO_DBG_MSG(szResult); return szResult;} /* end of szLpstr *//* * tFiletime - get a filetime property */static time_ttFiletime(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 *//* * vAnalyseSummaryInfo - analyse the summary information */static voidvAnalyseSummaryInfo(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 *//* * vAnalyseDocumentSummaryInfo - analyse the document summary information */static voidvAnalyseDocumentSummaryInfo(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 *//* * 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 *//* * vSet0SummaryInfo - set summary information from a Word for DOS file */voidvSet0SummaryInfo(FILE *pFile, const UCHAR *aucHeader){ UCHAR *aucBuffer; ULONG ulBeginSumdInfo, ulBeginNextBlock; size_t tLen; USHORT usCodepage, usOffset; TRACE_MSG("vSet0SummaryInfo"); fail(pFile == NULL || aucHeader == NULL); /* First check the header */ usCodepage = usGetWord(0x7e, aucHeader); DBG_DEC(usCodepage); switch (usCodepage) { case 850: usLid = 0x0809; break; /* Latin1 -> British English */ case 862: usLid = 0x040d; break; /* Hebrew */ case 866: usLid = 0x0419; break; /* Russian */ case 0: case 437: default: usLid = 0x0409; break; /* ASCII -> American English */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -