/****************************************************************************** ** libDXFrw - Library to read/write DXF files (ascii & binary) ** ** ** ** Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com ** ** ** ** This library is free software, licensed under the terms of the GNU ** ** General Public License as published by the Free Software Foundation, ** ** either version 2 of the License, or (at your option) any later version. ** ** You should have received a copy of the GNU General Public License ** ** along with this program. If not, see . ** ******************************************************************************/ #include #include #include #include #include #include #include "drw_dbg.h" #include "dwgreader21.h" #include "drw_textcodec.h" #include "../libdwgr.h" bool dwgReader21::readMetaData() { version = parent->getVersion(); decoder.setVersion(version, false); DRW_DBG("dwgReader21::readFileHeader()\n"); DRW_DBG("dwgReader21::parsing metadata\n"); if (! fileBuf->setPosition(11)) return false; maintenanceVersion = fileBuf->getRawChar8(); DRW_DBG("maintenance version= "); DRW_DBGH(maintenanceVersion); DRW_DBG("\nbyte at 0x0C= "); DRW_DBG(fileBuf->getRawChar8()); previewImagePos = fileBuf->getRawLong32(); DRW_DBG("previewImagePos (seekerImageData) = "); DRW_DBG(previewImagePos); DRW_DBG("\n\napp writer version= "); DRW_DBGH(fileBuf->getRawChar8()); DRW_DBG("\napp writer maintenance version= "); DRW_DBGH(fileBuf->getRawChar8()); duint16 cp = fileBuf->getRawShort16(); DRW_DBG("\ncodepage= "); DRW_DBG(cp); if (cp == 30) decoder.setCodePage("ANSI_1252", false); /* UNKNOUWN SECTION 2 bytes*/ DRW_DBG("\nUNKNOWN SECTION= "); DRW_DBG(fileBuf->getRawShort16()); DRW_DBG("\nUNKNOUWN SECTION 3b= "); DRW_DBG(fileBuf->getRawChar8()); duint32 secType = fileBuf->getRawLong32(); DRW_DBG("\nsecurity type flag= "); DRW_DBGH(secType); /* UNKNOWN2 SECTION 4 bytes*/ DRW_DBG("\nUNKNOWN SECTION 4bytes= "); DRW_DBG(fileBuf->getRawLong32()); DRW_DBG("\nSummary info address= "); DRW_DBGH(fileBuf->getRawLong32()); DRW_DBG("\nVBA project address= "); DRW_DBGH(fileBuf->getRawLong32()); DRW_DBG("\n0x00000080 32b= "); DRW_DBGH(fileBuf->getRawLong32()); DRW_DBG("\nApp info address= "); DRW_DBGH(fileBuf->getRawLong32()); //current position are 0x30 from here to 0x80 are undocumented DRW_DBG("\nAnother address? = "); DRW_DBGH(fileBuf->getRawLong32()); return true; } bool dwgReader21::parseSysPage(duint64 sizeCompressed, duint64 sizeUncompressed, duint64 correctionFactor, duint64 offset, duint8 *decompData){ //round to 8 duint64 alsize = (sizeCompressed + 7) &(-8); //minimum RS chunk: duint32 chunks = (((alsize * correctionFactor)+238)/239); duint64 fpsize = chunks * 255; if (! fileBuf->setPosition(offset)) return false; std::vector tmpDataRaw(fpsize); fileBuf->getBytes(&tmpDataRaw.front(), fpsize); std::vector tmpDataRS(fpsize); dwgRSCodec::decode239I(&tmpDataRaw.front(), &tmpDataRS.front(), fpsize/255); return dwgCompressor::decompress21(&tmpDataRS.front(), decompData, sizeCompressed, sizeUncompressed); } bool dwgReader21::parseDataPage(const dwgSectionInfo &si, duint8 *dData){ DRW_DBG("parseDataPage, section size: "); DRW_DBG(si.size); for (auto it=si.pages.begin(); it!=si.pages.end(); ++it){ dwgPageInfo pi = it->second; if (!fileBuf->setPosition(pi.address)) return false; std::vector tmpPageRaw(pi.size); fileBuf->getBytes(&tmpPageRaw.front(), pi.size); #ifdef DRW_DBG_DUMP DRW_DBG("\nSection OBJECTS raw data=\n"); for (unsigned int i=0, j=0; i< pi.size;i++) { DRW_DBGH( (unsigned char)tmpPageRaw[i]); if (j == 7) { DRW_DBG("\n"); j = 0; } else { DRW_DBG(", "); j++; } } DRW_DBG("\n"); #endif std::vector tmpPageRS(pi.size); duint8 chunks =pi.size / 255; dwgRSCodec::decode251I(&tmpPageRaw.front(), &tmpPageRS.front(), chunks); #ifdef DRW_DBG_DUMP DRW_DBG("\nSection OBJECTS RS data=\n"); for (unsigned int i=0, j=0; i< pi.size;i++) { DRW_DBGH( (unsigned char)tmpPageRS[i]); if (j == 7) { DRW_DBG("\n"); j = 0; } else { DRW_DBG(", "); j++; } } DRW_DBG("\n"); #endif DRW_DBG("\npage uncomp size: "); DRW_DBG(pi.uSize); DRW_DBG(" comp size: "); DRW_DBG(pi.cSize); DRW_DBG("\noffset: "); DRW_DBG(pi.startOffset); duint8 *pageData = dData + pi.startOffset; if (!dwgCompressor::decompress21(&tmpPageRS.front(), pageData, pi.cSize, pi.uSize)) { return false; } #ifdef DRW_DBG_DUMP DRW_DBG("\n\nSection OBJECTS decompressed data=\n"); for (unsigned int i=0, j=0; i< pi.uSize;i++) { DRW_DBGH( (unsigned char)pageData[i]); if (j == 7) { DRW_DBG("\n"); j = 0; } else { DRW_DBG(", "); j++; } } DRW_DBG("\n"); #endif } DRW_DBG("\n"); return true; } bool dwgReader21::readFileHeader() { DRW_DBG("\n\ndwgReader21::parsing file header\n"); if (! fileBuf->setPosition(0x80)) return false; duint8 fileHdrRaw[0x2FD];//0x3D8 fileBuf->getBytes(fileHdrRaw, 0x2FD); duint8 fileHdrdRS[0x2CD]; dwgRSCodec::decode239I(fileHdrRaw, fileHdrdRS, 3); #ifdef DRW_DBG_DUMP DRW_DBG("\ndwgReader21::parsed Reed Solomon decode:\n"); int j = 0; for (int i=0, j=0; i<0x2CD; i++){ DRW_DBGH( (unsigned char)fileHdrdRS[i]); if (j== 15){ j=0; DRW_DBG("\n"); } else{ j++; DRW_DBG(", "); } } DRW_DBG("\n"); #endif dwgBuffer fileHdrBuf(fileHdrdRS, 0x2CD, &decoder); DRW_DBG("\nCRC 64b= "); DRW_DBGH(fileHdrBuf.getRawLong64()); DRW_DBG("\nunknown key 64b= "); DRW_DBGH(fileHdrBuf.getRawLong64()); DRW_DBG("\ncomp data CRC 64b= "); DRW_DBGH(fileHdrBuf.getRawLong64()); dint32 fileHdrCompLength = fileHdrBuf.getRawLong32(); DRW_DBG("\ncompr len 4bytes= "); DRW_DBG(fileHdrCompLength); dint32 fileHdrCompLength2 = fileHdrBuf.getRawLong32(); DRW_DBG("\nlength2 4bytes= "); DRW_DBG(fileHdrCompLength2); int fileHdrDataLength = 0x110; std::vector fileHdrData; if (fileHdrCompLength < 0) { fileHdrDataLength = fileHdrCompLength * -1; fileHdrData.resize(fileHdrDataLength); fileHdrBuf.getBytes(&fileHdrData.front(), fileHdrDataLength); } else { DRW_DBG("\ndwgReader21:: file header are compressed:\n"); std::vector compByteStr(fileHdrCompLength); fileHdrBuf.getBytes(compByteStr.data(), fileHdrCompLength); fileHdrData.resize(fileHdrDataLength); if (!dwgCompressor::decompress21(compByteStr.data(), &fileHdrData.front(), fileHdrCompLength, fileHdrDataLength)) { return false; } } #ifdef DRW_DBG_DUMP DRW_DBG("\ndwgReader21::parsed file header:\n"); for (int i=0, j=0; i PagesMapData(PagesMapSizeUncompressed); if (!parseSysPage(PagesMapSizeCompressed, PagesMapSizeUncompressed, PagesMapCorrectionFactor, 0x480+PagesMapOffset, &PagesMapData.front())) { return false; } duint64 address = 0x480; duint64 i = 0; dwgBuffer PagesMapBuf(&PagesMapData.front(), PagesMapSizeUncompressed, &decoder); //stores temporarily info of all pages: std::unordered_mapsectionPageMapTmp; // dwgPageInfo *m_pages= new dwgPageInfo[PagesMaxId+1]; while (PagesMapSizeUncompressed > i ) { duint64 size = PagesMapBuf.getRawLong64(); dint64 id = PagesMapBuf.getRawLong64(); duint64 ind = id > 0 ? id : -id; i += 16; DRW_DBG("Page gap= "); DRW_DBG(id); DRW_DBG(" Page num= "); DRW_DBG(ind); DRW_DBG(" size= "); DRW_DBGH(size); DRW_DBG(" address= "); DRW_DBGH(address); DRW_DBG("\n"); sectionPageMapTmp[ind] = dwgPageInfo(ind, address,size); address += size; //TODO num can be negative indicating gap // seek += offset; } DRW_DBG("\n*** dwgReader21: Processing Section Map ***\n"); std::vector SectionsMapData( SectionsMapSizeUncompressed); dwgPageInfo sectionMap = sectionPageMapTmp[SectionsMapId]; if (!parseSysPage( SectionsMapSizeCompressed, SectionsMapSizeUncompressed, SectionsMapCorrectionFactor, sectionMap.address, &SectionsMapData.front()) ) { return false; } //reads sections: //Note: compressed value are not stored in file then, commpresed field are use to store // encoding value dwgBuffer SectionsMapBuf( &SectionsMapData.front(), SectionsMapSizeUncompressed, &decoder); duint8 nextId = 1; while(SectionsMapBuf.getPosition() < SectionsMapBuf.size()){ dwgSectionInfo secInfo; secInfo.size = SectionsMapBuf.getRawLong64(); DRW_DBG("\nSize of section (data size)= "); DRW_DBGH(secInfo.size); secInfo.maxSize = SectionsMapBuf.getRawLong64(); DRW_DBG("\nMax Decompressed Size= "); DRW_DBGH(secInfo.maxSize); secInfo.encrypted = SectionsMapBuf.getRawLong64(); //encrypted (doc: 0 no, 1 yes, 2 unkn) on read: objects 0 and encrypted yes DRW_DBG("\nencription= "); DRW_DBGH(secInfo.encrypted); DRW_DBG("\nHashCode = "); DRW_DBGH(SectionsMapBuf.getRawLong64()); duint64 SectionNameLength = SectionsMapBuf.getRawLong64(); DRW_DBG("\nSectionNameLength = "); DRW_DBG(SectionNameLength); DRW_DBG("\nUnknown = "); DRW_DBGH(SectionsMapBuf.getRawLong64()); secInfo.compressed = SectionsMapBuf.getRawLong64(); DRW_DBG("\nEncoding (compressed) = "); DRW_DBGH(secInfo.compressed); secInfo.pageCount = SectionsMapBuf.getRawLong64(); DRW_DBG("\nPage count= "); DRW_DBGH(secInfo.pageCount); secInfo.name = SectionsMapBuf.getUCSStr(SectionNameLength); DRW_DBG("\nSection name = "); DRW_DBG(secInfo.name); DRW_DBG("\n"); for (unsigned int i=0; i< secInfo.pageCount; i++){ duint64 po = SectionsMapBuf.getRawLong64(); duint32 ds = SectionsMapBuf.getRawLong64(); duint32 pn = SectionsMapBuf.getRawLong64(); DRW_DBG(" pag Id = "); DRW_DBGH(pn); DRW_DBG(" data size = "); DRW_DBGH(ds); dwgPageInfo pi = sectionPageMapTmp[pn]; //get a copy pi.dataSize = ds; pi.startOffset = po; pi.uSize = SectionsMapBuf.getRawLong64(); pi.cSize = SectionsMapBuf.getRawLong64(); secInfo.pages[pn]= pi;//complete copy in secInfo DRW_DBG("\n Page number= "); DRW_DBGH(secInfo.pages[pn].Id); DRW_DBG("\n address in file= "); DRW_DBGH(secInfo.pages[pn].address); DRW_DBG("\n size in file= "); DRW_DBGH(secInfo.pages[pn].size); DRW_DBG("\n Data size= "); DRW_DBGH(secInfo.pages[pn].dataSize); DRW_DBG("\n Start offset= "); DRW_DBGH(secInfo.pages[pn].startOffset); DRW_DBG("\n Page uncompressed size = "); DRW_DBGH(secInfo.pages[pn].uSize); DRW_DBG("\n Page compressed size = "); DRW_DBGH(secInfo.pages[pn].cSize); DRW_DBG("\n Page checksum = "); DRW_DBGH(SectionsMapBuf.getRawLong64()); DRW_DBG("\n Page CRC = "); DRW_DBGH(SectionsMapBuf.getRawLong64()); DRW_DBG("\n"); } if (!secInfo.name.empty()) { secInfo.Id = nextId++; DRW_DBG("Saved section Name= "); DRW_DBG( secInfo.name.c_str() ); DRW_DBG("\n"); sections[secEnum::getEnum(secInfo.name)] = secInfo; } } if (! fileBuf->isGood()) return false; DRW_DBG("\ndwgReader21::readFileHeader END\n"); return true; } bool dwgReader21::readDwgHeader(DRW_Header& hdr){ DRW_DBG("\ndwgReader21::readDwgHeader\n"); dwgSectionInfo si = sections[secEnum::HEADER]; if (si.Id < 0) { //not found, ends return false; } DRW_DBG("\nprepare section of size "); DRW_DBG(si.size);DRW_DBG("\n"); std::vector tmpHeaderData( si.size); if (!dwgReader21::parseDataPage( si, &tmpHeaderData.front())) { return false; } dwgBuffer dataBuf(&tmpHeaderData.front(), si.size, &decoder); dwgBuffer handleBuf(&tmpHeaderData.front(), si.size, &decoder); DRW_DBG("Header section sentinel= "); checkSentinel(&dataBuf, secEnum::HEADER, true); return dwgReader::readDwgHeader(hdr, &dataBuf, &handleBuf); } bool dwgReader21::readDwgClasses(){ DRW_DBG("\ndwgReader21::readDwgClasses"); dwgSectionInfo si = sections[secEnum::CLASSES]; if (si.Id<0)//not found, ends return false; DRW_DBG("\nprepare section of size "); DRW_DBG(si.size);DRW_DBG("\n"); std::vector tmpClassesData( si.size); bool ret = dwgReader21::parseDataPage(si, tmpClassesData.data()); if (!ret) { return ret; } dwgBuffer buff(tmpClassesData.data(), si.size, &decoder); DRW_DBG("classes section sentinel= "); checkSentinel(&buff, secEnum::CLASSES, true); duint32 size = buff.getRawLong32(); DRW_DBG("\ndata size in bytes "); DRW_DBG(size); duint32 bitSize = buff.getRawLong32(); DRW_DBG("\ntotal size in bits "); DRW_DBG(bitSize); duint32 maxClassNum = buff.getBitShort(); DRW_DBG("\nMaximum class number "); DRW_DBG(maxClassNum); DRW_DBG("\nRc 1 "); DRW_DBG(buff.getRawChar8()); DRW_DBG("\nRc 2 "); DRW_DBG(buff.getRawChar8()); DRW_DBG("\nBit "); DRW_DBG(buff.getBit()); /*******************************/ //prepare string stream dwgBuffer strBuff(tmpClassesData.data(), si.size, &decoder); duint32 strStartPos = bitSize + 159;//size in bits + 20 bytes (sn+size) - 1 bit (endbit) DRW_DBG("\nstrStartPos: "); DRW_DBG(strStartPos); strBuff.setPosition(strStartPos >> 3); strBuff.setBitPos(strStartPos & 7); DRW_DBG("\nclasses strings buff.getPosition: "); DRW_DBG(strBuff.getPosition()); DRW_DBG("\nclasses strings buff.getBitPos: "); DRW_DBG(strBuff.getBitPos()); DRW_DBG("\nendBit "); DRW_DBG(strBuff.getBit()); strStartPos -= 16;//decrement 16 bits DRW_DBG("\nstrStartPos: "); DRW_DBG(strStartPos); strBuff.setPosition(strStartPos >> 3); strBuff.setBitPos(strStartPos & 7); DRW_DBG("\nclasses strings buff.getPosition: "); DRW_DBG(strBuff.getPosition()); DRW_DBG("\nclasses strings buff.getBitPos: "); DRW_DBG(strBuff.getBitPos()); duint32 strDataSize = strBuff.getRawShort16(); DRW_DBG("\nstrDataSize: "); DRW_DBG(strDataSize); if (strDataSize & 0x8000) { strStartPos -= 16;//decrement 16 bits strDataSize &= 0x7FFF; //strip 0x8000; strBuff.setPosition(strStartPos >> 3); strBuff.setBitPos(strStartPos & 7); duint32 hiSize = strBuff.getRawShort16(); strDataSize |= (hiSize << 15); } strStartPos -= strDataSize; DRW_DBG("\nstrStartPos: "); DRW_DBG(strStartPos); strBuff.setPosition(strStartPos >> 3); strBuff.setBitPos(strStartPos & 7); DRW_DBG("\nclasses strings buff.getPosition: "); DRW_DBG(strBuff.getPosition()); DRW_DBG("\nclasses strings buff.getBitPos: "); DRW_DBG(strBuff.getBitPos()); /*******************************/ duint32 endDataPos = maxClassNum-499; DRW_DBG("\nbuff.getPosition: "); DRW_DBG(buff.getPosition()); for (duint32 i= 0; iparseDwg(version, &buff, &strBuff); classesmap[cl->classNum] = cl; DRW_DBG("\nbuff.getPosition: "); DRW_DBG(buff.getPosition()); } DRW_DBG("\nend classes data buff.getPosition: "); DRW_DBG(buff.getPosition()); DRW_DBG("\nend classes data buff.getBitPos: "); DRW_DBG(buff.getBitPos()); buff.setPosition(size+20);//sizeVal+sn+32bSize DRW_DBG("\nCRC: "); DRW_DBGH(buff.getRawShort16()); DRW_DBG("\nclasses section end sentinel= "); checkSentinel(&buff, secEnum::CLASSES, true); return buff.isGood(); } bool dwgReader21::readDwgHandles(){ DRW_DBG("\ndwgReader21::readDwgHandles"); dwgSectionInfo si = sections[secEnum::HANDLES]; if (si.Id<0)//not found, ends return false; DRW_DBG("\nprepare section of size "); DRW_DBG(si.size);DRW_DBG("\n"); std::vector tmpHandlesData(si.size); bool ret = dwgReader21::parseDataPage(si, tmpHandlesData.data()); if (!ret) return ret; dwgBuffer dataBuf(tmpHandlesData.data(), si.size, &decoder); ret = dwgReader::readDwgHandles(&dataBuf, 0, si.size); return ret; } /*********** objects ************************/ /** * Reads all the object referenced in the object map section of the DWG file * (using their object file offsets) */ bool dwgReader21::readDwgTables(DRW_Header& hdr) { DRW_DBG("\ndwgReader21::readDwgTables\n"); dwgSectionInfo si = sections[secEnum::OBJECTS]; if (si.Id<0)//not found, ends return false; DRW_DBG("\nprepare section of size "); DRW_DBG(si.size);DRW_DBG("\n"); dataSize = si.size; objData.reset( new duint8 [dataSize] ); bool ret = dwgReader21::parseDataPage(si, objData.get()); if (!ret) return ret; DRW_DBG("readDwgTables total data size= "); DRW_DBG(dataSize); DRW_DBG("\n"); dwgBuffer dataBuf(objData.get(), dataSize, &decoder); ret = dwgReader::readDwgTables(hdr, &dataBuf); return ret; } bool dwgReader21::readDwgBlocks(DRW_Interface& intfa){ bool ret = true; dwgBuffer dataBuf(objData.get(), dataSize, &decoder); ret = dwgReader::readDwgBlocks(intfa, &dataBuf); return ret; }