| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.net;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
 | 
 | 
/**  | 
 | 
 * This class provides input and output streams for telnet clients.  | 
 | 
 * This class overrides read to do CRLF processing as specified in  | 
 | 
 * RFC 854. The class assumes it is running on a system where lines  | 
 | 
 * are terminated with a single newline <LF> character.  | 
 | 
 *  | 
 | 
 * This is the relevant section of RFC 824 regarding CRLF processing:  | 
 | 
 *  | 
 | 
 * <pre>  | 
 | 
 * The sequence "CR LF", as defined, will cause the NVT to be  | 
 | 
 * positioned at the left margin of the next print line (as would,  | 
 | 
 * for example, the sequence "LF CR").  However, many systems and  | 
 | 
 * terminals do not treat CR and LF independently, and will have to  | 
 | 
 * go to some effort to simulate their effect.  (For example, some  | 
 | 
 * terminals do not have a CR independent of the LF, but on such  | 
 | 
 * terminals it may be possible to simulate a CR by backspacing.)  | 
 | 
 * Therefore, the sequence "CR LF" must be treated as a single "new  | 
 | 
 * line" character and used whenever their combined action is  | 
 | 
 * intended; the sequence "CR NUL" must be used where a carriage  | 
 | 
 * return alone is actually desired; and the CR character must be  | 
 | 
 * avoided in other contexts.  This rule gives assurance to systems  | 
 | 
 * which must decide whether to perform a "new line" function or a  | 
 | 
 * multiple-backspace that the TELNET stream contains a character  | 
 | 
 * following a CR that will allow a rational decision.  | 
 | 
 *  | 
 | 
 *    Note that "CR LF" or "CR NUL" is required in both directions  | 
 | 
 *    (in the default ASCII mode), to preserve the symmetry of the  | 
 | 
 *    NVT model.  Even though it may be known in some situations  | 
 | 
 *    (e.g., with remote echo and suppress go ahead options in  | 
 | 
 *    effect) that characters are not being sent to an actual  | 
 | 
 *    printer, nonetheless, for the sake of consistency, the protocol  | 
 | 
 *    requires that a NUL be inserted following a CR not followed by  | 
 | 
 *    a LF in the data stream.  The converse of this is that a NUL  | 
 | 
 *    received in the data stream after a CR (in the absence of  | 
 | 
 *    options negotiations which explicitly specify otherwise) should  | 
 | 
 *    be stripped out prior to applying the NVT to local character  | 
 | 
 *    set mapping.  | 
 | 
 * </pre>  | 
 | 
 *  | 
 | 
 * @author      Jonathan Payne  | 
 | 
 */  | 
 | 
 | 
 | 
public class TelnetInputStream extends FilterInputStream { | 
 | 
      | 
 | 
 | 
 | 
        because Newline is represented with just a LF character. */  | 
 | 
    boolean         stickyCRLF = false;  | 
 | 
    boolean         seenCR = false;  | 
 | 
 | 
 | 
    public boolean  binaryMode = false;  | 
 | 
 | 
 | 
    public TelnetInputStream(InputStream fd, boolean binary) { | 
 | 
        super(fd);  | 
 | 
        binaryMode = binary;  | 
 | 
    }  | 
 | 
 | 
 | 
    public void setStickyCRLF(boolean on) { | 
 | 
        stickyCRLF = on;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int read() throws IOException { | 
 | 
        if (binaryMode)  | 
 | 
            return super.read();  | 
 | 
 | 
 | 
        int c;  | 
 | 
 | 
 | 
        /* If last time we determined we saw a CRLF pair, and we're  | 
 | 
           not turning that into just a Newline (that is, we're  | 
 | 
           stickyCRLF), then return the LF part of that sticky  | 
 | 
           pair now. */  | 
 | 
 | 
 | 
        if (seenCR) { | 
 | 
            seenCR = false;  | 
 | 
            return '\n';  | 
 | 
        }  | 
 | 
 | 
 | 
        if ((c = super.read()) == '\r') {     | 
 | 
            switch (c = super.read()) { | 
 | 
            default:  | 
 | 
            case -1:                          | 
 | 
                throw new TelnetProtocolException("misplaced CR in input"); | 
 | 
 | 
 | 
            case 0:                           | 
 | 
                return '\r';  | 
 | 
 | 
 | 
            case '\n':                        | 
 | 
                if (stickyCRLF) { | 
 | 
                    seenCR = true;  | 
 | 
                    return '\r';  | 
 | 
                } else { | 
 | 
                    return '\n';  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return c;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    public int read(byte bytes[]) throws IOException { | 
 | 
        return read(bytes, 0, bytes.length);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public int read(byte bytes[], int off, int length) throws IOException { | 
 | 
        if (binaryMode)  | 
 | 
            return super.read(bytes, off, length);  | 
 | 
 | 
 | 
        int c;  | 
 | 
        int offStart = off;  | 
 | 
 | 
 | 
        while (--length >= 0) { | 
 | 
            c = read();  | 
 | 
            if (c == -1)  | 
 | 
                break;  | 
 | 
            bytes[off++] = (byte)c;  | 
 | 
        }  | 
 | 
        return (off > offStart) ? off - offStart : -1;  | 
 | 
    }  | 
 | 
}  |