/* * UCW Library -- Line utility for encoding and decoding base64 & base224 * * (c) 2008, Michal Vaner * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ #include #include #include #include #include #include #include #include static struct option opts[] = { { "encode64", 0, 0, 'e' }, { "decode64", 0, 0, 'd' }, { "encode224", 0, 0, 'E' }, { "decode224", 0, 0, 'D' }, { "prefix", 1, 0, 'p' }, { "blocks", 1, 0, 'b' }, { 0, 0, 0, 0 } }; static const struct { uint (*function)(byte *, const byte *, uint); uint in_block, out_block, num_blocks; uint add_prefix; } actions[] = { { base64_encode, BASE64_IN_CHUNK, BASE64_OUT_CHUNK, 20, 1 }, { base64_decode, BASE64_OUT_CHUNK, BASE64_IN_CHUNK, 20, 0 }, { base224_encode, BASE224_IN_CHUNK, BASE64_OUT_CHUNK, 6, 1 }, { base224_decode, BASE224_OUT_CHUNK, BASE224_IN_CHUNK, 6, 0 } }; int main(int argc, char **argv) { // Choose mode int mode = -1; char *prefix = NULL; uint blocks = 0; int opt; while ((opt = getopt_long(argc, argv, "edEDp:b:", opts, NULL)) >= 0) switch (opt) { case 'e': mode = 0; break; case 'd': mode = 1; break; case 'E': mode = 2; break; case 'D': mode = 3; break; case 'p': prefix = optarg; break; case 'b': { char *end; blocks = strtol(optarg, &end, 0); if ((blocks > 0) && !*end) break; } default: goto usage; } if (mode == -1) { usage: 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"); return 1; } if (!blocks) blocks = actions[mode].num_blocks; // Prepare buffers struct fastbuf *in = bfdopen_shared(0, 4096); struct fastbuf *out = bfdopen_shared(1, 4096); int has_offset = !actions[mode].add_prefix && prefix; uint offset = has_offset ? strlen(prefix) : 0; uint read_size = actions[mode].in_block * blocks + offset + has_offset; uint write_size = actions[mode].out_block * blocks; byte in_buff[read_size], out_buff[write_size]; uint isize; // Recode it while (isize = bread(in, in_buff, read_size)) { if (prefix) { if (actions[mode].add_prefix) bputs(out, prefix); else if ((isize < offset) || (in_buff[isize-1] != '\n') || (strncmp(prefix, in_buff, offset))) die("Invalid line syntax"); } uint osize = actions[mode].function(out_buff, in_buff + offset, isize - offset - has_offset); bwrite(out, out_buff, osize); if (actions[mode].add_prefix && prefix) bputc(out, '\n'); } bclose(in); bclose(out); return 0; }