This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to branch master-old
in repository trilead-ssh2.

commit a3c2b7d404149a7588f64c1840cdb7e9e301d408
Author: Matthew Johnson <[email protected]>
Date:   Sat Feb 20 14:14:59 2010 +0000

    new upstream
---
 debian/FAQ.html                               | 389 +++++++++++++
 debian/README.txt                             |  24 +
 debian/changelog                              |   9 +
 debian/control                                |   2 +-
 debian/copyright                              |   3 +-
 debian/examples/Basic.java                    |  91 +++
 debian/examples/BasicWithHTTPProxy.java       | 102 ++++
 debian/examples/PortForwarding.java           | 116 ++++
 debian/examples/PublicKeyAuthentication.java  |  80 +++
 debian/examples/SimpleVerifier.java           |  55 ++
 debian/examples/SingleThreadStdoutStderr.java | 142 +++++
 debian/examples/StdoutAndStderr.java          |  93 +++
 debian/examples/SwingShell.java               | 786 ++++++++++++++++++++++++++
 debian/examples/UsingKnownHosts.java          |  86 +++
 debian/libtrilead-ssh2-java.docs              |   6 +-
 debian/rules                                  |   3 -
 16 files changed, 1979 insertions(+), 8 deletions(-)

diff --git a/debian/FAQ.html b/debian/FAQ.html
new file mode 100644
index 0000000..979a6c3
--- /dev/null
+++ b/debian/FAQ.html
@@ -0,0 +1,389 @@
+<html>
+<title>Trilead SSH-2 for Java FAQ</title>
+<body>
+
+<a name="oben"></a>
+<h1>Trilead SSH-2 for Java FAQ</h1>
+
+<p>
+This FAQ includes information regarding topics that were discussed in e-mails 
between developers and users
+of the Trilead SSH-2 for Java library.
+</p>
+<p>
+Trilead homepage: <a 
href="http://www.trilead.ethz.ch";>http://www.trilead.ethz.ch</a><br>
+Last update of FAQ: oct-15-2007.
+</p>
+<p>
+Please report bugs, typos and any kind of suggestions to [email protected].
+Also, please visit our <a href="http://www.trilead.com/support";>support 
forum</a>.
+</p>
+
+<hr>
+
+<h2>Sections:</h2>
+
+<p>
+<ul>
+<li><a href="#env">When I start program XYZ with putty (or openssh, ..., 
whatever) then everything works.
+However, if I use "Session.execCommand", then XYZ behaves differently or does 
not work at all!</a></li>
+
+<li><a href="#blocking">My program sometimes hangs when I only read output 
from stdout!
+Or: can you explain me the story about the shared stdout/stderr window in the 
SSH-2 protocol?
+Or: what is this "StreamGobbler" thing all about?</a></li>
+
+<li><a href="#buffered">Why are the session's Input- and OutputStreams not 
buffered?</a></li>
+
+<li><a href="#sessioncommands">Why can't I execute several commands in one 
single session?</a></li>
+
+<li><a href="#sessionlimit">I cannot open more than 10 concurrent sessions (or 
SCP clients).</a></li>
+
+<li><a href="#passwordauth">Password authentication fails, I get 
"Authentication method password not
+supported by the server at this stage".</a></li>
+
+<li><a href="#puttygen">Why does public key authentication fail with my putty 
key?</a></li>
+
+<li><a href="#catmethod">I am sending data to a remote file using the "cat" 
method, but not all data is being written.</a></li>
+
+<li><a href="#pumptoremote">I want to pump data into a remote file, but the 
amount of data to be sent
+is not known at the time the transfer starts.</a></li>
+
+<li><a href="#swingshell">Do you have an example for the usage of feature 
XYZ?</a></li>
+</ul>
+</p>
+
+<hr><a name="env"></a><h2>When I start program XYZ with putty (or openssh, 
..., whatever) then everything
+works. However, if I use "Session.execCommand", then XYZ behaves differently 
or does not work at all!</h2>
+
+<h3>Short answer:</h3>
+
+<p>
+The most often source of problems when executing a command with 
<tt>Session.execCommand()</tt>
+are missing/wrong set environment variables on the remote machine. Make sure 
that the minimum needed
+environment for XYZ is the same, independentely on how the shell is being 
invoked.
+</p>
+
+<p>
+Example quickfix for bash users:
+</p>
+
+<p>
+<ol>
+<li>Define all your settings in the file <tt><b>~/.bashrc</b></tt></li>
+<li>Make sure that the file <tt><b>~/.bash_profile</b></tt> only contains the 
line <tt><b>source
+~/.bashrc</b></tt>.</li>
+<li>Before executing <tt>Session.execCommand()</tt>, do NOT aquire any type of 
pseudo terminal in the
+session. Be prepared to consume stdout and stderr data.</li>
+</ol>
+</p>
+
+<p>
+<b>Note:</b> If you really want to mimic the behavior of putty, then don't use 
Session.execCommand(), 
+instead aquire a pty (pseudo terminal) and then start a shell (use 
<tt>Session.requestPTY()</tt> and
+<tt>Session.startShell()</tt>). You then have to communicate with the shell 
process at the other end
+through stdin and stdout. However, you also have to implement terminal logic 
(e.g., escape sequence
+handling (unless you use a "dumb" pty), "expect-send" logic (output parsing, 
shell prompt detection), etc.).
+</p>
+
+<h3>Long answer:</h3>
+
+<p>
+If you login by using putty, then putty will normally request a "xterm" pty 
and your assigned shell
+(e.g., bash) will be started (a so called "interactive login shell"). In 
contrast, if you use
+<tt>Session.execCommand()</tt> to start a command then (unless you ask for it) 
no pty will be aquired
+and the command will be given to the shell as an argument (with the shell's 
"-c" option).
+</p>
+
+<p>
+The way a shell is being invoked has an effect on the set of initialization 
files which will be read be the shell.
+</p>
+
+<p>
+To demonstrate the difference, try the following (from the command line, e.g., 
with an OpenSSH client):
+</p>
+
+<p>
+<ol>
+<li>Login interactively and print the environment with the "env" 
command:<br>&nbsp;<br>
+<tt><b>[user@host ~] ssh 127.0.0.1<br>
+[user@host ~] env</b></tt><br>&nbsp;<br>
+</li>
+<li>Let the ssh server execute the "env" command (equivalent to using 
<tt>Session.executeCommand()</tt>):<br>&nbsp;<br>
+<tt><b>[user@host ~] ssh 127.0.0.1 "env"</b></tt>
+</li>
+</ol>
+</p>
+
+<p>
+If you compare the two outputs, then you will (unless you have adjusted your 
shell's settings)
+observe different environments.
+</p>
+
+<p>
+<b>If you are interested in the details, then please read the 
<tt>INVOCATION</tt> section in man page
+for the bash shell. You may notice that the definitions of "interactive" and 
"non-interactive" 
+(and combinations with "login") are little bit tricky.</b>
+</p>
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="blocking"></a><h2>My program sometimes hangs when I only read 
output from stdout!
+Or: can you explain me the story about the shared stdout/stderr window in the 
SSH-2 protocol?
+Or: what is this "StreamGobbler" thing all about?</h2>
+
+<p>
+In the SSH-2 low level protocol, each channel (e.g., session) has a receive 
window. When the remote
+SSH daemon has filled up our receive window, it must wait until we have 
consumed the input and are ready to accept new data.
+</p>
+
+<p>
+Unfortunately, the SSH-2 protocol defines a shared window for stderr and 
stdout. As a consequence,
+if, for example, the remote process produces a lot of stderr data and you 
never consume it, then after
+some time the local receive window will be full and the sender is blocked. If 
you then try to read()
+from stdout, your call will be blocked: there is no stdout data (locally) 
available and the SSH daemon
+cannot send you any, since the receive window is full (you would have to read 
some stderr data first
+to "free" up space in the receive window).
+</p>
+
+<p>
+Fortunately, Trilead SSH-2 uses a 30KB window - the above described scenario 
should be very rare.
+</p>
+
+<p>
+Many other SSH-2 client implementations just blindly consume any remotely 
produced data into a buffer
+which gets automatically extended - however, this can lead to another problem: 
in the extreme case
+the remote side can overflow you with data (e.g., leading to out of memory 
errors).
+</p>
+
+<p>
+What can you do about this?
+</p>
+
+<p>
+<ol>
+<li><b>Bad: Do nothing</b> - just work with stderr and stdout Inputstreams and 
hope that the 30KB
+window is enough for your application.</li>
+
+<li><b>Better, recommended for most users:</b> use two worker threads that 
consume remote stdout
+and stderr in parallel. Since you probably are not in the mood to program such 
a thing, you can use
+the StreamGobbler class supplied with Trilead SSH-2. The Streamgobbler is a 
special InputStream that
+uses an internal worker thread to read and buffer internally all data produced 
by another InputStream.
+It is very simple to use:<br> <tt><b><pre>InputStream stdout = new 
StreamGobbler(mysession.getStdout());
+
+InputStream stderr = new StreamGobbler(mysession.getStderr());</pre></b></tt>
+You then can access stdout and stderr in any order, in the background the 
StreamGobblers will
+automatically consume all data from the remote side and store in an internal 
buffer.</li>
+
+<li><b>Advanced:</b> you are paranoid and don't like programs that 
automatically extend buffers
+without asking you. You then have to implement a state machine. The condition 
wait facility offered by
+<tt>Session.waitForCondition()</tt> is exactly what you need: you can use it 
to wait until either stdout
+or stderr data has arrived and can be consumed with the two InputStreams. You 
can either use the return value
+of <tt>Session.waitForCondition()</tt> or check with 
<tt>InputStream.available()</tt>
+(for stdout and stderr) which InputStream has data available (i.e., a 
<tt>read()</tt> call will not block).
+Be careful when wrapping the InputStreams, also do not concurrently call 
read() on the InputStreams while calling
+<tt>Session.waitForCondition()</tt> (unless you know what you are 
doing).<br>Please have a look a the
+<tt>SingleThreadStdoutStderr.java</tt> example.</li>
+
+<li><b>The lazy way:</b> you don't mind if stdout and stderr data is being 
mixed into the same
+stream. Just allocate a "dumb" pty and the server will hopefully not send you 
any data on the stderr
+stream anymore. <b>Note:</b> by allocating a pty, the shell used to execute 
the command will probably 
+behave differently in terms of initialization (see also <a href="#env">this 
question</a>).</li>
+</ol>
+</p>
+
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="buffered"></a><h2>Why are the session's Input- and OutputStreams 
not buffered?</h2>
+
+<p>
+If you need it, then this library offers quite a raw type of access to the 
SSH-2 protocol stack.
+Of course, many people don't need that kind of low level access. If you need 
buffered streams,
+then you should the do the same thing as you would probably do with the 
streams of a TCP socket:
+wrap them with instances of BufferedInputStream and BufferedOutputStream. In 
case you use
+StreamGobblers for the InputStreams, then you don't need any additional 
wrappers, since the
+StreamGobblers implement buffering already.
+</p>
+<p>
+This code snippet will probably work well for most people:
+</p>
+<p>
+<tt>
+<pre>
+InputStream stdout = new StreamGobbler(mysession.getStdout());
+InputStream stderr = new StreamGobbler(mysession.getStderr());
+OutputStream stdin = new BufferedOutputStream(mysession.getStdin(), 8192);
+</pre>
+</tt>
+</p>
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="sessioncommands"></a><h2>Why can't I execute several commands in 
one single session?</h2>
+<p>
+If you use <tt>Session.execCommand()</tt>, then you indeed can only execute 
only one command per session.
+This is not a restriction of the library, but rather an enforcement by the 
underlying SSH-2 protocol
+(a <tt>Session</tt> object models the underlying SSH-2 session).
+</p>
+<p>
+There are several solutions:
+</p>
+<p>
+<ul>
+<li><b>Simple: Execute several commands in one batch</b>, e.g., something like 
<tt>Session.execCommand("echo
+Hello && echo again")</tt>.</li>
+<li><b>Simple: The intended way: simply open a new session for each 
command</b> - once you have opened a
+connection, you can ask for as many sessions as you want, they are only a 
"virtual" construct.</li>
+<li><b>Advanced: Don't use <tt>Session.execCommand()</tt>, but rather aquire a 
shell with
+<tt>Session.startShell()</tt></b>. See also <a href="#env">this 
question</a>.</li>
+</ul>
+</p>
+
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="sessionlimit"></a><h2>I cannot open more than 10 concurrent 
sessions (or SCP clients).</h2>
+<p>
+You are probably using OpenSSH. By looking at their source code you will find 
out that there
+is a hard-coded constant called MAX_SESSIONS in the session.c file which is 
set to "10" by default.
+This is a per connection limit. Unfortunately, it is not a run-time tunable 
parameter.
+However, this limit has no effect on the number of concurrent port 
forwardings. Please note: this information
+is based on the OpenSSH 4.3 release.
+</p>
+<p>
+Possible solutions:
+<ul>
+<li>(a) Recompile your SSH daemon</li>
+<li>(b) Try to live with this limit and keep the number of concurrent sessions 
<= 10.</li>
+<li>(c) Distribute your sessions over multiple concurrent SSH connections.</li>
+</ul>
+</p>
+<p>
+Just for completeness: starting from release 210, the thrown exception may 
look as follows:<br>
+<tt>
+<pre>
+java.io.IOException: Could not open channel (The server refused to open the 
channel (SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, 'open failed'))
+</pre>
+</tt>
+</p>
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="passwordauth"></a><h2>Password authentication fails, I get 
"Authentication method password
+not supported by the server at this stage".</h2>
+
+<p>
+Many default SSH server installations are configured to refuse the 
authentication type "password".
+Often, they only accept "publickey" and "keyboard-interactive". You have 
different options:
+</p>
+
+<p>
+<ul>
+<li><b>Enable password authentication.</b> E.g., in case of OpenSSH on Fedora, 
edit
+<code>/etc/sshd/sshd_config</code> and change the value of 
"PasswordAuthentication" to "yes",
+then send a HUP signal to the daemon so that it re-reads its 
configuration.</li>
+<li><b>Switch to public-key authentication.</b> Probably the best choice.</li>
+<li><b>Try to use keyboard-interactive authentication.</b> If you have a GUI 
that interacts with a user,
+then this is doable (check out the SwingShell.java example).</li>
+</ul>
+</p>
+
+<p>
+In general it is a good idea to call either 
<code>Connection.getRemainingAuthMethods()</code>
+or <code>Connection.isAuthMethodAvailable()</code> before using a certain 
authentication method.
+</p>
+
+<p>
+Please note that most servers let you in after one successful authentication 
step. However, in rare cases
+you may encounter servers that need several steps. I.e., if one of the 
<code>Connection.authenticateWithXXX()</code>
+methods returns <code>false</code> and 
<code>Connection.isAuthenticationPartialSuccess()</code> returns
+<code>true</code>, then further authentication is needed. For each step, to 
find out which authentication methods
+may proceed, you can use either the 
<code>Connection.getRemainingAuthMethods()</code> 
+or the <code>Connection.isAuthMethodAvailable()</code> method. Again, please 
have a look into the
+SwingShell.java example.
+</p>
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="puttygen"></a><h2>Why does public key authentication fail with my 
putty key?</h2>
+<p>
+When using putty private keys (e.g., .ppk files) with public key 
authentication, you get a
+"Publickey authentication failed" exception. The reason is that the library 
currently is not able to
+directly handle private keys in the proprietary format used by putty. However, 
you can use the
+"puttygen" tool (from the putty website) to convert your key to the desired 
format: load your key,
+then go to the conversions menu and select "Save OpenSSH key" (which saves the 
key in openssl PEM format,
+e.g., call it "private.pem").
+</p>
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="catmethod"></a><h2>I am sending data to a remote file using the 
"cat" method, but not all data is being written.</h2>
+<p>
+Please read carefully the answer to the following <a 
href="#pumptoremote">question</a>.
+</p>
+
+[<a href="#oben">TOP</a>]
+
+
+<hr><a name="pumptoremote"></a><h2>I want to pump data into a remote file, but 
the amount of data to be sent
+is not known at the time the transfer starts.</h2>
+<p>
+The SCP protocol communicates the amount of data to be sent at the start of 
the transfer,
+so SCP remains out of consideration. Possible other solutions:
+<ul>
+<li>Use the SFTP client. Recommended.</li>
+<li>Execute "cat > filename.txt" on the remote side and pump the data into 
stdin. This method is NOT recommended (and won't work on Windows...).</li>
+</ul>
+</p>
+<p>
+Be careful if you use the "cat" approach, as it may happen that not all your 
data will be
+written. If you close the stdin stream and immediatelly close the session (or 
the whole connection) then
+some SSH servers do not send the pending data to the process being executed 
("cat" in this case).
+You have to wait until "cat" has received the EOF and terminates before 
closing the session. However,
+waiting for the termination may not always work, since SSH servers sometimes 
"forget" to send the exit code
+of the remote process. The following code MAY work:
+</p>
+<p>
+<tt>
+<pre>
+Session sess = conn.openSession();
+sess.execCommand("cat > test.txt");
+OutputStream stdin = sess.getStdin();
+
+... out.write(...) ... out.write(...) ...
+
+/* The following flush() is only needed if you wrap the  */
+/* stdin stream (e.g., with a BufferedOutputStream).     */
+out.flush();
+
+/* Now let's send EOF */
+out.close();
+
+/* Let's wait until cat has finished                     */
+sess.waitForCondition(ChannelCondition.EXIT_STATUS, 2000);
+/* Better: put the above statement into a while loop!    */
+/* In ANY CASE: read the Javadocs for waitForCondition() */
+
+/* Show exit status, if available (otherwise "null")     */
+System.out.println("ExitCode: " + sess.getExitStatus());
+/* Now its hopefully safe to close the session           */
+sess.close();
+</pre>
+</tt>
+</p>
+<p>
+(Just a thought for another solution: execute <code>cat > test.txt && echo 
"FINISHED"</code>
+and wait until you get "FINISHED" on stdout... - try it on your own risk =)
+</p>
+
+[<a href="#oben">TOP</a>]
+
+<hr><a name="swingshell"></a><h2>Do you have an example for the usage of 
feature XYZ?</h2>
+<p>
+Please have at look at the examples section in the distribution, especially at 
the SwingShell.java example.
+</p>
+
+[<a href="#oben">TOP</a>]
+
+</body>
+</html>
+
diff --git a/debian/README.txt b/debian/README.txt
new file mode 100644
index 0000000..69bee5a
--- /dev/null
+++ b/debian/README.txt
@@ -0,0 +1,24 @@
+
+Trilead SSH-2 for Java - build 211
+==================================
+
+http://www.trilead.com
+
+Trilead SSH-2 for Java is a library which implements the SSH-2 protocol in 
pure Java
+(minimum required JRE: 1.4.2). It allows one to connect to SSH servers from 
within
+Java programs. It supports SSH sessions (remote command execution and shell 
access),
+local and remote port forwarding, local stream forwarding, X11 forwarding, SCP 
and SFTP.
+There are no dependencies on any JCE provider, as all crypto functionality is 
included.
+
+This distribution contains the source code, examples, javadoc and the FAQ.
+It also includes a pre-compiled jar version of the library which is ready to 
use.
+
+- Please read the included LICENCE.txt
+- Latest changes can be found in HISTORY.txt
+
+The latest version of the FAQ is available on the website.
+
+Please feel free to contact us. We welcome feedback of any kind!
+Contact: [email protected] or go to the public forum at 
http://www.trilead.com
+
+Zurich, October 2007
diff --git a/debian/changelog b/debian/changelog
index 11745d2..1d65963 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+trilead-ssh2 (6401-1) unstable; urgency=low
+
+  * Switch upstream to svnkit
+  * New upstream release
+  * Version is svn revision from svnkit
+  * Import readme, faq and examples from old upstream
+
+ -- Matthew Johnson <[email protected]>  Sat, 20 Feb 2010 13:52:54 +0000
+
 trilead-ssh2 (211-3) unstable; urgency=low
 
   * Use javahelper rather than dh_javadoc 
diff --git a/debian/control b/debian/control
index abc6885..a1ae852 100644
--- a/debian/control
+++ b/debian/control
@@ -5,7 +5,7 @@ Maintainer: Matthew Johnson <[email protected]>
 Build-Depends: debhelper (>> 7), javahelper (>=0.25)
 Build-Depends-Indep: default-jdk
 Standards-Version: 3.7.3
-Homepage: http://www.trilead.com/Products/Trilead-SSH-2-Java/
+Homepage: http://svn.svnkit.com/repos/svnkit/tags/1.3.2/contrib/trilead/
 
 Package: libtrilead-ssh2-java
 Architecture: all
diff --git a/debian/copyright b/debian/copyright
index 6c8ee89..2f12e07 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,6 +1,7 @@
 This package was Debianised by Matthew Johnson <[email protected]> on Wed Feb 
20 11:41:05 GMT 2008
 
-This package was downloaded from 
http://www.trilead.com/Download/Trilead-SSH-2-Java/.
+This package was originally downloaded from 
http://www.trilead.com/Download/Trilead-SSH-2-Java/,
+but now upstream is 
http://svn.svnkit.com/repos/svnkit/tags/1.3.2/contrib/trilead/
 
 Copyright (c) 2007 Trilead AG (http://www.trilead.com)
 
diff --git a/debian/examples/Basic.java b/debian/examples/Basic.java
new file mode 100644
index 0000000..7bd1577
--- /dev/null
+++ b/debian/examples/Basic.java
@@ -0,0 +1,91 @@
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.StreamGobbler;
+
+
+/**
+ * This is a very basic example that shows
+ * how one can login to a machine and execute a command.
+ *  
+ * @author Christian Plattner, [email protected]
+ * @version $Id: Basic.java,v 1.4 2007/10/15 12:49:57 cplattne Exp $
+ */
+public class Basic
+{
+       public static void main(String[] args)
+       {
+               String hostname = "127.0.0.1";
+               String username = "joe";
+               String password = "joespass";
+
+               try
+               {
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* Now connect */
+
+                       conn.connect();
+
+                       /* Authenticate.
+                        * If you get an IOException saying something like
+                        * "Authentication method password not supported by the 
server at this stage."
+                        * then please check the FAQ.
+                        */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPassword(username, password);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* Create a session */
+
+                       Session sess = conn.openSession();
+
+                       sess.execCommand("uname -a && date && uptime && who");
+
+                       System.out.println("Here is some information about the 
remote host:");
+
+                       /* 
+                        * This basic example does not handle stderr, which is 
sometimes dangerous
+                        * (please read the FAQ).
+                        */
+
+                       InputStream stdout = new 
StreamGobbler(sess.getStdout());
+
+                       BufferedReader br = new BufferedReader(new 
InputStreamReader(stdout));
+
+                       while (true)
+                       {
+                               String line = br.readLine();
+                               if (line == null)
+                                       break;
+                               System.out.println(line);
+                       }
+
+                       /* Show exit status, if available (otherwise "null") */
+
+                       System.out.println("ExitCode: " + sess.getExitStatus());
+
+                       /* Close this session */
+
+                       sess.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/examples/BasicWithHTTPProxy.java 
b/debian/examples/BasicWithHTTPProxy.java
new file mode 100644
index 0000000..73492db
--- /dev/null
+++ b/debian/examples/BasicWithHTTPProxy.java
@@ -0,0 +1,102 @@
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.HTTPProxyData;
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.StreamGobbler;
+
+/**
+ * This is a very basic example that shows
+ * how one can login to a machine (via a HTTP proxy)
+ * and execute a command.
+ *  
+ * @author Christian Plattner, [email protected]
+ * @version $Id: BasicWithHTTPProxy.java,v 1.3 2007/10/15 12:49:57 cplattne 
Exp $
+ */
+public class BasicWithHTTPProxy
+{
+       public static void main(String[] args)
+       {
+               String hostname = "my-ssh-server";
+               String username = "joe";
+               String password = "joespass";
+
+               String proxyHost = "192.168.1.1";
+               int proxyPort = 3128; // default port used by squid
+               
+               try
+               {
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* We want to connect through a HTTP proxy */
+                       
+                       conn.setProxyData(new HTTPProxyData(proxyHost, 
proxyPort));
+                       
+                       // if the proxy requires basic authentication:
+                       // conn.setProxyData(new HTTPProxyData(proxyHost, 
proxyPort, "username", "secret"));
+                       
+                       /* Now connect (through the proxy) */
+
+                       conn.connect();
+
+                       /* Authenticate.
+                        * If you get an IOException saying something like
+                        * "Authentication method password not supported by the 
server at this stage."
+                        * then please check the FAQ.
+                        */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPassword(username, password);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* Create a session */
+
+                       Session sess = conn.openSession();
+
+                       sess.execCommand("uname -a && date && uptime && who");
+
+                       System.out.println("Here is some information about the 
remote host:");
+
+                       /* 
+                        * This basic example does not handle stderr, which is 
sometimes dangerous
+                        * (please read the FAQ).
+                        */
+
+                       InputStream stdout = new 
StreamGobbler(sess.getStdout());
+
+                       BufferedReader br = new BufferedReader(new 
InputStreamReader(stdout));
+
+                       while (true)
+                       {
+                               String line = br.readLine();
+                               if (line == null)
+                                       break;
+                               System.out.println(line);
+                       }
+
+                       /* Show exit status, if available (otherwise "null") */
+
+                       System.out.println("ExitCode: " + sess.getExitStatus());
+
+                       /* Close this session */
+
+                       sess.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/examples/PortForwarding.java 
b/debian/examples/PortForwarding.java
new file mode 100644
index 0000000..dd8d4df
--- /dev/null
+++ b/debian/examples/PortForwarding.java
@@ -0,0 +1,116 @@
+import java.io.File;
+import java.io.IOException;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.LocalPortForwarder;
+
+/**
+ * This example shows how to deal with port forwardings.
+ *  
+ * @author Christian Plattner, [email protected]
+ * @version $Id: PortForwarding.java,v 1.2 2007/10/15 12:49:57 cplattne Exp $
+ */
+public class PortForwarding
+{
+       public static void sleepSomeTime(long milliSeconds)
+       {
+               try
+               {
+                       Thread.sleep(milliSeconds);
+               }
+               catch (InterruptedException e)
+               {
+               }
+       }
+
+       public static void main(String[] args)
+       {
+               String hostname = "127.0.0.1";
+               String username = "joe";
+
+               File keyfile = new File("~/.ssh/id_rsa"); // or "~/.ssh/id_dsa"
+               String keyfilePass = "joespass"; // will be ignored if not 
needed
+
+               try
+               {
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* Now connect */
+
+                       conn.connect();
+
+                       /* Authenticate */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPublicKey(username, keyfile, keyfilePass);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* ===== OK, now let's establish some local port 
forwardings ===== */
+
+                       /* Example Port Forwarding: -L 8080:www.icann.org:80 
(OpenSSH notation)
+                        * 
+                        * This works by allocating a socket to listen on 8080 
on the local interface (127.0.0.1).
+                        * Whenever a connection is made to this port 
(127.0.0.1:8080), the connection is forwarded
+                        * over the secure channel, and a connection is made to 
www.icann.org:80 from the remote
+                        * machine (i.e., the ssh server).
+                        * 
+                        * (the above text is based partially on the OpenSSH 
man page)
+                        */
+
+                       /* You can create as many of them as you want */
+
+                       LocalPortForwarder lpf1 = 
conn.createLocalPortForwarder(8080, "www.icann.org", 80);
+
+                       /* Now simply point your webbrowser to 127.0.0.1:8080 */
+                       /* (on the host where you execute this program)         
                */
+
+                       /* ===== OK, now let's establish some remote port 
forwardings ===== */
+
+                       /* Example Port Forwarding: -R 
127.0.0.1:8080:www.ripe.net:80 (OpenSSH notation)
+                        * 
+                        * Specifies that the port 127.0.0.1:8080 on the remote 
server is to be forwarded to the
+                        * given host and port on the local side.  This works 
by allocating a socket to listen to port
+                        * 8080 on the remote side (the ssh server), and 
whenever a connection is made to this port, the
+                        * connection is forwarded over the secure channel, and 
a connection is made to
+                        * www.ripe.net:80 by the Trilead SSH-2 library.
+                        * 
+                        * (the above text is based partially on the OpenSSH 
man page)
+                        */
+
+                       /* You can create as many of them as you want */
+
+                       conn.requestRemotePortForwarding("127.0.0.1", 8080, 
"www.ripe.net", 80);
+
+                       /* Now, on the ssh server, if you connect to 
127.0.0.1:8080, then the connection is forwarded
+                        * through the secure tunnel to the library, which in 
turn will forward the connection
+                        * to www.ripe.net:80. */
+
+                       /* Sleep a bit... (30 seconds) */
+                       sleepSomeTime(30000);
+
+                       /* Stop accepting remote connections that are being 
forwarded to www.ripe.net:80 */
+
+                       conn.cancelRemotePortForwarding(8080);
+
+                       /* Sleep a bit... (20 seconds) */
+                       sleepSomeTime(20000);
+
+                       /* Stop accepting connections on 127.0.0.1:8080 that 
are being forwarded to www.icann.org:80 */
+
+                       lpf1.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/examples/PublicKeyAuthentication.java 
b/debian/examples/PublicKeyAuthentication.java
new file mode 100644
index 0000000..f3cb554
--- /dev/null
+++ b/debian/examples/PublicKeyAuthentication.java
@@ -0,0 +1,80 @@
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.StreamGobbler;
+
+/**
+ * This example shows how to login using
+ * public key authentication.
+ *  
+ * @author Christian Plattner, [email protected]
+ * @version $Id: PublicKeyAuthentication.java,v 1.2 2007/10/15 12:49:57 
cplattne Exp $
+ */
+public class PublicKeyAuthentication
+{
+       public static void main(String[] args)
+       {
+               String hostname = "127.0.0.1";
+               String username = "joe";
+
+               File keyfile = new File("~/.ssh/id_rsa"); // or "~/.ssh/id_dsa"
+               String keyfilePass = "joespass"; // will be ignored if not 
needed
+
+               try
+               {
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* Now connect */
+
+                       conn.connect();
+
+                       /* Authenticate */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPublicKey(username, keyfile, keyfilePass);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* Create a session */
+
+                       Session sess = conn.openSession();
+
+                       sess.execCommand("uname -a && date && uptime && who");
+
+                       InputStream stdout = new 
StreamGobbler(sess.getStdout());
+
+                       BufferedReader br = new BufferedReader(new 
InputStreamReader(stdout));
+
+                       System.out.println("Here is some information about the 
remote host:");
+
+                       while (true)
+                       {
+                               String line = br.readLine();
+                               if (line == null)
+                                       break;
+                               System.out.println(line);
+                       }
+
+                       /* Close this session */
+
+                       sess.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/examples/SimpleVerifier.java 
b/debian/examples/SimpleVerifier.java
new file mode 100644
index 0000000..0cc9a79
--- /dev/null
+++ b/debian/examples/SimpleVerifier.java
@@ -0,0 +1,55 @@
+import com.trilead.ssh2.KnownHosts;
+import com.trilead.ssh2.ServerHostKeyVerifier;
+
+/**
+ * This example hostkey verifier is used by the
+ * UsingKnownHosts.java example.
+ *  
+ * @author Christian Plattner, [email protected]
+ * @version $Id: SimpleVerifier.java,v 1.4 2007/10/15 12:49:57 cplattne Exp $
+ */
+class SimpleVerifier implements ServerHostKeyVerifier
+{
+       KnownHosts database;
+
+       public SimpleVerifier(KnownHosts database)
+       {
+               if (database == null)
+                       throw new IllegalArgumentException();
+
+               this.database = database;
+       }
+
+       public boolean verifyServerHostKey(String hostname, int port, String 
serverHostKeyAlgorithm, byte[] serverHostKey)
+                       throws Exception
+       {
+               int result = database.verifyHostkey(hostname, 
serverHostKeyAlgorithm, serverHostKey);
+
+               switch (result)
+               {
+               case KnownHosts.HOSTKEY_IS_OK:
+
+                       return true; // We are happy
+
+               case KnownHosts.HOSTKEY_IS_NEW:
+
+                       // Unknown host? Blindly accept the key and put it into 
the cache.
+                       // Well, you definitely can do better (e.g., ask the 
user).
+
+                       // The following call will ONLY put the key into the 
memory cache!
+                       // To save it in a known hosts file, also call 
"KnownHosts.addHostkeyToFile(...)"
+                       database.addHostkey(new String[] { hostname }, 
serverHostKeyAlgorithm, serverHostKey);
+
+                       return true;
+
+               case KnownHosts.HOSTKEY_HAS_CHANGED:
+
+                       // Close the connection if the hostkey has changed.
+                       // Better: ask user and add new key to database.
+                       return false;
+
+               default:
+                       throw new IllegalStateException();
+               }
+       }
+}
\ No newline at end of file
diff --git a/debian/examples/SingleThreadStdoutStderr.java 
b/debian/examples/SingleThreadStdoutStderr.java
new file mode 100644
index 0000000..5887fa6
--- /dev/null
+++ b/debian/examples/SingleThreadStdoutStderr.java
@@ -0,0 +1,142 @@
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.trilead.ssh2.ChannelCondition;
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.Session;
+
+/**
+ * This example shows how to use the Session.waitForCondition
+ * method to implement a state machine approach for
+ * proper stdout/stderr output handling in a single thread.
+ * 
+ * @author Christian Plattner, [email protected]
+ * @version $Id: SingleThreadStdoutStderr.java,v 1.6 2007/10/15 12:49:57 
cplattne Exp $
+ */
+public class SingleThreadStdoutStderr
+{
+       public static void main(String[] args)
+       {
+               String hostname = "127.0.0.1";
+               String username = "joe";
+               String password = "joespass";
+
+               try
+               {
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* Now connect */
+
+                       conn.connect();
+
+                       /* Authenticate */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPassword(username, password);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* Create a session */
+
+                       Session sess = conn.openSession();
+
+                       sess.execCommand("echo \"Huge amounts of text on 
STDOUT\"; echo \"Huge amounts of text on STDERR\" >&2");
+
+                       /*
+                        * Advanced:
+                        * The following is a demo on how one can read from 
stdout and
+                        * stderr without having to use two parallel worker 
threads (i.e.,
+                        * we don't use the Streamgobblers here) and at the 
same time not
+                        * risking a deadlock (due to a filled SSH2 channel 
window, caused
+                        * by the stream which you are currently NOT reading 
from =).
+                        */
+
+                       /* Don't wrap these streams and don't let other threads 
work on
+                        * these streams while you work with 
Session.waitForCondition()!!!
+                        */
+
+                       InputStream stdout = sess.getStdout();
+                       InputStream stderr = sess.getStderr();
+
+                       byte[] buffer = new byte[8192];
+
+                       while (true)
+                       {
+                               if ((stdout.available() == 0) && 
(stderr.available() == 0))
+                               {
+                                       /* Even though currently there is no 
data available, it may be that new data arrives
+                                        * and the session's underlying channel 
is closed before we call waitForCondition().
+                                        * This means that EOF and STDOUT_DATA 
(or STDERR_DATA, or both) may
+                                        * be set together.
+                                        */
+
+                                       int conditions = 
sess.waitForCondition(ChannelCondition.STDOUT_DATA | 
ChannelCondition.STDERR_DATA
+                                                       | ChannelCondition.EOF, 
2000);
+
+                                       /* Wait no longer than 2 seconds (= 
2000 milliseconds) */
+
+                                       if ((conditions & 
ChannelCondition.TIMEOUT) != 0)
+                                       {
+                                               /* A timeout occured. */
+                                               throw new IOException("Timeout 
while waiting for data from peer.");
+                                       }
+
+                                       /* Here we do not need to check 
separately for CLOSED, since CLOSED implies EOF */
+
+                                       if ((conditions & ChannelCondition.EOF) 
!= 0)
+                                       {
+                                               /* The remote side won't send 
us further data... */
+
+                                               if ((conditions & 
(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0)
+                                               {
+                                                       /* ... and we have 
consumed all data in the local arrival window. */
+                                                       break;
+                                               }
+                                       }
+
+                                       /* OK, either STDOUT_DATA or 
STDERR_DATA (or both) is set. */
+
+                                       // You can be paranoid and check that 
the library is not going nuts:
+                                       // if ((conditions & 
(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0)
+                                       //      throw new 
IllegalStateException("Unexpected condition result (" + conditions + ")");
+                               }
+
+                               /* If you below replace "while" with "if", then 
the way the output appears on the local
+                                * stdout and stder streams is more "balanced". 
Addtionally reducing the buffer size
+                                * will also improve the interleaving, but 
performance will slightly suffer.
+                                * OKOK, that all matters only if you get HUGE 
amounts of stdout and stderr data =)
+                                */
+
+                               while (stdout.available() > 0)
+                               {
+                                       int len = stdout.read(buffer);
+                                       if (len > 0) // this check is somewhat 
paranoid
+                                               System.out.write(buffer, 0, 
len);
+                               }
+
+                               while (stderr.available() > 0)
+                               {
+                                       int len = stderr.read(buffer);
+                                       if (len > 0) // this check is somewhat 
paranoid
+                                               System.err.write(buffer, 0, 
len);
+                               }
+                       }
+
+                       /* Close this session */
+
+                       sess.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/examples/StdoutAndStderr.java 
b/debian/examples/StdoutAndStderr.java
new file mode 100644
index 0000000..257dc6b
--- /dev/null
+++ b/debian/examples/StdoutAndStderr.java
@@ -0,0 +1,93 @@
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.StreamGobbler;
+
+/**
+ * This example shows how to consume stdout/stderr output
+ * using two StreamGobblers. This is simpler to program
+ * than the state machine approach (see SingleThreadStdoutStderr.java),
+ * but you cannot control the amount of memory that is
+ * consumed by your application (i.e., in case the other
+ * side sends you lots of data).
+ * 
+ * @author Christian Plattner, [email protected]
+ * @version $Id: StdoutAndStderr.java,v 1.2 2007/10/15 12:49:57 cplattne Exp $
+ */
+public class StdoutAndStderr
+{
+       public static void main(String[] args)
+       {
+               String hostname = "127.0.0.1";
+               String username = "joe";
+               String password = "joespass";
+
+               try
+               {
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* Now connect */
+
+                       conn.connect();
+
+                       /* Authenticate */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPassword(username, password);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* Create a session */
+
+                       Session sess = conn.openSession();
+
+                       sess.execCommand("echo \"Text on STDOUT\"; echo \"Text 
on STDERR\" >&2");
+
+                       InputStream stdout = new 
StreamGobbler(sess.getStdout());
+                       InputStream stderr = new 
StreamGobbler(sess.getStderr());
+
+                       BufferedReader stdoutReader = new BufferedReader(new 
InputStreamReader(stdout));
+                       BufferedReader stderrReader = new BufferedReader(new 
InputStreamReader(stderr));
+
+                       System.out.println("Here is the output from stdout:");
+
+                       while (true)
+                       {
+                               String line = stdoutReader.readLine();
+                               if (line == null)
+                                       break;
+                               System.out.println(line);
+                       }
+
+                       System.out.println("Here is the output from stderr:");
+
+                       while (true)
+                       {
+                               String line = stderrReader.readLine();
+                               if (line == null)
+                                       break;
+                               System.out.println(line);
+                       }
+
+                       /* Close this session */
+
+                       sess.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/examples/SwingShell.java b/debian/examples/SwingShell.java
new file mode 100644
index 0000000..1426aca
--- /dev/null
+++ b/debian/examples/SwingShell.java
@@ -0,0 +1,786 @@
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.InteractiveCallback;
+import com.trilead.ssh2.KnownHosts;
+import com.trilead.ssh2.ServerHostKeyVerifier;
+import com.trilead.ssh2.Session;
+
+/**
+ * This is a very primitive SSH-2 dumb terminal (Swing based).
+ * <p>
+ * The purpose of this class is to demonstrate:
+ * <ul>
+ * <li>Verifying server hostkeys with an existing known_hosts file</li>
+ * <li>Displaying fingerprints of server hostkeys</li>
+ * <li>Adding a server hostkey to a known_hosts file (+hashing the hostname 
for security)</li>
+ * <li>Authentication with DSA, RSA, password and keyboard-interactive 
methods</li>
+ * </ul>
+ * 
+ * @author Christian Plattner, [email protected]
+ * @version $Id: SwingShell.java,v 1.10 2007/10/15 12:49:57 cplattne Exp $
+ * 
+ */
+public class SwingShell
+{
+       /* 
+        * NOTE: to get this feature to work, replace the "tilde" with your 
home directory,
+        * at least my JVM does not understand it. Need to check the specs.
+        */
+
+       static final String knownHostPath = "~/.ssh/known_hosts";
+       static final String idDSAPath = "~/.ssh/id_dsa";
+       static final String idRSAPath = "~/.ssh/id_rsa";
+
+       JFrame loginFrame = null;
+       JLabel hostLabel;
+       JLabel userLabel;
+       JTextField hostField;
+       JTextField userField;
+       JButton loginButton;
+
+       KnownHosts database = new KnownHosts();
+
+       public SwingShell()
+       {
+               File knownHostFile = new File(knownHostPath);
+               if (knownHostFile.exists())
+               {
+                       try
+                       {
+                               database.addHostkeys(knownHostFile);
+                       }
+                       catch (IOException e)
+                       {
+                       }
+               }
+       }
+
+       /**
+        * This dialog displays a number of text lines and a text field.
+        * The text field can either be plain text or a password field.
+        */
+       class EnterSomethingDialog extends JDialog
+       {
+               private static final long serialVersionUID = 1L;
+
+               JTextField answerField;
+               JPasswordField passwordField;
+
+               final boolean isPassword;
+
+               String answer;
+
+               public EnterSomethingDialog(JFrame parent, String title, String 
content, boolean isPassword)
+               {
+                       this(parent, title, new String[] { content }, 
isPassword);
+               }
+
+               public EnterSomethingDialog(JFrame parent, String title, 
String[] content, boolean isPassword)
+               {
+                       super(parent, title, true);
+
+                       this.isPassword = isPassword;
+
+                       JPanel pan = new JPanel();
+                       pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS));
+
+                       for (int i = 0; i < content.length; i++)
+                       {
+                               if ((content[i] == null) || (content[i] == ""))
+                                       continue;
+                               JLabel contentLabel = new JLabel(content[i]);
+                               pan.add(contentLabel);
+
+                       }
+
+                       answerField = new JTextField(20);
+                       passwordField = new JPasswordField(20);
+
+                       if (isPassword)
+                               pan.add(passwordField);
+                       else
+                               pan.add(answerField);
+
+                       KeyAdapter kl = new KeyAdapter()
+                       {
+                               public void keyTyped(KeyEvent e)
+                               {
+                                       if (e.getKeyChar() == '\n')
+                                               finish();
+                               }
+                       };
+
+                       answerField.addKeyListener(kl);
+                       passwordField.addKeyListener(kl);
+
+                       getContentPane().add(BorderLayout.CENTER, pan);
+
+                       setResizable(false);
+                       pack();
+                       setLocationRelativeTo(null);
+               }
+
+               private void finish()
+               {
+                       if (isPassword)
+                               answer = new 
String(passwordField.getPassword());
+                       else
+                               answer = answerField.getText();
+
+                       dispose();
+               }
+       }
+
+       /**
+        * TerminalDialog is probably the worst terminal emulator ever written 
- implementing
+        * a real vt100 is left as an exercise to the reader, i.e., to you =)
+        *
+        */
+       class TerminalDialog extends JDialog
+       {
+               private static final long serialVersionUID = 1L;
+
+               JPanel botPanel;
+               JButton logoffButton;
+               JTextArea terminalArea;
+
+               Session sess;
+               InputStream in;
+               OutputStream out;
+
+               int x, y;
+
+               /**
+                * This thread consumes output from the remote server and 
displays it in
+                * the terminal window.
+                *
+                */
+               class RemoteConsumer extends Thread
+               {
+                       char[][] lines = new char[y][];
+                       int posy = 0;
+                       int posx = 0;
+
+                       private void addText(byte[] data, int len)
+                       {
+                               for (int i = 0; i < len; i++)
+                               {
+                                       char c = (char) (data[i] & 0xff);
+
+                                       if (c == 8) // Backspace, VERASE
+                                       {
+                                               if (posx < 0)
+                                                       continue;
+                                               posx--;
+                                               continue;
+                                       }
+
+                                       if (c == '\r')
+                                       {
+                                               posx = 0;
+                                               continue;
+                                       }
+
+                                       if (c == '\n')
+                                       {
+                                               posy++;
+                                               if (posy >= y)
+                                               {
+                                                       for (int k = 1; k < y; 
k++)
+                                                               lines[k - 1] = 
lines[k];
+                                                       posy--;
+                                                       lines[y - 1] = new 
char[x];
+                                                       for (int k = 0; k < x; 
k++)
+                                                               lines[y - 1][k] 
= ' ';
+                                               }
+                                               continue;
+                                       }
+
+                                       if (c < 32)
+                                       {
+                                               continue;
+                                       }
+
+                                       if (posx >= x)
+                                       {
+                                               posx = 0;
+                                               posy++;
+                                               if (posy >= y)
+                                               {
+                                                       posy--;
+                                                       for (int k = 1; k < y; 
k++)
+                                                               lines[k - 1] = 
lines[k];
+                                                       lines[y - 1] = new 
char[x];
+                                                       for (int k = 0; k < x; 
k++)
+                                                               lines[y - 1][k] 
= ' ';
+                                               }
+                                       }
+
+                                       if (lines[posy] == null)
+                                       {
+                                               lines[posy] = new char[x];
+                                               for (int k = 0; k < x; k++)
+                                                       lines[posy][k] = ' ';
+                                       }
+
+                                       lines[posy][posx] = c;
+                                       posx++;
+                               }
+
+                               StringBuffer sb = new StringBuffer(x * y);
+
+                               for (int i = 0; i < lines.length; i++)
+                               {
+                                       if (i != 0)
+                                               sb.append('\n');
+
+                                       if (lines[i] != null)
+                                       {
+                                               sb.append(lines[i]);
+                                       }
+
+                               }
+                               setContent(sb.toString());
+                       }
+
+                       public void run()
+                       {
+                               byte[] buff = new byte[8192];
+
+                               try
+                               {
+                                       while (true)
+                                       {
+                                               int len = in.read(buff);
+                                               if (len == -1)
+                                                       return;
+                                               addText(buff, len);
+                                       }
+                               }
+                               catch (Exception e)
+                               {
+                               }
+                       }
+               }
+
+               public TerminalDialog(JFrame parent, String title, Session 
sess, int x, int y) throws IOException
+               {
+                       super(parent, title, true);
+
+                       this.sess = sess;
+
+                       in = sess.getStdout();
+                       out = sess.getStdin();
+
+                       this.x = x;
+                       this.y = y;
+
+                       botPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+
+                       logoffButton = new JButton("Logout");
+                       botPanel.add(logoffButton);
+
+                       logoffButton.addActionListener(new ActionListener()
+                       {
+                               public void actionPerformed(ActionEvent e)
+                               {
+                                       /* Dispose the dialog, 
"setVisible(true)" method will return */
+                                       dispose();
+                               }
+                       });
+
+                       Font f = new Font("Monospaced", Font.PLAIN, 16);
+
+                       terminalArea = new JTextArea(y, x);
+                       terminalArea.setFont(f);
+                       terminalArea.setBackground(Color.BLACK);
+                       terminalArea.setForeground(Color.ORANGE);
+                       /* This is a hack. We cannot disable the caret,
+                        * since setting editable to false also changes
+                        * the meaning of the TAB key - and I want to use it in 
bash.
+                        * Again - this is a simple DEMO terminal =)
+                        */
+                       terminalArea.setCaretColor(Color.BLACK);
+
+                       KeyAdapter kl = new KeyAdapter()
+                       {
+                               public void keyTyped(KeyEvent e)
+                               {
+                                       int c = e.getKeyChar();
+
+                                       try
+                                       {
+                                               out.write(c);
+                                       }
+                                       catch (IOException e1)
+                                       {
+                                       }
+                                       e.consume();
+                               }
+                       };
+
+                       terminalArea.addKeyListener(kl);
+
+                       getContentPane().add(terminalArea, BorderLayout.CENTER);
+                       getContentPane().add(botPanel, BorderLayout.PAGE_END);
+
+                       setResizable(false);
+                       pack();
+                       setLocationRelativeTo(parent);
+
+                       new RemoteConsumer().start();
+               }
+
+               public void setContent(String lines)
+               {
+                       // setText is thread safe, it does not have to be 
called from
+                       // the Swing GUI thread.
+                       terminalArea.setText(lines);
+               }
+       }
+
+       /**
+        * This ServerHostKeyVerifier asks the user on how to proceed if a key 
cannot be found
+        * in the in-memory database.
+        *
+        */
+       class AdvancedVerifier implements ServerHostKeyVerifier
+       {
+               public boolean verifyServerHostKey(String hostname, int port, 
String serverHostKeyAlgorithm,
+                               byte[] serverHostKey) throws Exception
+               {
+                       final String host = hostname;
+                       final String algo = serverHostKeyAlgorithm;
+
+                       String message;
+
+                       /* Check database */
+
+                       int result = database.verifyHostkey(hostname, 
serverHostKeyAlgorithm, serverHostKey);
+
+                       switch (result)
+                       {
+                       case KnownHosts.HOSTKEY_IS_OK:
+                               return true;
+
+                       case KnownHosts.HOSTKEY_IS_NEW:
+                               message = "Do you want to accept the hostkey 
(type " + algo + ") from " + host + " ?\n";
+                               break;
+
+                       case KnownHosts.HOSTKEY_HAS_CHANGED:
+                               message = "WARNING! Hostkey for " + host + " 
has changed!\nAccept anyway?\n";
+                               break;
+
+                       default:
+                               throw new IllegalStateException();
+                       }
+
+                       /* Include the fingerprints in the message */
+
+                       String hexFingerprint = 
KnownHosts.createHexFingerprint(serverHostKeyAlgorithm, serverHostKey);
+                       String bubblebabbleFingerprint = 
KnownHosts.createBubblebabbleFingerprint(serverHostKeyAlgorithm,
+                                       serverHostKey);
+
+                       message += "Hex Fingerprint: " + hexFingerprint + 
"\nBubblebabble Fingerprint: " + bubblebabbleFingerprint;
+
+                       /* Now ask the user */
+
+                       int choice = JOptionPane.showConfirmDialog(loginFrame, 
message);
+
+                       if (choice == JOptionPane.YES_OPTION)
+                       {
+                               /* Be really paranoid. We use a hashed hostname 
entry */
+
+                               String hashedHostname = 
KnownHosts.createHashedHostname(hostname);
+
+                               /* Add the hostkey to the in-memory database */
+
+                               database.addHostkey(new String[] { 
hashedHostname }, serverHostKeyAlgorithm, serverHostKey);
+
+                               /* Also try to add the key to a known_host file 
*/
+
+                               try
+                               {
+                                       KnownHosts.addHostkeyToFile(new 
File(knownHostPath), new String[] { hashedHostname },
+                                                       serverHostKeyAlgorithm, 
serverHostKey);
+                               }
+                               catch (IOException ignore)
+                               {
+                               }
+
+                               return true;
+                       }
+
+                       if (choice == JOptionPane.CANCEL_OPTION)
+                       {
+                               throw new Exception("The user aborted the 
server hostkey verification.");
+                       }
+
+                       return false;
+               }
+       }
+
+       /**
+        * The logic that one has to implement if "keyboard-interactive" 
autentication shall be
+        * supported.
+        *
+        */
+       class InteractiveLogic implements InteractiveCallback
+       {
+               int promptCount = 0;
+               String lastError;
+
+               public InteractiveLogic(String lastError)
+               {
+                       this.lastError = lastError;
+               }
+
+               /* the callback may be invoked several times, depending on how 
many questions-sets the server sends */
+
+               public String[] replyToChallenge(String name, String 
instruction, int numPrompts, String[] prompt,
+                               boolean[] echo) throws IOException
+               {
+                       String[] result = new String[numPrompts];
+
+                       for (int i = 0; i < numPrompts; i++)
+                       {
+                               /* Often, servers just send empty strings for 
"name" and "instruction" */
+
+                               String[] content = new String[] { lastError, 
name, instruction, prompt[i] };
+
+                               if (lastError != null)
+                               {
+                                       /* show lastError only once */
+                                       lastError = null;
+                               }
+
+                               EnterSomethingDialog esd = new 
EnterSomethingDialog(loginFrame, "Keyboard Interactive Authentication",
+                                               content, !echo[i]);
+
+                               esd.setVisible(true);
+
+                               if (esd.answer == null)
+                                       throw new IOException("Login aborted by 
user");
+
+                               result[i] = esd.answer;
+                               promptCount++;
+                       }
+
+                       return result;
+               }
+
+               /* We maintain a prompt counter - this enables the detection of 
situations where the ssh
+                * server is signaling "authentication failed" even though it 
did not send a single prompt.
+                */
+
+               public int getPromptCount()
+               {
+                       return promptCount;
+               }
+       }
+
+       /**
+        * The SSH-2 connection is established in this thread.
+        * If we would not use a separate thread (e.g., put this code in
+        * the event handler of the "Login" button) then the GUI would not
+        * be responsive (missing window repaints if you move the window etc.)
+        */
+       class ConnectionThread extends Thread
+       {
+               String hostname;
+               String username;
+
+               public ConnectionThread(String hostname, String username)
+               {
+                       this.hostname = hostname;
+                       this.username = username;
+               }
+
+               public void run()
+               {
+                       Connection conn = new Connection(hostname);
+
+                       try
+                       {
+                               /*
+                                * 
+                                * CONNECT AND VERIFY SERVER HOST KEY (with 
callback)
+                                * 
+                                */
+
+                               String[] hostkeyAlgos = 
database.getPreferredServerHostkeyAlgorithmOrder(hostname);
+
+                               if (hostkeyAlgos != null)
+                                       
conn.setServerHostKeyAlgorithms(hostkeyAlgos);
+
+                               conn.connect(new AdvancedVerifier());
+
+                               /*
+                                * 
+                                * AUTHENTICATION PHASE
+                                * 
+                                */
+
+                               boolean enableKeyboardInteractive = true;
+                               boolean enableDSA = true;
+                               boolean enableRSA = true;
+
+                               String lastError = null;
+
+                               while (true)
+                               {
+                                       if ((enableDSA || enableRSA) && 
conn.isAuthMethodAvailable(username, "publickey"))
+                                       {
+                                               if (enableDSA)
+                                               {
+                                                       File key = new 
File(idDSAPath);
+
+                                                       if (key.exists())
+                                                       {
+                                                               
EnterSomethingDialog esd = new EnterSomethingDialog(loginFrame, "DSA 
Authentication",
+                                                                               
new String[] { lastError, "Enter DSA private key password:" }, true);
+                                                               
esd.setVisible(true);
+
+                                                               boolean res = 
conn.authenticateWithPublicKey(username, key, esd.answer);
+
+                                                               if (res == true)
+                                                                       break;
+
+                                                               lastError = 
"DSA authentication failed.";
+                                                       }
+                                                       enableDSA = false; // 
do not try again
+                                               }
+
+                                               if (enableRSA)
+                                               {
+                                                       File key = new 
File(idRSAPath);
+
+                                                       if (key.exists())
+                                                       {
+                                                               
EnterSomethingDialog esd = new EnterSomethingDialog(loginFrame, "RSA 
Authentication",
+                                                                               
new String[] { lastError, "Enter RSA private key password:" }, true);
+                                                               
esd.setVisible(true);
+
+                                                               boolean res = 
conn.authenticateWithPublicKey(username, key, esd.answer);
+
+                                                               if (res == true)
+                                                                       break;
+
+                                                               lastError = 
"RSA authentication failed.";
+                                                       }
+                                                       enableRSA = false; // 
do not try again
+                                               }
+
+                                               continue;
+                                       }
+
+                                       if (enableKeyboardInteractive && 
conn.isAuthMethodAvailable(username, "keyboard-interactive"))
+                                       {
+                                               InteractiveLogic il = new 
InteractiveLogic(lastError);
+
+                                               boolean res = 
conn.authenticateWithKeyboardInteractive(username, il);
+
+                                               if (res == true)
+                                                       break;
+
+                                               if (il.getPromptCount() == 0)
+                                               {
+                                                       // aha. the server 
announced that it supports "keyboard-interactive", but when
+                                                       // we asked for it, it 
just denied the request without sending us any prompt.
+                                                       // That happens with 
some server versions/configurations.
+                                                       // We just disable the 
"keyboard-interactive" method and notify the user.
+
+                                                       lastError = 
"Keyboard-interactive does not work.";
+
+                                                       
enableKeyboardInteractive = false; // do not try this again
+                                               }
+                                               else
+                                               {
+                                                       lastError = 
"Keyboard-interactive auth failed."; // try again, if possible
+                                               }
+
+                                               continue;
+                                       }
+
+                                       if 
(conn.isAuthMethodAvailable(username, "password"))
+                                       {
+                                               final EnterSomethingDialog esd 
= new EnterSomethingDialog(loginFrame,
+                                                               "Password 
Authentication",
+                                                               new String[] { 
lastError, "Enter password for " + username }, true);
+
+                                               esd.setVisible(true);
+
+                                               if (esd.answer == null)
+                                                       throw new 
IOException("Login aborted by user");
+
+                                               boolean res = 
conn.authenticateWithPassword(username, esd.answer);
+
+                                               if (res == true)
+                                                       break;
+
+                                               lastError = "Password 
authentication failed."; // try again, if possible
+
+                                               continue;
+                                       }
+
+                                       throw new IOException("No supported 
authentication methods available.");
+                               }
+
+                               /*
+                                * 
+                                * AUTHENTICATION OK. DO SOMETHING.
+                                * 
+                                */
+
+                               Session sess = conn.openSession();
+
+                               int x_width = 90;
+                               int y_width = 30;
+
+                               sess.requestPTY("dumb", x_width, y_width, 0, 0, 
null);
+                               sess.startShell();
+
+                               TerminalDialog td = new 
TerminalDialog(loginFrame, username + "@" + hostname, sess, x_width, y_width);
+
+                               /* The following call blocks until the dialog 
has been closed */
+
+                               td.setVisible(true);
+
+                       }
+                       catch (IOException e)
+                       {
+                               //e.printStackTrace();
+                               JOptionPane.showMessageDialog(loginFrame, 
"Exception: " + e.getMessage());
+                       }
+
+                       /*
+                        * 
+                        * CLOSE THE CONNECTION.
+                        * 
+                        */
+
+                       conn.close();
+
+                       /*
+                        * 
+                        * CLOSE THE LOGIN FRAME - APPLICATION WILL BE EXITED 
(no more frames)
+                        * 
+                        */
+
+                       Runnable r = new Runnable()
+                       {
+                               public void run()
+                               {
+                                       loginFrame.dispose();
+                               }
+                       };
+
+                       SwingUtilities.invokeLater(r);
+               }
+       }
+
+       void loginPressed()
+       {
+               String hostname = hostField.getText().trim();
+               String username = userField.getText().trim();
+
+               if ((hostname.length() == 0) || (username.length() == 0))
+               {
+                       JOptionPane.showMessageDialog(loginFrame, "Please fill 
out both fields!");
+                       return;
+               }
+
+               loginButton.setEnabled(false);
+               hostField.setEnabled(false);
+               userField.setEnabled(false);
+
+               ConnectionThread ct = new ConnectionThread(hostname, username);
+
+               ct.start();
+       }
+
+       void showGUI()
+       {
+               loginFrame = new JFrame("Trilead SSH-2 for Java SwingShell");
+
+               hostLabel = new JLabel("Hostname:");
+               userLabel = new JLabel("Username:");
+
+               hostField = new JTextField("", 20);
+               userField = new JTextField("", 10);
+
+               loginButton = new JButton("Login");
+
+               loginButton.addActionListener(new ActionListener()
+               {
+                       public void actionPerformed(java.awt.event.ActionEvent 
e)
+                       {
+                               loginPressed();
+                       }
+               });
+
+               JPanel loginPanel = new JPanel();
+
+               loginPanel.add(hostLabel);
+               loginPanel.add(hostField);
+               loginPanel.add(userLabel);
+               loginPanel.add(userField);
+               loginPanel.add(loginButton);
+
+               loginFrame.getRootPane().setDefaultButton(loginButton);
+
+               loginFrame.getContentPane().add(loginPanel, 
BorderLayout.PAGE_START);
+               //loginFrame.getContentPane().add(textArea, 
BorderLayout.CENTER);
+
+               loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+               loginFrame.pack();
+               loginFrame.setResizable(false);
+               loginFrame.setLocationRelativeTo(null);
+               loginFrame.setVisible(true);
+       }
+
+       void startGUI()
+       {
+               Runnable r = new Runnable()
+               {
+                       public void run()
+                       {
+                               showGUI();
+                       }
+               };
+
+               SwingUtilities.invokeLater(r);
+
+       }
+
+       public static void main(String[] args)
+       {
+               SwingShell client = new SwingShell();
+               client.startGUI();
+       }
+}
diff --git a/debian/examples/UsingKnownHosts.java 
b/debian/examples/UsingKnownHosts.java
new file mode 100644
index 0000000..708e290
--- /dev/null
+++ b/debian/examples/UsingKnownHosts.java
@@ -0,0 +1,86 @@
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import com.trilead.ssh2.Connection;
+import com.trilead.ssh2.KnownHosts;
+import com.trilead.ssh2.Session;
+import com.trilead.ssh2.StreamGobbler;
+
+/**
+ * This example shows how to deal with "known_hosts" files.
+ *  
+ * @author Christian Plattner, [email protected]
+ * @version $Id: UsingKnownHosts.java,v 1.2 2007/10/15 12:49:57 cplattne Exp $
+ */
+public class UsingKnownHosts
+{
+       static KnownHosts database = new KnownHosts();
+
+       public static void main(String[] args) throws IOException
+       {
+               String hostname = "somehost";
+               String username = "joe";
+               String password = "joespass";
+
+               File knownHosts = new File("~/.ssh/known_hosts");
+
+               try
+               {
+                       /* Load known_hosts file into in-memory database */
+
+                       if (knownHosts.exists())
+                               database.addHostkeys(knownHosts);
+
+                       /* Create a connection instance */
+
+                       Connection conn = new Connection(hostname);
+
+                       /* Now connect and use the SimpleVerifier */
+
+                       conn.connect(new SimpleVerifier(database));
+
+                       /* Authenticate */
+
+                       boolean isAuthenticated = 
conn.authenticateWithPassword(username, password);
+
+                       if (isAuthenticated == false)
+                               throw new IOException("Authentication failed.");
+
+                       /* Create a session */
+
+                       Session sess = conn.openSession();
+
+                       sess.execCommand("uname -a && date && uptime && who");
+
+                       InputStream stdout = new 
StreamGobbler(sess.getStdout());
+                       BufferedReader br = new BufferedReader(new 
InputStreamReader(stdout));
+
+                       System.out.println("Here is some information about the 
remote host:");
+
+                       while (true)
+                       {
+                               String line = br.readLine();
+                               if (line == null)
+                                       break;
+                               System.out.println(line);
+                       }
+
+                       /* Close this session */
+
+                       sess.close();
+
+                       /* Close the connection */
+
+                       conn.close();
+
+               }
+               catch (IOException e)
+               {
+                       e.printStackTrace(System.err);
+                       System.exit(2);
+               }
+       }
+}
diff --git a/debian/libtrilead-ssh2-java.docs b/debian/libtrilead-ssh2-java.docs
index 2754efd..efc2692 100644
--- a/debian/libtrilead-ssh2-java.docs
+++ b/debian/libtrilead-ssh2-java.docs
@@ -1,3 +1,3 @@
-README.txt
-examples
-faq/FAQ.html
+debian/README.txt
+debian/examples
+debian/FAQ.html
diff --git a/debian/rules b/debian/rules
index a0bc1bb..cf662bb 100755
--- a/debian/rules
+++ b/debian/rules
@@ -8,6 +8,3 @@ export JAVA_HOME=/usr/lib/jvm/default-java
 %:
        dh --with javahelper $@
 
-override_dh_installchangelogs:
-       dh_installchangelogs HISTORY.txt
-

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-java/trilead-ssh2.git

_______________________________________________
pkg-java-commits mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

Reply via email to