1 /* 2 * Copyright (c) 1994, 1995, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.net; 27 28 import java.io.*; 29 30 /** 31 * This class provides input and output streams for telnet clients. 32 * This class overrides read to do CRLF processing as specified in 33 * RFC 854. The class assumes it is running on a system where lines 34 * are terminated with a single newline <LF> character. 35 * 36 * This is the relevant section of RFC 824 regarding CRLF processing: 37 * 38 * <pre> 39 * The sequence "CR LF", as defined, will cause the NVT to be 40 * positioned at the left margin of the next print line (as would, 41 * for example, the sequence "LF CR"). However, many systems and 42 * terminals do not treat CR and LF independently, and will have to 43 * go to some effort to simulate their effect. (For example, some 44 * terminals do not have a CR independent of the LF, but on such 45 * terminals it may be possible to simulate a CR by backspacing.) 46 * Therefore, the sequence "CR LF" must be treated as a single "new 47 * line" character and used whenever their combined action is 48 * intended; the sequence "CR NUL" must be used where a carriage 49 * return alone is actually desired; and the CR character must be 50 * avoided in other contexts. This rule gives assurance to systems 51 * which must decide whether to perform a "new line" function or a 52 * multiple-backspace that the TELNET stream contains a character 53 * following a CR that will allow a rational decision. 54 * 55 * Note that "CR LF" or "CR NUL" is required in both directions 56 * (in the default ASCII mode), to preserve the symmetry of the 57 * NVT model. Even though it may be known in some situations 58 * (e.g., with remote echo and suppress go ahead options in 59 * effect) that characters are not being sent to an actual 60 * printer, nonetheless, for the sake of consistency, the protocol 61 * requires that a NUL be inserted following a CR not followed by 62 * a LF in the data stream. The converse of this is that a NUL 63 * received in the data stream after a CR (in the absence of 64 * options negotiations which explicitly specify otherwise) should 65 * be stripped out prior to applying the NVT to local character 66 * set mapping. 67 * </pre> 68 * 69 * @author Jonathan Payne 70 */ 71 72 public class TelnetInputStream extends FilterInputStream { 73 /** If stickyCRLF is true, then we're a machine, like an IBM PC, 74 where a Newline is a CR followed by LF. On UNIX, this is false 75 because Newline is represented with just a LF character. */ 76 boolean stickyCRLF = false; 77 boolean seenCR = false; 78 79 public boolean binaryMode = false; 80 81 public TelnetInputStream(InputStream fd, boolean binary) { 82 super(fd); 83 binaryMode = binary; 84 } 85 86 public void setStickyCRLF(boolean on) { 87 stickyCRLF = on; 88 } 89 90 public int read() throws IOException { 91 if (binaryMode) 92 return super.read(); 93 94 int c; 95 96 /* If last time we determined we saw a CRLF pair, and we're 97 not turning that into just a Newline (that is, we're 98 stickyCRLF), then return the LF part of that sticky 99 pair now. */ 100 101 if (seenCR) { 102 seenCR = false; 103 return '\n'; 104 } 105 106 if ((c = super.read()) == '\r') { /* CR */ 107 switch (c = super.read()) { 108 default: 109 case -1: /* this is an error */ 110 throw new TelnetProtocolException("misplaced CR in input"); 111 112 case 0: /* NUL - treat CR as CR */ 113 return '\r'; 114 115 case '\n': /* CRLF - treat as NL */ 116 if (stickyCRLF) { 117 seenCR = true; 118 return '\r'; 119 } else { 120 return '\n'; 121 } 122 } 123 } 124 return c; 125 } 126 127 /** read into a byte array */ 128 public int read(byte bytes[]) throws IOException { 129 return read(bytes, 0, bytes.length); 130 } 131 132 /** 133 * Read into a byte array at offset <i>off</i> for length <i>length</i> 134 * bytes. 135 */ 136 public int read(byte bytes[], int off, int length) throws IOException { 137 if (binaryMode) 138 return super.read(bytes, off, length); 139 140 int c; 141 int offStart = off; 142 143 while (--length >= 0) { 144 c = read(); 145 if (c == -1) 146 break; 147 bytes[off++] = (byte)c; 148 } 149 return (off > offStart) ? off - offStart : -1; 150 } 151 } 152