minor cleanup, encodefile command in Base64.java
[org.ibex.crypto.git] / src / org / ibex / crypto / Base64.java
1 /*
2  * org.ibex.crypto.Base64 - By Brian Alliet
3  * Copyright (C) 2004 Brian Alliet
4  */
5 package org.ibex.crypto;
6
7 import java.io.*;
8
9 public final class Base64 {
10     private Base64() { /* can't be instansiated */ }
11     
12     private static final char[] encodeMap = {
13         'A','B','C','D','E','F','G','H',
14         'I','J','K','L','M','N','O','P',
15         'Q','R','S','T','U','V','W','X',
16         'Y','Z','a','b','c','d','e','f',
17         'g','h','i','j','k','l','m','n',
18         'o','p','q','r','s','t','u','v',
19         'w','x','y','z','0','1','2','3',
20         '4','5','6','7','8','9','+','/'
21     };
22
23     private static final int[] decodeMap = {
24         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
25         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
26         -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
27         52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,
28         -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
29         15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
30         -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
31         41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
32     };
33
34     public static void main(String[] args) throws IOException {
35         if(args.length == 2 && args[0].equals("encode"))
36             System.out.println(encode(getBytes(args[1])));
37         else if(args.length == 2 && args[0].equals("decode"))
38             System.out.write(decode(args[1]));
39         else if(args.length == 2 && args[0].equals("encodefile")) {
40             FileInputStream fis = new FileInputStream(args[1]);
41             ByteArrayOutputStream baos = new ByteArrayOutputStream();
42             byte[] buf = new byte[4096];
43             int n;
44             while((n = fis.read(buf)) != -1) baos.write(buf,0,n);
45             fis.close();
46             System.out.println(encode(baos.toByteArray()));
47         } else {
48             System.out.println("Usage: Base64 {encode,decode} filename");
49             System.exit(1);
50         }
51         System.exit(0);
52     }
53         
54     public static byte[] decode(String inString){
55         char[] in = inString.toCharArray();
56         int part=0;
57         int theBytes = 0;
58         byte[] out = new byte[in.length / 4 * 3];
59         int outPos = 0;
60         for(int i=0;i<in.length;i++){
61             int x = decodeMap[in[i] & 0x7f];
62             if(x == -1) continue;
63             if(x == -2) break;
64             theBytes = (theBytes << 6) | x;
65             part++;
66             if(part == 4){
67                 part = 0;
68                 out[outPos++] = (byte)((theBytes >>> 16) & 0xff);
69                 out[outPos++] = (byte)((theBytes >>>  8) & 0xff);
70                 out[outPos++] = (byte)((theBytes >>>  0) & 0xff);
71             }
72         }
73         switch(part){
74             case 3:
75                 out[outPos++] = (byte)((theBytes >>> 10) & 0xff);
76                 out[outPos++] = (byte)((theBytes >>> 2) & 0xff);
77                 break;
78             case 2: 
79                 out[outPos++] = (byte)((theBytes >> 4) & 0xff);
80                 break;
81         }
82         
83         if(outPos < out.length){
84             byte[] a = new byte[outPos];
85             System.arraycopy(out,0,a,0,outPos);
86             return a;
87         } else {
88             return out;
89         }
90     }
91
92     public static String encode(String in) { return encode(getBytes(in)); }
93     
94     public static String encode(byte[] in){
95         int part=0;
96         int theBytes = 0;
97         char[] out = new char[(in.length / 3 + 1) * 4];
98         int outPos = 0;
99         for(int i=0;i<in.length;i++){
100             theBytes = (theBytes << 8) | (in[i]&0xff);
101             part++;
102             if(part == 3){
103                 part = 0;
104                 out[outPos++] = encodeMap[(theBytes >>> 18) & 0x3f];
105                 out[outPos++] = encodeMap[(theBytes >>> 12) & 0x3f];
106                 out[outPos++] = encodeMap[(theBytes >>>  6) & 0x3f];
107                 out[outPos++] = encodeMap[(theBytes >>>  0) & 0x3f];
108             }
109         }
110         switch(part){
111             case 2:
112                 out[outPos++] = encodeMap[(theBytes >>>  10) & 0x3f];
113                 out[outPos++] = encodeMap[(theBytes >>>  4)  & 0x3f];
114                 out[outPos++] = encodeMap[(theBytes <<   2)  & 0x3f];
115                 out[outPos++] = '=';
116                 break;
117             case 1:
118                 out[outPos++] = encodeMap[(theBytes >>> 2) & 0x3f];
119                 out[outPos++] = encodeMap[(theBytes <<  4) & 0x3f];
120                 out[outPos++] = '=';
121                 out[outPos++] = '=';
122                 break;
123         }
124         return new String(out,0,outPos);
125     }
126     
127     public static byte[] getBytes(String s) {
128         try {
129                 return s.getBytes("US-ASCII");
130         } catch (UnsupportedEncodingException e) {
131                 throw new Error("should never happen");
132         }
133     }
134 }