mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 14:07:46 +08:00
381 lines
9.8 KiB
C#
381 lines
9.8 KiB
C#
using mRemoteNG.App;
|
|
using mRemoteNG.Connection;
|
|
using mRemoteNG.Connection.Protocol;
|
|
using mRemoteNG.Messages;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
namespace mRemoteNG.Config.Putty
|
|
{
|
|
public class XmingProvider : Provider
|
|
{
|
|
#region Private Fields
|
|
private const string RegistrySessionNameFormat = "{0} [registry]";
|
|
private const string RegistrySessionNamePattern = "(.*)\\ \\[registry\\]";
|
|
private static readonly RegistryProvider RegistryProvider = new RegistryProvider();
|
|
private static FileSystemWatcher _eventWatcher;
|
|
#endregion
|
|
|
|
#region Public Methods
|
|
public override string[] GetSessionNames(bool raw = false)
|
|
{
|
|
string sessionsFolderPath = GetSessionsFolderPath();
|
|
if (!Directory.Exists(sessionsFolderPath))
|
|
{
|
|
return new string[] {};
|
|
}
|
|
|
|
List<string> sessionNames = new List<string>();
|
|
foreach (string sessionName in Directory.GetFiles(sessionsFolderPath))
|
|
{
|
|
string _sessionFileName = Path.GetFileName(sessionName);
|
|
if (raw)
|
|
{
|
|
sessionNames.Add(_sessionFileName);
|
|
}
|
|
else
|
|
{
|
|
sessionNames.Add(System.Web.HttpUtility.UrlDecode(_sessionFileName.Replace("+", "%2B")));
|
|
}
|
|
}
|
|
|
|
if (raw)
|
|
{
|
|
if (!sessionNames.Contains("Default%20Settings")) // Do not localize
|
|
{
|
|
sessionNames.Insert(0, "Default%20Settings");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!sessionNames.Contains("Default Settings"))
|
|
{
|
|
sessionNames.Insert(0, "Default Settings");
|
|
}
|
|
}
|
|
|
|
List<string> registrySessionNames = new List<string>();
|
|
foreach (string sessionName in RegistryProvider.GetSessionNames(raw))
|
|
{
|
|
registrySessionNames.Add(string.Format(RegistrySessionNameFormat, sessionName));
|
|
}
|
|
|
|
sessionNames.AddRange(registrySessionNames);
|
|
sessionNames.Sort();
|
|
|
|
return sessionNames.ToArray();
|
|
}
|
|
|
|
public override PuttySessionInfo GetSession(string sessionName)
|
|
{
|
|
string registrySessionName = GetRegistrySessionName(sessionName);
|
|
if (!string.IsNullOrEmpty(registrySessionName))
|
|
{
|
|
return ModifyRegistrySessionInfo(RegistryProvider.GetSession(registrySessionName));
|
|
}
|
|
|
|
string sessionsFolderPath = GetSessionsFolderPath();
|
|
if (!Directory.Exists(sessionsFolderPath))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
string sessionFile = Path.Combine(sessionsFolderPath, sessionName);
|
|
if (!File.Exists(sessionFile))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
sessionName = System.Web.HttpUtility.UrlDecode(sessionName.Replace("+", "%2B"));
|
|
|
|
SessionFileReader sessionFileReader = new SessionFileReader(sessionFile);
|
|
PuttySessionInfo sessionInfo = new PuttySessionInfo();
|
|
sessionInfo.PuttySession = sessionName;
|
|
sessionInfo.Name = sessionName;
|
|
sessionInfo.Hostname = sessionFileReader.GetValue("HostName");
|
|
sessionInfo.Username = sessionFileReader.GetValue("UserName");
|
|
string protocol = sessionFileReader.GetValue("Protocol");
|
|
if (protocol == null)
|
|
{
|
|
protocol = "ssh";
|
|
}
|
|
switch (protocol.ToLowerInvariant())
|
|
{
|
|
case "raw":
|
|
sessionInfo.Protocol = ProtocolType.RAW;
|
|
break;
|
|
case "rlogin":
|
|
sessionInfo.Protocol = ProtocolType.Rlogin;
|
|
break;
|
|
case "serial":
|
|
return null;
|
|
case "ssh":
|
|
object sshVersionObject = sessionFileReader.GetValue("SshProt");
|
|
if (sshVersionObject != null)
|
|
{
|
|
int sshVersion = System.Convert.ToInt32(sshVersionObject);
|
|
if (sshVersion >= 2)
|
|
{
|
|
sessionInfo.Protocol = ProtocolType.SSH2;
|
|
}
|
|
else
|
|
{
|
|
sessionInfo.Protocol = ProtocolType.SSH1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sessionInfo.Protocol = ProtocolType.SSH2;
|
|
}
|
|
break;
|
|
case "telnet":
|
|
sessionInfo.Protocol = ProtocolType.Telnet;
|
|
break;
|
|
default:
|
|
return null;
|
|
}
|
|
sessionInfo.Port = Convert.ToInt32(sessionFileReader.GetValue("PortNumber"));
|
|
|
|
return sessionInfo;
|
|
}
|
|
|
|
public override void StartWatcher()
|
|
{
|
|
RegistryProvider.StartWatcher();
|
|
RegistryProvider.SessionChanged += OnRegistrySessionChanged;
|
|
|
|
if (_eventWatcher != null)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
try
|
|
{
|
|
_eventWatcher = new FileSystemWatcher(GetSessionsFolderPath());
|
|
_eventWatcher.NotifyFilter = (System.IO.NotifyFilters) (NotifyFilters.FileName | NotifyFilters.LastWrite);
|
|
_eventWatcher.Changed += OnFileSystemEventArrived;
|
|
_eventWatcher.Created += OnFileSystemEventArrived;
|
|
_eventWatcher.Deleted += OnFileSystemEventArrived;
|
|
_eventWatcher.Renamed += OnFileSystemEventArrived;
|
|
_eventWatcher.EnableRaisingEvents = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Runtime.MessageCollector.AddExceptionMessage("XmingPortablePuttySessions.Watcher.StartWatching() failed.", ex, MessageClass.WarningMsg, true);
|
|
}
|
|
}
|
|
|
|
public override void StopWatcher()
|
|
{
|
|
RegistryProvider.StopWatcher();
|
|
RegistryProvider.SessionChanged -= OnRegistrySessionChanged;
|
|
|
|
if (_eventWatcher == null)
|
|
{
|
|
return ;
|
|
}
|
|
_eventWatcher.EnableRaisingEvents = false;
|
|
_eventWatcher.Dispose();
|
|
_eventWatcher = null;
|
|
}
|
|
#endregion
|
|
|
|
#region Private Methods
|
|
private static string GetPuttyConfPath()
|
|
{
|
|
string puttyPath = "";
|
|
if (My.Settings.Default.UseCustomPuttyPath)
|
|
{
|
|
puttyPath = Convert.ToString(My.Settings.Default.CustomPuttyPath);
|
|
}
|
|
else
|
|
{
|
|
puttyPath = App.Info.GeneralAppInfo.PuttyPath;
|
|
}
|
|
return Path.Combine(Path.GetDirectoryName(puttyPath), "putty.conf");
|
|
}
|
|
|
|
private static string GetSessionsFolderPath()
|
|
{
|
|
string puttyConfPath = GetPuttyConfPath();
|
|
PuttyConfFileReader sessionFileReader = new PuttyConfFileReader(puttyConfPath);
|
|
string basePath = Environment.ExpandEnvironmentVariables(sessionFileReader.GetValue("sshk&sess"));
|
|
return Path.Combine(basePath, "sessions");
|
|
}
|
|
|
|
private static string GetRegistrySessionName(string sessionName)
|
|
{
|
|
Regex regex = new Regex(RegistrySessionNamePattern);
|
|
|
|
MatchCollection matches = regex.Matches(sessionName);
|
|
if (matches.Count < 1)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
GroupCollection groups = matches[0].Groups;
|
|
if (groups.Count < 1)
|
|
{
|
|
return string.Empty; // This should always include at least one item, but check anyway
|
|
}
|
|
|
|
return groups[1].Value;
|
|
}
|
|
|
|
private static PuttySessionInfo ModifyRegistrySessionInfo(PuttySessionInfo sessionInfo)
|
|
{
|
|
sessionInfo.Name = string.Format(RegistrySessionNameFormat, sessionInfo.Name);
|
|
sessionInfo.PuttySession = string.Format(RegistrySessionNameFormat, sessionInfo.PuttySession);
|
|
return sessionInfo;
|
|
}
|
|
|
|
private void OnFileSystemEventArrived(object sender, FileSystemEventArgs e)
|
|
{
|
|
OnSessionChanged(new SessionChangedEventArgs());
|
|
}
|
|
|
|
private void OnRegistrySessionChanged(object sender, SessionChangedEventArgs e)
|
|
{
|
|
OnSessionChanged(new SessionChangedEventArgs());
|
|
}
|
|
#endregion
|
|
|
|
#region Private Classes
|
|
private class PuttyConfFileReader
|
|
{
|
|
public PuttyConfFileReader(string puttyConfFile)
|
|
{
|
|
_puttyConfFile = puttyConfFile;
|
|
}
|
|
|
|
private string _puttyConfFile;
|
|
private bool _configurationLoaded = false;
|
|
private Dictionary<string, string> _configuration = new Dictionary<string, string>();
|
|
|
|
private void LoadConfiguration()
|
|
{
|
|
_configurationLoaded = true;
|
|
try
|
|
{
|
|
if (!File.Exists(_puttyConfFile))
|
|
{
|
|
return ;
|
|
}
|
|
using (StreamReader streamReader = new StreamReader(_puttyConfFile))
|
|
{
|
|
string line = "";
|
|
do
|
|
{
|
|
line = streamReader.ReadLine();
|
|
if (line == null)
|
|
{
|
|
break;
|
|
}
|
|
line = line.Trim();
|
|
if (line == string.Empty)
|
|
{
|
|
continue; // Blank line
|
|
}
|
|
if (line.Substring(0, 1) == ";")
|
|
{
|
|
continue; // Comment
|
|
}
|
|
string[] parts = line.Split(new char[] {'='}, 2);
|
|
if (parts.Length < 2)
|
|
{
|
|
continue;
|
|
}
|
|
if (_configuration.ContainsKey(parts[0]))
|
|
{
|
|
continue; // As per http://www.straightrunning.com/XmingNotes/portableputty.php only first entry is used
|
|
}
|
|
_configuration.Add(parts[0], parts[1]);
|
|
} while (true);
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Runtime.MessageCollector.AddExceptionMessage("PuttyConfFileReader.LoadConfiguration() failed.", ex, MessageClass.ErrorMsg, true);
|
|
}
|
|
}
|
|
|
|
public string GetValue(string setting)
|
|
{
|
|
if (!_configurationLoaded)
|
|
{
|
|
LoadConfiguration();
|
|
}
|
|
if (!_configuration.ContainsKey(setting))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
return _configuration[setting];
|
|
}
|
|
}
|
|
|
|
private class SessionFileReader
|
|
{
|
|
public SessionFileReader(string sessionFile)
|
|
{
|
|
_sessionFile = sessionFile;
|
|
}
|
|
|
|
private string _sessionFile;
|
|
private bool _sessionInfoLoaded = false;
|
|
private Dictionary<string, string> _sessionInfo = new Dictionary<string, string>();
|
|
|
|
private void LoadSessionInfo()
|
|
{
|
|
_sessionInfoLoaded = true;
|
|
try
|
|
{
|
|
if (!File.Exists(_sessionFile))
|
|
{
|
|
return ;
|
|
}
|
|
using (StreamReader streamReader = new StreamReader(_sessionFile))
|
|
{
|
|
string line = "";
|
|
do
|
|
{
|
|
line = streamReader.ReadLine();
|
|
if (line == null)
|
|
{
|
|
break;
|
|
}
|
|
string[] parts = line.Split(new char[] {'\\'});
|
|
if (parts.Length < 2)
|
|
{
|
|
continue;
|
|
}
|
|
_sessionInfo.Add(parts[0], parts[1]);
|
|
} while (true);
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Runtime.MessageCollector.AddExceptionMessage("SessionFileReader.LoadSessionInfo() failed.", ex, MessageClass.ErrorMsg, true);
|
|
}
|
|
}
|
|
|
|
public string GetValue(string setting)
|
|
{
|
|
if (!_sessionInfoLoaded)
|
|
{
|
|
LoadSessionInfo();
|
|
}
|
|
if (!_sessionInfo.ContainsKey(setting))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
return _sessionInfo[setting];
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
} |