1 /* 2 * Copyright (c) 1994, 2002, 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 write 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 TelnetOutputStream extends BufferedOutputStream { 73 boolean stickyCRLF = false; 74 boolean seenCR = false; 75 76 public boolean binaryMode = false; 77 78 public TelnetOutputStream(OutputStream fd, boolean binary) { 79 super(fd); 80 binaryMode = binary; 81 } 82 83 /** 84 * set the stickyCRLF flag. Tells wether the terminal considers CRLF as a single 85 * char. 86 * 87 * @param on the <code>boolean</code> to set the flag to. 88 */ 89 public void setStickyCRLF(boolean on) { 90 stickyCRLF = on; 91 } 92 93 /** 94 * Writes the int to the stream and does CR LF processing if necessary. 95 */ 96 public void write(int c) throws IOException { 97 if (binaryMode) { 98 super.write(c); 99 return; 100 } 101 102 if (seenCR) { 103 if (c != '\n') 104 super.write(0); 105 super.write(c); 106 if (c != '\r') 107 seenCR = false; 108 } else { // !seenCR 109 if (c == '\n') { 110 super.write('\r'); 111 super.write('\n'); 112 return; 113 } 114 if (c == '\r') { 115 if (stickyCRLF) 116 seenCR = true; 117 else { 118 super.write('\r'); 119 c = 0; 120 } 121 } 122 super.write(c); 123 } 124 } 125 126 /** 127 * Write the bytes at offset <i>off</i> in buffer <i>bytes</i> for 128 * <i>length</i> bytes. 129 */ 130 public void write(byte bytes[], int off, int length) throws IOException { 131 if (binaryMode) { 132 super.write(bytes, off, length); 133 return; 134 } 135 136 while (--length >= 0) { 137 write(bytes[off++]); 138 } 139 } 140 } 141