ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/basex/basex.c
Revision: 1.2
Committed: Sun Sep 23 21:18:52 2001 UTC (23 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +7 -6 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * version 1.5 2001-06-26
3 * slightly more robust
4 * "compression" levels
5 * '-I' for decode
6 * '-n' option
7 * ident strings can not contain whitespace
8 * version 1.4 2001-06-24
9 * version 1.3 1999-09-12
10 * version 1.2 1995-03-01
11 * version 1.1 1995-05-30
12 * version 1.0 1994-12-13
13 *
14 * remember to transfer files with
15 * Content-Encoding: 8bit
16 * Content-Transfer-Encoding: 8bit
17 *
18 * this is written in ISO-C89
19 * + getopt (e.g. -D_POSIX_C_SOURCE=2)
20 *
21 * basex -v -i "id" <input >output
22 * basex -d -I -v <input >output
23 *
24 * -V show version
25 * -d decode
26 * -v verbose
27 * -i <id> use identifier id
28 * -I print id to stderr on decryption
29 * -n do NOT create output
30 * -1 VERY conservative
31 * -5 rather conservative (almost rfc2822)
32 * -7 non-rfc2822, but should work (default)
33 * -9 maximum level (not that much better)
34 *
35 * ESCAPE -> ESCAPE 'A'
36 * 0x00 -> ESCAPE 'B'
37 * 0x0a -> ESCAPE 'C'
38 * 0x0d -> ESCAPE 'D'
39 * ESCAPE x, x != A-D unchanged
40 *
41 * uses adler32 checksum
42 */
43
44 /* next include is for getopt only */
45 #include <unistd.h>
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 #define MAXLINE (60000+3)
52 #define ESCAPE 0xff
53 #define MAXBLK 5000000L /* max. blksize on decode */
54 #define ID1 "BASEX ENCODED DATA" /* file header */
55 #define ID2 "X" /* control header */
56 #define ID3 '|' /* data header */
57
58 char version[] = "basex version 1.5 - 2001-06-26";
59
60 typedef unsigned long u32; /* 4 byte unsigned int */
61 typedef unsigned char u8; /* 1 byte unsigned int */
62
63 int verbose = 0;
64 int showident = 0;
65 int complevel = 7;
66 int nooutput = 0;
67
68 int linelen;
69 int blklen;
70
71 extern char *optarg;
72 /*extern int optind, opterr, optopt; */
73
74 u32
75 adler32 (u8 * data, int len)
76 {
77 u32 s1 = 1;
78 u32 s2 = 0;
79 u32 modulo = 65521;
80
81 while (--len)
82 {
83 s1 += *data++;
84 if (s1 >= modulo)
85 s1 -= modulo;
86
87 s2 += s1;
88 if (s2 >= modulo)
89 s2 -= modulo;
90
91 };
92 return (s2 << 16) + s1;
93 }
94
95 void
96 out_char (FILE * o, int code)
97 {
98 static char line[MAXLINE + 1];
99 static int llen = 0;
100
101 if (code == -2)
102 {
103 if (llen)
104 {
105 line[llen] = 0;
106 if (!nooutput)
107 fprintf (o, "%c%s\n", ID3, line);
108 }
109 }
110 else if (code == -1)
111 {
112 llen = 0;
113 }
114 else
115 {
116 line[llen++] = code;
117 if (llen >= linelen)
118 {
119 llen = 0;
120 line[linelen] = 0;
121 if (!nooutput)
122 fprintf (o, "%c%s\n", ID3, line);
123 }
124 }
125 }
126
127 int
128 encode (FILE * i, FILE * o, char *id)
129 {
130 u8 *block;
131 long blklen;
132 int len;
133
134 if (complevel <= 1)
135 {
136 linelen = 120;
137 blklen = 50000;
138 }
139 else if (complevel <= 5)
140 {
141 linelen = 996;
142 blklen = 50000;
143 }
144 else if (complevel <= 7)
145 {
146 linelen = 7996;
147 blklen = 50000;
148 }
149 else
150 {
151 linelen = 60000;
152 blklen = 5000000;
153 }
154
155 block = malloc (blklen);
156
157 if (!block)
158 {
159 fprintf (stderr, "unable to allocate %ld bytes", blklen * 2);
160 return 11;
161 }
162
163 if (!nooutput)
164 {
165 fprintf (o, "%s\n", ID1);
166 fprintf (o, "%s VERSION 2\n", ID2);
167 if (id)
168 fprintf (o, "%s IDENT %s\n", ID2, id);
169 }
170
171 /*fprintf (o, "%s CODEC AFE0C0DE\n", ID2);*/ /* default */
172 while ((len = fread (block, 1, blklen, i)) > 0)
173 {
174 u32 sum = adler32 (block, len);
175 u8 *p = block;
176
177 if (!nooutput)
178 fprintf (o, "%s BLOCK %d %08lx\n", ID2, len, sum);
179
180 out_char (o, -1);
181 while (len--)
182 {
183 int c = *p++ ^ (u8) sum++;
184
185 if (c == ESCAPE)
186 {
187 out_char (o, ESCAPE);
188 if (len)
189 {
190 switch (*p ^ (u8) sum)
191 {
192 case 'A':
193 case 'B':
194 case 'C':
195 case 'D':
196 out_char (o, 'A');
197 break;
198 default:
199 /* nothing */;
200 }
201 }
202 else
203 out_char (o, 'A');
204 }
205 else if (c == 0x00)
206 {
207 out_char (o, ESCAPE);
208 out_char (o, 'B');
209 }
210 else if (c == 0x0a)
211 {
212 out_char (o, ESCAPE);
213 out_char (o, 'C');
214 }
215 else if (c == 0x0d)
216 {
217 out_char (o, ESCAPE);
218 out_char (o, 'D');
219 }
220 else
221 {
222 out_char (o, c);
223 }
224 }
225
226 out_char (o, -2);
227 }
228
229 if (!nooutput)
230 fprintf (o, "%s END\n", ID2);
231
232 free (block);
233
234 return 0;
235 }
236
237 int
238 in_char (FILE * i, int code)
239 {
240 static int llen;
241 static char line[MAXLINE + 3];
242
243 if (code == -1)
244 {
245 llen = MAXLINE + 1;
246 return 0;
247 }
248 else
249 {
250 if (llen > MAXLINE
251 || line[llen] == 0
252 || line[llen] == '\r'
253 || line[llen] == '\n')
254 {
255 do {
256 if (!fgets (line, sizeof (line), i))
257 {
258 perror ("error on block read (file truncated?)");
259 return -1;
260 }
261 } while (line[0] != ID3);
262
263 llen = 1;
264 }
265
266 return (unsigned char) line[llen++];
267 }
268 }
269
270 int
271 decodeblock (FILE * i, u8 * data, int len, int sum)
272 {
273 int ch;
274
275 (void) in_char (i, -1);
276
277 while (len--)
278 {
279 ch = in_char (i, 0);
280 if (ch < 0)
281 return 8;
282
283 retry:
284 if (ch == ESCAPE)
285 {
286 switch ((ch = in_char (i, 0)))
287 {
288 case 'A': ch = ESCAPE; break;
289 case 'B': ch = 0x00; break;
290 case 'C': ch = 0x0a; break;
291 case 'D': ch = 0x0d; break;
292
293 default:
294 *data++ = (u8) ESCAPE ^ (u8) sum++; len--;
295 goto retry;
296 }
297 }
298
299 *data++ = (u8) ch ^ (u8) sum++;
300 }
301
302 return 0;
303 }
304
305 int
306 decode (FILE * i, FILE * o)
307 {
308 char input[255];
309 char *opt = input + sizeof (ID2) - 1 + 1;
310 long blklen;
311 int err;
312 u32 sum, sum2;
313
314 u32 codec = 0xafe1c0de;
315 int version = 0;
316 char ident[255];
317
318 ident[0] = 0;
319
320 do
321 {
322 if (!fgets (input, sizeof (input), i))
323 {
324 perror ("unable to find start of encoded data");
325 return 1;
326 }
327 }
328 while (strncmp (input, ID1, sizeof (ID1) - 1));
329
330 if (verbose)
331 fprintf (stderr, "basex header found, processing options\n");
332
333 for (;;)
334 {
335 if (!fgets (input, sizeof (input), i))
336 {
337 perror ("error while processing options");
338 return 2;
339 }
340
341 if (strncmp (input, ID2, sizeof (ID2) - 1) || *(opt - 1) != ' ')
342 {
343 fprintf (stderr, "garbage instead of option, ignored\n");
344 }
345 else
346 {
347 if (sscanf (opt, "VERSION %d\n", &version) == 1)
348 {
349 if (verbose)
350 fprintf (stderr, "option version %d\n", version);
351
352 if (version != 2)
353 {
354 fprintf (stderr, "unsupported version %d\n", version);
355 return 5;
356 }
357 }
358 else if (sscanf (opt, "CODEC %8lx\n", &codec) == 1)
359 {
360 if (verbose)
361 fprintf (stderr, "option codec %lx\n", codec);
362 }
363 else if (sscanf (opt, "IDENT %[^\n]\n", ident) == 1)
364 {
365 if (verbose || showident)
366 fprintf (stderr, "option ident %s\n", ident);
367 }
368 else if (strcmp (opt, "END\n") == 0)
369 {
370 if (verbose)
371 fprintf (stderr, "option end\n");
372
373 return 0;
374 }
375 else if (sscanf (opt, "BLOCK %ld %08lx\n", &blklen, &sum) == 2)
376 {
377 u8 *block;
378
379 if (verbose)
380 fprintf (stderr, "option block len %ld, checksum %08lx\n", blklen, sum);
381
382 if (blklen > MAXBLK)
383 {
384 fprintf (stderr, "block length too large (%ld>%ld)\n", blklen, MAXBLK);
385 return 4;
386 }
387
388 switch (codec)
389 {
390 case 0xafe1c0de:
391
392 block = malloc (blklen);
393
394 if (!block)
395 {
396 fprintf (stderr, "unable to allocate %ld bytes", blklen);
397 return 11;
398 }
399
400 err = decodeblock (i, block, blklen, sum);
401 if (err)
402 return err;
403
404 sum2 = adler32 (block, blklen);
405 if (sum != sum2)
406 {
407 fprintf (stderr, "checksumming error %08lx != %08lx\n", sum, sum2);
408 return 9;
409 }
410
411 if (!nooutput && fwrite (block, blklen, 1, o) <= 0)
412 {
413 perror ("write error");
414 return 10;
415 }
416
417 free (block);
418 break;
419
420 default:
421 fprintf (stderr, "unknown codec %08lx\n", codec);
422 return 3;
423 }
424 }
425 else
426 {
427 fprintf (stderr, "unknown or unrecognized option %s\n", opt);
428 return 2;
429 }
430 }
431 }
432 }
433
434 int
435 main (int argc, char *argv[])
436 {
437 int dec = 0;
438 char *id = 0;
439
440 for (;;)
441 {
442 int c = getopt (argc, argv, "Vvdi:In123456789");
443
444 if (c == EOF)
445 break;
446
447 switch (c)
448 {
449 case 'V':
450 puts (version);
451 exit (EXIT_SUCCESS);
452 break;
453
454 case 'v':
455 verbose = 1;
456 break;
457
458 case 'd':
459 dec = 1;
460 break;
461
462 case 'i':
463 id = optarg;
464 break;
465
466 case 'I':
467 showident = 1;
468 break;
469
470 case 'n':
471 nooutput = 1;
472 break;
473
474 case '1':
475 case '2':
476 case '3':
477 case '4':
478 complevel = 1;
479 break;
480 case '5':
481 case '6':
482 complevel = 5;
483 break;
484 case '7':
485 case '8':
486 complevel = 7;
487 break;
488 case '9':
489 complevel = 9;
490 break;
491
492 case '?':
493 fprintf (stderr, "encode: basex [-v] [-n] [-i id] [-1 | -5 | -7 | -9]\n");
494 fprintf (stderr, "decode: basex [-d] [-v] [-n] [-I]\n");
495 break;
496 }
497 }
498
499 if (verbose)
500 fprintf (stderr, "mode %s\n", dec ? "decoding" : "encoding");
501
502 if (dec)
503 return decode (stdin, stdout);
504 else
505 return encode (stdin, stdout, id);
506 }
507