/****************************************************************************** ** 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 "drw_dbg.h" #include "dwgutil.h" #include "rscodec.h" #include "../libdwgr.h" /** utility function * convert a int to string in hex **/ namespace DRW { std::string toHexStr(int n){ #if defined(__APPLE__) char buffer[9]= {'\0'}; snprintf(buffer,9, "%X", n); return std::string(buffer); #else std::ostringstream Convert; Convert << std::uppercase << std::hex << n; return Convert.str(); #endif } } /** * @brief dwgRSCodec::decode239I * @param in : input data (at least 255*blk bytes) * @param out : output data (at least 239*blk bytes) * @param blk number of codewords ( 1 cw == 255 bytes) */ void dwgRSCodec::decode239I(unsigned char *in, unsigned char *out, duint32 blk){ int k=0; unsigned char data[255]; RScodec rsc(0x96, 8, 8); //(255, 239) for (duint32 i=0; i> 2) | (compressedByte() << 6); *ll = (fb & 0x03); return cont; } duint32 dwgCompressor::longCompressionOffset(){ duint32 cont = 0; duint8 ll = compressedByte(); while (ll == 0x00 && compressedGood) { cont += 0xFF; ll = compressedByte(); } cont += ll; return cont; } duint32 dwgCompressor::long20CompressionOffset(){ // duint32 cont = 0; duint32 cont = 0x0F; duint8 ll = compressedByte(); while (ll == 0x00 && compressedGood){ // cont += 0xFF; ll = compressedByte(); } cont += ll; return cont; } duint32 dwgCompressor::litLength18(){ duint32 cont = 0; duint8 ll = compressedByte(); //no literal length, this byte is next opCode if (ll > 0x0F) { --compressedPos; return 0; } if (ll == 0x00) { cont = 0x0F; ll = compressedByte(); while (ll == 0x00 && compressedGood) {//repeat until ll != 0x00 cont += 0xFF; ll = compressedByte(); } } return cont + ll + 3; } bool dwgCompressor::decompress18(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize){ compressedBuffer = cbuf; decompBuffer = dbuf; compressedSize = csize; decompSize = dsize; compressedPos = 0; decompPos = 0; compressedGood = true; decompGood = true; DRW_DBG("dwgCompressor::decompress, last 2 bytes: "); DRW_DBGH(compressedBuffer[compressedSize - 2]);DRW_DBG(" ");DRW_DBGH(compressedBuffer[compressedSize - 1]);DRW_DBG("\n"); duint32 compBytes {0}; duint32 compOffset {0}; duint32 litCount {litLength18()}; //copy first literal length for (duint32 i = 0; i < litCount && buffersGood(); ++i) { decompSet( compressedByte()); } while (buffersGood()) { duint8 oc = compressedByte(); //next opcode if (oc == 0x10){ compBytes = longCompressionOffset()+ 9; compOffset = twoByteOffset(&litCount) + 0x3FFF; if (litCount == 0) litCount= litLength18(); } else if (oc > 0x11 && oc< 0x20){ compBytes = (oc & 0x0F) + 2; compOffset = twoByteOffset(&litCount) + 0x3FFF; if (litCount == 0) litCount= litLength18(); } else if (oc == 0x20){ compBytes = longCompressionOffset() + 0x21; compOffset = twoByteOffset(&litCount); if (litCount == 0) litCount= litLength18(); } else if (oc > 0x20 && oc< 0x40){ compBytes = oc - 0x1E; compOffset = twoByteOffset(&litCount); if (litCount == 0) litCount= litLength18(); } else if ( oc > 0x3F){ compBytes = ((oc & 0xF0) >> 4) - 1; duint8 ll2 = compressedByte(); compOffset = (ll2 << 2) | ((oc & 0x0C) >> 2); litCount = oc & 0x03; if (litCount < 1){ litCount= litLength18();} } else if (oc == 0x11){ DRW_DBG("dwgCompressor::decompress, end of input stream, Cpos: "); DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG("\n"); return true; //end of input stream } else { //ll < 0x10 DRW_DBG("WARNING dwgCompressor::decompress, failed, illegal char: "); DRW_DBGH(oc); DRW_DBG(", Cpos: "); DRW_DBG(compressedPos); DRW_DBG(", Dpos: "); DRW_DBG(decompPos); DRW_DBG("\n"); return false; //fails, not valid } //copy "compressed data", if size allows if (decompSize < decompPos + compBytes) { DRW_DBG("WARNING dwgCompressor::decompress18, bad compBytes size, Cpos: "); DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG(", need ");DRW_DBG(compBytes);DRW_DBG(", available ");DRW_DBG(decompSize - decompPos);DRW_DBG("\n"); // only copy what we can fit compBytes = decompSize - decompPos; } duint32 j {decompPos - compOffset - 1}; for (duint32 i = 0; i < compBytes && buffersGood(); i++) { decompSet( decompByte( j++)); } //copy "uncompressed data", if size allows if (decompSize < decompPos + litCount) { DRW_DBG("WARNING dwgCompressor::decompress18, bad litCount size, Cpos: "); DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG(", need ");DRW_DBG(litCount);DRW_DBG(", available ");DRW_DBG(decompSize - decompPos);DRW_DBG("\n"); // only copy what we can fit litCount = decompSize - decompPos; } for (duint32 i=0; i < litCount && buffersGood(); i++) { decompSet( compressedByte()); } } DRW_DBG("WARNING dwgCompressor::decompress, bad out, Cpos: ");DRW_DBG(compressedPos);DRW_DBG(", Dpos: ");DRW_DBG(decompPos);DRW_DBG("\n"); return false; } duint8 dwgCompressor::compressedByte(void) { duint8 result {0}; compressedGood = (compressedPos < compressedSize); if (compressedGood) { result = compressedBuffer[compressedPos]; ++compressedPos; } return result; } duint8 dwgCompressor::compressedByte(const duint32 index) { if (index < compressedSize) { return compressedBuffer[index]; } return 0; } duint32 dwgCompressor::compressedHiByte(void) { return static_cast(compressedByte()) << 8; } bool dwgCompressor::compressedInc(const dint32 inc /*= 1*/) { compressedPos += inc; compressedGood = (compressedPos <= compressedSize); return compressedGood; } duint8 dwgCompressor::decompByte(const duint32 index) { if (index < decompSize) { return decompBuffer[index]; } return 0; } void dwgCompressor::decompSet(const duint8 value) { decompGood = (decompPos < decompSize); if (decompGood) { decompBuffer[decompPos] = value; ++decompPos; } } bool dwgCompressor::buffersGood(void) { return compressedGood && decompGood; } void dwgCompressor::decrypt18Hdr(duint8 *buf, duint64 size, duint64 offset){ duint8 max = size / 4; duint32 secMask = 0x4164536b ^ offset; duint32* pHdr = reinterpret_cast(buf); for (duint8 j = 0; j < max; j++) *pHdr++ ^= secMask; } /*void dwgCompressor::decrypt18Data(duint8 *buf, duint32 size, duint32 offset){ duint8 max = size / 4; duint32 secMask = 0x4164536b ^ offset; duint32* pHdr = (duint32*)buf; for (duint8 j = 0; j < max; j++) *pHdr++ ^= secMask; }*/ duint32 dwgCompressor::litLength21(duint8 opCode) { duint32 length = 8u + opCode; if (0x17 == length) { duint32 n = compressedByte(); length += n; if (0xffu == n) { do { n = compressedByte(); n |= compressedHiByte(); length += n; } while (0xffffu == n); } } return length; } bool dwgCompressor::decompress21(duint8 *cbuf, duint8 *dbuf, duint64 csize, duint64 dsize){ compressedBuffer = cbuf; decompBuffer = dbuf; compressedSize = csize; decompSize = dsize; compressedPos = 0; decompPos = 0; compressedGood = true; decompGood = true; duint32 length {0}; duint32 sourceOffset {0}; duint8 opCode {compressedByte()}; if ((opCode >> 4) == 2){ compressedInc( 2); length = compressedByte() & 0x07; } while (buffersGood()) { if (length == 0) { length = litLength21(opCode); } copyCompBytes21( length); if (decompPos >= decompSize) { break; //check if last chunk are compressed & terminate } length = 0; opCode = compressedByte(); readInstructions21( opCode, sourceOffset, length); while (true) { //prevent crash with corrupted data if (sourceOffset > decompPos) { DRW_DBG("\nWARNING dwgCompressor::decompress21 => sourceOffset> dstIndex.\n"); DRW_DBG("csize = "); DRW_DBG(compressedSize); DRW_DBG(" srcIndex = "); DRW_DBG(compressedPos); DRW_DBG("\ndsize = "); DRW_DBG(decompSize); DRW_DBG(" dstIndex = "); DRW_DBG(decompPos); sourceOffset = decompPos; } //prevent crash with corrupted data if (length > decompSize - decompPos){ DRW_DBG("\nWARNING dwgCompressor::decompress21 => length > dsize - dstIndex.\n"); DRW_DBG("csize = "); DRW_DBG(compressedSize); DRW_DBG(" srcIndex = "); DRW_DBG(compressedPos); DRW_DBG("\ndsize = "); DRW_DBG(decompSize); DRW_DBG(" dstIndex = "); DRW_DBG(decompPos); length = decompSize - decompPos; compressedPos = compressedSize; //force exit compressedGood = false; } sourceOffset = decompPos - sourceOffset; for (duint32 i=0; i< length; i++) decompSet( decompByte( sourceOffset + i)); length = opCode & 7; if ((length != 0) || (compressedPos >= compressedSize)) { break; } opCode = compressedByte(); if ((opCode >> 4) == 0) { break; } if ((opCode >> 4) == 15) { opCode &= 15; } readInstructions21( opCode, sourceOffset, length); } if (compressedPos >= compressedSize) { break; } } DRW_DBG("\ncsize = "); DRW_DBG(compressedSize); DRW_DBG(" srcIndex = "); DRW_DBG(compressedPos); DRW_DBG("\ndsize = "); DRW_DBG(decompSize); DRW_DBG(" dstIndex = "); DRW_DBG(decompPos);DRW_DBG("\n"); return buffersGood(); } void dwgCompressor::readInstructions21(duint8 &opCode, duint32 &sourceOffset, duint32 &length){ switch (opCode >> 4) { case 0: length = (opCode & 0x0f) + 0x13; sourceOffset = compressedByte(); opCode = compressedByte(); length = ((opCode >> 3) & 0x10) + length; sourceOffset = ((opCode & 0x78) << 5) + 1 + sourceOffset; break; case 1: length = (opCode & 0xf) + 3; sourceOffset = compressedByte(); opCode = compressedByte(); sourceOffset = ((opCode & 0xf8) << 5) + 1 + sourceOffset; break; case 2: sourceOffset = compressedByte(); sourceOffset = (compressedHiByte() & 0xff00) | sourceOffset; length = opCode & 7; if ((opCode & 8) == 0) { opCode = compressedByte(); length = (opCode & 0xf8) + length; } else { ++sourceOffset; length = (static_cast(compressedByte()) << 3) + length; opCode = compressedByte(); length = (((opCode & 0xf8) << 8) + length) + 0x100; } break; default: length = opCode >> 4; sourceOffset = opCode & 15; opCode = compressedByte(); sourceOffset = (((opCode & 0xf8) << 1) + sourceOffset) + 1; break; } } const duint8 dwgCompressor::CopyOrder21_01[] = {0}; const duint8 dwgCompressor::CopyOrder21_02[] = {1,0}; const duint8 dwgCompressor::CopyOrder21_03[] = {2,1,0}; const duint8 dwgCompressor::CopyOrder21_04[] = {0,1,2,3}; const duint8 dwgCompressor::CopyOrder21_05[] = {4,0,1,2,3}; const duint8 dwgCompressor::CopyOrder21_06[] = {5,1,2,3,4,0}; const duint8 dwgCompressor::CopyOrder21_07[] = {6,5,1,2,3,4,0}; const duint8 dwgCompressor::CopyOrder21_08[] = {0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_09[] = {8,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_10[] = {9,1,2,3,4,5,6,7,8,0}; const duint8 dwgCompressor::CopyOrder21_11[] = {10,9,1,2,3,4,5,6,7,8,0}; const duint8 dwgCompressor::CopyOrder21_12[] = {8,9,10,11,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_13[] = {12,8,9,10,11,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_14[] = {13,9,10,11,12,1,2,3,4,5,6,7,8,0}; const duint8 dwgCompressor::CopyOrder21_15[] = {14,13,9,10,11,12,1,2,3,4,5,6,7,8,0}; const duint8 dwgCompressor::CopyOrder21_16[] = {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_17[] = {9,10,11,12,13,14,15,16,8,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_18[] = {17,9,10,11,12,13,14,15,16,1,2,3,4,5,6,7,8,0}; const duint8 dwgCompressor::CopyOrder21_19[] = {18,17,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_20[] = {16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_21[] = {20,16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_22[] = {21,20,16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_23[] = {22,21,20,16,17,18,19,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_24[] = {16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_25[] = {17,18,19,20,21,22,23,24,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_26[] = {25,17,18,19,20,21,22,23,24,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_27[] = {26,25,17,18,19,20,21,22,23,24,16,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_28[] = {24,25,26,27,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_29[] = {28,24,25,26,27,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_30[] = {29,28,24,25,26,27,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 dwgCompressor::CopyOrder21_31[] = {30,26,27,28,29,18,19,20,21,22,23,24,25,10,11,12,13,14,15,16,17,2,3,4,5,6,7,8,9,1,0}; const duint8 dwgCompressor::CopyOrder21_32[] = {24,25,26,27,28,29,30,31,16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7}; const duint8 *dwgCompressor::CopyOrder21[dwgCompressor::Block21OrderArray] = { nullptr, CopyOrder21_01, CopyOrder21_02, CopyOrder21_03, CopyOrder21_04, CopyOrder21_05, CopyOrder21_06, CopyOrder21_07, CopyOrder21_08, CopyOrder21_09, CopyOrder21_10, CopyOrder21_11, CopyOrder21_12, CopyOrder21_13, CopyOrder21_14, CopyOrder21_15, CopyOrder21_16, CopyOrder21_17, CopyOrder21_18, CopyOrder21_19, CopyOrder21_20, CopyOrder21_21, CopyOrder21_22, CopyOrder21_23, CopyOrder21_24, CopyOrder21_25, CopyOrder21_26, CopyOrder21_27, CopyOrder21_28, CopyOrder21_29, CopyOrder21_30, CopyOrder21_31, CopyOrder21_32 }; void dwgCompressor::copyBlock21(const duint32 length) { if (MaxBlock21Length < length) { return; } const duint8 *order {CopyOrder21[length]}; if (nullptr == order) { return; } for (duint32 index = 0; (length > index) && buffersGood(); ++index) { decompSet( compressedByte( compressedPos + order[index])); } compressedInc( length); } bool dwgCompressor::copyCompBytes21(duint32 length) { DRW_DBG("\ncopyCompBytes21() "); DRW_DBG(length); DRW_DBG("\n"); while (length >= MaxBlock21Length) { copyBlock21( MaxBlock21Length); length -= MaxBlock21Length; } copyBlock21( length); return buffersGood(); } secEnum::DWGSection secEnum::getEnum(const std::string &nameSec){ //TODO: complete it if (nameSec=="AcDb:Header"){ return HEADER; } else if (nameSec=="AcDb:Classes"){ return CLASSES; } else if (nameSec=="AcDb:SummaryInfo"){ return SUMARYINFO; } else if (nameSec=="AcDb:Preview"){ return PREVIEW; } else if (nameSec=="AcDb:VBAProject"){ return VBAPROY; } else if (nameSec=="AcDb:AppInfo"){ return APPINFO; } else if (nameSec=="AcDb:FileDepList"){ return FILEDEP; } else if (nameSec=="AcDb:RevHistory"){ return REVHISTORY; } else if (nameSec=="AcDb:Security"){ return SECURITY; } else if (nameSec=="AcDb:AcDbObjects"){ return OBJECTS; } else if (nameSec=="AcDb:ObjFreeSpace"){ return OBJFREESPACE; } else if (nameSec=="AcDb:Template"){ return TEMPLATE; } else if (nameSec=="AcDb:Handles"){ return HANDLES; } else if (nameSec=="AcDb:AcDsPrototype_1b"){ return PROTOTYPE; } else if (nameSec=="AcDb:AuxHeader"){ return AUXHEADER; } else if (nameSec=="AcDb:Signature"){ return SIGNATURE; } else if (nameSec=="AcDb:AppInfoHistory"){ //in ac1021 return APPINFOHISTORY; // } else if (nameSec=="AcDb:Extended Entity Data"){ // return EXTEDATA; // } else if (nameSec=="AcDb:PROXY ENTITY GRAPHICS"){ // return PROXYGRAPHICS; } return UNKNOWNS; }