|  | @@ -5,163 +5,19 @@ using System.Globalization;
 | 
	
		
			
				|  |  |  using System.Net;
 | 
	
		
			
				|  |  |  using System.Net.Sockets;
 | 
	
		
			
				|  |  |  using System.Text;
 | 
	
		
			
				|  |  | +#if !FEATURE_WAITHANDLE_DISPOSE
 | 
	
		
			
				|  |  | +using System.Threading;
 | 
	
		
			
				|  |  | +#endif // !FEATURE_WAITHANDLE_DISPOSE
 | 
	
		
			
				|  |  |  using Renci.SshNet.Abstractions;
 | 
	
		
			
				|  |  | -using Renci.SshNet.Common;
 | 
	
		
			
				|  |  |  using Renci.SshNet.Messages;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -namespace Renci.SshNet
 | 
	
		
			
				|  |  | +namespace Renci.SshNet.Common
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      /// <summary>
 | 
	
		
			
				|  |  |      /// Collection of different extension method
 | 
	
		
			
				|  |  |      /// </summary>
 | 
	
		
			
				|  |  |      internal static partial class Extensions
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  | -        private enum ShellQuoteState
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            Unquoted = 1,
 | 
	
		
			
				|  |  | -            SingleQuoted = 2,
 | 
	
		
			
				|  |  | -            Quoted = 3
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        /// <summary>
 | 
	
		
			
				|  |  | -        /// Quotes a <see cref="string"/> in a way to be suitable to be used with a shell.
 | 
	
		
			
				|  |  | -        /// </summary>
 | 
	
		
			
				|  |  | -        /// <param name="value">The <see cref="string"/> to quote.</param>
 | 
	
		
			
				|  |  | -        /// <returns>
 | 
	
		
			
				|  |  | -        /// A quoted <see cref="string"/>.
 | 
	
		
			
				|  |  | -        /// </returns>
 | 
	
		
			
				|  |  | -        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
 | 
	
		
			
				|  |  | -        /// <remarks>
 | 
	
		
			
				|  |  | -        /// <para>
 | 
	
		
			
				|  |  | -        /// If <paramref name="value"/> contains a single-quote, that character is embedded
 | 
	
		
			
				|  |  | -        /// in quotation marks (eg. "'"). Sequences of single-quotes are grouped in a one
 | 
	
		
			
				|  |  | -        /// pair of quotation marks.
 | 
	
		
			
				|  |  | -        /// </para>
 | 
	
		
			
				|  |  | -        /// <para>
 | 
	
		
			
				|  |  | -        /// If the <see cref="string"/> contains an exclamation mark (!), the C-Shell interprets
 | 
	
		
			
				|  |  | -        /// it as a meta-character for history substitution. This even works inside single-quotes
 | 
	
		
			
				|  |  | -        /// or quotation marks, unless escaped with a backslash (\).
 | 
	
		
			
				|  |  | -        /// </para>
 | 
	
		
			
				|  |  | -        /// <para>
 | 
	
		
			
				|  |  | -        /// References:
 | 
	
		
			
				|  |  | -        /// <list type="bullet">
 | 
	
		
			
				|  |  | -        ///   <item>
 | 
	
		
			
				|  |  | -        ///     <description><a href="http://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html">Shell Command Language</a></description>
 | 
	
		
			
				|  |  | -        ///   </item>
 | 
	
		
			
				|  |  | -        ///   <item>
 | 
	
		
			
				|  |  | -        ///     <description><a href="https://earthsci.stanford.edu/computing/unix/shell/specialchars.php">Unix C-Shell special characters and their uses</a></description>
 | 
	
		
			
				|  |  | -        ///   </item>
 | 
	
		
			
				|  |  | -        ///   <item>
 | 
	
		
			
				|  |  | -        ///     <description><a href="https://docstore.mik.ua/orelly/unix3/upt/ch27_13.htm">Differences Between Bourne and C Shell Quoting</a></description>
 | 
	
		
			
				|  |  | -        ///   </item>
 | 
	
		
			
				|  |  | -        /// </list>
 | 
	
		
			
				|  |  | -        /// </para>
 | 
	
		
			
				|  |  | -        /// </remarks>
 | 
	
		
			
				|  |  | -        public static string ShellQuote(this string value)
 | 
	
		
			
				|  |  | -        {
 | 
	
		
			
				|  |  | -            if (value == null)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                throw new ArgumentNullException("value");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            // result is at least value and leading/trailing single-quote
 | 
	
		
			
				|  |  | -            var sb = new StringBuilder(value.Length + 2);
 | 
	
		
			
				|  |  | -            var state = ShellQuoteState.Unquoted;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            foreach (var c in value)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                switch (c)
 | 
	
		
			
				|  |  | -                {
 | 
	
		
			
				|  |  | -                    case '\'':
 | 
	
		
			
				|  |  | -                        // embed a single-quote in quotes
 | 
	
		
			
				|  |  | -                        switch (state)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.Unquoted:
 | 
	
		
			
				|  |  | -                                // Start quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('"');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.Quoted:
 | 
	
		
			
				|  |  | -                                // Continue quoted string
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.SingleQuoted:
 | 
	
		
			
				|  |  | -                                // Close single quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('\'');
 | 
	
		
			
				|  |  | -                                // Start quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('"');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        state = ShellQuoteState.Quoted;
 | 
	
		
			
				|  |  | -                        break;
 | 
	
		
			
				|  |  | -                    case '!':
 | 
	
		
			
				|  |  | -                        // In C-Shell, an exclamatation point can only be protected from shell interpretation
 | 
	
		
			
				|  |  | -                        // when escaped by a backslash
 | 
	
		
			
				|  |  | -                        // Source:
 | 
	
		
			
				|  |  | -                        // https://earthsci.stanford.edu/computing/unix/shell/specialchars.php
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                        switch (state)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.Unquoted:
 | 
	
		
			
				|  |  | -                                sb.Append('\\');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.Quoted:
 | 
	
		
			
				|  |  | -                                // Close quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('"');
 | 
	
		
			
				|  |  | -                                sb.Append('\\');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.SingleQuoted:
 | 
	
		
			
				|  |  | -                                // Close single quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('\'');
 | 
	
		
			
				|  |  | -                                sb.Append('\\');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        state = ShellQuoteState.Unquoted;
 | 
	
		
			
				|  |  | -                        break;
 | 
	
		
			
				|  |  | -                    default:
 | 
	
		
			
				|  |  | -                        switch (state)
 | 
	
		
			
				|  |  | -                        {
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.Unquoted:
 | 
	
		
			
				|  |  | -                                // Start single-quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('\'');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.Quoted:
 | 
	
		
			
				|  |  | -                                // Close quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('"');
 | 
	
		
			
				|  |  | -                                // Start single quoted string
 | 
	
		
			
				|  |  | -                                sb.Append('\'');
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                            case ShellQuoteState.SingleQuoted:
 | 
	
		
			
				|  |  | -                                // Continue single quoted string
 | 
	
		
			
				|  |  | -                                break;
 | 
	
		
			
				|  |  | -                        }
 | 
	
		
			
				|  |  | -                        state = ShellQuoteState.SingleQuoted;
 | 
	
		
			
				|  |  | -                        break;
 | 
	
		
			
				|  |  | -                }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -                sb.Append(c);
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            switch (state)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                case ShellQuoteState.Unquoted:
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  | -                case ShellQuoteState.Quoted:
 | 
	
		
			
				|  |  | -                    // Close quoted string
 | 
	
		
			
				|  |  | -                    sb.Append('"');
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  | -                case ShellQuoteState.SingleQuoted:
 | 
	
		
			
				|  |  | -                    /* Close single quoted string */
 | 
	
		
			
				|  |  | -                    sb.Append('\'');
 | 
	
		
			
				|  |  | -                    break;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            if (sb.Length == 0)
 | 
	
		
			
				|  |  | -            {
 | 
	
		
			
				|  |  | -                sb.Append("''");
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            return sb.ToString();
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Determines whether the specified value is null or white space.
 | 
	
		
			
				|  |  |          /// </summary>
 | 
	
	
		
			
				|  | @@ -421,5 +277,35 @@ namespace Renci.SshNet
 | 
	
		
			
				|  |  |                  return false;
 | 
	
		
			
				|  |  |              return socket.Connected;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#if !FEATURE_SOCKET_DISPOSE
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Disposes the specified socket.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="socket">The socket.</param>
 | 
	
		
			
				|  |  | +        [DebuggerNonUserCode]
 | 
	
		
			
				|  |  | +        internal static void Dispose(this Socket socket)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (socket == null)
 | 
	
		
			
				|  |  | +                throw new NullReferenceException();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            socket.Close();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +#endif // !FEATURE_SOCKET_DISPOSE
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#if !FEATURE_WAITHANDLE_DISPOSE
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Disposes the specified handle.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        /// <param name="handle">The handle.</param>
 | 
	
		
			
				|  |  | +        [DebuggerNonUserCode]
 | 
	
		
			
				|  |  | +        internal static void Dispose(this WaitHandle handle)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (handle == null)
 | 
	
		
			
				|  |  | +                throw new NullReferenceException();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            handle.Close();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +#endif // !FEATURE_WAITHANDLE_DISPOSE
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |