001: /*
002: * MCS Media Computer Software Copyright (c) 2005 by MCS
003: * -------------------------------------- Created on 16.01.2004 by w.klaas
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy of
007: * the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: */
017: package de.mcs.utils.codecs;
018:
019: import java.io.ByteArrayInputStream;
020: import java.io.ByteArrayOutputStream;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024:
025: /**
026: * BASE64 encoder implementation. This object takes as parameter an input stream
027: * and an output stream. It encodes the input stream, using the BASE64 ENCODING
028: * rules, as defined in <a href="http://ds.internic.net/rfc/rfc1521.txt">MIME
029: * specification </a> and emit the resulting data to the output stream. see
030: * org.w3c.tools.codec.Base64Decoder This class is a modified version based on
031: * code obtained from the w3 consortium website, which is subject to their
032: * generic copyright notice:
033: * <dl>
034: * <dd><a href="http://www.w3.org/Consortium/Legal/">Copyright </a>©
035: * [$date-of-software] <a HREF="http://www.w3.org/">World Wide Web Consortium
036: * </a>, ( <a HREF="http://www.lcs.mit.edu/">Massachusetts Institute of
037: * Technology </a>, <a HREF="http://www.inria.fr/">Institut National de
038: * Recherche en Informatique et en Automatique </a>, <a
039: * HREF="http://www.keio.ac.jp/">Keio University </a>). All Rights Reserved.
040: * This program is distributed under the <a
041: * HREF="http://www.w3.org/Consortium/Legal/copyright-software-19980720.html">W3C's
042: * Software Intellectual Property License </a>. This program is distributed in
043: * the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
044: * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
045: * W3C License <a
046: * href="http://www.w3.org/Consortium/Legal/">http://www.w3.org/Consortium/Legal/
047: * </a> for more details.</dd>
048: * </dl>
049: *
050: * @version $Revision: 1.1 $
051: * @deprecated please use the base64 class.
052: */
053:
054: public final class Base64Encoder {
055: /** internal buffer size for ENCODING. */
056: private static final int BUFFER_SIZE = 1024;
057:
058: /** encoding byte array. */
059: private static final byte[] ENCODING = {
060: (byte) 'A',
061: (byte) 'B',
062: (byte) 'C',
063: (byte) 'D',
064: (byte) 'E',
065: (byte) 'F',
066: (byte) 'G',
067: (byte) 'H', // 0-7
068: (byte) 'I',
069: (byte) 'J',
070: (byte) 'K',
071: (byte) 'L',
072: (byte) 'M',
073: (byte) 'N',
074: (byte) 'O',
075: (byte) 'P', // 8-15
076: (byte) 'Q', (byte) 'R',
077: (byte) 'S',
078: (byte) 'T',
079: (byte) 'U',
080: (byte) 'V',
081: (byte) 'W',
082: (byte) 'X', // 16-23
083: (byte) 'Y', (byte) 'Z', (byte) 'a',
084: (byte) 'b',
085: (byte) 'c',
086: (byte) 'd',
087: (byte) 'e',
088: (byte) 'f', // 24-31
089: (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
090: (byte) 'k',
091: (byte) 'l',
092: (byte) 'm',
093: (byte) 'n', // 32-39
094: (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's',
095: (byte) 't',
096: (byte) 'u',
097: (byte) 'v', // 40-47
098: (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0',
099: (byte) '1', (byte) '2',
100: (byte) '3', // 48-55
101: (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8',
102: (byte) '9', (byte) '+', (byte) '/', // 56-63
103: (byte) '=' // 64
104: };
105:
106: /** to prevent instancing. */
107: private Base64Encoder() {
108: }
109:
110: /**
111: * Encodes data from supplied input to output.
112: *
113: * @param in
114: * The input stream to be encoded.
115: * @param out
116: * The output stream to write encoded data to.
117: * @throws IOException
118: * if something goes wrong
119: */
120: public static void encode(final InputStream in,
121: final OutputStream out) throws IOException {
122: process(in, out);
123: }
124:
125: /**
126: * Encodes from the supplied byte array and write the encoded data to the
127: * OutputStream <i>out </i>.
128: *
129: * @param input
130: * The byte array input to be encoded.
131: * @param out
132: * The output stream to write encoded data to.
133: * @throws IOException
134: * if something goes wrong
135: */
136: public static void encode(final byte[] input, final OutputStream out)
137: throws IOException {
138: ByteArrayInputStream in = new ByteArrayInputStream(input);
139: process(in, out);
140: }
141:
142: /**
143: * Encode the given string and return the encoded version as a string.
144: *
145: * @param input
146: * The string input to be encoded. It is assumed the string input
147: * uses characters from the ISO 8859-1 code page.
148: * @return A String, representing the encoded content of the input String.
149: * The returned string uses charactes from 8859-1 code page.
150: * @throws IOException
151: * if something goes wrong
152: */
153: public static String encode(final String input) throws IOException {
154: byte[] bytes;
155: bytes = input.getBytes("ISO-8859-1");
156: return encode(bytes);
157: }
158:
159: /**
160: * Encode the given byte array and return the encoded version as a string.
161: *
162: * @param bytes
163: * The byte array to be encoded.
164: * @return A String, representing the encoded content of the input bytes.
165: * The returned string uses charactes from 8859-1 code page.
166: * @throws IOException
167: * if something goes wrong
168: */
169: public static String encode(final byte[] bytes) throws IOException {
170: ByteArrayInputStream in = new ByteArrayInputStream(bytes);
171: ByteArrayOutputStream out = new ByteArrayOutputStream();
172: process(in, out);
173: return out.toString("ISO-8859-1");
174: }
175:
176: /**
177: * Run with one argument, prints the encoded version of it. With two, the
178: * second is assumed to be the name of a MessageDigest to be applied to the
179: * string before ENCODING (useful for generating password hashes).
180: * <p>
181: * Alternatively, use the openssl utility, for example:
182: * <p>
183: * echo -n "password" | openssl dgst -sha1 -binary | openssl base64
184: *
185: * @param args
186: * String[]
187: * @throws Exception
188: * if something goes wrong
189: */
190: public static void main(final String[] args) throws Exception {
191: if (args.length == 1) {
192: System.out.println("[" + Base64Encoder.encode(args[0])
193: + "]");
194: // joe:eoj -> am9lOmVvag==
195: // 12345678:87654321 -> MTIzNDU2Nzg6ODc2NTQzMjE=
196: } else if (args.length == 2) {
197: byte[] hash = java.security.MessageDigest.getInstance(
198: args[1]).digest(args[0].getBytes());
199: System.out.println("[" + Base64Encoder.encode(hash) + "]");
200: } else {
201: System.out
202: .println("Usage: Base64Encoder <string> <optional hash algorithm>");
203: }
204: }
205:
206: // Private ----------------------------------------------------------------
207: /**
208: * getting the first integer.
209: *
210: * @param buf
211: * byte array
212: * @param off
213: * offset
214: * @return int
215: */
216: private static int get1(final byte[] buf, final int off) {
217: return (buf[off] & 0xfc) >> 2;
218: }
219:
220: /**
221: * getting the second integer.
222: *
223: * @param buf
224: * byte array
225: * @param off
226: * offset
227: * @return int
228: */
229: private static int get2(final byte[] buf, final int off) {
230: return ((buf[off] & 0x3) << 4) | ((buf[off + 1] & 0xf0) >>> 4);
231: }
232:
233: /**
234: * getting the third integer.
235: *
236: * @param buf
237: * byte array
238: * @param off
239: * offset
240: * @return int
241: */
242: private static int get3(final byte[] buf, final int off) {
243: return ((buf[off + 1] & 0x0f) << 2)
244: | ((buf[off + 2] & 0xc0) >>> 6);
245: }
246:
247: /**
248: * getting the forth integer.
249: *
250: * @param buf
251: * byte array
252: * @param off
253: * offset
254: * @return int
255: */
256: private static int get4(final byte[] buf, final int off) {
257: return buf[off + 2] & 0x3f;
258: }
259:
260: /**
261: * Process the data: encode the input stream to the output stream. This
262: * method runs through the input stream, ENCODING it to the output stream.
263: *
264: * @param in
265: * input stream
266: * @param out
267: * output stream
268: * @exception IOException
269: * If we weren't able to access the input stream or the
270: * output stream.
271: */
272: private static void process(final InputStream in,
273: final OutputStream out) throws IOException {
274: byte[] buffer = new byte[BUFFER_SIZE];
275: int got = -1;
276: int off = 0;
277: int count = 0;
278: while ((got = in.read(buffer, off, BUFFER_SIZE - off)) > 0) {
279: if (got >= 3) {
280: got += off;
281: off = 0;
282: while (off + 3 <= got) {
283: int c1 = get1(buffer, off);
284: int c2 = get2(buffer, off);
285: int c3 = get3(buffer, off);
286: int c4 = get4(buffer, off);
287: switch (count) {
288: case 73:
289: out.write(ENCODING[c1]);
290: out.write(ENCODING[c2]);
291: out.write(ENCODING[c3]);
292: out.write('\n');
293: out.write(ENCODING[c4]);
294: count = 1;
295: break;
296: case 74:
297: out.write(ENCODING[c1]);
298: out.write(ENCODING[c2]);
299: out.write('\n');
300: out.write(ENCODING[c3]);
301: out.write(ENCODING[c4]);
302: count = 2;
303: break;
304: case 75:
305: out.write(ENCODING[c1]);
306: out.write('\n');
307: out.write(ENCODING[c2]);
308: out.write(ENCODING[c3]);
309: out.write(ENCODING[c4]);
310: count = 3;
311: break;
312: case 76:
313: out.write('\n');
314: out.write(ENCODING[c1]);
315: out.write(ENCODING[c2]);
316: out.write(ENCODING[c3]);
317: out.write(ENCODING[c4]);
318: count = 4;
319: break;
320: default:
321: out.write(ENCODING[c1]);
322: out.write(ENCODING[c2]);
323: out.write(ENCODING[c3]);
324: out.write(ENCODING[c4]);
325: count += 4;
326: break;
327: }
328: off += 3;
329: }
330: // Copy remaining bytes to beginning of buffer:
331: for (int i = 0; i < 3; i++) {
332: if (i < got - off) {
333: buffer[i] = buffer[off + i];
334: } else {
335: buffer[i] = ((byte) 0);
336: }
337: }
338: off = got - off;
339: } else {
340: // Total read amount is less then 3 bytes:
341: off += got;
342: }
343: }
344: // Manage the last bytes, from 0 to off:
345: switch (off) {
346: case 1:
347: out.write(ENCODING[get1(buffer, 0)]);
348: out.write(ENCODING[get2(buffer, 0)]);
349: out.write('=');
350: out.write('=');
351: break;
352: case 2:
353: out.write(ENCODING[get1(buffer, 0)]);
354: out.write(ENCODING[get2(buffer, 0)]);
355: out.write(ENCODING[get3(buffer, 0)]);
356: out.write('=');
357: default:
358: }
359: return;
360: }
361: }
|