diff options
Diffstat (limited to 'src/export/extract_version_2.c')
-rw-r--r-- | src/export/extract_version_2.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/export/extract_version_2.c b/src/export/extract_version_2.c new file mode 100644 index 0000000..fe85252 --- /dev/null +++ b/src/export/extract_version_2.c | |||
@@ -0,0 +1,131 @@ | |||
1 | #include <fcntl.h> | ||
2 | #include "mystdlib.h" | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <stdint.h> | ||
6 | #include <unistd.h> | ||
7 | |||
8 | /* lha header: | ||
9 | |||
10 | 00 Header length | ||
11 | 01 Header checksum [02-length] | ||
12 | 02 0x2d ('-') | ||
13 | 03 0x6c ('l') | ||
14 | 04 0x68 ('h') | ||
15 | 05 0x?? ('0' or '5') unsure | ||
16 | 06 0x2d ('-') | ||
17 | 07 0x?? LSB of compressed size | ||
18 | 08 0x?? .. | ||
19 | 09 0x00 .. | ||
20 | 10 0x00 MSB of compressed size, i.e. 0 | ||
21 | .. | ||
22 | 21 Length of path name | ||
23 | |||
24 | |||
25 | */ | ||
26 | |||
27 | static uint8_t mantra_in[] = { 0x68, 0x35, 0x2d, 0x6c }; | ||
28 | |||
29 | int main( int args, char **argv ) | ||
30 | { | ||
31 | int filenum = 0, run = 1; | ||
32 | size_t offset = 0, oldoffset = -1, reported = 0, enc_len = 32; | ||
33 | uint8_t mantra[4], id0, id5, *mappedfile; | ||
34 | MAP map; | ||
35 | |||
36 | /* For streets we do have a enc_len of 34 */ | ||
37 | while( run ) { | ||
38 | switch( getopt( args, argv, ":e:" ) ) { | ||
39 | case -1 : run = 0; break; | ||
40 | case 'e': | ||
41 | enc_len = atol( optarg ); | ||
42 | break; | ||
43 | default: | ||
44 | fputs( "Syntax: %s [-e encrypted_length (default: 32, for streets 34 or 0)] path-to-teiln.dat", stderr ); exit( 1 ); | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | run = 1; | ||
49 | |||
50 | if( optind == args ) | ||
51 | { fputs( "Missing filename.", stderr ); exit( 1 ); } | ||
52 | |||
53 | map = map_file( argv[optind], 1 ); | ||
54 | mappedfile = map->addr; | ||
55 | |||
56 | mantra[0] = mantra_in[0] ^ mappedfile[4]; | ||
57 | mantra[1] = mantra_in[1] ^ mappedfile[5]; | ||
58 | mantra[2] = mantra_in[2] ^ mappedfile[2]; | ||
59 | mantra[3] = mantra_in[3] ^ mappedfile[3]; | ||
60 | |||
61 | id0 = mappedfile[0]; | ||
62 | id5 = mappedfile[5]; | ||
63 | |||
64 | while( run ) | ||
65 | { | ||
66 | while( ( offset < map->size ) && ( | ||
67 | ( mappedfile[ offset + 0 ] != id0 ) || | ||
68 | ( mappedfile[ offset + 2 ] != ( '-' ^ mantra[2] )) || | ||
69 | ( mappedfile[ offset + 3 ] != ( 'l' ^ mantra[3] )) || | ||
70 | ( mappedfile[ offset + 4 ] != ( 'h' ^ mantra[0] )) || | ||
71 | ( mappedfile[ offset + 5 ] != id5 ) || | ||
72 | ( mappedfile[ offset + 6 ] != ( '-' ^ mantra[2] )) | ||
73 | ) ) offset++; | ||
74 | |||
75 | // printf( "Found an appropriate offset at: %zd\n", offset ); | ||
76 | |||
77 | if( reported < ( offset * 10 ) / map->size ) | ||
78 | { | ||
79 | reported++; | ||
80 | printf( "%zd%% ", 10 * reported ); | ||
81 | fflush( stdout ); | ||
82 | } | ||
83 | |||
84 | if( offset == map->size ) | ||
85 | run = 0; | ||
86 | |||
87 | if( oldoffset != -1 ) | ||
88 | { | ||
89 | uint8_t *mf = mappedfile + oldoffset, df[128]; | ||
90 | size_t filename_len, header_len; | ||
91 | char filename_template[32], filename[32]; | ||
92 | int i; | ||
93 | |||
94 | /* De-"crypt" obfuscation to our header copy */ | ||
95 | for( i=0; i<enc_len; ++i) | ||
96 | df[i] = mf[i] ^ mantra[i%4]; | ||
97 | |||
98 | /* Get values from LHA header */ | ||
99 | header_len = df[0] + 2; | ||
100 | filename_len = df[21]; | ||
101 | |||
102 | /* Copy rest of header, so we can checksum */ | ||
103 | for( i=enc_len; i<header_len; ++i) | ||
104 | df[i] = mf[i]; | ||
105 | |||
106 | /* Make up new sequental file name */ | ||
107 | snprintf( filename_template, sizeof(filename_template), "%%0%dd.lha", (int)filename_len ); | ||
108 | snprintf( filename, sizeof( filename ), filename_template, filenum++ ); | ||
109 | memcpy( ((uint8_t*)df) + 22, filename, filename_len); | ||
110 | |||
111 | /* Recalculate checksum with new file name */ | ||
112 | df[1] = 0; for( i=2; i<header_len; ++i) df[1] += df[i]; | ||
113 | |||
114 | /* Open file and dump our de-"crypted" header and then rest of file */ | ||
115 | i = open( filename, O_CREAT | O_TRUNC | O_WRONLY, 0644 ); | ||
116 | if( enc_len > header_len ) { | ||
117 | write( i, df, enc_len ); | ||
118 | write( i, mf + enc_len, offset - oldoffset - enc_len ); | ||
119 | } else { | ||
120 | write( i, df, header_len ); | ||
121 | write( i, mf + header_len, offset - oldoffset - header_len ); | ||
122 | } | ||
123 | close( i ); | ||
124 | } | ||
125 | oldoffset = offset; | ||
126 | offset++; | ||
127 | } | ||
128 | |||
129 | unmap_file( &map ); | ||
130 | return 0; | ||
131 | } | ||