home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / java / util / base64decoder.java next >
Text File  |  1995-08-11  |  5KB  |  168 lines

  1. /*
  2.  * @(#)BASE64Decoder.java    1.1 95/03/16 Chuck McManis
  3.  *
  4.  * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19. package java.util;
  20.  
  21. import java.io.OutputStream;
  22. import java.io.InputStream;
  23. import java.io.PrintStream;
  24.  
  25. /**
  26.  * This class implements a BASE64 Character decoder as specified in RFC1113.
  27.  *
  28.  * This RFC is part of the Privacy Enhanced Mail (PEM) specification which
  29.  * is published by the Internet Engineering Task Force (IETF). Unlike some
  30.  * other encoding schemes there is nothing in this encoding that tells
  31.  * the decoder where a buffer starts or stops, so to use it you will need
  32.  * to isolate your encoded data into a single chunk and then feed them
  33.  * this decoder. The simplest way to do that is to read all of the encoded
  34.  * data into a string and then use:
  35.  * <pre>
  36.  *    byte    mydata[];
  37.  *    BASE64Decoder base64 = new BASE64Decoder();
  38.  *
  39.  *    mydata = base64.decodeBuffer(bufferString);
  40.  * </pre>
  41.  * This will decode the String in <i>bufferString</i> and give you an array 
  42.  * of bytes in the array <i>myData</i>. 
  43.  *
  44.  * On errors, this class throws a CEFormatException with the following detail
  45.  * strings:
  46.  * <pre>
  47.  *    "BASE64Decoder: Bad Padding byte (2)."
  48.  *    "BASE64Decoder: Bad Padding byte (1)."
  49.  * </pre>
  50.  *
  51.  * @version    1.1, 16 Mar 1995
  52.  * @author    Chuck McManis
  53.  * @see        CharacterEncoder
  54.  * @see        BASE64Decoder
  55.  */
  56.  
  57. public class BASE64Decoder extends CharacterDecoder {
  58.     
  59.     /** This class has 3 bytes per atom */
  60.     int bytesPerAtom() {
  61.     return (3);
  62.     }
  63.  
  64.     /** This class has 48 bytes per encoded line */
  65.     int bytesPerLine() {
  66.     return (48);
  67.     }
  68.  
  69.     /**
  70.      * This character array provides the character to value map
  71.      * based on RFC1113.
  72.      */
  73.     private final static char pem_array[] = {
  74.     //       0   1   2   3   4   5   6   7
  75.         'A','B','C','D','E','F','G','H', // 0
  76.         'I','J','K','L','M','N','O','P', // 1
  77.         'Q','R','S','T','U','V','W','X', // 2
  78.         'Y','Z','a','b','c','d','e','f', // 3
  79.         'g','h','i','j','k','l','m','n', // 4
  80.         'o','p','q','r','s','t','u','v', // 5
  81.         'w','x','y','z','0','1','2','3', // 6
  82.         '4','5','6','7','8','9','+','/'  // 7
  83.     };
  84.  
  85.     byte decode_buffer[] = new byte[4];
  86.  
  87.     /**
  88.      * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
  89.      */
  90.     void decodeAtom(InputStream inStream, OutputStream outStream, int l) {
  91.     int    i;
  92.     byte    a = -1, b = -1, c = -1, d = -1;
  93.     StringBuffer s = new StringBuffer(4);
  94.  
  95.     decode_buffer[0] = (byte) inStream.read();
  96.     if (decode_buffer[0] == -1) {
  97.         throw new CEStreamExhausted();
  98.     }
  99.  
  100.     // check to see if we caught the trailing end of a <CR><LF>
  101.     if (decode_buffer[0] == '\n') {
  102.         i = inStream.read(decode_buffer, 0, 4);
  103.     } else {
  104.         i = inStream.read(decode_buffer, 1, 3);
  105.     }
  106.     if (i == -1) {
  107.         throw new CEStreamExhausted();
  108.     }
  109.  
  110.     for (i = 0; i < 64; i++) {
  111.         if (decode_buffer[0] == pem_array[i]) {
  112.         a = (byte) i;
  113.         }
  114.         if (decode_buffer[1] == pem_array[i]) {
  115.         b = (byte) i;
  116.         }
  117.         if (decode_buffer[2] == pem_array[i]) {
  118.         c = (byte) i;
  119.         }
  120.         if (decode_buffer[3] == pem_array[i]) {
  121.         d = (byte) i;
  122.         }
  123.     }
  124.     if ((l == 2) && (decode_buffer[3] != '=')) {
  125.         throw new CEFormatException("BASE64Decoder: Bad Padding byte (2).");
  126.     }
  127.     if ((l == 1) && 
  128.         ((decode_buffer[2] != '=') || (decode_buffer[3] != '='))) {
  129.         throw new CEFormatException("BASE64Decoder: Bad Padding byte (1).");
  130.     }
  131.     
  132.     for (i = 0; i < 4; i++) s.appendChar((char) decode_buffer[i]);
  133.     switch (l) {
  134.     case 1:
  135.         outStream.write( (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
  136.         break;
  137.     case 2:
  138.         outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
  139.         outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
  140.         break;
  141.     case 3:
  142.         outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
  143.         outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
  144.         outStream.write( (byte) (((c << 6) & 0xc0) | (d  & 0x3f)) );
  145.         break;
  146.     }
  147.     return;
  148.     }
  149.  
  150.     /**
  151.      * decodeLineSuffix in this decoder simply finds the [newLine] and
  152.      * positions us past it.
  153.      */
  154.     void decodeLineSuffix(InputStream inStream, OutputStream outStream) {
  155.     int c;
  156.     
  157.     while (true) {
  158.         c = inStream.read();
  159.         if (c == -1) {
  160.         throw new CEStreamExhausted();
  161.         }
  162.         if ((c == '\n') || (c == '\r')) {
  163.         break;
  164.         }
  165.     }
  166.     }
  167. }
  168.