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

# User Rev Content
1 root 1.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