Example #1
0
StyleData *StyleData::clone() const {
  StyleData *data = new StyleData();
  for (int i = 0; i < getStyleCount(); i++)
    data->addStyle(getStyleIndex(i), getStyle(i)->clone());
  return data;
}
Example #2
0
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;
}