/* * Extract and verify the header of a resource fork. */ /*static*/ bool ReformatResourceFork::ReadHeader(const uint8_t* srcBuf, long srcLen, long* pFileVersion, long* pFileToMap, long* pFileMapSize, bool* pLittleEndian) { if (srcLen < 128) { LOGI("ReformatResource: invalid len %d", srcLen); return false; } *pFileVersion = Get32LE(srcBuf); if (*pFileVersion == 0) *pLittleEndian = true; else *pLittleEndian = false; *pFileVersion = Get32(srcBuf, *pLittleEndian); *pFileToMap = Get32(srcBuf+4, *pLittleEndian); *pFileMapSize = Get32(srcBuf+8, *pLittleEndian); if (*pFileVersion != 0) return false; if (*pFileMapSize <= 0 || *pFileMapSize >= srcLen || *pFileToMap <= 0 || *pFileToMap >= srcLen) { return false; } return true; }
/* * Print the contents of the text blocks. * * We're assured that the text block format is correct because we had to * skip through them earlier. We don't really need to worry about running * off the end due to a bad file. */ const uint8_t* ReformatAWGS_WP::FindTextBlock(const Chunk* pChunk, int blockNum) { const uint8_t* blockPtr = pChunk->textBlocks; uint32_t blockSize; while (blockNum--) { blockSize = Get32LE(blockPtr); blockPtr += 4 + blockSize; } return blockPtr; }
/* * Skip past a series of text blocks. * * Returns "true" on success, "false" on failure. */ bool ReformatAWGS_WP::SkipTextBlocks(const uint8_t** pSrcBuf, long* pSrcLen, int textBlockCount) { uint32_t blockSize; const uint8_t* srcBuf = *pSrcBuf; long srcLen = *pSrcLen; LOGI("Scanning %d text blocks", textBlockCount); if (srcLen < 4) return false; while (textBlockCount--) { blockSize = Get32LE(srcBuf); srcBuf += 4; srcLen -= 4; LOGI("+++ blockSize=%lu srcLen=%ld", blockSize, srcLen); if ((long) blockSize < kMinTextBlockSize) { LOGI("Block size too small (%d - %d)", blockSize, Get16LE(srcBuf)); return false; } if ((long) blockSize > srcLen) { LOGI("Ran off the end in doc text blocks"); return false; } if (Get16LE(srcBuf) != blockSize || Get16LE(srcBuf+2) != blockSize) { LOGI("AWGS WARNING: inconsistent block size values (%ld vs %d/%d)", blockSize, Get16LE(srcBuf), Get16LE(srcBuf+2)); /* okay to ignore it, so long as everything else works out */ } srcBuf += blockSize; srcLen -= blockSize; } *pSrcBuf = srcBuf; *pSrcLen = srcLen; return true; }
/* * Output a single chunk. We do this by walking down the saveArray. */ void ReformatAWGS_WP::PrintChunk(const Chunk* pChunk) { const int kDefaultStatusBits = kAWGSJustifyLeft | kAWGSSingleSpace; SaveArrayEntry sae; const uint8_t* saveArray; int saCount; const uint8_t* blockPtr; long blockLen; const uint8_t* pRuler; uint16_t rulerStatusBits; saveArray = pChunk->saveArray; saCount = pChunk->saveArrayCount; for ( ; saCount > 0; saCount--, saveArray += kSaveArrayEntryLen) { UnpackSaveArrayEntry(saveArray, &sae); /* * Page-break paragraphs have no real data and an invalid value * in the "rulerNum" field. So we just throw out a page break * here and call it a day. */ if (sae.attributes == 0x0001) { /* this is a page-break paragraph */ RTFSetColor(kColorMediumBlue); RTFSetFont(kFontCourierNew); RTFSetFontSize(10); BufPrintf("<page-break>"); RTFSetColor(kColorNone); RTFNewPara(); RTFPageBreak(); // only supported by Word continue; } if (sae.rulerNum < pChunk->numRulers) { pRuler = pChunk->rulers + sae.rulerNum * kRulerEntryLen; rulerStatusBits = Get16LE(pRuler + 2); } else { LOGI("AWGS_WP GLITCH: invalid ruler index %d", sae.rulerNum); rulerStatusBits = kDefaultStatusBits; } if (rulerStatusBits & kAWGSJustifyFull) RTFParaJustify(); else if (rulerStatusBits & kAWGSJustifyRight) RTFParaRight(); else if (rulerStatusBits & kAWGSJustifyCenter) RTFParaCenter(); else if (rulerStatusBits & kAWGSJustifyLeft) RTFParaLeft(); RTFSetPara(); /* * Find the text block that holds this paragraph. We could speed * this up by creating an array of entries rather than walking the * list every time. However, the block count tends to be fairly * small (e.g. 7 for a 16K doc). */ blockPtr = FindTextBlock(pChunk, sae.textBlock); if (blockPtr == NULL) { LOGI("AWGS_WP bad textBlock %d", sae.textBlock); return; } blockLen = (long) Get32LE(blockPtr); if (blockLen <= 0 || blockLen > 65535) { LOGI("AWGS_WP invalid block len %d", blockLen); return; } blockPtr += 4; if (sae.offset >= blockLen) { LOGI("AWGS_WP bad offset: %d, blockLen=%ld", sae.offset, blockLen); return; } PrintParagraph(blockPtr + sae.offset, blockLen - sae.offset); } }