]> icculus.org git repositories - taylor/freespace2.git/blob - src/scramble/scramble.cpp
merge updated toolset
[taylor/freespace2.git] / src / scramble / scramble.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/scramble/scramble.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Module for file scrambler
16  *
17  * $Log$
18  * Revision 1.3  2003/01/30 20:05:01  relnev
19  * ported (Taylor Richards)
20  *
21  * Revision 1.2  2002/06/09 04:41:25  relnev
22  * added copyright header
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:10  root
25  * Initial import.
26  *
27  * 
28  * 3     3/25/99 11:26a Dave
29  * Beefed up encryption scheme so that even someone viewing the
30  * disassembly would have a hard time cracking it.
31  * 
32  * 2     10/24/98 11:41p Dave
33  * 
34  * 1     10/24/98 11:31p Dave
35  * 
36  * 7     8/09/98 4:44p Lawrance
37  * support alternate encryption scheme (doesn't pack chars into 7 bits)
38  * 
39  * 6     4/14/98 4:14p Lawrance
40  * fix bug with ships and weapons tbl preprocessing
41  * 
42  * 5     4/14/98 1:39p Lawrance
43  * Add command line switches to preprocess ship and weapon tables
44  * 
45  * 4     3/31/98 1:14a Lawrance
46  * Get .tbl and mission file encryption working.
47  * 
48  * 3     3/30/98 5:57p Lawrance
49  * add some comments
50  * 
51  * 2     3/30/98 5:51p Lawrance
52  * file encryption and decryption
53  *
54  * $NoKeywords: $
55  *
56 */
57
58 #include <stdlib.h>
59 #include <stdio.h>
60 #ifndef PLAT_UNIX
61 #include <io.h>
62 #else
63 #include <sys/stat.h>
64 #endif
65 #include <string.h>
66
67 #include "pstypes.h"
68 #include "encrypt.h"
69 #include "scramble.h"
70
71 #undef malloc
72 #undef free
73 #undef strdup
74
75 #ifndef PLAT_UNIX
76 #define strncasecmp strnicmp
77 #define strcasecmp stricmp
78 #else
79 int _filelength (int fd)
80 {
81         struct stat buf;
82         if (fstat (fd, &buf) == -1)
83                 return -1;
84
85         return buf.st_size;
86 }
87 #endif
88
89 #define MAX_LINE_LEN    512
90
91 //static int Use_8bit = 0;      // set to 1 to disable 7bit character packing
92 static int Use_8bit = 1;
93
94
95 // strip out any ships tbl data not used in demo (ie entries without @ preceding name)
96 void scramble_read_ships_tbl(char **text, int *text_len, FILE *fp)
97 {
98         char    line[MAX_LINE_LEN+1];
99         char    token_line[MAX_LINE_LEN+1];
100         char    *dest;
101         int     line_len, discard_line = 1, keep_all_lines = 0, post_discard = 0;
102         char    seps[]   = " ,\t\n";
103         char    *token;
104
105         *text_len = _filelength(fileno(fp));
106         *text = (char*)malloc(*text_len+1);
107
108         dest = *text;
109
110         while ( fgets(line, MAX_LINE_LEN, fp) != NULL ) {
111
112                 line_len = strlen(line);
113                 memcpy(token_line, line, line_len+1);
114
115                 if ( !keep_all_lines ) {
116                         token = strtok( token_line, seps );
117
118                         if ( token ) {
119                                 if ( !strncasecmp("#End", token, 4) ) {
120                                         keep_all_lines = 1;
121                                 } else if ( !strncasecmp("#Ship", token, 5) ) {
122                                         discard_line = 0;
123                                         post_discard = 1;
124                                 } else if ( !strncasecmp("$Name:", token, 6) ) {
125                                         token = strtok( NULL, seps );
126                                         if ( token ) {
127                                                 if ( token[0] == '@' ) {
128                                                         discard_line = 0;
129                                                 } else {
130                                                         discard_line = 1;
131                                                 }
132                                         }
133                                 }
134                         }
135                 }
136
137                 if ( !discard_line || keep_all_lines ) {
138                         memcpy(dest, line, line_len);
139                         dest += line_len;
140                 }
141
142                 if ( post_discard ) {
143                         discard_line = 1;
144                         post_discard = 0;
145                 } 
146         }
147
148         *text_len = dest - *text;
149 }
150
151 // strip out any weapons tbl data not used in demo (ie entries without @ preceding name)
152 void scramble_read_weapons_tbl(char **text, int *text_len, FILE *fp)
153 {
154         char    line[MAX_LINE_LEN+1];
155         char    token_line[MAX_LINE_LEN+1];
156         char    *dest;
157         int     line_len, discard_line = 1, keep_all_lines = 0, post_discard = 0;
158         char    seps[]   = " ,\t\n";
159         char    *token = NULL;
160
161         *text_len = _filelength(fileno(fp));
162         *text = (char*)malloc(*text_len+1);
163
164         dest = *text;
165
166         while ( fgets(line, MAX_LINE_LEN, fp) != NULL ) {
167
168                 line_len = strlen(line);
169                 memcpy(token_line, line, line_len+1);
170
171                 if ( !keep_all_lines ) {
172                         token = strtok( token_line, seps );
173
174                         if ( token ) {
175                                 if ( !strncasecmp("#Countermeasures", token, 16) ) {
176                                         keep_all_lines = 1;
177                                 } else if ( !strncasecmp("#End", token, 4) || !strncasecmp("#Beam", token, 5) || !strncasecmp("#Primary", token, 8) || !strncasecmp("#Secondary", token, 10) ) {
178                                         discard_line = 0;
179                                         post_discard = 1;
180                                 } else if ( !strncasecmp("$Name:", token, 6) ) {
181                                         discard_line = 1;
182                                         token = strtok( NULL, seps );
183                                         if ( token ) {
184                                                 if ( token[0] == '@' ) {
185                                                         discard_line = 0;
186                                                 }
187                                         }
188                                 }
189                         }
190                 }
191
192                 if ( (token[0] != ';') && (!discard_line || keep_all_lines) ) {
193                         memcpy(dest, line, line_len);
194                         dest += line_len;
195                 }
196
197                 if ( post_discard ) {
198                         discard_line = 1;
199                         post_discard = 0;
200                 } 
201         }
202
203         *text_len = dest - *text;
204 }
205
206 void scramble_read_default(char **text, int *text_len, FILE *fp)
207 {
208         *text_len = _filelength(fileno(fp));
209         *text = (char*)malloc(*text_len+1);
210         fread( *text, *text_len, 1, fp );
211 }
212
213 // scramble a file
214 //
215 // input:       src_filename    =>      filename of text to scramble
216 //                              dest_filename   =>      optional, this is the filename scrambled data will get stored to
217 void scramble_file(char *src_filename, char *dest_filename, int preprocess)
218 {
219         FILE    *fp;
220         int     text_len, scramble_len;
221         char    *text, *scramble_text;
222
223         fp = fopen(src_filename, "rb");
224         if ( !fp ) {
225                 return;
226         }
227
228         // read in data, maybe preprocess
229         switch(preprocess) {
230         case PREPROCESS_SHIPS_TBL:
231                 scramble_read_ships_tbl(&text, &text_len, fp);
232                 break;
233         case PREPROCESS_WEAPONS_TBL:
234                 scramble_read_weapons_tbl(&text, &text_len, fp);
235                 break;
236         default:
237                 // read in the raw data
238                 scramble_read_default(&text, &text_len, fp);
239                 break;
240         }
241
242         fclose(fp);
243
244         // open up file for writing scrambled text
245         if ( dest_filename ) {
246                 fp = fopen(dest_filename, "wb");
247         } else {
248                 fp = fopen(src_filename, "wb");
249         }
250
251         if ( !fp ) {
252                 return;
253         }
254
255         scramble_text = (char*)malloc(text_len+32);
256
257         encrypt(text, text_len, scramble_text, &scramble_len, Use_8bit);
258         
259         // write out scrambled data
260         fwrite( scramble_text, scramble_len, 1, fp );
261
262         free(text);
263         free(scramble_text);
264         fclose(fp);
265 }
266
267 // unscramble a file
268 //
269 // input:       src_filename    =>      filename of scrambled text
270 //                              dest_filename   =>      optional, this is the filename unscrambled text data will get stored to
271 void unscramble_file(char *src_filename, char *dest_filename)
272 {
273         FILE    *fp;
274         int     scramble_len, text_len;
275         char    *text, *scramble_text;
276
277         fp = fopen(src_filename, "rb");
278         if ( !fp ) {
279                 return;
280         }
281
282         // read in the scrambled data
283         scramble_len = _filelength(fileno(fp));
284         scramble_text = (char*)malloc(scramble_len+1);
285         fread( scramble_text, scramble_len, 1, fp );
286         fclose(fp);
287
288         // open up file for writing unscrambled text
289         if ( dest_filename ) {
290                 fp = fopen(dest_filename, "wb");
291         } else {
292                 fp = fopen(src_filename, "wb");
293         }
294         if ( !fp ) {
295                 return;
296         }
297
298         // assume original text no larger than double scrambled size
299         text = (char*)malloc(scramble_len*2);
300
301         unencrypt(scramble_text, scramble_len, text, &text_len);
302
303         // write out unscrambled data
304         fwrite( text, text_len, 1, fp );
305
306         free(text);
307         free(scramble_text);
308         fclose(fp);
309 }
310
311 void print_instructions()
312 {
313         printf("Encrypt: scramble [-st] [-wt] <filename_in> [filename_out] \n");
314         printf("Decrypt: scramble -u <filename_in> [filename_out] \n");
315 }
316
317 int main(int argc, char *argv[])
318 {
319         switch (argc) {
320         case 2:
321                 encrypt_init();
322                 scramble_file(argv[1]);
323                 break;
324         case 3:
325                 encrypt_init();
326                 if ( !strcasecmp("-u", argv[1]) ) {
327                         unscramble_file(argv[2]);
328                 } else if ( !strcasecmp("-st", argv[1]) ) {
329                         scramble_file(argv[2], argv[2], PREPROCESS_SHIPS_TBL);
330                 } else if ( !strcasecmp("-wt", argv[1]) ) {
331                         scramble_file(argv[2], argv[2], PREPROCESS_WEAPONS_TBL);
332                 } else {
333                         scramble_file(argv[1], argv[2]);
334                 }
335                 break;
336         case 4:
337                 encrypt_init();
338                 if ( !strcasecmp("-u", argv[1]) ) {
339                         unscramble_file(argv[2], argv[3]);
340                 } else if ( !strcasecmp("-st", argv[1]) ) {
341                         scramble_file(argv[2], argv[3], PREPROCESS_SHIPS_TBL);
342                 } else if ( !strcasecmp("-wt", argv[1]) ) {
343                         scramble_file(argv[2], argv[3], PREPROCESS_WEAPONS_TBL);
344                 } else {
345                         print_instructions();
346                 }
347                 break;
348         default:
349                 print_instructions();
350                 break;
351         }
352
353         return 0;
354 }
355