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

# User Rev Content
1 root 1.1 /*
2     * version 1.5 2001-06-26
3 root 1.2 * slightly more robust
4     * "compression" levels
5     * '-I' for decode
6     * '-n' option
7     * ident strings can not contain whitespace
8 root 1.1 * 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 root 1.2 else if (sscanf (opt, "IDENT %[^\n]\n", ident) == 1)
364 root 1.1 {
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 root 1.2 fprintf (stderr, "encode: basex [-v] [-n] [-i id] [-1 | -5 | -7 | -9]\n");
494 root 1.1 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