| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 | using System;using System.Collections.Generic;using System.IO;using System.Collections.ObjectModel;using System.Text;using System.Diagnostics.CodeAnalysis;namespace Renci.SshNet{    /// <summary>    /// Provides client connection to SSH server.    /// </summary>    public class SshClient : BaseClient    {        /// <summary>        /// Holds the list of forwarded ports        /// </summary>        private List<ForwardedPort> _forwardedPorts = new List<ForwardedPort>();        private bool _disposeConnectionInfo;                private Stream _inputStream;        /// <summary>        /// Gets the list of forwarded ports.        /// </summary>        public IEnumerable<ForwardedPort> ForwardedPorts        {            get            {                return this._forwardedPorts.AsReadOnly();            }        }        #region Constructors        /// <summary>        /// Initializes a new instance of the <see cref="SshClient"/> class.        /// </summary>        /// <param name="connectionInfo">The connection info.</param>        /// <exception cref="ArgumentNullException"><paramref name="connectionInfo"/> is null.</exception>        public SshClient(ConnectionInfo connectionInfo)            : base(connectionInfo)        {        }        /// <summary>        /// Initializes a new instance of the <see cref="SshClient"/> class.        /// </summary>        /// <param name="host">Connection host.</param>        /// <param name="port">Connection port.</param>        /// <param name="username">Authentication username.</param>        /// <param name="password">Authentication password.</param>        /// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>        /// <exception cref="ArgumentException"><paramref name="host"/> is invalid, or <paramref name="username"/> is null or contains whitespace characters.</exception>        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="System.Net.IPEndPoint.MinPort"/> and <see cref="System.Net.IPEndPoint.MaxPort"/>.</exception>        [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification="Disposed in Dispose(bool) method.")]        public SshClient(string host, int port, string username, string password)            : this(new PasswordConnectionInfo(host, port, username, password))        {            this._disposeConnectionInfo = true;        }        /// <summary>        /// Initializes a new instance of the <see cref="SshClient"/> class.        /// </summary>        /// <param name="host">Connection host.</param>        /// <param name="username">Authentication username.</param>        /// <param name="password">Authentication password.</param>        /// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>        /// <exception cref="ArgumentException"><paramref name="host"/> is invalid, or <paramref name="username"/> is null or contains whitespace characters.</exception>        public SshClient(string host, string username, string password)            : this(host, 22, username, password)        {        }        /// <summary>        /// Initializes a new instance of the <see cref="SshClient"/> class.        /// </summary>        /// <param name="host">Connection host.</param>        /// <param name="port">Connection port.</param>        /// <param name="username">Authentication username.</param>        /// <param name="keyFiles">Authentication private key file(s) .</param>        /// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is null.</exception>        /// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is null or contains whitespace characters.</exception>        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="System.Net.IPEndPoint.MinPort"/> and <see cref="System.Net.IPEndPoint.MaxPort"/>.</exception>        [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]        public SshClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)            : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles))        {            this._disposeConnectionInfo = true;        }        /// <summary>        /// Initializes a new instance of the <see cref="SshClient"/> class.        /// </summary>        /// <param name="host">Connection host.</param>        /// <param name="username">Authentication username.</param>        /// <param name="keyFiles">Authentication private key file(s) .</param>        /// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is null.</exception>        /// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is null or contains whitespace characters.</exception>        public SshClient(string host, string username, params PrivateKeyFile[] keyFiles)            : this(host, 22, username, keyFiles)        {        }        #endregion        /// <summary>        /// Called when client is disconnecting from the server.        /// </summary>        protected override void OnDisconnecting()        {            base.OnDisconnecting();            foreach (var port in this._forwardedPorts)            {                port.Stop();            }        }        /// <summary>        /// Adds the forwarded port.        /// </summary>        /// <param name="port">The port.</param>        public void AddForwardedPort(ForwardedPort port)         {            //  Ensure that connection is established.            this.EnsureConnection();            if (port.Session != null && port.Session != this.Session)                throw new InvalidOperationException("Forwarded port is already added to a different client.");            port.Session = this.Session;            this._forwardedPorts.Add(port);        }        /// <summary>        /// Stops and removes the forwarded port from the list.        /// </summary>        /// <param name="port">Forwarded port.</param>        /// <exception cref="ArgumentNullException"><paramref name="port"/> is null.</exception>        public void RemoveForwardedPort(ForwardedPort port)        {            if (port == null)                throw new ArgumentNullException("port");            //  Stop port forwarding before removing it            port.Stop();            port.Session = null;            this._forwardedPorts.Remove(port);        }        /// <summary>        /// Creates the command to be executed.        /// </summary>        /// <param name="commandText">The command text.</param>        /// <returns><see cref="SshCommand"/> object.</returns>        public SshCommand CreateCommand(string commandText)        {            return this.CreateCommand(commandText, Encoding.UTF8);        }        /// <summary>        /// Creates the command to be executed with specified encoding.        /// </summary>        /// <param name="commandText">The command text.</param>        /// <param name="encoding">The encoding to use for results.</param>        /// <returns><see cref="SshCommand"/> object which uses specified encoding.</returns>        public SshCommand CreateCommand(string commandText, Encoding encoding)        {            //  Ensure that connection is established.            this.EnsureConnection();            return new SshCommand(this.Session, commandText, encoding);        }        /// <summary>        /// Creates and executes the command.        /// </summary>        /// <param name="commandText">The command text.</param>        /// <returns>Returns an instance of <see cref="SshCommand"/> with execution results.</returns>        /// <remarks>This method internally uses asynchronous calls.</remarks>        /// <exception cref="ArgumentException">CommandText property is empty.</exception>        /// <exception cref="Renci.SshNet.Common.SshException">Invalid Operation - An existing channel was used to execute this command.</exception>        /// <exception cref="InvalidOperationException">Asynchronous operation is already in progress.</exception>        public SshCommand RunCommand(string commandText)        {                        var cmd = this.CreateCommand(commandText);            cmd.Execute();            return cmd;        }        /// <summary>        /// Creates the shell.        /// </summary>        /// <param name="input">The input.</param>        /// <param name="output">The output.</param>        /// <param name="extendedOutput">The extended output.</param>        /// <param name="terminalName">Name of the terminal.</param>        /// <param name="columns">The columns.</param>        /// <param name="rows">The rows.</param>        /// <param name="width">The width.</param>        /// <param name="height">The height.</param>        /// <param name="terminalMode">The terminal mode.</param>        /// <param name="bufferSize">Size of the internal read buffer.</param>        /// <returns>Returns a representation of a <see cref="Shell"/> object.</returns>        public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, string terminalMode, int bufferSize)        {            //  Ensure that connection is established.            this.EnsureConnection();            return new Shell(this.Session, input, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, bufferSize);        }        /// <summary>        /// Creates the shell.        /// </summary>        /// <param name="input">The input.</param>        /// <param name="output">The output.</param>        /// <param name="extendedOutput">The extended output.</param>        /// <param name="terminalName">Name of the terminal.</param>        /// <param name="columns">The columns.</param>        /// <param name="rows">The rows.</param>        /// <param name="width">The width.</param>        /// <param name="height">The height.</param>        /// <param name="terminalMode">The terminal mode.</param>        /// <returns>Returns a representation of a <see cref="Shell"/> object.</returns>        public Shell CreateShell(Stream input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, string terminalMode)        {            return this.CreateShell(input, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, 1024);        }        /// <summary>        /// Creates the shell.        /// </summary>        /// <param name="input">The input.</param>        /// <param name="output">The output.</param>        /// <param name="extendedOutput">The extended output.</param>        /// <returns>Returns a representation of a <see cref="Shell"/> object.</returns>        public Shell CreateShell(Stream input, Stream output, Stream extendedOutput)        {            return this.CreateShell(input, output, extendedOutput, string.Empty, 0, 0, 0, 0, string.Empty, 1024);        }        /// <summary>        /// Creates the shell.        /// </summary>        /// <param name="encoding">The encoding to use to send the input.</param>        /// <param name="input">The input.</param>        /// <param name="output">The output.</param>        /// <param name="extendedOutput">The extended output.</param>        /// <param name="terminalName">Name of the terminal.</param>        /// <param name="columns">The columns.</param>        /// <param name="rows">The rows.</param>        /// <param name="width">The width.</param>        /// <param name="height">The height.</param>        /// <param name="terminalMode">The terminal mode.</param>        /// <param name="bufferSize">Size of the internal read buffer.</param>        /// <returns>Returns a representation of a <see cref="Shell"/> object.</returns>        public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width , uint height , string terminalMode, int bufferSize)        {            //  Ensure that connection is established.            this.EnsureConnection();            this._inputStream = new MemoryStream();            var writer = new StreamWriter(this._inputStream, encoding);            writer.Write(input);            writer.Flush();            this._inputStream.Seek(0, SeekOrigin.Begin);            return this.CreateShell(this._inputStream, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, bufferSize);        }        /// <summary>        /// Creates the shell.        /// </summary>        /// <param name="encoding">The encoding.</param>        /// <param name="input">The input.</param>        /// <param name="output">The output.</param>        /// <param name="extendedOutput">The extended output.</param>        /// <param name="terminalName">Name of the terminal.</param>        /// <param name="columns">The columns.</param>        /// <param name="rows">The rows.</param>        /// <param name="width">The width.</param>        /// <param name="height">The height.</param>        /// <param name="terminalMode">The terminal mode.</param>        /// <returns>Returns a representation of a <see cref="Shell"/> object.</returns>        public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, string terminalMode)        {            return this.CreateShell(encoding, input, output, extendedOutput, terminalName, columns, rows, width, height, terminalMode, 1024);        }        /// <summary>        /// Creates the shell.        /// </summary>        /// <param name="encoding">The encoding.</param>        /// <param name="input">The input.</param>        /// <param name="output">The output.</param>        /// <param name="extendedOutput">The extended output.</param>        /// <returns>Returns a representation of a <see cref="Shell"/> object.</returns>        public Shell CreateShell(Encoding encoding, string input, Stream output, Stream extendedOutput)        {            return this.CreateShell(encoding, input, output, extendedOutput, string.Empty, 0, 0, 0, 0, string.Empty, 1024);        }        /// <summary>        /// Releases unmanaged and - optionally - managed resources        /// </summary>        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged ResourceMessages.</param>        protected override void Dispose(bool disposing)        {            base.Dispose(disposing);            if (this._disposeConnectionInfo)                ((IDisposable)this.ConnectionInfo).Dispose();            if (this._inputStream != null)            {                this._inputStream.Dispose();                this._inputStream = null;            }        }    }}
 |