summaryrefslogtreecommitdiff
path: root/org/apache/commons/net/telnet
diff options
context:
space:
mode:
authorJoe Robinson <joe@lc8n.com>2010-10-27 14:21:09 +0100
committerJoe Robinson <joe@lc8n.com>2010-10-27 14:21:09 +0100
commit063284837c8c366e5502b1b0264b8eb807b61732 (patch)
treefff3a1e1e5afaa671485b9d990704658276627ac /org/apache/commons/net/telnet
Basic upload functionality to predifined location, with basic file browser
Diffstat (limited to 'org/apache/commons/net/telnet')
-rw-r--r--org/apache/commons/net/telnet/EchoOptionHandler.java90
-rw-r--r--org/apache/commons/net/telnet/InvalidTelnetOptionException.java62
-rw-r--r--org/apache/commons/net/telnet/SimpleOptionHandler.java96
-rw-r--r--org/apache/commons/net/telnet/SuppressGAOptionHandler.java89
-rw-r--r--org/apache/commons/net/telnet/Telnet.java1317
-rw-r--r--org/apache/commons/net/telnet/TelnetClient.java306
-rw-r--r--org/apache/commons/net/telnet/TelnetCommand.java132
-rw-r--r--org/apache/commons/net/telnet/TelnetInputStream.java630
-rw-r--r--org/apache/commons/net/telnet/TelnetNotificationHandler.java66
-rw-r--r--org/apache/commons/net/telnet/TelnetOption.java193
-rw-r--r--org/apache/commons/net/telnet/TelnetOptionHandler.java272
-rw-r--r--org/apache/commons/net/telnet/TelnetOutputStream.java152
-rw-r--r--org/apache/commons/net/telnet/TerminalTypeOptionHandler.java136
-rw-r--r--org/apache/commons/net/telnet/WindowSizeOptionHandler.java188
14 files changed, 3729 insertions, 0 deletions
diff --git a/org/apache/commons/net/telnet/EchoOptionHandler.java b/org/apache/commons/net/telnet/EchoOptionHandler.java
new file mode 100644
index 0000000..8c43f85
--- /dev/null
+++ b/org/apache/commons/net/telnet/EchoOptionHandler.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet echo option RFC 857.
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+public class EchoOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Constructor for the EchoOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ * <p>
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public EchoOptionHandler(boolean initlocal, boolean initremote,
+ boolean acceptlocal, boolean acceptremote)
+ {
+ super(TelnetOption.ECHO, initlocal, initremote,
+ acceptlocal, acceptremote);
+ }
+
+ /***
+ * Constructor for the EchoOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ ***/
+ public EchoOptionHandler()
+ {
+ super(TelnetOption.ECHO, false, false, false, false);
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[],
+ int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/InvalidTelnetOptionException.java b/org/apache/commons/net/telnet/InvalidTelnetOptionException.java
new file mode 100644
index 0000000..740d185
--- /dev/null
+++ b/org/apache/commons/net/telnet/InvalidTelnetOptionException.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The InvalidTelnetOptionException is the exception that is
+ * thrown whenever a TelnetOptionHandler with an invlaid
+ * option code is registered in TelnetClient with addOptionHandler.
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+public class InvalidTelnetOptionException extends Exception
+{
+
+ /***
+ * Option code
+ ***/
+ private int optionCode = -1;
+
+ /***
+ * Error message
+ ***/
+ private String msg;
+
+ /***
+ * Constructor for the exception.
+ * <p>
+ * @param message - Error message.
+ * @param optcode - Option code.
+ ***/
+ public InvalidTelnetOptionException(String message, int optcode)
+ {
+ optionCode = optcode;
+ msg = message;
+ }
+
+ /***
+ * Gets the error message of ths exception.
+ * <p>
+ * @return the error message.
+ ***/
+ @Override
+ public String getMessage()
+ {
+ return (msg + ": " + optionCode);
+ }
+}
diff --git a/org/apache/commons/net/telnet/SimpleOptionHandler.java b/org/apache/commons/net/telnet/SimpleOptionHandler.java
new file mode 100644
index 0000000..3395508
--- /dev/null
+++ b/org/apache/commons/net/telnet/SimpleOptionHandler.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Simple option handler that can be used for options
+ * that don't require subnegotiation.
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+public class SimpleOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Constructor for the SimpleOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ * <p>
+ * @param optcode - option code.
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public SimpleOptionHandler(int optcode,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote)
+ {
+ super(optcode, initlocal, initremote,
+ acceptlocal, acceptremote);
+ }
+
+ /***
+ * Constructor for the SimpleOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ * <p>
+ * @param optcode - option code.
+ ***/
+ public SimpleOptionHandler(int optcode)
+ {
+ super(optcode, false, false, false, false);
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/SuppressGAOptionHandler.java b/org/apache/commons/net/telnet/SuppressGAOptionHandler.java
new file mode 100644
index 0000000..aa18452
--- /dev/null
+++ b/org/apache/commons/net/telnet/SuppressGAOptionHandler.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet suppress go ahead option RFC 858.
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+public class SuppressGAOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Constructor for the SuppressGAOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ * <p>
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public SuppressGAOptionHandler(boolean initlocal, boolean initremote,
+ boolean acceptlocal, boolean acceptremote)
+ {
+ super(TelnetOption.SUPPRESS_GO_AHEAD, initlocal, initremote,
+ acceptlocal, acceptremote);
+ }
+
+ /***
+ * Constructor for the SuppressGAOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ ***/
+ public SuppressGAOptionHandler()
+ {
+ super(TelnetOption.SUPPRESS_GO_AHEAD, false, false, false, false);
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/Telnet.java b/org/apache/commons/net/telnet/Telnet.java
new file mode 100644
index 0000000..c05b563
--- /dev/null
+++ b/org/apache/commons/net/telnet/Telnet.java
@@ -0,0 +1,1317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import org.apache.commons.net.SocketClient;
+
+/**
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ */
+
+class Telnet extends SocketClient
+{
+ static final boolean debug = /*true;*/ false;
+
+ static final boolean debugoptions = /*true;*/ false;
+
+ static final byte[] _COMMAND_DO = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.DO
+ };
+
+ static final byte[] _COMMAND_DONT = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.DONT
+ };
+
+ static final byte[] _COMMAND_WILL = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.WILL
+ };
+
+ static final byte[] _COMMAND_WONT = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.WONT
+ };
+
+ static final byte[] _COMMAND_SB = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.SB
+ };
+
+ static final byte[] _COMMAND_SE = {
+ (byte)TelnetCommand.IAC, (byte)TelnetCommand.SE
+ };
+
+ static final int _WILL_MASK = 0x01, _DO_MASK = 0x02,
+ _REQUESTED_WILL_MASK = 0x04, _REQUESTED_DO_MASK = 0x08;
+
+ /* public */
+ static final int DEFAULT_PORT = 23;
+
+ int[] _doResponse, _willResponse, _options;
+
+ /* TERMINAL-TYPE option (start)*/
+ /***
+ * Terminal type option
+ ***/
+ protected static final int TERMINAL_TYPE = 24;
+
+ /***
+ * Send (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_SEND = 1;
+
+ /***
+ * Is (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_IS = 0;
+
+ /***
+ * Is sequence (for subnegotiation)
+ ***/
+ static final byte[] _COMMAND_IS = {
+ (byte) TERMINAL_TYPE, (byte) TERMINAL_TYPE_IS
+ };
+
+ /***
+ * Terminal type
+ ***/
+ private String terminalType = null;
+ /* TERMINAL-TYPE option (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+ /***
+ * Array of option handlers
+ ***/
+ private TelnetOptionHandler optionHandlers[];
+
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+ /***
+ * AYT sequence
+ ***/
+ static final byte[] _COMMAND_AYT = {
+ (byte) TelnetCommand.IAC, (byte) TelnetCommand.AYT
+ };
+
+ /***
+ * monitor to wait for AYT
+ ***/
+ private Object aytMonitor = new Object();
+
+ /***
+ * flag for AYT
+ ***/
+ private boolean aytFlag = true;
+ /* Code Section added for supporting AYT (end)*/
+
+ /***
+ * The stream on which to spy
+ ***/
+ private OutputStream spyStream = null;
+
+ /***
+ * The notification handler
+ ***/
+ private TelnetNotificationHandler __notifhand = null;
+ /***
+ * Empty Constructor
+ ***/
+ Telnet()
+ {
+ setDefaultPort(DEFAULT_PORT);
+ _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ optionHandlers =
+ new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ /***
+ * This constructor lets you specify the terminal type.
+ * <p>
+ * @param termtype - terminal type to be negotiated (ej. VT100)
+ ***/
+ Telnet(String termtype)
+ {
+ setDefaultPort(DEFAULT_PORT);
+ _doResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _willResponse = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ _options = new int[TelnetOption.MAX_OPTION_VALUE + 1];
+ terminalType = termtype;
+ optionHandlers =
+ new TelnetOptionHandler[TelnetOption.MAX_OPTION_VALUE + 1];
+ }
+ /* TERMINAL-TYPE option (end)*/
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a will has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsWill(int option)
+ {
+ return ((_options[option] & _WILL_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a wont has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsWont(int option)
+ {
+ return !_stateIsWill(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a do has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsDo(int option)
+ {
+ return ((_options[option] & _DO_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a dont has been acknowledged
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _stateIsDont(int option)
+ {
+ return !_stateIsDo(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a will has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedWill(int option)
+ {
+ return ((_options[option] & _REQUESTED_WILL_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a wont has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedWont(int option)
+ {
+ return !_requestedWill(option);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a do has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedDo(int option)
+ {
+ return ((_options[option] & _REQUESTED_DO_MASK) != 0);
+ }
+
+ /***
+ * Looks for the state of the option.
+ * <p>
+ * @return returns true if a dont has been reuqested
+ * <p>
+ * @param option - option code to be looked up.
+ ***/
+ boolean _requestedDont(int option)
+ {
+ return !_requestedDo(option);
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWill(int option)
+ {
+ _options[option] |= _WILL_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (_requestedWill(option))
+ {
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setWill(true);
+
+ int subneg[] =
+ optionHandlers[option].startSubnegotiationLocal();
+
+ if (subneg != null)
+ {
+ try
+ {
+ _sendSubnegotiation(subneg);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception in option subnegotiation"
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setDo(int option)
+ {
+ _options[option] |= _DO_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (_requestedDo(option))
+ {
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setDo(true);
+
+ int subneg[] =
+ optionHandlers[option].startSubnegotiationRemote();
+
+ if (subneg != null)
+ {
+ try
+ {
+ _sendSubnegotiation(subneg);
+ }
+ catch (IOException e)
+ {
+ System.err.println("Exception in option subnegotiation"
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantWill(int option)
+ {
+ _options[option] |= _REQUESTED_WILL_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantDo(int option)
+ {
+ _options[option] |= _REQUESTED_DO_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWont(int option)
+ {
+ _options[option] &= ~_WILL_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setWill(false);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setDont(int option)
+ {
+ _options[option] &= ~_DO_MASK;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ optionHandlers[option].setDo(false);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantWont(int option)
+ {
+ _options[option] &= ~_REQUESTED_WILL_MASK;
+ }
+
+ /***
+ * Sets the state of the option.
+ * <p>
+ * @param option - option code to be set.
+ ***/
+ void _setWantDont(int option)
+ {
+ _options[option] &= ~_REQUESTED_DO_MASK;
+ }
+
+ /**
+ * Processes a DO request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processDo(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED DO: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_DO,
+ option);
+ }
+
+ boolean acceptNewState = false;
+
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ acceptNewState = optionHandlers[option].getAcceptLocal();
+ }
+ else
+ {
+ /* open TelnetOptionHandler functionality (end)*/
+ /* TERMINAL-TYPE option (start)*/
+ if (option == TERMINAL_TYPE)
+ {
+ if ((terminalType != null) && (terminalType.length() > 0))
+ {
+ acceptNewState = true;
+ }
+ }
+ /* TERMINAL-TYPE option (end)*/
+ /* open TelnetOptionHandler functionality (start)*/
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ if (_willResponse[option] > 0)
+ {
+ --_willResponse[option];
+ if (_willResponse[option] > 0 && _stateIsWill(option))
+ {
+ --_willResponse[option];
+ }
+ }
+
+ if (_willResponse[option] == 0)
+ {
+ if (_requestedWont(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+
+ if (acceptNewState)
+ {
+ _setWantWill(option);
+ _sendWill(option);
+ }
+ else
+ {
+ ++_willResponse[option];
+ _sendWont(option);
+ }
+ }
+ else
+ {
+ // Other end has acknowledged option.
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ }
+ }
+
+ _setWill(option);
+ }
+
+ /**
+ * Processes a DONT request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processDont(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED DONT: "
+ + TelnetOption.getOption(option));
+ }
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_DONT,
+ option);
+ }
+ if (_willResponse[option] > 0)
+ {
+ --_willResponse[option];
+ if (_willResponse[option] > 0 && _stateIsWont(option))
+ {
+ --_willResponse[option];
+ }
+ }
+
+ if (_willResponse[option] == 0 && _requestedWill(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ /* FIX for a BUG in the negotiation (start)*/
+ if ((_stateIsWill(option)) || (_requestedWill(option)))
+ {
+ _sendWont(option);
+ }
+
+ _setWantWont(option);
+ /* FIX for a BUG in the negotiation (end)*/
+ }
+
+ _setWont(option);
+ }
+
+
+ /**
+ * Processes a WILL request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processWill(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED WILL: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_WILL,
+ option);
+ }
+
+ boolean acceptNewState = false;
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (optionHandlers[option] != null)
+ {
+ acceptNewState = optionHandlers[option].getAcceptRemote();
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ if (_doResponse[option] > 0)
+ {
+ --_doResponse[option];
+ if (_doResponse[option] > 0 && _stateIsDo(option))
+ {
+ --_doResponse[option];
+ }
+ }
+
+ if (_doResponse[option] == 0 && _requestedDont(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+
+ if (acceptNewState)
+ {
+ _setWantDo(option);
+ _sendDo(option);
+ }
+ else
+ {
+ ++_doResponse[option];
+ _sendDont(option);
+ }
+ }
+
+ _setDo(option);
+ }
+
+ /**
+ * Processes a WONT request.
+ *
+ * @param option - option code to be set.
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processWont(int option) throws IOException
+ {
+ if (debugoptions)
+ {
+ System.err.println("RECEIVED WONT: "
+ + TelnetOption.getOption(option));
+ }
+
+ if (__notifhand != null)
+ {
+ __notifhand.receivedNegotiation(
+ TelnetNotificationHandler.RECEIVED_WONT,
+ option);
+ }
+
+ if (_doResponse[option] > 0)
+ {
+ --_doResponse[option];
+ if (_doResponse[option] > 0 && _stateIsDont(option))
+ {
+ --_doResponse[option];
+ }
+ }
+
+ if (_doResponse[option] == 0 && _requestedDo(option))
+ {
+
+ switch (option)
+ {
+
+ default:
+ break;
+
+ }
+
+ /* FIX for a BUG in the negotiation (start)*/
+ if ((_stateIsDo(option)) || (_requestedDo(option)))
+ {
+ _sendDont(option);
+ }
+
+ _setWantDont(option);
+ /* FIX for a BUG in the negotiation (end)*/
+ }
+
+ _setDont(option);
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ /**
+ * Processes a suboption negotiation.
+ *
+ * @param suboption - subnegotiation data received
+ * @param suboptionLength - length of data received
+ * @throws IOException - Exception in I/O.
+ **/
+ void _processSuboption(int suboption[], int suboptionLength)
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("PROCESS SUBOPTION.");
+ }
+
+ /* open TelnetOptionHandler functionality (start)*/
+ if (suboptionLength > 0)
+ {
+ if (optionHandlers[suboption[0]] != null)
+ {
+ int responseSuboption[] =
+ optionHandlers[suboption[0]].answerSubnegotiation(suboption,
+ suboptionLength);
+ _sendSubnegotiation(responseSuboption);
+ }
+ else
+ {
+ if (suboptionLength > 1)
+ {
+ if (debug)
+ {
+ for (int ii = 0; ii < suboptionLength; ii++)
+ {
+ System.err.println("SUB[" + ii + "]: "
+ + suboption[ii]);
+ }
+ }
+ if ((suboption[0] == TERMINAL_TYPE)
+ && (suboption[1] == TERMINAL_TYPE_SEND))
+ {
+ _sendTerminalType();
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /***
+ * Sends terminal type information.
+ * <p>
+ * @throws IOException - Exception in I/O.
+ ***/
+ final synchronized void _sendTerminalType()
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("SEND TERMINAL-TYPE: " + terminalType);
+ }
+ if (terminalType != null)
+ {
+ _output_.write(_COMMAND_SB);
+ _output_.write(_COMMAND_IS);
+ _output_.write(terminalType.getBytes());
+ _output_.write(_COMMAND_SE);
+ _output_.flush();
+ }
+ }
+
+ /* TERMINAL-TYPE option (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+ /**
+ * Manages subnegotiation for Terminal Type.
+ *
+ * @param subn - subnegotiation data to be sent
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendSubnegotiation(int subn[])
+ throws IOException
+ {
+ if (debug)
+ {
+ System.err.println("SEND SUBNEGOTIATION: ");
+ if (subn != null)
+ {
+ for (int ii = 0; ii < subn.length; ii++)
+ {
+ System.err.println("subn[" + ii + "]=" + subn[ii]);
+ }
+ }
+ }
+ if (subn != null)
+ {
+ byte byteresp[] = new byte[subn.length];
+ for (int ii = 0; ii < subn.length; ii++)
+ {
+ byteresp[ii] = (byte) subn[ii];
+ }
+
+ _output_.write(_COMMAND_SB);
+ _output_.write(byteresp);
+ _output_.write(_COMMAND_SE);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+ /***
+ * Processes the response of an AYT
+ ***/
+ final synchronized void _processAYTResponse()
+ {
+ if (!aytFlag)
+ {
+ synchronized (aytMonitor)
+ {
+ aytFlag = true;
+ try
+ {
+ aytMonitor.notifyAll();
+ }
+ catch (IllegalMonitorStateException e)
+ {
+ System.err.println("Exception notifying:" + e.getMessage());
+ }
+ }
+ }
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /***
+ * Called upon connection.
+ * <p>
+ * @throws IOException - Exception in I/O.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ /* (start). BUGFIX: clean the option info for each connection*/
+ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
+ {
+ _doResponse[ii] = 0;
+ _willResponse[ii] = 0;
+ _options[ii] = 0;
+ if (optionHandlers[ii] != null)
+ {
+ optionHandlers[ii].setDo(false);
+ optionHandlers[ii].setWill(false);
+ }
+ }
+ /* (end). BUGFIX: clean the option info for each connection*/
+
+ super._connectAction_();
+ _input_ = new BufferedInputStream(_input_);
+ _output_ = new BufferedOutputStream(_output_);
+
+ /* open TelnetOptionHandler functionality (start)*/
+ for (int ii = 0; ii < TelnetOption.MAX_OPTION_VALUE + 1; ii++)
+ {
+ if (optionHandlers[ii] != null)
+ {
+ if (optionHandlers[ii].getInitLocal())
+ {
+ try
+ {
+ _requestWill(optionHandlers[ii].getOptionCode());
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+
+ if (optionHandlers[ii].getInitRemote())
+ {
+ try
+ {
+ _requestDo(optionHandlers[ii].getOptionCode());
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+ }
+
+ /**
+ * Sends a DO.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendDo(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("DO: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_DO);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a DO.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestDo(int option)
+ throws IOException
+ {
+ if ((_doResponse[option] == 0 && _stateIsDo(option))
+ || _requestedDo(option))
+ {
+ return ;
+ }
+ _setWantDo(option);
+ ++_doResponse[option];
+ _sendDo(option);
+ }
+
+ /**
+ * Sends a DONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendDont(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("DONT: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_DONT);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a DONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestDont(int option)
+ throws IOException
+ {
+ if ((_doResponse[option] == 0 && _stateIsDont(option))
+ || _requestedDont(option))
+ {
+ return ;
+ }
+ _setWantDont(option);
+ ++_doResponse[option];
+ _sendDont(option);
+ }
+
+
+ /**
+ * Sends a WILL.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendWill(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("WILL: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_WILL);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a WILL.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestWill(int option)
+ throws IOException
+ {
+ if ((_willResponse[option] == 0 && _stateIsWill(option))
+ || _requestedWill(option))
+ {
+ return ;
+ }
+ _setWantWill(option);
+ ++_doResponse[option];
+ _sendWill(option);
+ }
+
+ /**
+ * Sends a WONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendWont(int option)
+ throws IOException
+ {
+ if (debug || debugoptions)
+ {
+ System.err.println("WONT: " + TelnetOption.getOption(option));
+ }
+ _output_.write(_COMMAND_WONT);
+ _output_.write(option);
+
+ /* Code Section added for sending the negotiation ASAP (start)*/
+ _output_.flush();
+ /* Code Section added for sending the negotiation ASAP (end)*/
+ }
+
+ /**
+ * Requests a WONT.
+ *
+ * @param option - Option code.
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _requestWont(int option)
+ throws IOException
+ {
+ if ((_willResponse[option] == 0 && _stateIsWont(option))
+ || _requestedWont(option))
+ {
+ return ;
+ }
+ _setWantWont(option);
+ ++_doResponse[option];
+ _sendWont(option);
+ }
+
+ /**
+ * Sends a byte.
+ *
+ * @param b - byte to send
+ * @throws IOException - Exception in I/O.
+ **/
+ final synchronized void _sendByte(int b)
+ throws IOException
+ {
+ _output_.write(b);
+
+ /* Code Section added for supporting spystreams (start)*/
+ _spyWrite(b);
+ /* Code Section added for supporting spystreams (end)*/
+
+ }
+
+ /* Code Section added for supporting AYT (start)*/
+ /**
+ * Sends an Are You There sequence and waits for the result.
+ *
+ * @param timeout - Time to wait for a response (millis.)
+ * @throws IOException - Exception in I/O.
+ * @throws IllegalArgumentException - Illegal argument
+ * @throws InterruptedException - Interrupted during wait.
+ * @return true if AYT received a response, false otherwise
+ **/
+ final boolean _sendAYT(long timeout)
+ throws IOException, IllegalArgumentException, InterruptedException
+ {
+ boolean retValue = false;
+ synchronized (aytMonitor)
+ {
+ synchronized (this)
+ {
+ aytFlag = false;
+ _output_.write(_COMMAND_AYT);
+ _output_.flush();
+ }
+
+ try
+ {
+ aytMonitor.wait(timeout);
+ if (aytFlag == false)
+ {
+ retValue = false;
+ aytFlag = true;
+ }
+ else
+ {
+ retValue = true;
+ }
+ }
+ catch (IllegalMonitorStateException e)
+ {
+ System.err.println("Exception processing AYT:"
+ + e.getMessage());
+ }
+ }
+
+ return (retValue);
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+
+ /**
+ * Registers a new TelnetOptionHandler for this telnet to use.
+ *
+ * @param opthand - option handler to be registered.
+ * @throws InvalidTelnetOptionException - The option code is invalid.
+ **/
+ void addOptionHandler(TelnetOptionHandler opthand)
+ throws InvalidTelnetOptionException
+ {
+ int optcode = opthand.getOptionCode();
+ if (TelnetOption.isValidOption(optcode))
+ {
+ if (optionHandlers[optcode] == null)
+ {
+ optionHandlers[optcode] = opthand;
+ if (isConnected())
+ {
+ if (opthand.getInitLocal())
+ {
+ try
+ {
+ _requestWill(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+
+ if (opthand.getInitRemote())
+ {
+ try
+ {
+ _requestDo(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while initializing option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Already registered option", optcode));
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Invalid Option Code", optcode));
+ }
+ }
+
+ /**
+ * Unregisters a TelnetOptionHandler.
+ *
+ * @param optcode - Code of the option to be unregistered.
+ * @throws InvalidTelnetOptionException - The option code is invalid.
+ **/
+ void deleteOptionHandler(int optcode)
+ throws InvalidTelnetOptionException
+ {
+ if (TelnetOption.isValidOption(optcode))
+ {
+ if (optionHandlers[optcode] == null)
+ {
+ throw (new InvalidTelnetOptionException(
+ "Unregistered option", optcode));
+ }
+ else
+ {
+ TelnetOptionHandler opthand = optionHandlers[optcode];
+ optionHandlers[optcode] = null;
+
+ if (opthand.getWill())
+ {
+ try
+ {
+ _requestWont(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while turning off option: "
+ + e.getMessage());
+ }
+ }
+
+ if (opthand.getDo())
+ {
+ try
+ {
+ _requestDont(optcode);
+ }
+ catch (IOException e)
+ {
+ System.err.println(
+ "Exception while turning off option: "
+ + e.getMessage());
+ }
+ }
+ }
+ }
+ else
+ {
+ throw (new InvalidTelnetOptionException(
+ "Invalid Option Code", optcode));
+ }
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting spystreams (start)*/
+ /***
+ * Registers an OutputStream for spying what's going on in
+ * the Telnet session.
+ * <p>
+ * @param spystream - OutputStream on which session activity
+ * will be echoed.
+ ***/
+ void _registerSpyStream(OutputStream spystream)
+ {
+ spyStream = spystream;
+ }
+
+ /***
+ * Stops spying this Telnet.
+ * <p>
+ ***/
+ void _stopSpyStream()
+ {
+ spyStream = null;
+ }
+
+ /***
+ * Sends a read char on the spy stream.
+ * <p>
+ * @param ch - character read from the session
+ ***/
+ void _spyRead(int ch)
+ {
+ if (spyStream != null)
+ {
+ try
+ {
+ if (ch != '\r')
+ {
+ spyStream.write(ch);
+ if (ch == '\n')
+ {
+ spyStream.write('\r');
+ }
+ spyStream.flush();
+ }
+ }
+ catch (IOException e)
+ {
+ spyStream = null;
+ }
+ }
+ }
+
+ /***
+ * Sends a written char on the spy stream.
+ * <p>
+ * @param ch - character written to the session
+ ***/
+ void _spyWrite(int ch)
+ {
+ if (!(_stateIsDo(TelnetOption.ECHO)
+ && _requestedDo(TelnetOption.ECHO)))
+ {
+ if (spyStream != null)
+ {
+ try
+ {
+ spyStream.write(ch);
+ spyStream.flush();
+ }
+ catch (IOException e)
+ {
+ spyStream = null;
+ }
+ }
+ }
+ }
+ /* Code Section added for supporting spystreams (end)*/
+
+ /***
+ * Registers a notification handler to which will be sent
+ * notifications of received telnet option negotiation commands.
+ * <p>
+ * @param notifhand - TelnetNotificationHandler to be registered
+ ***/
+ public void registerNotifHandler(TelnetNotificationHandler notifhand)
+ {
+ __notifhand = notifhand;
+ }
+
+ /***
+ * Unregisters the current notification handler.
+ * <p>
+ ***/
+ public void unregisterNotifHandler()
+ {
+ __notifhand = null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/TelnetClient.java b/org/apache/commons/net/telnet/TelnetClient.java
new file mode 100644
index 0000000..3237779
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetClient.java
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.net.io.FromNetASCIIInputStream;
+import org.apache.commons.net.io.ToNetASCIIOutputStream;
+
+/***
+ * The TelnetClient class implements the simple network virtual
+ * terminal (NVT) for the Telnet protocol according to RFC 854. It
+ * does not implement any of the extra Telnet options because it
+ * is meant to be used within a Java program providing automated
+ * access to Telnet accessible resources.
+ * <p>
+ * The class can be used by first connecting to a server using the
+ * SocketClient
+ * {@link org.apache.commons.net.SocketClient#connect connect}
+ * method. Then an InputStream and OutputStream for sending and
+ * receiving data over the Telnet connection can be obtained by
+ * using the {@link #getInputStream getInputStream() } and
+ * {@link #getOutputStream getOutputStream() } methods.
+ * When you finish using the streams, you must call
+ * {@link #disconnect disconnect } rather than simply
+ * closing the streams.
+ * <p>
+ * <p>
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ ***/
+
+public class TelnetClient extends Telnet
+{
+ private InputStream __input;
+ private OutputStream __output;
+ protected boolean readerThread = true;
+
+ /***
+ * Default TelnetClient constructor.
+ ***/
+ public TelnetClient()
+ {
+ /* TERMINAL-TYPE option (start)*/
+ super ("VT100");
+ /* TERMINAL-TYPE option (end)*/
+ __input = null;
+ __output = null;
+ }
+
+ /* TERMINAL-TYPE option (start)*/
+ public TelnetClient(String termtype)
+ {
+ super (termtype);
+ __input = null;
+ __output = null;
+ }
+ /* TERMINAL-TYPE option (end)*/
+
+ void _flushOutputStream() throws IOException
+ {
+ _output_.flush();
+ }
+ void _closeOutputStream() throws IOException
+ {
+ _output_.close();
+ }
+
+ /***
+ * Handles special connection requirements.
+ * <p>
+ * @exception IOException If an error occurs during connection setup.
+ ***/
+ @Override
+ protected void _connectAction_() throws IOException
+ {
+ super._connectAction_();
+ InputStream input;
+ TelnetInputStream tmp;
+
+ if (FromNetASCIIInputStream.isConversionRequired())
+ input = new FromNetASCIIInputStream(_input_);
+ else
+ input = _input_;
+
+
+ tmp = new TelnetInputStream(input, this, readerThread);
+ if(readerThread)
+ {
+ tmp._start();
+ }
+ // __input CANNOT refer to the TelnetInputStream. We run into
+ // blocking problems when some classes use TelnetInputStream, so
+ // we wrap it with a BufferedInputStream which we know is safe.
+ // This blocking behavior requires further investigation, but right
+ // now it looks like classes like InputStreamReader are not implemented
+ // in a safe manner.
+ __input = new BufferedInputStream(tmp);
+ __output = new ToNetASCIIOutputStream(new TelnetOutputStream(this));
+ }
+
+ /***
+ * Disconnects the telnet session, closing the input and output streams
+ * as well as the socket. If you have references to the
+ * input and output streams of the telnet connection, you should not
+ * close them yourself, but rather call disconnect to properly close
+ * the connection.
+ ***/
+ @Override
+ public void disconnect() throws IOException
+ {
+ if (__input != null)
+ __input.close();
+ if (__output != null)
+ __output.close();
+ super.disconnect();
+ }
+
+ /***
+ * Returns the telnet connection output stream. You should not close the
+ * stream when you finish with it. Rather, you should call
+ * {@link #disconnect disconnect }.
+ * <p>
+ * @return The telnet connection output stream.
+ ***/
+ public OutputStream getOutputStream()
+ {
+ return __output;
+ }
+
+ /***
+ * Returns the telnet connection input stream. You should not close the
+ * stream when you finish with it. Rather, you should call
+ * {@link #disconnect disconnect }.
+ * <p>
+ * @return The telnet connection input stream.
+ ***/
+ public InputStream getInputStream()
+ {
+ return __input;
+ }
+
+ /***
+ * Returns the state of the option on the local side.
+ * <p>
+ * @param option - Option to be checked.
+ * <p>
+ * @return The state of the option on the local side.
+ ***/
+ public boolean getLocalOptionState(int option)
+ {
+ /* BUG (option active when not already acknowledged) (start)*/
+ return (_stateIsWill(option) && _requestedWill(option));
+ /* BUG (option active when not already acknowledged) (end)*/
+ }
+
+ /***
+ * Returns the state of the option on the remote side.
+ * <p>
+ * @param option - Option to be checked.
+ * <p>
+ * @return The state of the option on the remote side.
+ ***/
+ public boolean getRemoteOptionState(int option)
+ {
+ /* BUG (option active when not already acknowledged) (start)*/
+ return (_stateIsDo(option) && _requestedDo(option));
+ /* BUG (option active when not already acknowledged) (end)*/
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /* Code Section added for supporting AYT (start)*/
+
+ /***
+ * Sends an Are You There sequence and waits for the result.
+ * <p>
+ * @throws InterruptedException
+ * @throws IllegalArgumentException
+ * @throws IOException
+ * <p>
+ * @param timeout - Time to wait for a response (millis.)
+ * <p>
+ * @return true if AYT received a response, false otherwise
+ ***/
+ public boolean sendAYT(long timeout)
+ throws IOException, IllegalArgumentException, InterruptedException
+ {
+ return (_sendAYT(timeout));
+ }
+ /* Code Section added for supporting AYT (start)*/
+
+ /* open TelnetOptionHandler functionality (start)*/
+
+ /***
+ * Registers a new TelnetOptionHandler for this telnet client to use.
+ * <p>
+ * @param opthand - option handler to be registered.
+ * <p>
+ * @throws InvalidTelnetOptionException
+ ***/
+ @Override
+ public void addOptionHandler(TelnetOptionHandler opthand)
+ throws InvalidTelnetOptionException
+ {
+ super.addOptionHandler(opthand);
+ }
+ /* open TelnetOptionHandler functionality (end)*/
+
+ /***
+ * Unregisters a TelnetOptionHandler.
+ * <p>
+ * @param optcode - Code of the option to be unregistered.
+ * <p>
+ * @throws InvalidTelnetOptionException
+ ***/
+ @Override
+ public void deleteOptionHandler(int optcode)
+ throws InvalidTelnetOptionException
+ {
+ super.deleteOptionHandler(optcode);
+ }
+
+ /* Code Section added for supporting spystreams (start)*/
+ /***
+ * Registers an OutputStream for spying what's going on in
+ * the TelnetClient session.
+ * <p>
+ * @param spystream - OutputStream on which session activity
+ * will be echoed.
+ ***/
+ public void registerSpyStream(OutputStream spystream)
+ {
+ super._registerSpyStream(spystream);
+ }
+
+ /***
+ * Stops spying this TelnetClient.
+ * <p>
+ ***/
+ public void stopSpyStream()
+ {
+ super._stopSpyStream();
+ }
+ /* Code Section added for supporting spystreams (end)*/
+
+ /***
+ * Registers a notification handler to which will be sent
+ * notifications of received telnet option negotiation commands.
+ * <p>
+ * @param notifhand - TelnetNotificationHandler to be registered
+ ***/
+ @Override
+ public void registerNotifHandler(TelnetNotificationHandler notifhand)
+ {
+ super.registerNotifHandler(notifhand);
+ }
+
+ /***
+ * Unregisters the current notification handler.
+ * <p>
+ ***/
+ @Override
+ public void unregisterNotifHandler()
+ {
+ super.unregisterNotifHandler();
+ }
+
+ /***
+ * Sets the status of the reader thread.
+ * The reader thread status will apply to all subsequent connections
+ * <p>
+ * @param flag - true switches the reader thread on, false switches it off
+ ***/
+ public void setReaderThread(boolean flag)
+ {
+ readerThread = flag;
+ }
+
+ /***
+ * Gets the status of the reader thread.
+ * <p>
+ * @return true if the reader thread is on, false otherwise
+ ***/
+ public boolean getReaderThread()
+ {
+ return (readerThread);
+ }
+}
diff --git a/org/apache/commons/net/telnet/TelnetCommand.java b/org/apache/commons/net/telnet/TelnetCommand.java
new file mode 100644
index 0000000..725057b
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetCommand.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/**
+ * The TelnetCommand class cannot be instantiated and only serves as a
+ * storehouse for telnet command constants.
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.telnet.Telnet
+ * @see org.apache.commons.net.telnet.TelnetClient
+ */
+
+public final class TelnetCommand
+{
+ /*** The maximum value a command code can have. This value is 255. ***/
+ public static final int MAX_COMMAND_VALUE = 255;
+
+ /*** Interpret As Command code. Value is 255 according to RFC 854. ***/
+ public static final int IAC = 255;
+
+ /*** Don't use option code. Value is 254 according to RFC 854. ***/
+ public static final int DONT = 254;
+
+ /*** Request to use option code. Value is 253 according to RFC 854. ***/
+ public static final int DO = 253;
+
+ /*** Refuse to use option code. Value is 252 according to RFC 854. ***/
+ public static final int WONT = 252;
+
+ /*** Agree to use option code. Value is 251 according to RFC 854. ***/
+ public static final int WILL = 251;
+
+ /*** Start subnegotiation code. Value is 250 according to RFC 854. ***/
+ public static final int SB = 250;
+
+ /*** Go Ahead code. Value is 249 according to RFC 854. ***/
+ public static final int GA = 249;
+
+ /*** Erase Line code. Value is 248 according to RFC 854. ***/
+ public static final int EL = 248;
+
+ /*** Erase Character code. Value is 247 according to RFC 854. ***/
+ public static final int EC = 247;
+
+ /*** Are You There code. Value is 246 according to RFC 854. ***/
+ public static final int AYT = 246;
+
+ /*** Abort Output code. Value is 245 according to RFC 854. ***/
+ public static final int AO = 245;
+
+ /*** Interrupt Process code. Value is 244 according to RFC 854. ***/
+ public static final int IP = 244;
+
+ /*** Break code. Value is 243 according to RFC 854. ***/
+ public static final int BREAK = 243;
+
+ /*** Data mark code. Value is 242 according to RFC 854. ***/
+ public static final int DM = 242;
+
+ /*** No Operation code. Value is 241 according to RFC 854. ***/
+ public static final int NOP = 241;
+
+ /*** End subnegotiation code. Value is 240 according to RFC 854. ***/
+ public static final int SE = 240;
+
+ /*** End of record code. Value is 239. ***/
+ public static final int EOR = 239;
+
+ /*** Abort code. Value is 238. ***/
+ public static final int ABORT = 238;
+
+ /*** Suspend process code. Value is 237. ***/
+ public static final int SUSP = 237;
+
+ /*** End of file code. Value is 236. ***/
+ public static final int EOF = 236;
+
+ /*** Synchronize code. Value is 242. ***/
+ public static final int SYNCH = 242;
+
+ /*** String representations of commands. ***/
+ private static final String __commandString[] = {
+ "IAC", "DONT", "DO", "WONT", "WILL", "SB", "GA", "EL", "EC", "AYT",
+ "AO", "IP", "BRK", "DMARK", "NOP", "SE", "EOR", "ABORT", "SUSP", "EOF"
+ };
+
+ private static final int __FIRST_COMMAND = IAC;
+ private static final int __LAST_COMMAND = EOF;
+
+ /***
+ * Returns the string representation of the telnet protocol command
+ * corresponding to the given command code.
+ * <p>
+ * @param code The command code of the telnet protocol command.
+ * @return The string representation of the telnet protocol command.
+ ***/
+ public static final String getCommand(int code)
+ {
+ return __commandString[__FIRST_COMMAND - code];
+ }
+
+ /***
+ * Determines if a given command code is valid. Returns true if valid,
+ * false if not.
+ * <p>
+ * @param code The command code to test.
+ * @return True if the command code is valid, false if not.
+ **/
+ public static final boolean isValidCommand(int code)
+ {
+ return (code <= __FIRST_COMMAND && code >= __LAST_COMMAND);
+ }
+
+ // Cannot be instantiated
+ private TelnetCommand()
+ { }
+}
diff --git a/org/apache/commons/net/telnet/TelnetInputStream.java b/org/apache/commons/net/telnet/TelnetInputStream.java
new file mode 100644
index 0000000..8a83b68
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetInputStream.java
@@ -0,0 +1,630 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+
+/***
+ *
+ * <p>
+ *
+ * <p>
+ * <p>
+ * @author Daniel F. Savarese
+ * @author Bruno D'Avanzo
+ ***/
+
+
+final class TelnetInputStream extends BufferedInputStream implements Runnable
+{
+ static final int _STATE_DATA = 0, _STATE_IAC = 1, _STATE_WILL = 2,
+ _STATE_WONT = 3, _STATE_DO = 4, _STATE_DONT = 5,
+ _STATE_SB = 6, _STATE_SE = 7, _STATE_CR = 8, _STATE_IAC_SB = 9;
+
+ private boolean __hasReachedEOF, __isClosed;
+ private boolean __readIsWaiting;
+ private int __receiveState, __queueHead, __queueTail, __bytesAvailable;
+ private int[] __queue;
+ private TelnetClient __client;
+ private Thread __thread;
+ private IOException __ioException;
+
+ /* TERMINAL-TYPE option (start)*/
+ private int __suboption[] = new int[256];
+ private int __suboption_count = 0;
+ /* TERMINAL-TYPE option (end)*/
+
+ private boolean __threaded;
+
+ TelnetInputStream(InputStream input, TelnetClient client,
+ boolean readerThread)
+ {
+ super(input);
+ __client = client;
+ __receiveState = _STATE_DATA;
+ __isClosed = true;
+ __hasReachedEOF = false;
+ // Make it 2049, because when full, one slot will go unused, and we
+ // want a 2048 byte buffer just to have a round number (base 2 that is)
+ __queue = new int[2049];
+ __queueHead = 0;
+ __queueTail = 0;
+ __bytesAvailable = 0;
+ __ioException = null;
+ __readIsWaiting = false;
+ __threaded = false;
+ if(readerThread)
+ __thread = new Thread(this);
+ else
+ __thread = null;
+ }
+
+ TelnetInputStream(InputStream input, TelnetClient client) {
+ this(input, client, true);
+ }
+
+ void _start()
+ {
+ if(__thread == null)
+ return;
+
+ int priority;
+ __isClosed = false;
+ // TODO remove this
+ // Need to set a higher priority in case JVM does not use pre-emptive
+ // threads. This should prevent scheduler induced deadlock (rather than
+ // deadlock caused by a bug in this code).
+ priority = Thread.currentThread().getPriority() + 1;
+ if (priority > Thread.MAX_PRIORITY)
+ priority = Thread.MAX_PRIORITY;
+ __thread.setPriority(priority);
+ __thread.setDaemon(true);
+ __thread.start();
+ __threaded = true;
+ }
+
+
+ // synchronized(__client) critical sections are to protect against
+ // TelnetOutputStream writing through the telnet client at same time
+ // as a processDo/Will/etc. command invoked from TelnetInputStream
+ // tries to write.
+ private int __read(boolean mayBlock) throws IOException
+ {
+ int ch;
+
+_loop:
+ while (true)
+ {
+
+ // If there is no more data AND we were told not to block, just return -2. (More efficient than exception.)
+ if(!mayBlock && super.available() == 0)
+ return -2;
+
+ // Otherwise, exit only when we reach end of stream.
+ if ((ch = super.read()) < 0)
+ return -1;
+
+ ch = (ch & 0xff);
+
+ /* Code Section added for supporting AYT (start)*/
+ synchronized (__client)
+ {
+ __client._processAYTResponse();
+ }
+ /* Code Section added for supporting AYT (end)*/
+
+ /* Code Section added for supporting spystreams (start)*/
+ __client._spyRead(ch);
+ /* Code Section added for supporting spystreams (end)*/
+
+_mainSwitch:
+ switch (__receiveState)
+ {
+
+ case _STATE_CR:
+ if (ch == '\0')
+ {
+ // Strip null
+ continue;
+ }
+ // How do we handle newline after cr?
+ // else if (ch == '\n' && _requestedDont(TelnetOption.ECHO) &&
+
+ // Handle as normal data by falling through to _STATE_DATA case
+
+ case _STATE_DATA:
+ if (ch == TelnetCommand.IAC)
+ {
+ __receiveState = _STATE_IAC;
+ continue;
+ }
+
+
+ if (ch == '\r')
+ {
+ synchronized (__client)
+ {
+ if (__client._requestedDont(TelnetOption.BINARY))
+ __receiveState = _STATE_CR;
+ else
+ __receiveState = _STATE_DATA;
+ }
+ }
+ else
+ __receiveState = _STATE_DATA;
+ break;
+
+ case _STATE_IAC:
+ switch (ch)
+ {
+ case TelnetCommand.WILL:
+ __receiveState = _STATE_WILL;
+ continue;
+ case TelnetCommand.WONT:
+ __receiveState = _STATE_WONT;
+ continue;
+ case TelnetCommand.DO:
+ __receiveState = _STATE_DO;
+ continue;
+ case TelnetCommand.DONT:
+ __receiveState = _STATE_DONT;
+ continue;
+ /* TERMINAL-TYPE option (start)*/
+ case TelnetCommand.SB:
+ __suboption_count = 0;
+ __receiveState = _STATE_SB;
+ continue;
+ /* TERMINAL-TYPE option (end)*/
+ case TelnetCommand.IAC:
+ __receiveState = _STATE_DATA;
+ break;
+ default:
+ break;
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_WILL:
+ synchronized (__client)
+ {
+ __client._processWill(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_WONT:
+ synchronized (__client)
+ {
+ __client._processWont(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_DO:
+ synchronized (__client)
+ {
+ __client._processDo(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ case _STATE_DONT:
+ synchronized (__client)
+ {
+ __client._processDont(ch);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ /* TERMINAL-TYPE option (start)*/
+ case _STATE_SB:
+ switch (ch)
+ {
+ case TelnetCommand.IAC:
+ __receiveState = _STATE_IAC_SB;
+ continue;
+ default:
+ // store suboption char
+ __suboption[__suboption_count++] = ch;
+ break;
+ }
+ __receiveState = _STATE_SB;
+ continue;
+ case _STATE_IAC_SB:
+ switch (ch)
+ {
+ case TelnetCommand.SE:
+ synchronized (__client)
+ {
+ __client._processSuboption(__suboption, __suboption_count);
+ __client._flushOutputStream();
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ default:
+ __receiveState = _STATE_SB;
+ break;
+ }
+ __receiveState = _STATE_DATA;
+ continue;
+ /* TERMINAL-TYPE option (end)*/
+ }
+
+ break;
+ }
+
+ return ch;
+ }
+
+ // synchronized(__client) critical sections are to protect against
+ // TelnetOutputStream writing through the telnet client at same time
+ // as a processDo/Will/etc. command invoked from TelnetInputStream
+ // tries to write.
+ private void __processChar(int ch) throws InterruptedException
+ {
+ // Critical section because we're altering __bytesAvailable,
+ // __queueTail, and the contents of _queue.
+ synchronized (__queue)
+ {
+ while (__bytesAvailable >= __queue.length - 1)
+ {
+ // The queue is full. We need to wait before adding any more data to it. Hopefully the stream owner
+ // will consume some data soon!
+ if(__threaded)
+ {
+ __queue.notify();
+ try
+ {
+ __queue.wait();
+ }
+ catch (InterruptedException e)
+ {
+ throw e;
+ }
+ }
+ else
+ {
+ // We've been asked to add another character to the queue, but it is already full and there's
+ // no other thread to drain it. This should not have happened!
+ throw new IllegalStateException("Queue is full! Cannot process another character.");
+ }
+ }
+
+ // Need to do this in case we're not full, but block on a read
+ if (__readIsWaiting && __threaded)
+ {
+ __queue.notify();
+ }
+
+ __queue[__queueTail] = ch;
+ ++__bytesAvailable;
+
+ if (++__queueTail >= __queue.length)
+ __queueTail = 0;
+ }
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ // Critical section because we're altering __bytesAvailable,
+ // __queueHead, and the contents of _queue in addition to
+ // testing value of __hasReachedEOF.
+ synchronized (__queue)
+ {
+
+ while (true)
+ {
+ if (__ioException != null)
+ {
+ IOException e;
+ e = __ioException;
+ __ioException = null;
+ throw e;
+ }
+
+ if (__bytesAvailable == 0)
+ {
+ // Return -1 if at end of file
+ if (__hasReachedEOF)
+ return -1;
+
+ // Otherwise, we have to wait for queue to get something
+ if(__threaded)
+ {
+ __queue.notify();
+ try
+ {
+ __readIsWaiting = true;
+ __queue.wait();
+ __readIsWaiting = false;
+ }
+ catch (InterruptedException e)
+ {
+ throw new InterruptedIOException("Fatal thread interruption during read.");
+ }
+ }
+ else
+ {
+ //__alreadyread = false;
+ __readIsWaiting = true;
+ int ch;
+ boolean mayBlock = true; // block on the first read only
+
+ do
+ {
+ try
+ {
+ if ((ch = __read(mayBlock)) < 0)
+ if(ch != -2)
+ return (ch);
+ }
+ catch (InterruptedIOException e)
+ {
+ synchronized (__queue)
+ {
+ __ioException = e;
+ __queue.notifyAll();
+ try
+ {
+ __queue.wait(100);
+ }
+ catch (InterruptedException interrupted)
+ {
+ }
+ }
+ return (-1);
+ }
+
+
+ try
+ {
+ if(ch != -2)
+ {
+ __processChar(ch);
+ }
+ }
+ catch (InterruptedException e)
+ {
+ if (__isClosed)
+ return (-1);
+ }
+
+ // Reads should not block on subsequent iterations. Potentially, this could happen if the
+ // remaining buffered socket data consists entirely of Telnet command sequence and no "user" data.
+ mayBlock = false;
+
+ }
+ // Continue reading as long as there is data available and the queue is not full.
+ while (super.available() > 0 && __bytesAvailable < __queue.length - 1);
+
+ __readIsWaiting = false;
+ }
+ continue;
+ }
+ else
+ {
+ int ch;
+
+ ch = __queue[__queueHead];
+
+ if (++__queueHead >= __queue.length)
+ __queueHead = 0;
+
+ --__bytesAvailable;
+
+ // Need to explicitly notify() so available() works properly
+ if(__bytesAvailable == 0 && __threaded) {
+ __queue.notify();
+ }
+
+ return ch;
+ }
+ }
+ }
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and
+ * returns the number of bytes read. Returns -1 if the end of the
+ * stream has been reached.
+ * <p>
+ * @param buffer The byte array in which to store the data.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the message has been reached.
+ * @exception IOException If an error occurs in reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[]) throws IOException
+ {
+ return read(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Reads the next number of bytes from the stream into an array and returns
+ * the number of bytes read. Returns -1 if the end of the
+ * message has been reached. The characters are stored in the array
+ * starting from the given offset and up to the length specified.
+ * <p>
+ * @param buffer The byte array in which to store the data.
+ * @param offset The offset into the array at which to start storing data.
+ * @param length The number of bytes to read.
+ * @return The number of bytes read. Returns -1 if the
+ * end of the stream has been reached.
+ * @exception IOException If an error occurs while reading the underlying
+ * stream.
+ ***/
+ @Override
+ public int read(byte buffer[], int offset, int length) throws IOException
+ {
+ int ch, off;
+
+ if (length < 1)
+ return 0;
+
+ // Critical section because run() may change __bytesAvailable
+ synchronized (__queue)
+ {
+ if (length > __bytesAvailable)
+ length = __bytesAvailable;
+ }
+
+ if ((ch = read()) == -1)
+ return -1;
+
+ off = offset;
+
+ do
+ {
+ buffer[offset++] = (byte)ch;
+ }
+ while (--length > 0 && (ch = read()) != -1);
+
+ //__client._spyRead(buffer, off, offset - off);
+ return (offset - off);
+ }
+
+
+ /*** Returns false. Mark is not supported. ***/
+ @Override
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ // Critical section because run() may change __bytesAvailable
+ synchronized (__queue)
+ {
+ return __bytesAvailable;
+ }
+ }
+
+
+ // Cannot be synchronized. Will cause deadlock if run() is blocked
+ // in read because BufferedInputStream read() is synchronized.
+ @Override
+ public void close() throws IOException
+ {
+ // Completely disregard the fact thread may still be running.
+ // We can't afford to block on this close by waiting for
+ // thread to terminate because few if any JVM's will actually
+ // interrupt a system read() from the interrupt() method.
+ super.close();
+
+ synchronized (__queue)
+ {
+ __hasReachedEOF = true;
+ __isClosed = true;
+
+ if (__thread != null && __thread.isAlive())
+ {
+ __thread.interrupt();
+ }
+
+ __queue.notifyAll();
+ }
+
+ __threaded = false;
+ }
+
+ public void run()
+ {
+ int ch;
+
+ try
+ {
+_outerLoop:
+ while (!__isClosed)
+ {
+ try
+ {
+ if ((ch = __read(true)) < 0)
+ break;
+ }
+ catch (InterruptedIOException e)
+ {
+ synchronized (__queue)
+ {
+ __ioException = e;
+ __queue.notifyAll();
+ try
+ {
+ __queue.wait(100);
+ }
+ catch (InterruptedException interrupted)
+ {
+ if (__isClosed)
+ break _outerLoop;
+ }
+ continue;
+ }
+ } catch(RuntimeException re) {
+ // We treat any runtime exceptions as though the
+ // stream has been closed. We close the
+ // underlying stream just to be sure.
+ super.close();
+ // Breaking the loop has the effect of setting
+ // the state to closed at the end of the method.
+ break _outerLoop;
+ }
+
+ try
+ {
+ __processChar(ch);
+ }
+ catch (InterruptedException e)
+ {
+ if (__isClosed)
+ break _outerLoop;
+ }
+ }
+ }
+ catch (IOException ioe)
+ {
+ synchronized (__queue)
+ {
+ __ioException = ioe;
+ }
+ }
+
+ synchronized (__queue)
+ {
+ __isClosed = true; // Possibly redundant
+ __hasReachedEOF = true;
+ __queue.notify();
+ }
+
+ __threaded = false;
+ }
+}
+
+/* Emacs configuration
+ * Local variables: **
+ * mode: java **
+ * c-basic-offset: 4 **
+ * indent-tabs-mode: nil **
+ * End: **
+ */
diff --git a/org/apache/commons/net/telnet/TelnetNotificationHandler.java b/org/apache/commons/net/telnet/TelnetNotificationHandler.java
new file mode 100644
index 0000000..d509021
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetNotificationHandler.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The TelnetNotificationHandler interface can be used to handle
+ * notification of options negotiation commands received on a telnet
+ * session.
+ * <p>
+ * The user can implement this interface and register a
+ * TelnetNotificationHandler by using the registerNotificationHandler()
+ * of TelnetClient to be notified of option negotiation commands.
+ * <p>
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+
+public interface TelnetNotificationHandler
+{
+ /***
+ * The remote party sent a DO command.
+ ***/
+ public static final int RECEIVED_DO = 1;
+
+ /***
+ * The remote party sent a DONT command.
+ ***/
+ public static final int RECEIVED_DONT = 2;
+
+ /***
+ * The remote party sent a WILL command.
+ ***/
+ public static final int RECEIVED_WILL = 3;
+
+ /***
+ * The remote party sent a WONT command.
+ ***/
+ public static final int RECEIVED_WONT = 4;
+
+ /***
+ * Callback method called when TelnetClient receives an option
+ * negotiation command.
+ * <p>
+ * @param negotiation_code - type of negotiation command received
+ * (RECEIVED_DO, RECEIVED_DONT, RECEIVED_WILL, RECEIVED_WONT)
+ * <p>
+ * @param option_code - code of the option negotiated
+ * <p>
+ ***/
+ public void receivedNegotiation(int negotiation_code, int option_code);
+}
diff --git a/org/apache/commons/net/telnet/TelnetOption.java b/org/apache/commons/net/telnet/TelnetOption.java
new file mode 100644
index 0000000..77799b6
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetOption.java
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The TelnetOption class cannot be instantiated and only serves as a
+ * storehouse for telnet option constants.
+ * <p>
+ * Details regarding Telnet option specification can be found in RFC 855.
+ * <p>
+ * <p>
+ * @author Daniel F. Savarese
+ * @see org.apache.commons.net.telnet.Telnet
+ * @see org.apache.commons.net.telnet.TelnetClient
+ ***/
+
+public class TelnetOption
+{
+ /*** The maximum value an option code can have. This value is 255. ***/
+ public static final int MAX_OPTION_VALUE = 255;
+
+ public static final int BINARY = 0;
+
+ public static final int ECHO = 1;
+
+ public static final int PREPARE_TO_RECONNECT = 2;
+
+ public static final int SUPPRESS_GO_AHEAD = 3;
+
+ public static final int APPROXIMATE_MESSAGE_SIZE = 4;
+
+ public static final int STATUS = 5;
+
+ public static final int TIMING_MARK = 6;
+
+ public static final int REMOTE_CONTROLLED_TRANSMISSION = 7;
+
+ public static final int NEGOTIATE_OUTPUT_LINE_WIDTH = 8;
+
+ public static final int NEGOTIATE_OUTPUT_PAGE_SIZE = 9;
+
+ public static final int NEGOTIATE_CARRIAGE_RETURN = 10;
+
+ public static final int NEGOTIATE_HORIZONTAL_TAB_STOP = 11;
+
+ public static final int NEGOTIATE_HORIZONTAL_TAB = 12;
+
+ public static final int NEGOTIATE_FORMFEED = 13;
+
+ public static final int NEGOTIATE_VERTICAL_TAB_STOP = 14;
+
+ public static final int NEGOTIATE_VERTICAL_TAB = 15;
+
+ public static final int NEGOTIATE_LINEFEED = 16;
+
+ public static final int EXTENDED_ASCII = 17;
+
+ public static final int FORCE_LOGOUT = 18;
+
+ public static final int BYTE_MACRO = 19;
+
+ public static final int DATA_ENTRY_TERMINAL = 20;
+
+ public static final int SUPDUP = 21;
+
+ public static final int SUPDUP_OUTPUT = 22;
+
+ public static final int SEND_LOCATION = 23;
+
+ public static final int TERMINAL_TYPE = 24;
+
+ public static final int END_OF_RECORD = 25;
+
+ public static final int TACACS_USER_IDENTIFICATION = 26;
+
+ public static final int OUTPUT_MARKING = 27;
+
+ public static final int TERMINAL_LOCATION_NUMBER = 28;
+
+ public static final int REGIME_3270 = 29;
+
+ public static final int X3_PAD = 30;
+
+ public static final int WINDOW_SIZE = 31;
+
+ public static final int TERMINAL_SPEED = 32;
+
+ public static final int REMOTE_FLOW_CONTROL = 33;
+
+ public static final int LINEMODE = 34;
+
+ public static final int X_DISPLAY_LOCATION = 35;
+
+ public static final int OLD_ENVIRONMENT_VARIABLES = 36;
+
+ public static final int AUTHENTICATION = 37;
+
+ public static final int ENCRYPTION = 38;
+
+ public static final int NEW_ENVIRONMENT_VARIABLES = 39;
+
+ public static final int EXTENDED_OPTIONS_LIST = 255;
+
+ private static final int __FIRST_OPTION = BINARY;
+ private static final int __LAST_OPTION = EXTENDED_OPTIONS_LIST;
+
+ private static final String __optionString[] = {
+ "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS",
+ "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD",
+ "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT",
+ "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+ "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID",
+ "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED",
+ "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
+ "ENCRYPT", "NEW-ENVIRON", "TN3270E", "XAUTH", "CHARSET", "RSP",
+ "Com Port Control", "Suppress Local Echo", "Start TLS",
+ "KERMIT", "SEND-URL", "FORWARD_X", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "TELOPT PRAGMA LOGON", "TELOPT SSPI LOGON",
+ "TELOPT PRAGMA HEARTBEAT", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "", "", "",
+ "Extended-Options-List"
+ };
+
+
+ /***
+ * Returns the string representation of the telnet protocol option
+ * corresponding to the given option code.
+ * <p>
+ * @param code The option code of the telnet protocol option
+ * @return The string representation of the telnet protocol option.
+ ***/
+ public static final String getOption(int code)
+ {
+ if(__optionString[code].length() == 0)
+ {
+ return "UNASSIGNED";
+ }
+ else
+ {
+ return __optionString[code];
+ }
+ }
+
+
+ /***
+ * Determines if a given option code is valid. Returns true if valid,
+ * false if not.
+ * <p>
+ * @param code The option code to test.
+ * @return True if the option code is valid, false if not.
+ **/
+ public static final boolean isValidOption(int code)
+ {
+ return (code <= __LAST_OPTION);
+ }
+
+ // Cannot be instantiated
+ private TelnetOption()
+ { }
+}
diff --git a/org/apache/commons/net/telnet/TelnetOptionHandler.java b/org/apache/commons/net/telnet/TelnetOptionHandler.java
new file mode 100644
index 0000000..52486ba
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetOptionHandler.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * The TelnetOptionHandler class is the base class to be used
+ * for implementing handlers for telnet options.
+ * <p>
+ * TelnetOptionHandler implements basic option handling
+ * functionality and defines abstract methods that must be
+ * implemented to define subnegotiation behaviour.
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+public abstract class TelnetOptionHandler
+{
+ /***
+ * Option code
+ ***/
+ private int optionCode = -1;
+
+ /***
+ * true if the option should be activated on the local side
+ ***/
+ private boolean initialLocal = false;
+
+ /***
+ * true if the option should be activated on the remote side
+ ***/
+ private boolean initialRemote = false;
+
+ /***
+ * true if the option should be accepted on the local side
+ ***/
+ private boolean acceptLocal = false;
+
+ /***
+ * true if the option should be accepted on the remote side
+ ***/
+ private boolean acceptRemote = false;
+
+ /***
+ * true if the option is active on the local side
+ ***/
+ private boolean doFlag = false;
+
+ /***
+ * true if the option is active on the remote side
+ ***/
+ private boolean willFlag = false;
+
+ /***
+ * Constructor for the TelnetOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ * <p>
+ * @param optcode - Option code.
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public TelnetOptionHandler(int optcode,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote)
+ {
+ optionCode = optcode;
+ initialLocal = initlocal;
+ initialRemote = initremote;
+ acceptLocal = acceptlocal;
+ acceptRemote = acceptremote;
+ }
+
+
+ /***
+ * Returns the option code for this option.
+ * <p>
+ * @return Option code.
+ ***/
+ public int getOptionCode()
+ {
+ return (optionCode);
+ }
+
+ /***
+ * Returns a boolean indicating whether to accept a DO
+ * request coming from the other end.
+ * <p>
+ * @return true if a DO request shall be accepted.
+ ***/
+ public boolean getAcceptLocal()
+ {
+ return (acceptLocal);
+ }
+
+ /***
+ * Returns a boolean indicating whether to accept a WILL
+ * request coming from the other end.
+ * <p>
+ * @return true if a WILL request shall be accepted.
+ ***/
+ public boolean getAcceptRemote()
+ {
+ return (acceptRemote);
+ }
+
+ /***
+ * Set behaviour of the option for DO requests coming from
+ * the other end.
+ * <p>
+ * @param accept - if true, subsequent DO requests will be accepted.
+ ***/
+ public void setAcceptLocal(boolean accept)
+ {
+ acceptLocal = accept;
+ }
+
+ /***
+ * Set behaviour of the option for WILL requests coming from
+ * the other end.
+ * <p>
+ * @param accept - if true, subsequent WILL requests will be accepted.
+ ***/
+ public void setAcceptRemote(boolean accept)
+ {
+ acceptRemote = accept;
+ }
+
+ /***
+ * Returns a boolean indicating whether to send a WILL request
+ * to the other end upon connection.
+ * <p>
+ * @return true if a WILL request shall be sent upon connection.
+ ***/
+ public boolean getInitLocal()
+ {
+ return (initialLocal);
+ }
+
+ /***
+ * Returns a boolean indicating whether to send a DO request
+ * to the other end upon connection.
+ * <p>
+ * @return true if a DO request shall be sent upon connection.
+ ***/
+ public boolean getInitRemote()
+ {
+ return (initialRemote);
+ }
+
+ /***
+ * Tells this option whether to send a WILL request upon connection.
+ * <p>
+ * @param init - if true, a WILL request will be sent upon subsequent
+ * connections.
+ ***/
+ public void setInitLocal(boolean init)
+ {
+ initialLocal = init;
+ }
+
+ /***
+ * Tells this option whether to send a DO request upon connection.
+ * <p>
+ * @param init - if true, a DO request will be sent upon subsequent
+ * connections.
+ ***/
+ public void setInitRemote(boolean init)
+ {
+ initialRemote = init;
+ }
+
+ /***
+ * Method called upon reception of a subnegotiation for this option
+ * coming from the other end.
+ * Must be implemented by the actual TelnetOptionHandler to specify
+ * which response must be sent for the subnegotiation request.
+ * <p>
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ * <p>
+ * @return response to be sent to the subnegotiation sequence. TelnetClient
+ * will add IAC SB & IAC SE. null means no response
+ ***/
+ public abstract int[] answerSubnegotiation(int suboptionData[],
+ int suboptionLength);
+
+ /***
+ * This method is invoked whenever this option is acknowledged active on
+ * the local end (TelnetClient sent a WILL, remote side sent a DO).
+ * The method is used to specify a subnegotiation sequence that will be
+ * sent by TelnetClient when the option is activated.
+ * <p>
+ * @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
+ * will add IAC SB & IAC SE. null means no subnegotiation.
+ ***/
+ public abstract int[] startSubnegotiationLocal();
+
+ /***
+ * This method is invoked whenever this option is acknowledged active on
+ * the remote end (TelnetClient sent a DO, remote side sent a WILL).
+ * The method is used to specify a subnegotiation sequence that will be
+ * sent by TelnetClient when the option is activated.
+ * <p>
+ * @return subnegotiation sequence to be sent by TelnetClient. TelnetClient
+ * will add IAC SB & IAC SE. null means no subnegotiation.
+ ***/
+ public abstract int[] startSubnegotiationRemote();
+
+ /***
+ * Returns a boolean indicating whether a WILL request sent to the other
+ * side has been acknowledged.
+ * <p>
+ * @return true if a WILL sent to the other side has been acknowledged.
+ ***/
+ boolean getWill()
+ {
+ return willFlag;
+ }
+
+ /***
+ * Tells this option whether a WILL request sent to the other
+ * side has been acknowledged (invoked by TelnetClient).
+ * <p>
+ * @param state - if true, a WILL request has been acknowledged.
+ ***/
+ void setWill(boolean state)
+ {
+ willFlag = state;
+ }
+
+ /***
+ * Returns a boolean indicating whether a DO request sent to the other
+ * side has been acknowledged.
+ * <p>
+ * @return true if a DO sent to the other side has been acknowledged.
+ ***/
+ boolean getDo()
+ {
+ return doFlag;
+ }
+
+
+ /***
+ * Tells this option whether a DO request sent to the other
+ * side has been acknowledged (invoked by TelnetClient).
+ * <p>
+ * @param state - if true, a DO request has been acknowledged.
+ ***/
+ void setDo(boolean state)
+ {
+ doFlag = state;
+ }
+}
diff --git a/org/apache/commons/net/telnet/TelnetOutputStream.java b/org/apache/commons/net/telnet/TelnetOutputStream.java
new file mode 100644
index 0000000..fd796d1
--- /dev/null
+++ b/org/apache/commons/net/telnet/TelnetOutputStream.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/***
+ *
+ * <p>
+ *
+ * <p>
+ * <p>
+ * @author Daniel F. Savarese
+ ***/
+
+
+final class TelnetOutputStream extends OutputStream
+{
+ private TelnetClient __client;
+ private boolean __convertCRtoCRLF = true;
+ private boolean __lastWasCR = false;
+
+ TelnetOutputStream(TelnetClient client)
+ {
+ __client = client;
+ }
+
+
+ /***
+ * Writes a byte to the stream.
+ * <p>
+ * @param ch The byte to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(int ch) throws IOException
+ {
+
+ synchronized (__client)
+ {
+ ch &= 0xff;
+
+ if (__client._requestedWont(TelnetOption.BINARY))
+ {
+ if (__lastWasCR)
+ {
+ if (__convertCRtoCRLF)
+ {
+ __client._sendByte('\n');
+ if (ch == '\n')
+ {
+ __lastWasCR = false;
+ return ;
+ }
+ }
+ else if (ch != '\n')
+ __client._sendByte('\0');
+ }
+
+ __lastWasCR = false;
+
+ switch (ch)
+ {
+ case '\r':
+ __client._sendByte('\r');
+ __lastWasCR = true;
+ break;
+ case TelnetCommand.IAC:
+ __client._sendByte(TelnetCommand.IAC);
+ __client._sendByte(TelnetCommand.IAC);
+ break;
+ default:
+ __client._sendByte(ch);
+ break;
+ }
+ }
+ else if (ch == TelnetCommand.IAC)
+ {
+ __client._sendByte(ch);
+ __client._sendByte(TelnetCommand.IAC);
+ }
+ else
+ __client._sendByte(ch);
+ }
+ }
+
+
+ /***
+ * Writes a byte array to the stream.
+ * <p>
+ * @param buffer The byte array to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(byte buffer[]) throws IOException
+ {
+ write(buffer, 0, buffer.length);
+ }
+
+
+ /***
+ * Writes a number of bytes from a byte array to the stream starting from
+ * a given offset.
+ * <p>
+ * @param buffer The byte array to write.
+ * @param offset The offset into the array at which to start copying data.
+ * @param length The number of bytes to write.
+ * @exception IOException If an error occurs while writing to the underlying
+ * stream.
+ ***/
+ @Override
+ public void write(byte buffer[], int offset, int length) throws IOException
+ {
+ synchronized (__client)
+ {
+ while (length-- > 0)
+ write(buffer[offset++]);
+ }
+ }
+
+ /*** Flushes the stream. ***/
+ @Override
+ public void flush() throws IOException
+ {
+ __client._flushOutputStream();
+ }
+
+ /*** Closes the stream. ***/
+ @Override
+ public void close() throws IOException
+ {
+ __client._closeOutputStream();
+ }
+}
diff --git a/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java b/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
new file mode 100644
index 0000000..0cbe0c0
--- /dev/null
+++ b/org/apache/commons/net/telnet/TerminalTypeOptionHandler.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet terminal type option RFC 1091.
+ * <p>
+ * @author Bruno D'Avanzo
+ ***/
+public class TerminalTypeOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Terminal type
+ ***/
+ private String termType = null;
+
+ /***
+ * Terminal type option
+ ***/
+ protected static final int TERMINAL_TYPE = 24;
+
+ /***
+ * Send (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_SEND = 1;
+
+ /***
+ * Is (for subnegotiation)
+ ***/
+ protected static final int TERMINAL_TYPE_IS = 0;
+
+ /***
+ * Constructor for the TerminalTypeOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ * <p>
+ * @param termtype - terminal type that will be negotiated.
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public TerminalTypeOptionHandler(String termtype,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote)
+ {
+ super(TelnetOption.TERMINAL_TYPE, initlocal, initremote,
+ acceptlocal, acceptremote);
+ termType = termtype;
+ }
+
+ /***
+ * Constructor for the TerminalTypeOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ * <p>
+ * @param termtype - terminal type that will be negotiated.
+ ***/
+ public TerminalTypeOptionHandler(String termtype)
+ {
+ super(TelnetOption.TERMINAL_TYPE, false, false, false, false);
+ termType = termtype;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ * <p>
+ * @return terminal type information
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ if ((suboptionData != null) && (suboptionLength > 1)
+ && (termType != null))
+ {
+ if ((suboptionData[0] == TERMINAL_TYPE)
+ && (suboptionData[1] == TERMINAL_TYPE_SEND))
+ {
+ int response[] = new int[termType.length() + 2];
+
+ response[0] = TERMINAL_TYPE;
+ response[1] = TERMINAL_TYPE_IS;
+
+ for (int ii = 0; ii < termType.length(); ii++)
+ {
+ response[ii + 2] = termType.charAt(ii);
+ }
+
+ return response;
+ }
+ }
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}
diff --git a/org/apache/commons/net/telnet/WindowSizeOptionHandler.java b/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
new file mode 100644
index 0000000..34bb46f
--- /dev/null
+++ b/org/apache/commons/net/telnet/WindowSizeOptionHandler.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.net.telnet;
+
+/***
+ * Implements the telnet window size option RFC 1073.
+ * <p>
+ * @author Yuval Kashtan
+ * @version $Id: WindowSizeOptionHandler.java 658520 2008-05-21 01:14:11Z sebb $
+ * @since 2.0
+ ***/
+public class WindowSizeOptionHandler extends TelnetOptionHandler
+{
+ /***
+ * Horizontal Size
+ ***/
+ private int m_nWidth = 80;
+
+ /***
+ * Vertical Size
+ ***/
+ private int m_nHeight = 24;
+
+ /***
+ * Window size option
+ ***/
+ protected static final int WINDOW_SIZE = 31;
+
+ /***
+ * Constructor for the WindowSizeOptionHandler. Allows defining desired
+ * initial setting for local/remote activation of this option and
+ * behaviour in case a local/remote activation request for this
+ * option is received.
+ * <p>
+ * @param nWidth - Window width.
+ * @param nHeight - Window Height
+ * @param initlocal - if set to true, a WILL is sent upon connection.
+ * @param initremote - if set to true, a DO is sent upon connection.
+ * @param acceptlocal - if set to true, any DO request is accepted.
+ * @param acceptremote - if set to true, any WILL request is accepted.
+ ***/
+ public WindowSizeOptionHandler(
+ int nWidth,
+ int nHeight,
+ boolean initlocal,
+ boolean initremote,
+ boolean acceptlocal,
+ boolean acceptremote
+ ) {
+ super (
+ TelnetOption.WINDOW_SIZE,
+ initlocal,
+ initremote,
+ acceptlocal,
+ acceptremote
+ );
+
+ m_nWidth = nWidth;
+ m_nHeight = nHeight;
+ }
+
+ /***
+ * Constructor for the WindowSizeOptionHandler. Initial and accept
+ * behaviour flags are set to false
+ * <p>
+ * @param nWidth - Window width.
+ * @param nHeight - Window Height
+ ***/
+ public WindowSizeOptionHandler(
+ int nWidth,
+ int nHeight
+ ) {
+ super (
+ TelnetOption.WINDOW_SIZE,
+ false,
+ false,
+ false,
+ false
+ );
+
+ m_nWidth = nWidth;
+ m_nHeight = nHeight;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @param suboptionData - the sequence received, whithout IAC SB & IAC SE
+ * @param suboptionLength - the length of data in suboption_data
+ * <p>
+ * @return terminal type information
+ ***/
+ @Override
+ public int[] answerSubnegotiation(int suboptionData[], int suboptionLength)
+ {
+ return null;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * This will send the client Height and Width to the server.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationLocal()
+ {
+ int nCompoundWindowSize = m_nWidth * 0x10000 + m_nHeight;
+ int nResponseSize = 5;
+ int nIndex;
+ int nShift;
+ int nTurnedOnBits;
+
+ if ((m_nWidth % 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ if ((m_nWidth / 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ if ((m_nHeight % 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ if ((m_nHeight / 0x100) == 0xFF) {
+ nResponseSize += 1;
+ }
+
+ //
+ // allocate response array
+ //
+ int response[] = new int[nResponseSize];
+
+ //
+ // Build response array.
+ // ---------------------
+ // 1. put option name.
+ // 2. loop through Window size and fill the values,
+ // 3. duplicate 'ff' if needed.
+ //
+
+ response[0] = WINDOW_SIZE; // 1 //
+
+ for ( // 2 //
+ nIndex=1, nShift = 24;
+ nIndex < nResponseSize;
+ nIndex++, nShift -=8
+ ) {
+ nTurnedOnBits = 0xFF;
+ nTurnedOnBits <<= nShift;
+ response[nIndex] = (nCompoundWindowSize & nTurnedOnBits) >>> nShift;
+
+ if (response[nIndex] == 0xff) { // 3 //
+ nIndex++;
+ response[nIndex] = 0xff;
+ }
+ }
+
+ return response;
+ }
+
+ /***
+ * Implements the abstract method of TelnetOptionHandler.
+ * <p>
+ * @return always null (no response to subnegotiation)
+ ***/
+ @Override
+ public int[] startSubnegotiationRemote()
+ {
+ return null;
+ }
+}