StyleData *StyleData::clone() const { StyleData *data = new StyleData(); for (int i = 0; i < getStyleCount(); i++) data->addStyle(getStyleIndex(i), getStyle(i)->clone()); return data; }
bool OleMainStream::readStylesheet(const char *headerBuffer, const OleEntry &tableEntry) { //STSH structure is a stylesheet unsigned int beginStshInfo = OleUtil::getU4Bytes(headerBuffer, 0xa2); // address of STSH structure std::size_t stshInfoLength = (std::size_t)OleUtil::getU4Bytes(headerBuffer, 0xa6); // length of STSH structure OleStream tableStream(myStorage, tableEntry, myBaseStream); char *buffer = new char[stshInfoLength]; if (!tableStream.seek(beginStshInfo, true)) { ZLLogger::Instance().println("DocPlugin", "problems with reading STSH structure"); return false; } if (tableStream.read(buffer, stshInfoLength) != stshInfoLength) { ZLLogger::Instance().println("DocPlugin", "problems with reading STSH structure, invalid length"); return false; } std::size_t stdCount = (std::size_t)OleUtil::getU2Bytes(buffer, 2); std::size_t stdBaseInFile = (std::size_t)OleUtil::getU2Bytes(buffer, 4); myStyleSheet.resize(stdCount); std::vector<bool> isFilled; isFilled.resize(stdCount, false); std::size_t stdLen = 0; bool styleSheetWasChanged = false; do { //make it in while loop, because some base style can be after their successors styleSheetWasChanged = false; for (std::size_t index = 0, offset = 2 + (std::size_t)OleUtil::getU2Bytes(buffer, 0); index < stdCount; index++, offset += 2 + stdLen) { stdLen = (std::size_t)OleUtil::getU2Bytes(buffer, offset); if (isFilled.at(index)) { continue; } if (stdLen == 0) { //if record is empty, left it default isFilled[index] = true; continue; } Style styleInfo = myStyleSheet.at(index); const unsigned int styleAndBaseType = OleUtil::getU2Bytes(buffer, offset + 4); const unsigned int styleType = styleAndBaseType % 16; const unsigned int baseStyleId = styleAndBaseType / 16; if (baseStyleId == Style::STYLE_NIL || baseStyleId == Style::STYLE_USER) { //if based on nil or user style, left default } else { int baseStyleIndex = getStyleIndex(baseStyleId, isFilled, myStyleSheet); if (baseStyleIndex < 0) { //this base style is not filled yet, so pass it at some time continue; } styleInfo = myStyleSheet.at(baseStyleIndex); styleInfo.StyleIdCurrent = Style::STYLE_INVALID; } // parse STD structure unsigned int tmp = OleUtil::getU2Bytes(buffer, offset + 6); unsigned int upxCount = tmp % 16; styleInfo.StyleIdNext = tmp / 16; //adding current style myStyleSheet[index] = styleInfo; isFilled[index] = true; styleSheetWasChanged = true; std::size_t pos = 2 + stdBaseInFile; std::size_t nameLen = (std::size_t)OleUtil::getU2Bytes(buffer, offset + pos); nameLen = nameLen * 2 + 2; //from Unicode characters to bytes + Unicode null charachter length pos += 2 + nameLen; if (pos % 2 != 0) { ++pos; } if (pos >= stdLen) { continue; } std::size_t upxLen = (std::size_t)OleUtil::getU2Bytes(buffer, offset + pos); if (pos + upxLen > stdLen) { //UPX length too large continue; } //for style info styleType must be equal 1 if (styleType == 1 && upxCount >= 1) { if (upxLen >= 2) { styleInfo.StyleIdCurrent = OleUtil::getU2Bytes(buffer, offset + pos + 2); getStyleInfo(0, buffer + offset + pos + 4, upxLen - 2, styleInfo); myStyleSheet[index] = styleInfo; } pos += 2 + upxLen; if (pos % 2 != 0) { ++pos; } upxLen = (std::size_t)OleUtil::getU2Bytes(buffer, offset + pos); } if (upxLen == 0 || pos + upxLen > stdLen) { //too small/too large continue; } //for char info styleType can be equal 1 or 2 if ((styleType == 1 && upxCount >= 2) || (styleType == 2 && upxCount >= 1)) { CharInfo charInfo; getCharInfo(0, Style::STYLE_INVALID, buffer + offset + pos + 2, upxLen, charInfo); styleInfo.CurrentCharInfo = charInfo; myStyleSheet[index] = styleInfo; } } } while (styleSheetWasChanged); delete[] buffer; return true; }