0

I'm trying to write a simple telnet client in Swing (similar to Putty). I have the base functionality working, but I'm getting funny escape characters, like "Z [H [J". I'm also not getting a screen worth of contents like putty does.


This is what my application displays:


FreeBSD/i386 (m-net.arbornet.org) (pts/15)

login:newuser Password:

Z[H[J Welcome to M-Net America's First Public-Access UNIX System!

Press any key to Continue.


When I connect using putty, after entering my login and password, the screen clears the following displays. Any thoughts on how I can achieve the same?


FreeBSD/i386 (m-net.arbornet.org) (pts/6)

login: newuser Password: Welcome to M-Net, America's First Public-Acess UNIX System!

M-Net is a free-access community service provided by Arbornet, Inc., a non-profit Ann Arbor corporation. Use of M-Net is absolutely free--enjoy! If you decide you like M-Net enough to be a supporter later on (M-Net is sustained by user contributions), type "support" any time after you log in to the system. Thank you for calling M-Net, and welcome!

            What's happening here

Hi. I'm the newuser program. I'm completely automated. I'm going to teach you a very small amount about how to use this system more effectively. Then I'm going to move on and ask you a few questions. I'll give you a chance to correct your answers, and then I will create an account for you (based on your answers). After that, I'm done, and I'll let you on the system with your new account. First, allow me to tell you a little more about M-Net.

    What is M-Net?

M-Net is, first and foremost, a fun place. We hope you enjoy logging into M-Net--but M-Net also exists as a community resource. Arbornet, Inc., the

Press any key to Continue


Below is the entire compilable and runnable code for my application. After running, click "Connect" (with no password) to see what I've described. This will open a telnet connection to arbornet.org (a site that provides free shell accounts) as logs in as newuser with no password.


package ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.BadLocationException;

import org.apache.commons.net.telnet.TelnetClient;

public class SwingTelnetClient extends JFrame {
    private static final long serialVersionUID = 1L;
    JLabel lblServer = new JLabel();
    JLabel lblUserId = new JLabel();
    JLabel lblPassword = new JLabel();
    JButton btnConnect = new JButton();
    JButton btnDisconnect = new JButton();
    JTextField txtServer = new JTextField();
    JTextField txtUserId = new JTextField();
    JPasswordField txtPassword = new JPasswordField();
    JLabel lblCommand = new JLabel();
    JTextArea txtConsole = new JTextArea();
    JTextField txtCommand = new JTextField();
    JScrollPane scrollPane = new JScrollPane();

    PrintStream consolePrintStream = null;
    MyTelnetClient client;

    public SwingTelnetClient() {
        setTitle("Simple Telnet Client");

        JPanel panel = createMainPanel();
        addListeners();
        this.setPreferredSize(new Dimension(800, 400));
        this.getContentPane().add(panel);
    }

    private JPanel createMainPanel() {

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());

        panel.add(createTopPanel(), BorderLayout.NORTH);

        txtConsole.setColumns(50);
        txtConsole.setSize(300, 300);
        txtConsole.setBackground(Color.black);
        txtConsole.setForeground(Color.green);
        txtConsole.setFont(new Font("Terminal", 0, 16));
        txtConsole.setFocusable(false);
        scrollPane.getViewport().add(txtConsole);

        panel.add(scrollPane, BorderLayout.CENTER);
        panel.add(createBottomPanel(), BorderLayout.SOUTH);

        return panel;
    }

    private void addListeners() {
        btnConnect.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                client = new MyTelnetClient(txtServer.getText());

                consolePrintStream = new PrintStream(new FilteredStream(client.getOut()));
                System.setErr(consolePrintStream);
                System.setOut(consolePrintStream);

                client.connect(txtUserId.getText(), txtPassword.getText());

                txtCommand.requestFocus();

            }
        });

        btnDisconnect.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                client.disconnect();
                txtConsole.setText("Disconnected");
                txtUserId.requestFocus();

            }
        });

        txtPassword.addKeyListener(new KeyListener() {

            public void keyTyped(KeyEvent e) {
            }

            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    btnConnect.doClick();
                }
            }

            public void keyPressed(KeyEvent e) {
            }
        });

        txtCommand.addKeyListener(new KeyListener() {

            public void keyTyped(KeyEvent e) {
            }

            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    String command = txtCommand.getText().trim();

                    if (command.equals("exit")) {
                        client.disconnect();
                        txtConsole.setText("Disconnected");
                        txtUserId.requestFocus();
                    } else if (command.equals("clear")) {
                        txtConsole.setText("");
                    } else {
                        client.sendCommand(command);
                    }

                    txtCommand.setText("");
                }
            }

            public void keyPressed(KeyEvent e) {
            }
        });

        txtServer.addFocusListener(new SelectAllFocusListener(txtServer));
        txtUserId.addFocusListener(new SelectAllFocusListener(txtUserId));
        txtPassword.addFocusListener(new SelectAllFocusListener(txtPassword));
    }

    private JPanel createTopPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
        panel.setPreferredSize(new Dimension(300, 70));

        lblServer.setText("Server");
        lblUserId.setText("User Id");
        lblPassword.setText("Password");

        txtServer.setText("arbornet.org");
        txtUserId.setText("newuser");
        txtPassword.setText("");
        btnConnect.setText("Connect");
        btnConnect.setSize(30, 25);
        btnDisconnect.setText("Disconnect");
        btnDisconnect.setSize(30, 25);

        txtServer.setColumns(20);
        txtUserId.setColumns(15);
        txtPassword.setColumns(15);

        panel.add(lblServer);
        panel.add(txtServer);
        panel.add(lblUserId);
        panel.add(txtUserId);
        panel.add(lblPassword);
        panel.add(txtPassword);
        panel.add(btnConnect);
        panel.add(btnDisconnect);

        return panel;
    }

    private JPanel createBottomPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));

        lblCommand.setText("Execute Command");

        txtCommand.setColumns(50);

        panel.add(lblCommand);
        panel.add(txtCommand);

        return panel;
    }

    public static void main(String[] args) {
        SwingTelnetClient main = new SwingTelnetClient();
        main.pack();
        main.show();
    }

    private void scrollToBottom() {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    int endPosition = txtConsole.getDocument().getLength();
                    Rectangle bottom = txtConsole.modelToView(endPosition);
                    txtConsole.scrollRectToVisible(bottom);
                } catch (BadLocationException e) {
                    System.err.println("Could not scroll to " + e);
                }
            }
        });
    }

    class SelectAllFocusListener implements FocusListener {
        JTextField textField;

        public SelectAllFocusListener(JTextField textField) {
            this.textField = textField;
        }

        public void focusLost(FocusEvent e) {
        }

        public void focusGained(FocusEvent e) {
            textField.selectAll();
        }
    }

    class FilteredStream extends FilterOutputStream {
        public FilteredStream(OutputStream aStream) {
            super(aStream);
        }

        public void write(byte b[]) throws IOException {
            String aString = new String(b);
            txtConsole.append(aString);
        }

        public void write(byte b[], int off, int len) throws IOException {
            String aString = new String(b, off, len);
            txtConsole.append(aString);
            scrollToBottom();
        }
    }

    class MyTelnetClient {

        private static final String ENCODING = "ISO-8859-1";

        private TelnetClient telnet = new TelnetClient();

        private InputStream in;

        private PrintStream out;

        private String prompt = "$";

        ReaderThread readerThread;

        public MyTelnetClient(String server) {

            try {

                // Connect to the specified server

                telnet.connect(server, 23);

                in = telnet.getInputStream();

                out = new PrintStream(telnet.getOutputStream());

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        public void connect(String user, String password) {
            try {

                readUntil("login:");
                write(user);
                readUntil("Password:");
                write(password);
                startReading();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public String readUntilPrompt() {
            return readUntil(prompt + " ");
        }

        public void startReading() {
            readerThread = new ReaderThread("reader", in);
            readerThread.start();
        }

        public String readUntil(String pattern) {

            try {

                char lastChar = pattern.charAt(pattern.length() - 1);
                StringBuffer sb = new StringBuffer();
                char ch = (char) in.read();

                while (true) {

                    System.out.print(ch);
                    sb.append(ch);

                    if (ch == lastChar) {
                        if (sb.toString().endsWith(pattern)) {
                            return sb.toString();
                        }
                    }

                    ch = (char) in.read();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;

        }

        public void disconnect() {

            try {
                telnet.disconnect();
            } catch (Exception e) {
            }
        }

        public String sendCommand(String command) {

            try {
                write(command);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }

        private void write(String value) {

            try {
                out.println(value);
                out.flush();
                System.out.println(value);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        public InputStream getIn() {
            return in;
        }

        public PrintStream getOut() {
            return out;
        }

        class ReaderThread extends Thread {
            InputStream is;
            boolean keepRunning = true;

            public ReaderThread(String str, InputStream is) {
                super(str);
                this.is = is;
            }

            public void run() {

                while (true) {

                    try {
                        char ch = (char) in.read();
                        System.out.print(ch);
                    } catch (IOException e) {
                        // Swallow intentionally. Don't want stacktrace to
                        // appear in console.
                    }
                }

            }
        }

    }
}
stilltrackin
  • 111
  • 1
  • 1
  • 7
  • 2
    please 90pct of this code isn't related with your question, please edit your question with [SSCCE](http://sscce.org/) – mKorbel Feb 18 '12 at 22:56
  • 2
    Here's a shorter, working [example](http://stackoverflow.com/a/3245805/230513) for reference. – trashgod Feb 18 '12 at 23:01

1 Answers1

0

You'll need to parse the escape codes the server is sending you. This can be a little fiddly, because you'll have to do this as a separate parsing layer over the top of your telnet parsing (which detects and handles the IAC sequences and such), and there's nothing stopping the server sending you data one byte at a time.

Jack Kelly
  • 18,264
  • 2
  • 56
  • 81