]> mj.ucw.cz Git - libucw.git/blob - ucw/utils/ucw-basecode.c
XTypes: CF_XTYPE requires '&' before xt_*, just like most other parameters in CF_...
[libucw.git] / ucw / utils / ucw-basecode.c
1 /*
2  *      UCW Library -- Line utility for encoding and decoding base64 & base224
3  *
4  *      (c) 2008, Michal Vaner <vorner@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <string.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13
14 #include <ucw/lib.h>
15 #include <ucw/base64.h>
16 #include <ucw/base224.h>
17 #include <ucw/fastbuf.h>
18 #include <ucw/getopt.h>
19
20 static struct option opts[] = {
21   { "encode64", 0, 0, 'e' },
22   { "decode64", 0, 0, 'd' },
23   { "encode224", 0, 0, 'E' },
24   { "decode224", 0, 0, 'D' },
25   { "prefix", 1, 0, 'p' },
26   { "blocks", 1, 0, 'b' },
27   { 0, 0, 0, 0 }
28 };
29
30 static const struct {
31   uint (*function)(byte *, const byte *, uint);
32   uint in_block, out_block, num_blocks;
33   uint add_prefix;
34 } actions[] = {
35   {
36     base64_encode,
37     BASE64_IN_CHUNK, BASE64_OUT_CHUNK, 20,
38     1
39   },
40   {
41     base64_decode,
42     BASE64_OUT_CHUNK, BASE64_IN_CHUNK, 20,
43     0
44   },
45   {
46     base224_encode,
47     BASE224_IN_CHUNK, BASE64_OUT_CHUNK, 6,
48     1
49   },
50   {
51     base224_decode,
52     BASE224_OUT_CHUNK, BASE224_IN_CHUNK, 6,
53     0
54   }
55 };
56
57 int main(int argc, char **argv)
58 {
59   // Choose mode
60   int mode = -1;
61   char *prefix = NULL;
62   uint blocks = 0;
63   int opt;
64   while ((opt = getopt_long(argc, argv, "edEDp:b:", opts, NULL)) >= 0)
65     switch (opt)
66     {
67       case 'e': mode = 0; break;
68       case 'd': mode = 1; break;
69       case 'E': mode = 2; break;
70       case 'D': mode = 3; break;
71       case 'p': prefix = optarg; break;
72       case 'b':
73         {
74           char *end;
75           blocks = strtol(optarg, &end, 0);
76           if ((blocks > 0) && !*end)
77             break;
78         }
79       default: goto usage;
80     }
81
82   if (mode == -1)
83   {
84     usage:
85     fprintf(stderr, "ucw-basecode mode [--prefix=prefix] [--blocks=number_of_blocks]\nMode is one of:\n\t--encode64 (-e)\n\t--decode64 (-d)\n\t--encode224 (-E)\n\t--decode224 (-D)\n");
86     return 1;
87   }
88   if (!blocks)
89     blocks = actions[mode].num_blocks;
90
91   // Prepare buffers
92   struct fastbuf *in = bfdopen_shared(0, 4096);
93   struct fastbuf *out = bfdopen_shared(1, 4096);
94   int has_offset = !actions[mode].add_prefix && prefix;
95   uint offset = has_offset ? strlen(prefix) : 0;
96   uint read_size = actions[mode].in_block * blocks + offset + has_offset;
97   uint write_size = actions[mode].out_block * blocks;
98   byte in_buff[read_size], out_buff[write_size];
99   uint isize;
100
101   // Recode it
102   while (isize = bread(in, in_buff, read_size))
103   {
104     if (prefix)
105     {
106       if (actions[mode].add_prefix)
107         bputs(out, prefix);
108       else
109         if ((isize < offset) || (in_buff[isize-1] != '\n')
110             || (strncmp(prefix, in_buff, offset)))
111           die("Invalid line syntax");
112     }
113     uint osize = actions[mode].function(out_buff, in_buff + offset, isize - offset - has_offset);
114     bwrite(out, out_buff, osize);
115     if (actions[mode].add_prefix && prefix)
116       bputc(out, '\n');
117   }
118
119   bclose(in);
120   bclose(out);
121   return 0;
122 }