001: /* ====================================================================
002: * The LateralNZ Software License, Version 1.0
003: *
004: * Copyright (c) 2003 LateralNZ. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by
021: * LateralNZ (http://www.lateralnz.org/) and other third parties."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. The names "LateralNZ" must not be used to endorse or promote
026: * products derived from this software without prior written
027: * permission. For written permission, please
028: * contact oss@lateralnz.org.
029: *
030: * 5. Products derived from this software may not be called "Panther",
031: * or "Lateral" or "LateralNZ", nor may "PANTHER" or "LATERAL" or
032: * "LATERALNZ" appear in their name, without prior written
033: * permission of LateralNZ.
034: *
035: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: *
049: * This software consists of voluntary contributions made by many
050: * individuals on behalf of LateralNZ. For more
051: * information on Lateral, please see http://www.lateralnz.com/ or
052: * http://www.lateralnz.org
053: *
054: */
055: package org.lateralnz.common.telnet;
056:
057: import java.net.Socket;
058: import java.io.InputStream;
059: import java.io.IOException;
060: import java.io.OutputStream;
061:
062: import org.lateralnz.common.util.IOUtils;
063:
064: public class BaseHandler extends Thread implements Constants {
065: private boolean running = true;
066:
067: private Socket sock;
068: protected InputStream in;
069: protected OutputStream out;
070: private boolean echo = true;
071: protected StringBuffer line = new StringBuffer();
072: private int linepos = 0;
073:
074: private BaseHandler() {
075: }
076:
077: public BaseHandler(Server parent, Socket sock) throws IOException {
078: this .sock = sock;
079: this .in = sock.getInputStream();
080: this .out = sock.getOutputStream();
081:
082: write(new int[] { IAC, WILL, ECHO });
083: // out.write(new byte[]{ IAC, DONT, ECHO });
084: write(new int[] { IAC, WONT, LINEMODE });
085: write(new int[] { IAC, DONT, LINEMODE });
086: write(new int[] { IAC, WILL, SUPPRESS_GO_AHEAD });
087: write(new int[] { IAC, DO, SUPPRESS_GO_AHEAD });
088: // out.write(new byte[]{ IAC, SB, TERMINAL_TYPE });
089: // out.write(new byte[]{ IAC,SB,(byte)24,(byte)255,(byte)240});
090: out.flush();
091:
092: start();
093: }
094:
095: protected boolean deleteChar() throws IOException {
096: if (line.length() > 0) {
097: out.write(8);
098: out.write(32);
099: out.write(8);
100: out.flush();
101: line.deleteCharAt(line.length() - 1);
102: return true;
103: } else {
104: return false;
105: }
106: }
107:
108: protected void sendCursor(int count, int dir) throws IOException {
109: for (int i = 0; i < count; i++) {
110: if (dir == ESC_LEFT) {
111: write(new int[] { ESCAPE, (int) '[', (int) 'D' });
112: } else {
113: write(new int[] { ESCAPE, (int) '[', (int) 'C' });
114: }
115: }
116: }
117:
118: public void setEcho(boolean echo) {
119: this .echo = echo;
120: }
121:
122: public void write(int[] bytes) throws IOException {
123: for (int i = 0; i < bytes.length; i++) {
124: out.write(bytes[i]);
125: }
126: }
127:
128: /**
129: * currently makes a best guess effort to read the escape sequence
130: * but basically ignores them.
131: */
132: private void getEscapeSequence() throws IOException {
133: int esc = -1;
134: int mod = -1;
135:
136: char c = (char) in.read();
137: char c2;
138: char c3;
139: switch (c) {
140: case '[':
141: c2 = (char) in.read();
142: if (c2 >= '0' && c2 <= '9') {
143: c3 = (char) in.read();
144: } else if (c2 == 'A') {
145: esc = ESC_UP;
146: mod = 1;
147: } else if (c2 == 'B') {
148: esc = ESC_DOWN;
149: mod = 1;
150: } else if (c2 == 'D') {
151: esc = ESC_LEFT;
152: mod = 1;
153: } else if (c2 == 'C') {
154: esc = ESC_RIGHT;
155: mod = 1;
156: }
157: break;
158: case '(':
159: in.read();
160: break;
161: case '?':
162: c2 = (char) in.read();
163: if (c2 == '2' || c2 == '6') {
164: in.read();
165: }
166: break;
167: case 'c':
168: case 'D':
169: case 'E':
170: case 'M':
171: case '7':
172: case '8':
173: case '=':
174: case '>':
175: case 'G':
176: case 'H':
177: case 'I':
178: case 'J':
179: case 'N':
180: case 'O':
181: case 'Z':
182: }
183: handleEscape(esc, mod);
184: }
185:
186: public void run() {
187: try {
188: while (running) {
189: int i = in.read();
190: if (i == -1) {
191: running = false;
192: break;
193: }
194:
195: // Interpret As Command received
196: if (i == 255) {
197: System.out.println(Server.getCommandString(i, in
198: .read(), in.read()));
199: continue;
200: }
201:
202: if (i < 32 && handleControlChar(i)) {
203: continue;
204: }
205: // escape sequence
206: else if (i == 27) {
207: getEscapeSequence();
208: continue;
209: }
210: // backspace or delete
211: else if (i == 127 || i == 8) {
212: if (line.length() > 0) {
213: deleteChar();
214: }
215: continue;
216: }
217:
218: if (echo) {
219: out.write(i);
220: }
221: line.append((char) i);
222:
223: this .yield();
224: }
225: } catch (IOException ioe) {
226: ioe.printStackTrace();
227: } finally {
228: IOUtils.close(out);
229: IOUtils.close(in);
230: IOUtils.close(sock);
231: }
232: }
233:
234: public boolean handleControlChar(int c) throws IOException {
235: switch (c) {
236: case 0:
237: return true;
238: case 9:
239: out.write((int) ' ');
240: out.write((int) ' ');
241: line.append(" ");
242: return true;
243: case 10:
244: case 13:
245: out.write(10);
246: out.write(13);
247: handleInput(line.toString());
248: line.delete(0, line.length());
249: return true;
250: case 4:
251: case 24:
252: System.out.println("received eot");
253: running = false;
254: return true;
255: }
256: return false;
257: }
258:
259: public boolean handleEscape(int esc, int mod) throws IOException {
260: return false;
261: }
262:
263: public boolean handleInput(String line) throws IOException {
264: System.out.println(line);
265: return false;
266: }
267: }
|