annotate src/fschmidt/util/java/Base64.java @ 68:00520880ad02

add fschmidt source
author Franklin Schmidt <fschmidt@gmail.com>
date Sun, 05 Oct 2025 17:24:15 -0600
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
68
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
1 /*
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
2 Copyright (c) 2008 Franklin Schmidt <fschmidt@gmail.com>
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
3
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
4 Permission is hereby granted, free of charge, to any person obtaining a copy
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
5 of this software and associated documentation files (the "Software"), to deal
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
6 in the Software without restriction, including without limitation the rights
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
8 copies of the Software, and to permit persons to whom the Software is
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
9 furnished to do so, subject to the following conditions:
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
10
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
11 The above copyright notice and this permission notice shall be included in
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
12 all copies or substantial portions of the Software.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
13
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
20 THE SOFTWARE.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
21 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
22
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
23 package fschmidt.util.java;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
24
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
25 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
26 * Base64 encoding and decoding (MIME spec RFC 1521).
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
27 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
28 public class Base64 {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
29
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
30 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
31 * Stand alone test
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
32 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
33 public static void main(String[] args)
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
34 throws Exception {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
35 if (args.length < 2) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
36 System.out.println("Usage: Base64 <encode/decode> <inString>");
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
37 System.exit(0);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
38 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
39
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
40 String inString = args[1];
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
41 System.out.println("InString = " + inString);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
42
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
43 if (args[0].equalsIgnoreCase("encode")) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
44
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
45 String encodedString = Base64.encode(inString.getBytes());
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
46 System.out.println("EncodedString = " + encodedString);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
47
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
48 } else {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
49 String outString = new String(Base64.decode(inString));
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
50 System.out.println("DecodedString = " + outString);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
51 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
52 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
53
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
54 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
55 * Base64-encode binary data.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
56 *
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
57 * @param bytes A buffer holding the data to encode.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
58 * @return String String containing the encoded data
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
59 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
60 public static String encode(byte[] bytes) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
61 return encode(bytes, false);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
62 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
63
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
64 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
65 * base64-encode binary data.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
66 *
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
67 * @param bytes A buffer holding the data to encode.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
68 * @param lineBreaks true if the encoded data will be broken
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
69 * into 64-character lines with CRLF pairs.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
70 * @return String String containing the encoded data
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
71 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
72 public static String encode(byte[] bytes,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
73 boolean lineBreaks) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
74
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
75 /* slightly bigger buffer than we usually need */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
76 StringBuilder buf= new StringBuilder((int)(bytes.length * 1.4));
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
77
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
78 int temp = 0; /* holder for the current group of 24 bits */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
79 int charsWritten = 0; /* count of char written (to current line if lineBreaks == true) */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
80 int bytesRead = 0; /* count of bytes read in the current 24-bit group */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
81 for(int index = 0; index < bytes.length; ++index) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
82
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
83 temp <<= 8;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
84 temp |= (((int)bytes[index]) & EIGHT_BITS);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
85 ++bytesRead;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
86 if(bytesRead == 3) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
87 /* The lower 3 bytes of temp now hold the 24 bits of a
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
88 * translation group. Write them out as 4 characters
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
89 * that represent 6 bits each.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
90 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
91 buf.append(valueToChar[(temp >> 18) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
92 buf.append(valueToChar[(temp >> 12) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
93 buf.append(valueToChar[(temp >> 6) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
94 buf.append(valueToChar[(temp >> 0) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
95 temp = 0;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
96 bytesRead = 0;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
97 charsWritten += 4;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
98 if(lineBreaks && charsWritten >= 64) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
99 buf.append(CRLF);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
100 charsWritten = 0;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
101 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
102 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
103 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
104
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
105 // The input byte[] is exhaused.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
106 // If there were fewer than 3 bytes in the last translation group,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
107 // we must complete the output and pad it to a multiple of 4 chars.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
108
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
109 switch(bytesRead){
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
110 case 1:
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
111 // The low 8 bits of temp take 2 characters to represent.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
112 buf.append(valueToChar[(temp >> 2) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
113 buf.append(valueToChar[(temp << 4) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
114 buf.append('='); // padding
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
115 buf.append('='); // padding
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
116 if(lineBreaks) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
117 buf.append(CRLF);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
118 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
119 break;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
120
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
121 case 2:
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
122 // The low 16 bits of temp take 3 characters to represent
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
123 buf.append(valueToChar[(temp >> 10) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
124 buf.append(valueToChar[(temp >> 4) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
125 buf.append(valueToChar[(temp << 2) & SIX_BITS]);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
126 buf.append('='); // padding
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
127 if(lineBreaks){
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
128 buf.append(CRLF);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
129 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
130 break;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
131
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
132 default:
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
133 // There were exactly 3 bytes in the last group. No padding needed.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
134 break;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
135 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
136 if(charsWritten > 0 && lineBreaks) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
137 buf.append(CRLF);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
138 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
139 return buf.toString();
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
140 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
141
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
142 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
143 * Decode a base64-encoded string into binary data.<P>
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
144 *
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
145 * Ignores (skips over) carriage-return and line-feed characters.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
146 * Stops decoding when it encounters the base64 pad character ('=')
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
147 * or when characters are encountered that are not MIME/base64 numerals.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
148 *
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
149 * @param mimeStr a String containing the base64-encoded data
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
150 * @return a byte[] containing the decoded binary data.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
151 * @exception RuntimeException if the mimeStr parameter violates
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
152 * the base64 encoding rules.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
153 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
154 public static byte[] decode(String mimeStr) throws RuntimeException {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
155
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
156 int inputLength = mimeStr.length();
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
157 byte decoded[] = new byte[inputLength];
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
158 int temp = 0; // accumulator for 24-bit translation group
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
159 int charsRead = 0; // characters read in current translation group
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
160 int bytesWritten = 0; // count of bytes written into decoded[]
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
161 char currChar; // current character from mimeStr
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
162 byte currByte; // base64 value represented by currChar
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
163 int equalCount = 0; // The number of '=' characters we've encountered.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
164
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
165 for (int i = 0; i < inputLength; ++i) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
166 currChar = mimeStr.charAt(i);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
167 if (currChar == CR || currChar == LF) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
168 //Skip over carriage return or line-feed character.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
169 continue;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
170 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
171 try {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
172 currByte = charToValue[(byte)currChar];
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
173 } catch(ArrayIndexOutOfBoundsException obe) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
174 currByte = BAD_VAL;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
175 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
176 if (currByte == BAD_VAL) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
177 if (charsRead == 0) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
178 /*
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
179 * First character of a translation group is a
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
180 * non-base64 character. We have presumably
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
181 * reached the end of base64 encoded data.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
182 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
183 break;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
184 } else if (currChar == '=' & charsRead >= 2) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
185 // Only the 3d and 4th characters may be '='
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
186 currByte = 0;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
187 ++equalCount;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
188 } else {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
189 //String[] errArgs = new String[]{"Base64"};
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
190 throw new InvalidCharEncodedStringException(); //RuntimeException("E_INVALID_CHAR_ENCODED_STRING");
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
191 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
192 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
193 temp <<= 6;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
194 temp |= currByte;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
195 ++charsRead;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
196 if (charsRead == 4) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
197 /*
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
198 * temp has all 24 bits of the translation group,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
199 * write the bytes to decode[]
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
200 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
201 decoded[bytesWritten++]= (byte)(temp >> 16);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
202 if(equalCount < 2) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
203 decoded[bytesWritten++]= (byte)(temp >> 8);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
204 if(equalCount < 1) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
205 decoded[bytesWritten++]= (byte)(temp >> 0);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
206 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
207 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
208 charsRead = 0;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
209 temp = 0;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
210 if (equalCount > 0) {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
211 // Encoded data is not permitted after an '=', we must be done.
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
212 break;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
213 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
214 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
215 } // end for == end of string
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
216
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
217 // Trim array to exact length
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
218 byte result[] = new byte[bytesWritten];
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
219 System.arraycopy(decoded, 0, result, 0, bytesWritten);
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
220 return result;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
221 }
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
222
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
223 private static final byte BAD_VAL = (byte)0xFF;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
224
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
225 private static final int SIX_BITS = 0x3F;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
226 private static final int EIGHT_BITS = 0xFF;
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
227
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
228 private static final char CR = '\r';
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
229 private static final char LF = '\n';
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
230
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
231 private static final String CRLF = "\r\n";
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
232
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
233 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
234 * Value to be encoded is an index into this array, so the
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
235 * character representation of byte value = valueToChar[value]
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
236 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
237 private static final char valueToChar[] = {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
238 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
239 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
240 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
241 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
242 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
243 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
244 'w', 'x', 'y', 'z', '0', '1', '2', '3',
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
245 '4', '5', '6', '7', '8', '9', '+', '/'
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
246 };
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
247
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
248 /**
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
249 * The ASCII value of a character is an index into this array, so that
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
250 * decoded byte value = charToValue[(byte)(character)]. <P>
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
251 *
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
252 * Characters that are not valid base64 numerals are detected
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
253 * one of two ways: either the expression above yeilds BAD_VAL
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
254 * or the array access gives an ArrayIndexOutOfBoundsException. <P>
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
255 *
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
256 */
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
257 private static final byte charToValue[] = {
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
258 BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
259 BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
260 BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
261 BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
262 BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
263 BAD_VAL, BAD_VAL, BAD_VAL, 62, BAD_VAL, BAD_VAL, BAD_VAL, 63,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
264 52, 53, 54, 55, 56, 57, 58, 59,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
265 60, 61, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
266 BAD_VAL, 0, 1, 2, 3, 4, 5, 6,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
267 7, 8, 9, 10, 11, 12, 13, 14,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
268 15, 16, 17, 18, 19, 20, 21, 22,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
269 23, 24, 25, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
270 BAD_VAL, 26, 27, 28, 29, 30, 31, 32,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
271 33, 34, 35, 36, 37, 38, 39, 40,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
272 41, 42, 43, 44, 45, 46, 47, 48,
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
273 49, 50, 51, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL, BAD_VAL
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
274 };
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
275
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
276 public static final class InvalidCharEncodedStringException extends RuntimeException {}
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
277
00520880ad02 add fschmidt source
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
278 }