1 /******************************************************************************
2 **  libDXFrw - Library to read/write DXF files (ascii & binary)              **
3 **                                                                           **
4 **  Copyright (C) 2011-2015 José F. Soriano, rallazz@gmail.com               **
5 **                                                                           **
6 **  This library is free software, licensed under the terms of the GNU       **
7 **  General Public License as published by the Free Software Foundation,     **
8 **  either version 2 of the License, or (at your option) any later version.  **
9 **  You should have received a copy of the GNU General Public License        **
10 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.    **
11 ******************************************************************************/
12 
13 #include <sstream>
14 #include "drw_dbg.h"
15 #include "dwgutil.h"
16 #include "rscodec.h"
17 #include "../libdwgr.h"
18 
19 #if __cplusplus >= 201500
20 #define FALLTHROUGH [[fallthrough]];
21 #elif defined(__clang__)
22 #define FALLTHROUGH [[clang::fallthrough]];
23 #elif defined(__GNUC__) && __GNUC__ >= 7
24 #define FALLTHROUGH [[gnu::fallthrough]];
25 #else
26 #define FALLTHROUGH
27 #endif
28 
29 #include "qgslogger.h"
30 
31 /**
32  * Utility function
33  * convert a int to string in hex
34  **/
35 namespace DRW
36 {
toHexStr(int n)37   std::string toHexStr( int n )
38   {
39 #if defined(__APPLE__)
40     char buffer[9] = {'\0'};
41     snprintf( buffer, 9, "%X", n );
42     return std::string( buffer );
43 #else
44     std::ostringstream Convert;
45     Convert << std::uppercase << std::hex << n;
46     return Convert.str();
47 #endif
48   }
49 }
50 
51 /**
52  * @brief dwgRSCodec::decode239I
53  * @param in : input data (at least 255*blk bytes)
54  * @param out : output data (at least 239*blk bytes)
55  * @param blk number of codewords ( 1 cw == 255 bytes)
56  */
decode239I(unsigned char * in,unsigned char * out,duint32 blk)57 void dwgRSCodec::decode239I( unsigned char *in, unsigned char *out, duint32 blk )
58 {
59   int k = 0;
60   unsigned char data[255];
61   RScodec rsc( 0x96, 8, 8 ); //(255, 239)
62   for ( duint32 i = 0; i < blk; i++ )
63   {
64     k = i;
65     for ( int j = 0; j < 255; j++ )
66     {
67       data[j] = in[k];
68       k += blk;
69     }
70     int r = rsc.decode( data );
71     if ( r < 0 )
72     {
73       QgsDebugMsg( "WARNING: dwgRSCodec::decode239I, can't correct all errors" );
74     }
75     k = i * 239;
76     for ( int j = 0; j < 239; j++ )
77     {
78       out[k++] = data[j];
79     }
80   }
81 }
82 
83 /**
84  * @brief dwgRSCodec::decode251I
85  * @param in : input data (at least 255*blk bytes)
86  * @param out : output data (at least 251*blk bytes)
87  * @param blk number of codewords ( 1 cw == 255 bytes)
88  */
decode251I(unsigned char * in,unsigned char * out,duint32 blk)89 void dwgRSCodec::decode251I( unsigned char *in, unsigned char *out, duint32 blk )
90 {
91   int k = 0;
92   unsigned char data[255];
93   RScodec rsc( 0xB8, 8, 2 ); //(255, 251)
94   for ( duint32 i = 0; i < blk; i++ )
95   {
96     k = i;
97     for ( int j = 0; j < 255; j++ )
98     {
99       data[j] = in[k];
100       k += blk;
101     }
102     int r = rsc.decode( data );
103     if ( r < 0 )
104     {
105       QgsDebugMsg( "WARNING: dwgRSCodec::decode251I, can't correct all errors" );
106     }
107     k = i * 251;
108     for ( int j = 0; j < 251; j++ )
109     {
110       out[k++] = data[j];
111     }
112   }
113 }
114 
twoByteOffset(duint32 * ll)115 duint32 dwgCompressor::twoByteOffset( duint32 *ll )
116 {
117   duint32 cont = 0;
118   duint8 fb = bufC[pos++];
119   cont = ( fb >> 2 ) | ( bufC[pos++] << 6 );
120   *ll = ( fb & 0x03 );
121   return cont;
122 }
123 
longCompressionOffset()124 duint32 dwgCompressor::longCompressionOffset()
125 {
126   duint32 cont = 0;
127   duint8 ll = bufC[pos++];
128   while ( ll == 0x00 )
129   {
130     cont += 0xFF;
131     ll = bufC[pos++];
132   }
133   cont += ll;
134   return cont;
135 }
136 
long20CompressionOffset()137 duint32 dwgCompressor::long20CompressionOffset()
138 {
139 //    duint32 cont = 0;
140   duint32 cont = 0x0F;
141   duint8 ll = bufC[pos++];
142   while ( ll == 0x00 )
143   {
144 //        cont += 0xFF;
145     ll = bufC[pos++];
146   }
147   cont += ll;
148   return cont;
149 }
150 
litLength18()151 duint32 dwgCompressor::litLength18()
152 {
153   duint32 cont = 0;
154   duint8 ll = bufC[pos++];
155   //no literal length, this byte is next opCode
156   if ( ll > 0x0F )
157   {
158     pos--;
159     return 0;
160   }
161 
162   if ( ll == 0x00 )
163   {
164     cont = 0x0F;
165     ll = bufC[pos++];
166     while ( ll == 0x00 ) //repeat until ll != 0x00
167     {
168       cont += 0xFF;
169       ll = bufC[pos++];
170     }
171   }
172   cont += ll;
173   cont += 3; //already sum 3
174   return cont;
175 }
176 
decompress18(duint8 * cbuf,duint8 * dbuf,duint32 csize,duint32 dsize)177 void dwgCompressor::decompress18( duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize )
178 {
179   bufC = cbuf;
180   bufD = dbuf;
181   sizeC = csize - 2;
182   sizeD = dsize;
183   QgsDebugMsgLevel( QString( "last 2 bytes: 0x%1 0x%2" ).arg( bufC[sizeC], 0, 16 ).arg( bufC[sizeC + 1], 0, 16 ), 5 );
184   sizeC = csize;
185 
186   duint32 compBytes;
187   duint32 compOffset;
188   duint32 litCount;
189 
190   pos = 0; //current position in compressed buffer
191   rpos = 0; //current position in resulting decompressed buffer
192   litCount = litLength18();
193   //copy first literal length
194   for ( duint32 i = 0; i < litCount; ++i )
195   {
196     bufD[rpos++] = bufC[pos++];
197   }
198 
199   while ( pos < csize && ( rpos < dsize + 1 ) ) //rpos < dsize to prevent crash more robust are needed
200   {
201     duint8 oc = bufC[pos++]; //next opcode
202     if ( oc == 0x10 )
203     {
204       compBytes = longCompressionOffset() + 9;
205       compOffset = twoByteOffset( &litCount ) + 0x3FFF;
206       if ( litCount == 0 )
207         litCount = litLength18();
208     }
209     else if ( oc > 0x11 && oc < 0x20 )
210     {
211       compBytes = ( oc & 0x0F ) + 2;
212       compOffset = twoByteOffset( &litCount ) + 0x3FFF;
213       if ( litCount == 0 )
214         litCount = litLength18();
215     }
216     else if ( oc == 0x20 )
217     {
218       compBytes = longCompressionOffset() + 0x21;
219       compOffset = twoByteOffset( &litCount );
220       if ( litCount == 0 )
221         litCount = litLength18();
222       else
223         oc = 0x00;
224     }
225     else if ( oc > 0x20 && oc < 0x40 )
226     {
227       compBytes = oc - 0x1E;
228       compOffset = twoByteOffset( &litCount );
229       if ( litCount == 0 )
230         litCount = litLength18();
231     }
232     else if ( oc > 0x3F )
233     {
234       compBytes = ( ( oc & 0xF0 ) >> 4 ) - 1;
235       duint8 ll2 = bufC[pos++];
236       compOffset = ( ll2 << 2 ) | ( ( oc & 0x0C ) >> 2 );
237       litCount = oc & 0x03;
238       if ( litCount < 1 )
239       {
240         litCount = litLength18();
241       }
242     }
243     else if ( oc == 0x11 )
244     {
245       QgsDebugMsgLevel( QString( "end of input stream, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ), 5 );
246       return; //end of input stream
247     }
248     else   //ll < 0x10
249     {
250       QgsDebugMsg( QString( "failed illegal char, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ) );
251       return; //fails, not valid
252     }
253     //copy "compressed data", TODO Needed verify out of bounds
254     duint32 remaining = sizeD - ( litCount + rpos );
255     if ( remaining < compBytes )
256     {
257       compBytes = remaining;
258       QgsDebugMsg( QString( "bad compBytes size, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ) );
259     }
260     for ( duint32 i = 0, j = rpos - compOffset - 1; i < compBytes; i++ )
261     {
262       bufD[rpos++] = bufD[j++];
263     }
264     //copy "uncompressed data", TODO Needed verify out of bounds
265     for ( duint32 i = 0; i < litCount; i++ )
266     {
267       bufD[rpos++] = bufC[pos++];
268     }
269   }
270   QgsDebugMsg( QString( "bad out, Cpos:%1, Dpos:%2" ).arg( pos ).arg( rpos ) );
271 }
272 
273 
decrypt18Hdr(duint8 * buf,duint32 size,duint32 offset)274 void dwgCompressor::decrypt18Hdr( duint8 *buf, duint32 size, duint32 offset )
275 {
276   duint8 max = size / 4;
277   duint32 secMask = 0x4164536b ^ offset;
278   duint32 *pHdr = ( duint32 * )buf;
279   for ( duint8 j = 0; j < max; j++ )
280     *pHdr++ ^= secMask;
281 }
282 
283 /*void dwgCompressor::decrypt18Data(duint8 *buf, duint32 size, duint32 offset){
284     duint8 max = size / 4;
285     duint32 secMask = 0x4164536b ^ offset;
286     duint32* pHdr = (duint32*)buf;
287     for (duint8 j = 0; j < max; j++)
288         *pHdr++ ^= secMask;
289 }*/
290 
litLength21(duint8 * cbuf,duint8 oc,duint32 * si)291 duint32 dwgCompressor::litLength21( duint8 *cbuf, duint8 oc, duint32 *si )
292 {
293 
294   duint32 srcIndex = *si;
295 
296   duint32 length = oc + 8;
297   if ( length == 0x17 )
298   {
299     duint32 n = cbuf[srcIndex++];
300     length += n;
301     if ( n == 0xff )
302     {
303       do
304       {
305         n = cbuf[srcIndex++];
306         n |= ( duint32 )( cbuf[srcIndex++] << 8 );
307         length += n;
308       }
309       while ( n == 0xffff );
310     }
311   }
312 
313   *si = srcIndex;
314   return length;
315 }
316 
decompress21(duint8 * cbuf,duint8 * dbuf,duint32 csize,duint32 dsize)317 void dwgCompressor::decompress21( duint8 *cbuf, duint8 *dbuf, duint32 csize, duint32 dsize )
318 {
319   duint32 srcIndex = 0;
320   duint32 dstIndex = 0;
321   duint32 length = 0;
322   duint32 sourceOffset;
323   duint8 opCode;
324 
325   opCode = cbuf[srcIndex++];
326   if ( ( opCode >> 4 ) == 2 )
327   {
328     srcIndex = srcIndex + 2;
329     length = cbuf[srcIndex++] & 0x07;
330   }
331 
332   while ( srcIndex < csize && ( dstIndex < dsize + 1 ) ) //dstIndex < dsize to prevent crash more robust are needed
333   {
334     if ( length == 0 )
335       length = litLength21( cbuf, opCode, &srcIndex );
336     copyCompBytes21( cbuf, dbuf, length, srcIndex, dstIndex );
337     srcIndex += length;
338     dstIndex += length;
339     if ( dstIndex >= dsize ) break; //check if last chunk are compressed & terminate
340 
341     length = 0;
342     opCode = cbuf[srcIndex++];
343     readInstructions21( cbuf, &srcIndex, &opCode, &sourceOffset, &length );
344     while ( true )
345     {
346       //prevent crash with corrupted data
347       if ( sourceOffset > dstIndex )
348       {
349         QgsDebugMsg( QString( "WARNING sourceOffset > dstIndex: csize=%1, srcIndex=%2 dsize=%3 dstIndex=%4" )
350                      .arg( csize ).arg( srcIndex ).arg( dsize ).arg( dstIndex )
351                    );
352         sourceOffset = dstIndex;
353       }
354       //prevent crash with corrupted data
355       if ( length > dsize - dstIndex )
356       {
357         QgsDebugMsg( QString( "WARNING length > dsize - dstIndex: csize=%1, srcIndex=%2 dsize=%3 dstIndex=%4" )
358                      .arg( csize ).arg( srcIndex ).arg( dsize ).arg( dstIndex )
359                    );
360         length = dsize - dstIndex;
361         srcIndex = csize;//force exit
362       }
363       sourceOffset = dstIndex - sourceOffset;
364       for ( duint32 i = 0; i < length; i++ )
365         dbuf[dstIndex++] = dbuf[sourceOffset + i];
366 
367       length = opCode & 7;
368       if ( ( length != 0 ) || ( srcIndex >= csize ) )
369       {
370         break;
371       }
372       opCode = cbuf[srcIndex++];
373       if ( ( opCode >> 4 ) == 0 )
374       {
375         break;
376       }
377       if ( ( opCode >> 4 ) == 15 )
378       {
379         opCode &= 15;
380       }
381       readInstructions21( cbuf, &srcIndex, &opCode, &sourceOffset, &length );
382     }
383   }
384   QgsDebugMsg( QString( "csize=%1, srcIndex=%2 dsize=%3 dstIndex=%4" )
385                .arg( csize ).arg( srcIndex ).arg( dsize ).arg( dstIndex )
386              );
387 }
388 
readInstructions21(duint8 * cbuf,duint32 * si,duint8 * oc,duint32 * so,duint32 * l)389 void dwgCompressor::readInstructions21( duint8 *cbuf, duint32 *si, duint8 *oc, duint32 *so, duint32 *l )
390 {
391   duint32 length;
392   duint32 srcIndex = *si;
393   duint32 sourceOffset;
394   unsigned char opCode = *oc;
395   switch ( ( opCode >> 4 ) )
396   {
397     case 0:
398       length = ( opCode & 0xf ) + 0x13;
399       sourceOffset = cbuf[srcIndex++];
400       opCode = cbuf[srcIndex++];
401       length = ( ( opCode >> 3 ) & 0x10 ) + length;
402       sourceOffset = ( ( opCode & 0x78 ) << 5 ) + 1 + sourceOffset;
403       break;
404     case 1:
405       length = ( opCode & 0xf ) + 3;
406       sourceOffset = cbuf[srcIndex++];
407       opCode = cbuf[srcIndex++];
408       sourceOffset = ( ( opCode & 0xf8 ) << 5 ) + 1 + sourceOffset;
409       break;
410     case 2:
411       sourceOffset = cbuf[srcIndex++];
412       sourceOffset = ( ( cbuf[srcIndex++] << 8 ) & 0xff00 ) | sourceOffset;
413       length = opCode & 7;
414       if ( ( opCode & 8 ) == 0 )
415       {
416         opCode = cbuf[srcIndex++];
417         length = ( opCode & 0xf8 ) + length;
418       }
419       else
420       {
421         sourceOffset++;
422         length = ( cbuf[srcIndex++] << 3 ) + length;
423         opCode = cbuf[srcIndex++];
424         length = ( ( ( opCode & 0xf8 ) << 8 ) + length ) + 0x100;
425       }
426       break;
427     default:
428       length = opCode >> 4;
429       sourceOffset = opCode & 15;
430       opCode = cbuf[srcIndex++];
431       sourceOffset = ( ( ( opCode & 0xf8 ) << 1 ) + sourceOffset ) + 1;
432       break;
433   }
434   *oc = opCode;
435   *si = srcIndex;
436   *so = sourceOffset;
437   *l = length;
438 }
439 
440 
copyCompBytes21(duint8 * cbuf,duint8 * dbuf,duint32 l,duint32 si,duint32 di)441 void dwgCompressor::copyCompBytes21( duint8 *cbuf, duint8 *dbuf, duint32 l, duint32 si, duint32 di )
442 {
443   duint32 length = l;
444   duint32 dix = di;
445   duint32 six = si;
446 
447   while ( length > 31 )
448   {
449     //in doc: 16-31, 0-15
450     for ( duint32 i = six + 24; i < six + 32; i++ )
451       dbuf[dix++] = cbuf[i];
452     for ( duint32 i = six + 16; i < six + 24; i++ )
453       dbuf[dix++] = cbuf[i];
454     for ( duint32 i = six + 8; i < six + 16; i++ )
455       dbuf[dix++] = cbuf[i];
456     for ( duint32 i = six; i < six + 8; i++ )
457       dbuf[dix++] = cbuf[i];
458     six = six + 32;
459     length = length - 32;
460   }
461 
462   switch ( length )
463   {
464     case 0:
465       break;
466     case 1: //OK
467       dbuf[dix] = cbuf[six];
468       break;
469     case 2: //OK
470       dbuf[dix++] = cbuf[six + 1];
471       dbuf[dix] = cbuf[six];
472       break;
473     case 3: //OK
474       dbuf[dix++] = cbuf[six + 2];
475       dbuf[dix++] = cbuf[six + 1];
476       dbuf[dix] = cbuf[six];
477       break;
478     case 4: //OK
479       for ( int i = 0; i < 4; i++ ) //RLZ is OK, or are inverse?, OK
480         dbuf[dix++] = cbuf[six++];
481       break;
482     case 5: //OK
483       dbuf[dix++] = cbuf[six + 4];
484       for ( int i = 0; i < 4; i++ )
485         dbuf[dix++] = cbuf[six++];
486       break;
487     case 6: //OK
488       dbuf[dix++] = cbuf[six + 5];
489       for ( int i = 1; i < 5; i++ )
490         dbuf[dix++] = cbuf[six + i];
491       dbuf[dix] = cbuf[six];
492       break;
493     case 7:
494       //in doc: six+5, six+6, 1-5, six+0
495       dbuf[dix++] = cbuf[six + 6];
496       dbuf[dix++] = cbuf[six + 5];
497       for ( int i = 1; i < 5; i++ )
498         dbuf[dix++] = cbuf[six + i];
499       dbuf[dix] = cbuf[six];
500 
501       FALLTHROUGH
502 
503     case 8: //OK
504       for ( int i = 0; i < 8; i++ ) //RLZ 4[0],4[4] or 4[4],4[0]
505         dbuf[dix++] = cbuf[six++];
506       break;
507     case 9: //OK
508       dbuf[dix++] = cbuf[six + 8];
509       for ( int i = 0; i < 8; i++ )
510         dbuf[dix++] = cbuf[six++];
511       break;
512     case 10: //OK
513       dbuf[dix++] = cbuf[six + 9];
514       for ( int i = 1; i < 9; i++ )
515         dbuf[dix++] = cbuf[six + i];
516       dbuf[dix] = cbuf[six];
517       break;
518     case 11:
519       //in doc: six+9, six+10, 1-9, six+0
520       dbuf[dix++] = cbuf[six + 10];
521       dbuf[dix++] = cbuf[six + 9];
522       for ( int i = 1; i < 9; i++ )
523         dbuf[dix++] = cbuf[six + i];
524       dbuf[dix] = cbuf[six];
525       break;
526     case 12: //OK
527       for ( int i = 8; i < 12; i++ )
528         dbuf[dix++] = cbuf[six + i];
529       for ( int i = 0; i < 8; i++ )
530         dbuf[dix++] = cbuf[six++];
531       break;
532     case 13: //OK
533       dbuf[dix++] = cbuf[six + 12];
534       for ( int i = 8; i < 12; i++ )
535         dbuf[dix++] = cbuf[six + i];
536       for ( int i = 0; i < 8; i++ )
537         dbuf[dix++] = cbuf[six++];
538       break;
539     case 14: //OK
540       dbuf[dix++] = cbuf[six + 13];
541       for ( int i = 9; i < 13; i++ )
542         dbuf[dix++] = cbuf[six + i];
543       for ( int i = 1; i < 9; i++ )
544         dbuf[dix++] = cbuf[six + i];
545       dbuf[dix] = cbuf[six];
546       break;
547     case 15:
548       //in doc: six+13, six+14, 9-12, 1-8, six+0
549       dbuf[dix++] = cbuf[six + 14];
550       dbuf[dix++] = cbuf[six + 13];
551       for ( int i = 9; i < 13; i++ )
552         dbuf[dix++] = cbuf[six + i];
553       for ( int i = 1; i < 9; i++ )
554         dbuf[dix++] = cbuf[six + i];
555       dbuf[dix] = cbuf[six];
556       break;
557     case 16: //OK
558       for ( int i = 8; i < 16; i++ )
559         dbuf[dix++] = cbuf[six + i];
560       for ( int i = 0; i < 8; i++ )
561         dbuf[dix++] = cbuf[six++];
562       break;
563     case 17: //Seems OK
564       for ( int i = 9; i < 17; i++ )
565         dbuf[dix++] = cbuf[six + i];
566       dbuf[dix++] = cbuf[six + 8];
567       for ( int i = 0; i < 8; i++ )
568         dbuf[dix++] = cbuf[six++];
569       break;
570     case 18:
571       //in doc: six+17, 1-16, six+0
572       dbuf[dix++] = cbuf[six + 17];
573       for ( int i = 9; i < 17; i++ )
574         dbuf[dix++] = cbuf[six + i];
575       for ( int i = 1; i < 9; i++ )
576         dbuf[dix++] = cbuf[six + i];
577       dbuf[dix] = cbuf[six];
578       break;
579     case 19:
580       //in doc: 16-18, 0-15
581       dbuf[dix++] = cbuf[six + 18];
582       dbuf[dix++] = cbuf[six + 17];
583       dbuf[dix++] = cbuf[six + 16];
584       for ( int i = 8; i < 16; i++ )
585         dbuf[dix++] = cbuf[six + i];
586       for ( int i = 0; i < 8; i++ )
587         dbuf[dix++] = cbuf[six++];
588       break;
589     case 20:
590       //in doc: 16-19, 0-15
591       for ( int i = 16; i < 20; i++ )
592         dbuf[dix++] = cbuf[six + i];
593       for ( int i = 8; i < 16; i++ )
594         dbuf[dix++] = cbuf[six + i];
595       for ( int i = 0; i < 8; i++ )
596         dbuf[dix++] = cbuf[six++];
597       break;
598     case 21:
599       //in doc: six+20, 16-19, 0-15
600       dbuf[dix++] = cbuf[six + 20];
601       for ( int i = 16; i < 20; i++ )
602         dbuf[dix++] = cbuf[six + i];
603       for ( int i = 8; i < 16; i++ )
604         dbuf[dix++] = cbuf[six + i];
605       for ( int i = 0; i < 8; i++ )
606         dbuf[dix++] = cbuf[six + i];
607       break;
608     case 22:
609       //in doc: six+20, six+21, 16-19, 0-15
610       dbuf[dix++] = cbuf[six + 21];
611       dbuf[dix++] = cbuf[six + 20];
612       for ( int i = 16; i < 20; i++ )
613         dbuf[dix++] = cbuf[six + i];
614       for ( int i = 8; i < 16; i++ )
615         dbuf[dix++] = cbuf[six + i];
616       for ( int i = 0; i < 8; i++ )
617         dbuf[dix++] = cbuf[six++];
618       break;
619     case 23:
620       //in doc: six+20, six+21, six+22, 16-19, 0-15
621       dbuf[dix++] = cbuf[six + 22];
622       dbuf[dix++] = cbuf[six + 21];
623       dbuf[dix++] = cbuf[six + 20];
624       for ( int i = 16; i < 20; i++ )
625         dbuf[dix++] = cbuf[six + i];
626       for ( int i = 8; i < 16; i++ )
627         dbuf[dix++] = cbuf[six + i];
628       for ( int i = 0; i < 8; i++ )
629         dbuf[dix++] = cbuf[six + i];
630       break;
631     case 24:
632       //in doc: 16-23, 0-15
633       for ( int i = 16; i < 24; i++ )
634         dbuf[dix++] = cbuf[six + i];
635       for ( int i = 8; i < 16; i++ )
636         dbuf[dix++] = cbuf[six + i];
637       for ( int i = 0; i < 8; i++ )
638         dbuf[dix++] = cbuf[six++];
639       break;
640     case 25:
641       //in doc: 17-24, six+16, 0-15
642       for ( int i = 17; i < 25; i++ )
643         dbuf[dix++] = cbuf[six + i];
644       dbuf[dix++] = cbuf[six + 16];
645       for ( int i = 8; i < 16; i++ )
646         dbuf[dix++] = cbuf[six + i];
647       for ( int i = 0; i < 8; i++ )
648         dbuf[dix++] = cbuf[six++];
649       break;
650     case 26:
651       //in doc: six+25, 17-24, six+16, 0-15
652       dbuf[dix++] = cbuf[six + 25];
653       for ( int i = 17; i < 25; i++ )
654         dbuf[dix++] = cbuf[six + i];
655       dbuf[dix++] = cbuf[six + 16];
656       for ( int i = 8; i < 16; i++ )
657         dbuf[dix++] = cbuf[six + i];
658       for ( int i = 0; i < 8; i++ )
659         dbuf[dix++] = cbuf[six++];
660       break;
661     case 27:
662       //in doc: six+25, six+26, 17-24, six+16, 0-15
663       dbuf[dix++] = cbuf[six + 26];
664       dbuf[dix++] = cbuf[six + 25];
665       for ( int i = 17; i < 25; i++ )
666         dbuf[dix++] = cbuf[six + i];
667       dbuf[dix++] = cbuf[six + 16];
668       for ( int i = 8; i < 16; i++ )
669         dbuf[dix++] = cbuf[six + i];
670       for ( int i = 0; i < 8; i++ )
671         dbuf[dix++] = cbuf[six++];
672       break;
673     case 28:
674       //in doc: 24-27, 16-23, 0-15
675       for ( int i = 24; i < 28; i++ )
676         dbuf[dix++] = cbuf[six + i];
677       for ( int i = 16; i < 24; i++ )
678         dbuf[dix++] = cbuf[six + i];
679       for ( int i = 8; i < 16; i++ )
680         dbuf[dix++] = cbuf[six + i];
681       for ( int i = 0; i < 8; i++ )
682         dbuf[dix++] = cbuf[six++];
683       break;
684     case 29:
685       //in doc: six+28, 24-27, 16-23, 0-15
686       dbuf[dix++] = cbuf[six + 28];
687       for ( int i = 24; i < 28; i++ )
688         dbuf[dix++] = cbuf[six + i];
689       for ( int i = 16; i < 24; i++ )
690         dbuf[dix++] = cbuf[six + i];
691       for ( int i = 8; i < 16; i++ )
692         dbuf[dix++] = cbuf[six + i];
693       for ( int i = 0; i < 8; i++ )
694         dbuf[dix++] = cbuf[six++];
695       break;
696     case 30:
697       //in doc: six+28, six+29, 24-27, 16-23, 0-15
698       dbuf[dix++] = cbuf[six + 29];
699       dbuf[dix++] = cbuf[six + 28];
700       for ( int i = 24; i < 28; i++ )
701         dbuf[dix++] = cbuf[six + i];
702       for ( int i = 16; i < 24; i++ )
703         dbuf[dix++] = cbuf[six + i];
704       for ( int i = 8; i < 16; i++ )
705         dbuf[dix++] = cbuf[six + i];
706       for ( int i = 0; i < 8; i++ )
707         dbuf[dix++] = cbuf[six++];
708       break;
709     case 31:
710       //in doc: six+30, 26-29, 18-25, 2-17, 0-1
711       dbuf[dix++] = cbuf[six + 30];
712       for ( int i = 26; i < 30; i++ )
713         dbuf[dix++] = cbuf[six + i];
714       for ( int i = 18; i < 26; i++ )
715         dbuf[dix++] = cbuf[six + i];
716       /*        for (int i = 2; i<18; i++)
717                   dbuf[dix++] = cbuf[six+i];*/
718       for ( int i = 10; i < 18; i++ )
719         dbuf[dix++] = cbuf[six + i];
720       for ( int i = 2; i < 10; i++ )
721         dbuf[dix++] = cbuf[six + i];
722       dbuf[dix++] = cbuf[six + 1];
723       dbuf[dix] = cbuf[six];
724       break;
725     default:
726       QgsDebugMsg( "WARNING bad output." );
727       break;
728   }
729 }
730 
731 
getEnum(std::string nameSec)732 secEnum::DWGSection secEnum::getEnum( std::string nameSec )
733 {
734   //TODO: complete it
735   if ( nameSec == "AcDb:Header" )
736   {
737     return HEADER;
738   }
739   else if ( nameSec == "AcDb:Classes" )
740   {
741     return CLASSES;
742   }
743   else if ( nameSec == "AcDb:SummaryInfo" )
744   {
745     return SUMMARYINFO;
746   }
747   else if ( nameSec == "AcDb:Preview" )
748   {
749     return PREVIEW;
750   }
751   else if ( nameSec == "AcDb:VBAProject" )
752   {
753     return VBAPROY;
754   }
755   else if ( nameSec == "AcDb:AppInfo" )
756   {
757     return APPINFO;
758   }
759   else if ( nameSec == "AcDb:FileDepList" )
760   {
761     return FILEDEP;
762   }
763   else if ( nameSec == "AcDb:RevHistory" )
764   {
765     return REVHISTORY;
766   }
767   else if ( nameSec == "AcDb:Security" )
768   {
769     return SECURITY;
770   }
771   else if ( nameSec == "AcDb:AcDbObjects" )
772   {
773     return OBJECTS;
774   }
775   else if ( nameSec == "AcDb:ObjFreeSpace" )
776   {
777     return OBJFREESPACE;
778   }
779   else if ( nameSec == "AcDb:Template" )
780   {
781     return TEMPLATE;
782   }
783   else if ( nameSec == "AcDb:Handles" )
784   {
785     return HANDLES;
786   }
787   else if ( nameSec == "AcDb:AcDsPrototype_1b" )
788   {
789     return PROTOTYPE;
790   }
791   else if ( nameSec == "AcDb:AuxHeader" )
792   {
793     return AUXHEADER;
794   }
795   else if ( nameSec == "AcDb:Signature" )
796   {
797     return SIGNATURE;
798   }
799   else if ( nameSec == "AcDb:AppInfoHistory" )  //in ac1021
800   {
801     return APPINFOHISTORY;
802 //    } else if (nameSec=="AcDb:Extended Entity Data"){
803 //        return EXTEDATA;
804 //    } else if (nameSec=="AcDb:PROXY ENTITY GRAPHICS"){
805 //        return PROXYGRAPHICS;
806   }
807   return UNKNOWNS;
808 }
809