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