]> mj.ucw.cz Git - libucw.git/blob - lib/basecode.c
3c7f0c4866e4df14b700ac960b9268faa0206fb0
[libucw.git] / lib / 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 "lib/lib.h"
15 #include "lib/base64.h"
16 #include "lib/base224.h"
17 #include "lib/fastbuf.h"
18 #include "lib/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   uns (*function)(byte *, const byte *, uns);
32   uns in_block, out_block, num_blocks;
33   uns 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   uns 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, "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   uns offset = (!actions[mode].add_prefix && prefix) ? strlen(prefix) : 0;
95   uns read_size = actions[mode].in_block * blocks + offset + !!offset;
96   uns write_size = actions[mode].out_block * blocks;
97   byte in_buff[read_size], out_buff[write_size];
98   uns isize;
99
100   // Recode it
101   while (isize = bread(in, in_buff, read_size))
102   {
103     if (prefix)
104     {
105       if (actions[mode].add_prefix)
106         bputs(out, prefix);
107       else
108         if ((isize < offset) || (in_buff[isize-1] != '\n')
109             || (strncmp(prefix, in_buff, offset)))
110           die("Invalid line syntax");
111     }
112     uns osize = actions[mode].function(out_buff, in_buff + offset, isize - offset - !!offset);
113     bwrite(out, out_buff, osize);
114     if (actions[mode].add_prefix && prefix)
115       bputc(out, '\n');
116   }
117
118   bclose(in);
119   bclose(out);
120   return 0;
121 }