home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 25 / CDROM25.iso / Share / prog / VJ11 / VJTRIAL.EXE / IE30Java.exe / classd.exe / sun / misc / UUDecoder.java < prev    next >
Encoding:
Java Source  |  1997-01-27  |  7.6 KB  |  250 lines

  1. /*
  2.  * @(#)UUDecoder.java    1.6 95/10/08 Chuck McManis
  3.  *
  4.  * Copyright (c) 1994 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 sun.misc;
  20.  
  21. import java.io.InputStream;
  22. import java.io.OutputStream;
  23. import java.io.PrintStream;
  24. import java.io.IOException;
  25.  
  26. /**
  27.  * This class implements a Berkeley uu character decoder. This decoder
  28.  * was made famous by the uudecode program.
  29.  *
  30.  * The basic character coding is algorithmic, taking 6 bits of binary
  31.  * data and adding it to an ASCII ' ' (space) character. This converts
  32.  * these six bits into a printable representation. Note that it depends
  33.  * on the ASCII character encoding standard for english. Groups of three
  34.  * bytes are converted into 4 characters by treating the three bytes
  35.  * a four 6 bit groups, group 1 is byte 1's most significant six bits,
  36.  * group 2 is byte 1's least significant two bits plus byte 2's four
  37.  * most significant bits. etc.
  38.  *
  39.  * In this encoding, the buffer prefix is:
  40.  * <pre>
  41.  *     begin [mode] [filename]
  42.  * </pre>
  43.  *
  44.  * This is followed by one or more lines of the form:
  45.  * <pre>
  46.  *    (len)(data)(data)(data) ...
  47.  * </pre>
  48.  * where (len) is the number of bytes on this line. Note that groupings
  49.  * are always four characters, even if length is not a multiple of three
  50.  * bytes. When less than three characters are encoded, the values of the
  51.  * last remaining bytes is undefined and should be ignored.
  52.  *
  53.  * The last line of data in a uuencoded buffer is represented by a single
  54.  * space character. This is translated by the decoding engine to a line
  55.  * length of zero. This is immediately followed by a line which contains
  56.  * the word 'end[newline]'
  57.  *
  58.  * If an error is encountered during decoding this class throws a
  59.  * CEFormatException. The specific detail messages are:
  60.  *
  61.  * <pre>
  62.  *    "UUDecoder: No begin line."
  63.  *    "UUDecoder: Malformed begin line."
  64.  *    "UUDecoder: Short Buffer."
  65.  *    "UUDecoder: Bad Line Length."
  66.  *    "UUDecoder: Missing 'end' line."
  67.  * </pre>
  68.  *
  69.  * @version     1.6, 10/08/95
  70.  * @author      Chuck McManis
  71.  * @see        CharacterDecoder
  72.  * @see        UUEncoder
  73.  */
  74. public class UUDecoder extends CharacterDecoder {
  75.  
  76.     /** 
  77.      * This string contains the name that was in the buffer being decoded.
  78.      */
  79.     public String bufferName;
  80.  
  81.     /**
  82.      * Represents UNIX(tm) mode bits. Generally three octal digits 
  83.      * representing read, write, and execute permission of the owner, 
  84.      * group owner, and  others. They should be interpreted as the bit groups:
  85.      * <pre>
  86.      * (owner) (group) (others)
  87.      *    rwx      rwx     rwx     (r = read, w = write, x = execute)
  88.      *</pre>
  89.      *
  90.      */
  91.     public int mode;
  92.  
  93.  
  94.     /**
  95.      * UU encoding specifies 3 bytes per atom.
  96.      */
  97.     int bytesPerAtom() {
  98.     return (3);    
  99.     }
  100.  
  101.     /**
  102.      * All UU lines have 45 bytes on them, for line length of 15*4+1 or 61
  103.      * characters per line.
  104.      */
  105.     int bytesPerLine() {
  106.     return (45);
  107.     }
  108.  
  109.     /** This is used to decode the atoms */
  110.     private byte decoderBuffer[] = new byte[4];
  111.  
  112.     /**
  113.      * Decode a UU atom. Note that if l is less than 3 we don't write
  114.      * the extra bits, however the encoder always encodes 4 character
  115.      * groups even when they are not needed.
  116.      */
  117.     void decodeAtom(InputStream inStream, OutputStream outStream, int l) 
  118.     throws IOException {
  119.     int i, c1, c2, c3, c4;
  120.     int a, b, c;
  121.     StringBuffer x = new StringBuffer();
  122.  
  123.     for (i = 0; i < 4; i++) {
  124.         c1 = inStream.read();
  125.         if (c1 == -1) {
  126.             throw new CEStreamExhausted();
  127.         }
  128.         x.append((char)c1);
  129.         decoderBuffer[i] = (byte) ((c1 - ' ') & 0x3f);
  130.     }
  131.     a = ((decoderBuffer[0] << 2) & 0xfc) | ((decoderBuffer[1] >>> 4) & 3);
  132.     b = ((decoderBuffer[1] << 4) & 0xf0) | ((decoderBuffer[2] >>> 2) & 0xf);
  133.     c = ((decoderBuffer[2] << 6) & 0xc0) | (decoderBuffer[3] & 0x3f);
  134.     outStream.write((byte)(a & 0xff));
  135.     if (l > 1) {
  136.         outStream.write((byte)( b & 0xff));
  137.     }
  138.     if (l > 2) {
  139.         outStream.write((byte)(c&0xff));
  140.     }
  141.     }
  142.     
  143.     /**
  144.      * For uuencoded buffers, the data begins with a line of the form:
  145.      *         begin MODE FILENAME
  146.      * This line always starts in column 1.
  147.      */
  148.     void decodeBufferPrefix(InputStream inStream, OutputStream outStream) throws IOException {
  149.     int    c;
  150.     StringBuffer q = new StringBuffer(32);
  151.     String r;
  152.     boolean sawNewLine;
  153.  
  154.     /*
  155.      * This works by ripping through the buffer until it finds a 'begin'
  156.      * line or the end of the buffer.
  157.      */
  158.     sawNewLine = true;
  159.     while (true) {
  160.         c = inStream.read();
  161.         if (c == -1) {
  162.         throw new CEFormatException("UUDecoder: No begin line.");
  163.         }
  164.         if ((c == 'b')  && sawNewLine){
  165.         c = inStream.read();
  166.         if (c == 'e') {
  167.             break;
  168.         }
  169.         }
  170.         sawNewLine = (c == '\n') || (c == '\r');
  171.     }
  172.     
  173.     /* 
  174.      * Now we think its begin, (we've seen ^be) so verify it here.
  175.          */
  176.     while ((c != '\n') && (c != '\r')) {
  177.         c = inStream.read();
  178.         if (c == -1) {
  179.         throw new CEFormatException("UUDecoder: No begin line.");
  180.         }
  181.         if ((c != '\n') && (c != '\r')) {
  182.         q.append((char)c);
  183.         }
  184.     }
  185.     r = q.toString();
  186.     if (r.indexOf(' ') != 3) {
  187.         throw new CEFormatException("UUDecoder: Malformed begin line.");
  188.     }
  189.     mode = Integer.parseInt(r.substring(4,7));
  190.     bufferName = r.substring(r.indexOf(' ',6)+1);
  191.     }
  192.  
  193.     /**
  194.      * In uuencoded buffers, encoded lines start with a character that
  195.      * represents the number of bytes encoded in this line. The last
  196.      * line of input is always a line that starts with a single space
  197.      * character, which would be a zero length line.
  198.      */ 
  199.     int decodeLinePrefix(InputStream inStream, OutputStream outStream) throws IOException {
  200.     int    c;
  201.  
  202.     c = inStream.read();
  203.     if (c == ' ') {
  204.         c = inStream.read(); /* discard the trailing <newline> */
  205.         throw new CEStreamExhausted();
  206.     } else if (c == -1) {
  207.         throw new CEFormatException("UUDecoder: Short Buffer.");
  208.     }
  209.     
  210.     c = (c - ' ') & 0x3f;
  211.     if (c > bytesPerLine()) {
  212.         throw new CEFormatException("UUDecoder: Bad Line Length.");
  213.     }
  214.     return (c);
  215.     }
  216.  
  217.  
  218.     /**
  219.      * Find the end of the line for the next operation.
  220.      */
  221.     void decodeLineSuffix(InputStream inStream, OutputStream outStream) throws IOException { 
  222.     int c;
  223.     while (true) {
  224.         c = inStream.read();
  225.         if (c == -1) {
  226.         throw new CEStreamExhausted();
  227.         }
  228.         if (c == '\n') {
  229.         break;
  230.         }
  231.     }
  232.     }
  233.  
  234.     /**
  235.      * UUencoded files have a buffer suffix which consists of the word
  236.      * end. This line should immediately follow the line with a single
  237.      * space in it.
  238.      */
  239.     void decodeBufferSuffix(InputStream inStream, OutputStream outStream) throws IOException  {
  240.     int    c;
  241.  
  242.     c = inStream.read(decoderBuffer);
  243.     if ((decoderBuffer[0] != 'e') || (decoderBuffer[1] != 'n') ||
  244.         (decoderBuffer[2] != 'd')) {
  245.         throw new CEFormatException("UUDecoder: Missing 'end' line.");
  246.     }
  247.     }
  248.      
  249. }
  250.