|
@@ -23,15 +23,142 @@ using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.IO;
|
|
|
|
+using System.Linq;
|
|
using System.Text;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Forms;
|
|
using Microsoft.Win32;
|
|
using Microsoft.Win32;
|
|
|
|
|
|
|
|
+public enum Option
|
|
|
|
+{
|
|
|
|
+ None,
|
|
|
|
+ Set,
|
|
|
|
+ Optional,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+public interface Handler
|
|
|
|
+{
|
|
|
|
+ IList<string> Usages
|
|
|
|
+ {
|
|
|
|
+ get;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Option DoMatch(string arg);
|
|
|
|
+ bool Find();
|
|
|
|
+ void Execute(Uri uri, string user, string password);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+public abstract class FindInPathMixin
|
|
|
|
+{
|
|
|
|
+ protected string FindInPath(string program)
|
|
|
|
+ {
|
|
|
|
+ foreach (string location in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator))
|
|
|
|
+ {
|
|
|
|
+ string path = Path.Combine(location, "putty.exe");
|
|
|
|
+ if (File.Exists(path))
|
|
|
|
+ return path;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+public class Putty : FindInPathMixin, Handler
|
|
|
|
+{
|
|
|
|
+ private Regex option = new Regex(@"^(?:/|--?)putty(?:[:=](?<putty_path>.*))?$", RegexOptions.IgnoreCase);
|
|
|
|
+ private string path = null;
|
|
|
|
+
|
|
|
|
+ public IList<string> Usages
|
|
|
|
+ {
|
|
|
|
+ get
|
|
|
|
+ {
|
|
|
|
+ return new string[] { "/putty[:<putty-path>] -- Use PuTTY to connect" };
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public Option DoMatch(string arg)
|
|
|
|
+ {
|
|
|
|
+ Match match;
|
|
|
|
+
|
|
|
|
+ if ((match = option.Match(arg)).Success)
|
|
|
|
+ {
|
|
|
|
+ Group group = match.Groups["putty_path"];
|
|
|
|
+ if (group.Success)
|
|
|
|
+ path = group.Value;
|
|
|
|
+ return Option.Set;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ return Option.None;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public bool Find()
|
|
|
|
+ {
|
|
|
|
+ if (path != null)
|
|
|
|
+ goto found;
|
|
|
|
+
|
|
|
|
+ foreach (RegistryHive hive in new RegistryHive[] { RegistryHive.CurrentUser, RegistryHive.LocalMachine })
|
|
|
|
+ {
|
|
|
|
+ IList<RegistryView> views = new List<RegistryView>(new RegistryView[] { RegistryView.Registry32 });
|
|
|
|
+ if (Environment.Is64BitOperatingSystem)
|
|
|
|
+ views.Insert(0, RegistryView.Registry64);
|
|
|
|
+
|
|
|
|
+ foreach (RegistryView view in views)
|
|
|
|
+ using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, view), key = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PuTTY_is1"))
|
|
|
|
+ if (key != null)
|
|
|
|
+ {
|
|
|
|
+ string location = (string)key.GetValue("InstallLocation");
|
|
|
|
+ if (location == null)
|
|
|
|
+ continue;
|
|
|
|
+ path = Path.Combine(location, "putty.exe");
|
|
|
|
+ if (File.Exists(path))
|
|
|
|
+ {
|
|
|
|
+ Debug.WriteLine("Found PuTTY in registry: {0}", path, null);
|
|
|
|
+ goto found;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ path = null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((path = FindInPath("putty.exe")) != null)
|
|
|
|
+ {
|
|
|
|
+ Debug.WriteLine("Found PuTTY in path: {0}", path, null);
|
|
|
|
+ goto found;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ found:
|
|
|
|
+ path = path.Trim();
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void Execute(Uri uri, string user, string password)
|
|
|
|
+ {
|
|
|
|
+ if (!Find())
|
|
|
|
+ throw new Exception("Could not find PuTTY executable.");
|
|
|
|
+
|
|
|
|
+ StringBuilder args = new StringBuilder();
|
|
|
|
+ if (password != null)
|
|
|
|
+ args.AppendFormat("-pw {0} ", password);
|
|
|
|
+ if (uri.Port != -1)
|
|
|
|
+ args.AppendFormat("-P {0} ", uri.Port);
|
|
|
|
+ if (user != null)
|
|
|
|
+ args.AppendFormat("{0}@", user);
|
|
|
|
+ args.Append(uri.Host);
|
|
|
|
+
|
|
|
|
+ Debug.WriteLine("Running PuTTY command: {0} {1}", path, args);
|
|
|
|
+ Process.Start(path, args.ToString());
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
public class SshHandler
|
|
public class SshHandler
|
|
{
|
|
{
|
|
- private enum Handler { Unspecified, Putty };
|
|
+ private static IList<Handler> handlers = new Handler[]
|
|
- private static Handler handler = Handler.Unspecified;
|
|
+ {
|
|
|
|
+ new Putty(),
|
|
|
|
+ };
|
|
|
|
+ private static Handler handler = null;
|
|
private static string puttyPath = null;
|
|
private static string puttyPath = null;
|
|
|
|
|
|
public static int Main(string[] args)
|
|
public static int Main(string[] args)
|
|
@@ -41,7 +168,6 @@ public class SshHandler
|
|
try
|
|
try
|
|
{
|
|
{
|
|
Regex usage = new Regex(@"^(?:/|--?)(?:h|help|usage|\?)$", RegexOptions.IgnoreCase);
|
|
Regex usage = new Regex(@"^(?:/|--?)(?:h|help|usage|\?)$", RegexOptions.IgnoreCase);
|
|
- Regex putty = new Regex(@"^(?:/|--?)putty(?:[:=](?<putty_path>.*))?$", RegexOptions.IgnoreCase);
|
|
|
|
IList<string> uriParts = null;
|
|
IList<string> uriParts = null;
|
|
|
|
|
|
foreach (string arg in args)
|
|
foreach (string arg in args)
|
|
@@ -50,16 +176,7 @@ public class SshHandler
|
|
if (usage.IsMatch(arg))
|
|
if (usage.IsMatch(arg))
|
|
return Usage(0);
|
|
return Usage(0);
|
|
|
|
|
|
- Match match;
|
|
+ if (!MatchHandler(arg))
|
|
-
|
|
|
|
- if ((match = putty.Match(arg)).Success)
|
|
|
|
- {
|
|
|
|
- handler = Handler.Putty;
|
|
|
|
- Group group = match.Groups["putty_path"];
|
|
|
|
- if (group.Success)
|
|
|
|
- puttyPath = group.Value;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
uriParts = new List<string>(new string[] { arg });
|
|
uriParts = new List<string>(new string[] { arg });
|
|
}
|
|
}
|
|
else
|
|
else
|
|
@@ -68,19 +185,14 @@ public class SshHandler
|
|
if (uriParts != null)
|
|
if (uriParts != null)
|
|
{
|
|
{
|
|
Uri uri = new Uri(string.Join(" ", uriParts), UriKind.Absolute);
|
|
Uri uri = new Uri(string.Join(" ", uriParts), UriKind.Absolute);
|
|
|
|
+ string user, password;
|
|
|
|
|
|
- switch (handler)
|
|
+ SetUserPassword(uri, out user, out password);
|
|
- {
|
|
+
|
|
- case Handler.Unspecified:
|
|
+ if (handler == null)
|
|
- if (FindPutty())
|
|
+ handler = FindHandler();
|
|
- Putty(uri);
|
|
+
|
|
- else
|
|
+ handler.Execute(uri, user, password);
|
|
- throw new Exception("Could not find a suitable SSH application.");
|
|
|
|
- break;
|
|
|
|
- case Handler.Putty:
|
|
|
|
- Putty(uri);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
else
|
|
else
|
|
return Usage(1);
|
|
return Usage(1);
|
|
@@ -97,11 +209,27 @@ public class SshHandler
|
|
private static int Usage(int code)
|
|
private static int Usage(int code)
|
|
{
|
|
{
|
|
MessageBox.Show("ssh-handler [/putty[:<putty-path>]] <ssh-url>\n\n" +
|
|
MessageBox.Show("ssh-handler [/putty[:<putty-path>]] <ssh-url>\n\n" +
|
|
- "/putty[:<putty-path>] -- Use PuTTY to connect", "SSH Handler Usage", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
+ string.Join("\n", handlers.SelectMany(handler => handler.Usages)), "SSH Handler Usage", MessageBoxButtons.OK,
|
|
|
|
+ MessageBoxIcon.Information);
|
|
return code;
|
|
return code;
|
|
}
|
|
}
|
|
|
|
|
|
- private static void UserPassword(Uri uri, out string user, out string password)
|
|
+ private static bool MatchHandler(string arg)
|
|
|
|
+ {
|
|
|
|
+ foreach (Handler handler in handlers)
|
|
|
|
+ switch (handler.DoMatch(arg))
|
|
|
|
+ {
|
|
|
|
+ case Option.Set:
|
|
|
|
+ SshHandler.handler = handler;
|
|
|
|
+ goto case Option.Optional;
|
|
|
|
+ case Option.Optional:
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void SetUserPassword(Uri uri, out string user, out string password)
|
|
{
|
|
{
|
|
if (uri.UserInfo.Length != 0)
|
|
if (uri.UserInfo.Length != 0)
|
|
{
|
|
{
|
|
@@ -116,72 +244,12 @@ public class SshHandler
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- private static bool FindPutty()
|
|
+ private static Handler FindHandler()
|
|
- {
|
|
|
|
- if (puttyPath != null)
|
|
|
|
- goto found;
|
|
|
|
-
|
|
|
|
- foreach (RegistryHive hive in new RegistryHive[] { RegistryHive.CurrentUser, RegistryHive.LocalMachine })
|
|
|
|
- {
|
|
|
|
- IList<RegistryView> views = new List<RegistryView>(new RegistryView[] { RegistryView.Registry32 });
|
|
|
|
- if (Environment.Is64BitOperatingSystem)
|
|
|
|
- views.Insert(0, RegistryView.Registry64);
|
|
|
|
-
|
|
|
|
- foreach (RegistryView view in views)
|
|
|
|
- using (RegistryKey baseKey = RegistryKey.OpenBaseKey(hive, view), key = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PuTTY_is1"))
|
|
|
|
- if (key != null)
|
|
|
|
- {
|
|
|
|
- string path = (string)key.GetValue("InstallLocation");
|
|
|
|
- if (path == null)
|
|
|
|
- continue;
|
|
|
|
- puttyPath = Path.Combine(path, "putty.exe");
|
|
|
|
- if (File.Exists(puttyPath))
|
|
|
|
- {
|
|
|
|
- Debug.WriteLine("Found PuTTY in registry: {0}", puttyPath, null);
|
|
|
|
- goto found;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- puttyPath = null;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- foreach (string path in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator))
|
|
|
|
- {
|
|
|
|
- puttyPath = Path.Combine(path, "putty.exe");
|
|
|
|
- if (File.Exists(puttyPath))
|
|
|
|
- {
|
|
|
|
- Debug.WriteLine("Found PuTTY in path: {0}", puttyPath, null);
|
|
|
|
- goto found;
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
- puttyPath = null;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- found:
|
|
|
|
- puttyPath = puttyPath.Trim();
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private static void Putty(Uri uri)
|
|
|
|
{
|
|
{
|
|
- if (!FindPutty())
|
|
+ foreach (Handler handler in handlers)
|
|
- throw new Exception("Could not find PuTTY executable.");
|
|
+ if (handler.Find())
|
|
-
|
|
+ return handler;
|
|
- string user, password;
|
|
|
|
- UserPassword(uri, out user, out password);
|
|
|
|
-
|
|
|
|
- StringBuilder args = new StringBuilder();
|
|
|
|
- if (password != null)
|
|
|
|
- args.AppendFormat("-pw {0} ", password);
|
|
|
|
- if (uri.Port != -1)
|
|
|
|
- args.AppendFormat("-P {0} ", uri.Port);
|
|
|
|
- if (user != null)
|
|
|
|
- args.AppendFormat("{0}@", user);
|
|
|
|
- args.Append(uri.Host);
|
|
|
|
|
|
|
|
- Debug.WriteLine("Running PuTTY command: {0} {1}", puttyPath, args);
|
|
+ throw new Exception("Could not find a suitable SSH application.");
|
|
- Process.Start(puttyPath, args.ToString());
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|