JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / src / javajs / util / Base64.java
1 // Version 1.0a\r
2 // Copyright (C) 1998, James R. Weeks and BioElectroMech.\r
3 // Visit BioElectroMech at www.obrador.com.  Email James@obrador.com.\r
4 \r
5 // See license.txt for details about the allowed used of this software.\r
6 // This software is based in part on the work of the Independent JPEG Group.\r
7 // See IJGreadme.txt for details about the Independent JPEG Group's license.\r
8 \r
9 // This encoder is inspired by the Java Jpeg encoder by Florian Raemy,\r
10 // studwww.eurecom.fr/~raemy.\r
11 // It borrows a great deal of code and structure from the Independent\r
12 // Jpeg Group's Jpeg 6a library, Copyright Thomas G. Lane.\r
13 // See license.txt for details.\r
14 \r
15 package javajs.util;\r
16 \r
17 \r
18 public class Base64 {\r
19 \r
20   //                              0         1         2         3         4         5         6\r
21   //                              0123456789012345678901234567890123456789012345678901234567890123\r
22   private static String base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\r
23   //                              41----------------------5A\r
24   //                                                        61----------------------7A\r
25   //                                                                                  30------39    \r
26   //                                                                                            2B  \r
27   //                                                                                             2F\r
28   //                                                 alternative "URL-SAFE"     2D and 5F       -_\r
29   \r
30   private static int[] decode64 = new int[] {\r
31     0,0,0,0,     0,0,0,0,     0,0,0,0,     0,0,0,0,      //0x00-0x0F\r
32     0,0,0,0,     0,0,0,0,     0,0,0,0,     0,0,0,0,      //0x10-0x1F\r
33     0,0,0,0,     0,0,0,0,     0,0,0,62,    0,62,0,63,    //0x20-0x2F\r
34     52,53,54,55, 56,57,58,59, 60,61,0,0,   0,0,0,0,      //0x30-0x3F\r
35     0,0,1,2,     3,4,5,6,     7,8,9,10,    11,12,13,14,  //0x40-0x4F\r
36     15,16,17,18, 19,20,21,22, 23,24,25,0,  0,0,0,63,     //0x50-0x5F\r
37     0,26,27,28,  29,30,31,32, 33,34,35,36, 37,38,39,40,  //0x60-0x6F\r
38     41,42,43,44, 45,46,47,48, 49,50,51,0,  0,0,0,0,      //0x70-0x7F\r
39   };\r
40     \r
41 //  public static void write(byte[] bytes, OutputChannel out) {\r
42 //    SB sb = getBase64(bytes);\r
43 //    int len = sb.length();\r
44 //    byte[] b = new byte[1];\r
45 //    for (int i = 0; i < len; i++) {\r
46 //      b[0] = (byte) sb.charAt(i);\r
47 //      out.write(b, 0, 1);\r
48 //    }\r
49 //  }\r
50 \r
51   public static byte[] getBytes64(byte[] bytes) {\r
52     return getBase64(bytes).toBytes(0, -1);\r
53   }\r
54 \r
55   /**\r
56    * \r
57    * @param bytes\r
58    * @return BASE64-encoded string, without ";base64,"\r
59    */\r
60   public static SB getBase64(byte[] bytes) {\r
61     long nBytes = bytes.length;\r
62     SB sout = new SB();\r
63     if (nBytes == 0)\r
64       return sout;\r
65     for (int i = 0, nPad = 0; i < nBytes && nPad == 0;) {\r
66       if (i % 75 == 0 && i != 0)\r
67         sout.append("\r\n");\r
68       nPad = (i + 2 == nBytes ? 1 : i + 1 == nBytes ? 2 : 0);\r
69       int outbytes = ((bytes[i++] << 16) & 0xFF0000)\r
70           | ((nPad == 2 ? 0 : bytes[i++] << 8) & 0x00FF00)\r
71           | ((nPad >= 1 ? 0 : (int) bytes[i++]) & 0x0000FF);\r
72       //System.out.println(Integer.toHexString(outbytes));\r
73       sout.appendC(base64.charAt((outbytes >> 18) & 0x3F));\r
74       sout.appendC(base64.charAt((outbytes >> 12) & 0x3F));\r
75       sout.appendC(nPad == 2 ? '=' : base64.charAt((outbytes >> 6) & 0x3F));\r
76       sout.appendC(nPad >= 1 ? '=' : base64.charAt(outbytes & 0x3F));\r
77     }\r
78     return sout;\r
79   }\r
80 \r
81   //Note: Just a simple decoder here. Nothing fancy at all\r
82   //      Because of the 0s in decode64, this is not a VERIFIER\r
83   //      Rather, it may decode even bad Base64-encoded data\r
84   //\r
85   // Bob Hanson 4/2007\r
86   \r
87   public static byte[] decodeBase64(String strBase64) {\r
88     int nBytes = 0;\r
89     int ch;\r
90     int pt0 = strBase64.indexOf(";base64,") + 1;\r
91     if (pt0 > 0)\r
92       pt0 += 7;\r
93     char[] chars64 = strBase64.toCharArray();\r
94     int len64 = chars64.length;\r
95     if (len64 == 0)\r
96       return new byte[0];\r
97     for (int i = len64; --i >= pt0;)\r
98       nBytes += ((ch = chars64[i] & 0x7F) == 'A' || decode64[ch] > 0 ? 3 : 0);\r
99     nBytes = nBytes >> 2;\r
100     byte[] bytes = new byte[nBytes];\r
101     int offset = 18;\r
102     for (int i = pt0, pt = 0, b = 0; i < len64; i++) {\r
103       if (decode64[ch = chars64[i] & 0x7F] > 0 || ch == 'A' || ch == '=') {\r
104         b |= decode64[ch] << offset;\r
105         //System.out.println(chars64[i] + " " + decode64[ch] + " " + offset + " " + Integer.toHexString(b));\r
106         offset -= 6;\r
107         if (offset < 0) {\r
108           bytes[pt++] = (byte) ((b & 0xFF0000) >> 16);\r
109           if (pt < nBytes)\r
110             bytes[pt++] = (byte) ((b & 0xFF00) >> 8);\r
111           if (pt < nBytes)\r
112             bytes[pt++] = (byte) (b & 0xFF);\r
113           offset = 18;\r
114           b =  0;\r
115         }\r
116       }\r
117     }\r
118     return bytes;\r
119   }    \r
120 }