btparser/cparser/tests/exp_lex/RARTemplate.bt

457 lines
12 KiB
Plaintext

1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15: LittleEndian ( ) ;
16:
17: local const uint16 SignatureLen = 7 ;
18: const string RarSignature = "Rar!" + '\x1A' + '\x07' ;
19:
20:
21:
22: struct FileHeadBlock ;
23: struct OldCommentBlock ;
24: struct OldSubBlock ;
25: struct SubBlock ;
26:
27:
28:
29: enum < byte > RarBlockType
30: {
31: MARKER = 0x72 , ARCHIVE , FILE_OR_DIR , COMMENT_OLD , AV_OLD_1 , SUBBLOCK_OLD , RR_OLD , AV_OLD_2 , SUBBLOCK , _END_
32: } ;
33:
34:
35:
36: local uint16 _flags = 0 ;
37:
38:
39: local uquad iBlocksCounter = 0 ;
40: local uquad iFiles = 0 ;
41: local uquad iDirs = 0 ;
42: local uquad iComments = 0 ;
43: local uquad iSubBlocks = 0 ;
44: local uquad iUniNames = 0 ;
45: local uquad iBadCRCCounter = 0 ;
46: local ubyte iMinVerToUnpack = 0xFF ;
47: local ubyte iMaxVerToUnpack = 0 ;
48: local uquad iTotalUnpackedSize = 0 ;
49: local uint iAV1 = 0 ;
50: local uint iAV2 = 0 ;
51:
52:
53:
54: enum < ubyte > OsType
55: {
56: _MS_DOS , _OS_2 , _Win32 , _Unix , _Mac_OS , _BeOS
57: } ;
58:
59: enum < char > PackMethod
60: {
61: Store = '0' , Fastest , Fast , Normal , Good , Best
62: } ;
63:
64: enum < uint16 > SubType_OldStyle
65: {
66: OS2_EA = 0x100
67: } ;
68:
69: struct UnixStyleAttrs
70: {
71: uint32 owner_may_eXecute : 1 ;
72: uint32 owner_may_Write : 1 ;
73: uint32 owner_may_Read : 1 ;
74:
75: uint32 group_may_eXecute : 1 ;
76: uint32 gorup_may_Write : 1 ;
77: uint32 group_may_Read : 1 ;
78:
79: uint32 everybody_may_eXecute : 1 ;
80: uint32 everybody_may_Write : 1 ;
81: uint32 everybody_may_Read : 1 ;
82:
83: uint32 _s : 1 ;
84: uint32 _s : 1 ;
85:
86: uint32 _unused : 21 ;
87: } ;
88:
89: struct DosFileAttrs
90: {
91: uint32 READONLY : 1 ;
92: uint32 HIDDEN : 1 ;
93: uint32 SYSTEM : 1 ;
94: uint32 VOLUME : 1 ;
95: uint32 DIRECTORY : 1 ;
96: uint32 ARCHIVE : 1 ;
97: uint32 _res : 26 ;
98: } ;
99:
100: struct WinFileAttrs
101: {
102: uint32 READONLY : 1 ;
103: uint32 HIDDEN : 1 ;
104: uint32 SYSTEM : 1 ;
105: uint32 VOLUME : 1 ;
106: uint32 DIRECTORY : 1 ;
107: uint32 ARCHIVE : 1 ;
108: uint32 DEVICE : 1 ;
109: uint32 NORMAL : 1 ;
110: uint32 TEMPORARY : 1 ;
111: uint32 SPARSE_FILE : 1 ;
112: uint32 REPARSE_POINT : 1 ;
113: uint32 COMPRESSED : 1 ;
114: uint32 OFFLINE : 1 ;
115: uint32 NOT_CONTENT_INDEXED : 1 ;
116: uint32 ENCRYPTED : 1 ;
117: uint32 _res2 : 17 ;
118: } ;
119:
120: struct CommonBlockFlags
121: {
122: ushort _reserved : 14 ;
123: ushort OLD_VERSION_IGNORE : 1 ;
124: ushort ADD_SIZE_PRESENT : 1 ;
125: } ;
126:
127: struct MainHeadFlags
128: {
129: ubyte ARCHIVE_VOLUME : 1 ;
130: ubyte ARCHIVE_COMMENT_PRESENT : 1 ;
131: ubyte ARCHIVE_LOCKED : 1 ;
132: ubyte ARCHIVE_SOLID : 1 ;
133: ubyte NEW_VOLUME_NAMING : 1 ;
134: ubyte AV_PRESENT : 1 ;
135: ubyte RECOVERY_PRESENT : 1 ;
136: ubyte BLOCK_HEADERS_ENCRYPTED : 1 ;
137: ubyte IS_FIRST_VOLUME : 1 ;
138: ubyte _reserved : 5 ;
139: ubyte OLD_VERSION_IGNORE : 1 ;
140: ubyte ADD_SIZE_PRESENT : 1 ;
141: } ;
142:
143:
144: enum < byte > FileDictType
145: {
146: _64K , _128K , _256K , _512K , _1024K , _2048K , _4096K , _Directory
147: } ;
148:
149: struct FileHeadFlags
150: {
151: ubyte from_PREV_VOLUME : 1 ;
152: ubyte to_NEXT_VOLUME : 1 ;
153: ubyte PASSWORD_ENCRYPTED : 1 ;
154: ubyte FILE_COMMENT_PRESENT : 1 ;
155: ubyte SOLID : 1 ;
156: FileDictType DICTIONARY : 3 ;
157: ubyte HIGH_SIZE : 1 ;
158: ubyte has_UNICODE_FILENAME : 1 ;
159: ubyte ENCRYPTION_SALT : 1 ;
160: ubyte IS_OLD_FILE_VERSION : 1 ;
161: ubyte EXTENDED_TIME_INFO : 1 ;
162: ubyte _reserved : 1 ;
163: ubyte OLD_VERSION_IGNORE : 1 ;
164: ubyte ADD_SIZE_PRESENT : 1 ;
165: } ;
166:
167: struct RarBlock
168: {
169: local quad iOfs = FTell ( ) ;
170:
171: uint16 HEAD_CRC < format = hex , fgcolor = cRed > ;
172:
173: RarBlockType HeadType < fgcolor = cGreen > ;
174:
175: _flags = ReadUShort ( FTell ( ) ) ;
176:
177: if ( HeadType == ARCHIVE )
178: MainHeadFlags HEAD_FLAGS ;
179: else if ( HeadType == FILE_OR_DIR )
180: FileHeadFlags HEAD_FLAGS ;
181: else
182: CommonBlockFlags HEAD_FLAGS ;
183:
184: ++ iBlocksCounter ;
185:
186: if ( HeadType < MARKER || HeadType > _END_ )
187: {
188: Warning ( "Unknown Header Type (0x%02x) in Block #%Lu" , HeadType , iBlocksCounter ) ;
189: Printf ( "Unknown Header Type (0x%02x) in Block #%Lu\n" , HeadType , iBlocksCounter ) ;
190: }
191:
192: uint16 HeaderSize ;
193:
194: if ( HeaderSize < 7 )
195: {
196: Warning ( "Invalid block size (%u) in Block #%Lu" , HeaderSize , iBlocksCounter ) ;
197: Printf ( "Invalid block size (%u) in Block #%Lu\n" , HeaderSize , iBlocksCounter ) ;
198: return - 1 ;
199: }
200:
201: if ( HeadType != MARKER )
202: {
203: local uint16 crcCheck = Checksum ( CHECKSUM_CRC32 , startof ( HeadType ) , HeaderSize - sizeof ( HEAD_CRC ) ) & 0xFFFF ;
204: if ( crcCheck != HEAD_CRC )
205: {
206: Warning ( "Header CRC mismatch in Block #%Lu" , iBlocksCounter ) ;
207: Printf ( "Header CRC mismatch in Block #%Lu: expected CRC is 0x%X, got 0x%X\n" , iBlocksCounter , crcCheck , HEAD_CRC ) ;
208: ++ iBadCRCCounter ;
209: }
210: }
211:
212: if ( HEAD_FLAGS . ADD_SIZE_PRESENT )
213: uint32 RawDataSize ;
214: else
215: local uint32 RawDataSize = 0 ;
216:
217: switch ( HeadType ) {
218: case ARCHIVE :
219: uint16 _reserved1 ;
220: uint32 _reserved2 ;
221: if ( HEAD_FLAGS . ARCHIVE_COMMENT_PRESENT ) struct RarBlock MainComment ;
222: break ;
223: case FILE_OR_DIR :
224: if ( HEAD_FLAGS . DICTIONARY == 7 )
225: {
226: ++ iDirs ;
227: FileHeadBlock dir ;
228: }
229: else
230: {
231: ++ iFiles ;
232: FileHeadBlock file ;
233: }
234: break ;
235: case COMMENT_OLD :
236: OldCommentBlock cmm ;
237: break ;
238: case SUBBLOCK_OLD :
239: OldSubBlocksub ;
240: break ;
241: case SUBBLOCK :
242: SubBlock sub ;
243: break ;
244: case AV_OLD_1 :
245: ++ iAV1 ;
246: Printf ( "*** AV was found (RAR v. < 2.60) @ block #%Lu.\n" , iBlocksCounter ) ;
247: break ;
248: case AV_OLD_2 :
249: ++ iAV2 ;
250: Printf ( "*** AV was found (RAR v. 2.60 - 2.9x) @ block #%Lu.\n" , iBlocksCounter ) ;
251: break ;
252: }
253:
254: iOfs = HeaderSize - ( FTell ( ) - iOfs ) ;
255:
256: if ( iOfs > 0 )
257: ubyte _reserved [ iOfs ] ;
258:
259: if ( RawDataSize > 0 )
260: ubyte _raw [ RawDataSize ] < format = hex , fgcolor = cBlue > ;
261: } ;
262:
263: struct FileHeadBlock
264: {
265: uint32 UnpackedSize ;
266: iTotalUnpackedSize += UnpackedSize ;
267:
268: OsType Host_OS ;
269: uint32 FileCRC32 < format = hex > ;
270: DOSTIME FileTime ;
271: DOSDATE FileDate ;
272: ubyte VersionToUnpack ;
273:
274: if ( VersionToUnpack > iMaxVerToUnpack )
275: iMaxVerToUnpack = VersionToUnpack ;
276:
277: if ( VersionToUnpack < iMinVerToUnpack )
278: iMinVerToUnpack = VersionToUnpack ;
279:
280: PackMethod Method ;
281: uint16 NameSize ;
282:
283: switch ( Host_OS ) {
284: case _Win32 :
285: WinFileAttrs Attributes ;
286: break ;
287: case _MS_DOS :
288: case _Mac_OS :
289: case _OS_2 :
290: DosFileAttrs Attributes ;
291: break ;
292: case _Unix :
293: case _BeOS :
294: UnixStyleAttrs Attributes ;
295: break ;
296: default :
297: uint32 Attributes < format = binary > ;
298: }
299:
300: if ( _flags & 0x100 )
301: {
302: uint32 HIGH_PACK_SIZE ;
303: uint32 HIGH_UNP_SIZE ;
304:
305: iTotalUnpackSize += ( HIGH_UNP_SIZE << 32 ) ;
306: }
307:
308: if ( _flags & 0x200 )
309: {
310: ++ iUniNames ;
311:
312: string FileName ;
313: uint16 WideFileNameData [ ( NameSize - sizeof ( FileName ) ) / 2 ] ;
314: }
315: else
316: char FileName [ NameSize ] ;
317:
318: if ( _flags & 0x8 )
319: {
320: RarBlock FileComment ;
321: }
322:
323: if ( _flags & 0x400 )
324: uquad SALT < format = hex > ;
325: } ;
326:
327:
328:
329: struct OldCommentBlock {
330: ++ iComments ;
331:
332: uint16 UnpackedSize ;
333: ubyte VersionToUnpack ;
334: PackMethod Method ;
335: uint16 CommentCRC < format = hex > ;
336:
337: Printf ( "*** Old style CommentBlock: (Block #%Lu)\n" , iBlocksCounter ) ;
338: } ;
339:
340: struct OldSubBlock {
341: ++ iSubBlocks ;
342:
343: SubType_OldStyle SubType ;
344: ubyte _reserved ;
345:
346: Printf ( "*** Old style SubBlock: %u (Block #%Lu)\n" , SubType , iBlocksCounter ) ;
347: } ;
348:
349: struct SubBlock {
350: ++ iSubBlocks ;
351:
352: ubyte _unknown_to_me_1 [ 15 ] ;
353: ubyte SubTypeLen ;
354: ubyte _unknown_to_me_2 [ 5 ] ;
355: char SubType [ SubTypeLen ] ;
356:
357: Printf ( "*** SubBlock: %s (Block #%Lu)\n" , SubType + '\0' , iBlocksCounter ) ;
358: switch ( SubType ) {
359: case "CMT" :
360: ++ iComments ;
361: break ;
362: case "AV" :
363: Printf ( "*** Authenticity Verification info (RAR v. 3.x) @ block #%Lu.\n" , iBlocksCounter ) ;
364: break ;
365: case "RR" :
366: Printf ( "*** Recovery Record was found (RAR v. 3.x) @ block #%Lu.\n" , iBlocksCounter ) ;
367: break ;
368: }
369: } ;
370:
371:
372:
373: local string fn = GetFileName ( ) ;
374: local quad SignaturePos = 0 ;
375: local char Signature [ SignatureLen ] ;
376:
377: if ( Strstr ( fn , ".rar" ) != Strlen ( fn ) - 4 )
378: {
379: Warning ( "Seeking for RAR signature..." ) ;
380:
381: local quad _p = FindFirst ( RarSignature ) ;
382: if ( _p >= 0 )
383: FSeek ( _p ) ;
384: else
385: {
386: Warning ( "Not a RAR archive!" ) ;
387: return - 1 ;
388: }
389:
390: Warning ( "RAR signature found at 0x%08x." , _p ) ;
391: Printf ( "RAR signature found at 0x%08x.\n" , _p ) ;
392: }
393: else
394: {
395: ReadBytes ( Signature , SignaturePos , SignatureLen ) ;
396:
397: if ( Strcmp ( Signature , RarSignature ) )
398: {
399: Warning ( "Invalid RAR Archive Signature!" ) ;
400: return SignaturePos ;
401: }
402: }
403:
404: RarBlock Marker ;
405:
406: RarBlock ArcHeader ;
407: if ( ArcHeader . HeadType != ARCHIVE )
408: {
409: Warning ( "Main archive header is either bad or missing!" ) ;
410: return - 2 ;
411: }
412: else
413: {
414: Printf ( "It is a %s%s %s %s RAR archive.\n" ,
415: SignaturePos > 0 ? "SelF-eXtractable " : "" ,
416: ArcHeader . HEAD_FLAGS . ARCHIVE_LOCKED ? "LOCKED" : "non-locked" ,
417: ArcHeader . HEAD_FLAGS . ARCHIVE_SOLID ? "SOLID" : "regular" ,
418: ArcHeader . HEAD_FLAGS . ARCHIVE_VOLUME ? "VOLUME'd" : "one-part" ) ;
419:
420: if ( ArcHeader . HEAD_FLAGS . ARCHIVE_COMMENT_PRESENT )
421: Printf ( "Main comment is present.\n" ) ;
422: if ( ArcHeader . HEAD_FLAGS . AV_PRESENT )
423: Printf ( "Old style Authenticity Verification is present.\n" ) ;
424: if ( ArcHeader . HEAD_FLAGS . RECOVERY_PRESENT )
425: Printf ( "Recovery Record is present.\n" ) ;
426:
427: if ( ArcHeader . HEAD_FLAGS . BLOCK_HEADERS_ENCRYPTED )
428: {
429: Printf ( "It's an encrypted archive. Cannot proceed, exiting...\n" ) ;
430: return - 3 ;
431: }
432: }
433:
434: while ( ! FEof ( ) )
435: {
436: RarBlock block ;
437: }
438:
439: if ( block . HeadType != _END_ && iMaxVerToUnpack > 20 )
440: {
441: Warning ( "END Marker block was expected here." ) ;
442: }
443:
444: if ( iFiles || iDirs )
445: {
446: Printf ( "Version to unpack: %u.%u\n" , iMaxVerToUnpack / 10 , iMaxVerToUnpack % 10 ) ;
447: if ( iMinVerToUnpack != iMaxVerToUnpack )
448: Printf ( "Some data can also be retrieved by an earlier version of %u.%u\n" ,
449: iMinVerToUnpack / 10 , iMinVerToUnpack % 10 ) ;
450: }
451:
452: Printf ( "Files: %Lu, Dirs: %Lu, Comments: %Lu, SubBlocks: %Lu, Unpacked Size: %Lu\n" , iFiles , iDirs , iComments , iSubBlocks , iTotalUnpackedSize ) ;
453: Printf ( "UNICODE Names: %Lu\n" , iUniNames ) ;
454: if ( iBadCRCCounter )
455: Printf ( "%Lu blocks corrupted.\n" , iBadCRCCounter ) ;
456: Printf ( "Done. %Lu blocks processed.\n" , iBlocksCounter ) ;
457: tok_eof