forked from difcareer/010templates
-
Notifications
You must be signed in to change notification settings - Fork 3
/
GZipTemplate.bt
executable file
·185 lines (155 loc) · 5.63 KB
/
GZipTemplate.bt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
//--------------------------------------
//--- 010 Editor v4.0.3 Binary Template
//
// File: GZipTemplate.bt
// Author: Tim "diff" Strazzere <[email protected]> <[email protected]>
// Revision: 1.2
// Purpose: Quick template for parsing GZip data/files
//--------------------------------------
//
// Version 1.2
// - Fix processing of part numbers for continuation based gzips
// - Added some notes on the encrypted header information
//
// Version 1.1
// - Fix small typos
// - Added comments to fields
// - Fix compression/flag names according to gzip 1.2.4 source
// - Added uncompressed length and CRC32
// - Check for different common magic bytes, and display properly
// - Minor code clean up
//
// Version 1.0
// - First implementation of the template
//
// TODO:
// - Parse encrypted header information
// GZip's should be Little Endian only
LittleEndian();
// utility type to show the magic bytes in the value column
typedef ubyte MAGIC[2] <read=MAGICRead, format=hex>;
string MAGICRead(MAGIC magic) {
string ret;
string tmp;
int i;
for(i = 0; i<2; i++) {
SPrintf(tmp, "%.2X", magic[i]);
ret += tmp;
}
return ret;
}
typedef enum <ubyte> {
// All below, except DEFLATE are reserved
STORED = 0,
COMPRESSED = 1,
PACKED = 2,
LZHED = 3,
RESERVED_4 = 4,
RESERVED_5 = 5,
RESERVED_6 = 6,
RESERVED_7 = 7,
// Default (and most common)
DEFLATE = 8
} COMPRESSION;
// TODO : Probably some better way to do this
typedef struct {
// File is probably ascii text (determined by compressor)
byte FLAG_ASCII_TEXT : 1;
// Continuation of multi-part gzip file
byte FLAG_CONTINUATION : 1;
// Generic extra field present
byte FLAG_EXTRA : 1;
// Original filename present
byte FLAG_NAME : 1;
// File comment present
byte FLAG_COMMENT : 1;
// Is file encrypted?
byte FLAG_ENCRYPTED : 1;
// Reserved for future use (nothing as of gzip 1.2.4
byte FLAG_RESERVED : 1;
byte FLAG_RESERVED : 1;
} FLAGS;
typedef enum <byte> {
FAT_FILESYSTEM = 0,
AMIGA = 1,
VMS = 2,
UNIX = 3,
VM_CMS = 4,
ATARI_TOS = 5,
HPFS_FILESYSTEM = 6,
MACINTOSH = 7,
Z_SYSTEM = 8,
CPM = 9,
TOPS_20 = 10,
NTFS_FILESYSTEM = 11,
QDOS = 12,
ACORN_RISCOS = 13,
UNKNOWN = 255
} OS;
typedef struct {
MAGIC magic_bytes <format=hex, comment="Magic bytes for the file">;
// Should be a better way to parse the magic bytes and complain to user...
if(magic_bytes[0] == 0x1F) {
if(magic_bytes[1] == 0x8B) {
// GZIP_MAGIC
Printf("Appears to be a valid GZIP compressed file, attempting to parse.\n");
} else if(magic_bytes[1] == 0x1E) {
// PACK_MAGIC
Printf("Appears to be a generic compressed file, attempting to parse - don't expect much though.\n");
} else if(magic_bytes[1] == 0x9E) {
// OLD_GZIP_MAGIC
Printf("Appears to be an old GZip compressed file, attempting to parse - don't expect much though.\n");
} else if(magic_bytes[1] == 0xA0) {
// LZH_MAGIC
Printf("Appears to be a LZH compressed file, attempting to parse - don't expect much though.\n");
}
} else if(magic_bytes[0] == 0x50 && magic_bytes[1] == 0x4B) {
Warning("Appears to be a possible ZIP file - unable to parse with this template!");
Exit(-1);
} else {
Warning("Does not appear to be a GZip file!");
Exit(-1);
}
COMPRESSION compression_method <comment="Compression method used by engine">;
FLAGS flags <comment="Optional flags for compressed section">;
// Convert to proper timestamp
uint modification_time <comment="Unix timestamp of the file modification time">;
// Extra flags
ubyte extra_flags <comment="Extra flags, dependant on compression method">;
// OS where compression took place
OS operating_system <comment="Operating system compression took place on">;
// The file is marked as a continuation, so it should have a part number
if(flags.FLAG_CONTINUATION == 1) {
ushort part <comment="Part number of the continuation">;
}
// Read in extras from flags
if(flags.FLAG_EXTRA == 1) {
ushort extra_length <comment="Length of extra field">;
byte extra_bytes[extra_length] <comment="Data for extra field">;
}
if(flags.FLAG_NAME == 1) {
string original_file_name <comment="Original file name">;
}
if(flags.FLAG_COMMENT == 1) {
string file_comment <comment="File comment">;
}
// TODO: Parse encrypted header info
// -- according to the docs this is grabbed from the zip lib (crypt.h/crypt.c)
// which according to their docs is hardly used or fully supported.
// It would appear you would need to compile this directly into your gzip
// sources for it to properly work, even though it's considered "valid".
if(flags.FLAG_ENCRYPTED == 1) {
// 12 bytes of encryption header data
}
} gzip_header;
// Structure of gzip file
struct {
// Header information
gzip_header header <comment="GZip header information">;
// Everything else should just be compress bytes, less the last 8 bytes
// which contain the CRC32 and uncompressed size
byte compressed[FileSize() - FTell() - 8] <comment="compressed data section">;
uint CRC32 <format=hex, comment="CRC of the data section">;
// 4 bytes uncompressed input size modulo 2^32
uint uncompressed_sized <comment="Size of the uncompressed input">;
} gzip_file;