After exploring generics, overloaded methods and interfaces, I came up with this solution. Let me know if you think there is something better:
IDirectory.cs:
using System;
using System.Text;
namespace ReleaseManager.Interfaces
{
interface IDirectory
{
void Connect(string Host, int Port, string Username, string Password, string Fingerprint);
string GetWorkingDirectory(string Directory);
void ListDirectory(string Directory);
void CreateDirectory(string Directory);
void DeleteDirectory(string Directory);
Boolean DirectoryExists(string Directory);
void WriteAllText(string FileName, string Content, Encoding enc);
void CopyFile(string srcFile, string dstFile);
void Disconnect();
}
}
Directory.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace ReleaseManager.BusinessObjects
{
public class RemoteDirInfo
{
public string Name { get; set; }
public string ModifiedDate { get; set; }
}
public class RemoteFileInfo
{
public string Name { get; set; }
public string ModifiedDate { get; set; }
public long Size { get; set; }
}
public class RemoteInfo
{
public string Error { get; set; }
public string CurrentDirectory { get; set; }
public List<RemoteDirInfo> DirInfo { get; set; }
public List<RemoteFileInfo> FileInfo { get; set; }
}
}
FTPDirectory.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ReleaseManager.Interfaces;
using System.Net.FtpClient;
using System.Net;
using System.Text;
using System.IO;
namespace ReleaseManager.BusinessObjects
{
public class FTPDirectory : IDirectory
{
private FtpClient client;
public RemoteInfo Info;
public FTPDirectory()
{
this.client = new FtpClient();
this.Info = new RemoteInfo();
this.Info.DirInfo = new List<RemoteDirInfo>();
this.Info.FileInfo = new List<RemoteFileInfo>();
this.Info.Error = "";
}
public void Connect(string Host, int Port, string Username, string Password, string Fingerprint)
{
int ftpPort = 21; // default ftp port
if (Port != 0)
ftpPort = Port;
this.client.Host = Host;
this.client.Port = ftpPort;
this.client.Credentials = new NetworkCredential(Username, Password);
}
public string GetWorkingDirectory(string Directory)
{
this.client.SetWorkingDirectory(Directory);
return this.client.GetWorkingDirectory();
}
public void ListDirectory(string Directory)
{
this.client.SetWorkingDirectory(Directory);
foreach (var item in this.client.GetListing(this.client.GetWorkingDirectory()))
{
switch (item.Type)
{
case FtpFileSystemObjectType.Directory:
if (item.Name != "." && item.Name != "..")
this.Info.DirInfo.Add(new RemoteDirInfo
{
Name = item.Name,
ModifiedDate = item.Modified.ToString("yyyy/MM/dd HH:mm:ss")
});
break;
case FtpFileSystemObjectType.File:
this.Info.FileInfo.Add(new RemoteFileInfo
{
Name = item.Name,
ModifiedDate = item.Modified.ToString("yyyy/MM/dd HH:mm:ss"),
Size = item.Size
});
break;
}
}
}
public void CreateDirectory(string Directory)
{
this.client.CreateDirectory(Directory);
}
public void DeleteDirectory(string Directory)
{
this.client.DeleteDirectory(Directory, true, FtpListOption.Recursive);
}
public void CopyFile(string srcFile, string dstFile)
{
using (var fileStream = System.IO.File.OpenRead(srcFile))
using (var ftpStream = this.client.OpenWrite(dstFile.Replace("\\", "/")))
{
var buffer = new byte[8 * 1024];
int count;
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
ftpStream.Write(buffer, 0, count);
}
}
}
public void WriteAllText(string Filename, string Content, Encoding enc = null)
{
byte[] byteArray;
if (enc == null)
byteArray = Encoding.ASCII.GetBytes(Content);
else
byteArray = enc.GetBytes(Content);
using (MemoryStream stream = new MemoryStream(byteArray))
using (var ftpStream = this.client.OpenWrite(Filename.Replace("\\", "/")))
{
var buffer = new byte[8 * 1024];
int count;
while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ftpStream.Write(buffer, 0, count);
}
}
}
public Boolean DirectoryExists(string Directory)
{
return this.client.DirectoryExists(Directory);
}
public void Disconnect()
{
this.client.Disconnect();
}
}
}
SFTPDirectory.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ReleaseManager.Interfaces;
using Renci.SshNet;
using Renci.SshNet.Common;
using Renci.SshNet.Sftp;
using System.Text;
using System.IO;
namespace ReleaseManager.BusinessObjects
{
public class SFTPDirectory : IDirectory
{
public SftpClient client;
public RemoteInfo Info;
public SFTPDirectory()
{
this.Info = new RemoteInfo();
this.Info.DirInfo = new List<RemoteDirInfo>();
this.Info.FileInfo = new List<RemoteFileInfo>();
this.Info.Error = "";
}
public void Connect(string Host, int Port, string Username, string Password, string Fingerprint)
{
int sftpPort = 22; // default sftp port
if (Port != 0)
sftpPort = Port;
ConnectionInfo connInfo = new ConnectionInfo(Host, sftpPort, Username, new AuthenticationMethod[]{
new PasswordAuthenticationMethod(Username, Password)
});
this.client = new SftpClient(connInfo);
this.client.HostKeyReceived += delegate(object sender, HostKeyEventArgs e)
{
if (Fingerprint.ToLower() == (e.HostKeyName + " " + e.KeyLength + " " + BitConverter.ToString(e.FingerPrint).Replace("-", ":")).ToLower())
e.CanTrust = true;
else
e.CanTrust = false;
};
this.client.Connect();
}
public string GetWorkingDirectory(string Directory)
{
return Directory;
}
public void ListDirectory(string Directory)
{
List<SftpFile> files = this.client.ListDirectory(Directory).ToList();
foreach (var file in files)
{
if (file.IsDirectory)
{
if (file.Name != "." && file.Name != "..")
this.Info.DirInfo.Add(new RemoteDirInfo
{
Name = file.Name,
ModifiedDate = file.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss")
});
}
else
{
this.Info.FileInfo.Add(new RemoteFileInfo
{
Name = file.Name,
ModifiedDate = file.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss"),
Size = file.Length
});
}
}
}
public void CreateDirectory(string Directory)
{
this.client.CreateDirectory(Directory);
}
public void DeleteDirectory(string Directory)
{
this.client.DeleteDirectory(Directory);
}
public void CopyFile(string srcFile, string dstFile)
{
using (var uplfileStream = System.IO.File.OpenRead(srcFile))
{
this.client.UploadFile(uplfileStream, dstFile.Replace("\\", "/"), true);
}
}
public void WriteAllText(string Filename, string Content, Encoding enc = null)
{
byte[] byteArray;
if (enc == null)
byteArray = Encoding.ASCII.GetBytes(Content);
else
byteArray = enc.GetBytes(Content);
using (MemoryStream stream = new MemoryStream(byteArray))
{
this.client.UploadFile(stream, Filename.Replace("\\", "/"), true);
}
}
public Boolean DirectoryExists(string Directory)
{
return this.client.Exists(Directory);
}
public void Disconnect()
{
this.client.Disconnect();
}
}
}
LocalDirectory.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ReleaseManager.Interfaces;
using System.Net;
using System.Text;
using System.IO;
namespace ReleaseManager.BusinessObjects
{
public class LocalDirectory : IDirectory
{
public RemoteInfo Info;
public LocalDirectory()
{
this.Info = new RemoteInfo();
this.Info.DirInfo = new List<RemoteDirInfo>();
this.Info.FileInfo = new List<RemoteFileInfo>();
this.Info.Error = "";
}
public void Connect(string Host, int Port, string Username, string Password, string Fingerprint)
{
}
public string GetWorkingDirectory(string Directory)
{
return Directory;
}
public void ListDirectory(string Directory)
{
DirectoryInfo di = new DirectoryInfo(Directory);
foreach (var item in di.EnumerateDirectories("*"))
{
if (item.Name != "." && item.Name != "..")
this.Info.DirInfo.Add(new RemoteDirInfo
{
Name = item.Name,
ModifiedDate = item.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss")
});
}
foreach (var item in di.EnumerateFiles("*"))
{
this.Info.FileInfo.Add(new RemoteFileInfo
{
Name = item.Name,
ModifiedDate = item.LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss"),
Size = item.Length
});
}
}
public void CreateDirectory(string Directory)
{
System.IO.Directory.CreateDirectory(Directory);
}
public void DeleteDirectory(string Directory)
{
System.IO.Directory.Delete(Directory, true);
}
public void CopyFile(string srcFile, string dstFile)
{
System.IO.File.Copy(srcFile, dstFile);
}
public void WriteAllText(string Filename, string Content, Encoding enc = null)
{
if (enc == null)
System.IO.File.WriteAllText(Filename, Content);
else
System.IO.File.WriteAllText(Filename, Content, enc);
}
public Boolean DirectoryExists(string Directory)
{
return System.IO.Directory.Exists(Directory);
}
public void Disconnect()
{
}
}
}
Implementation of RemoteBrowse method:
public JsonResult RemoteBrowse(string Protocol, string Host, int Port, string Username, string Password, string Directory, string Fingerprint = "")
{
dynamic Connector = null;
MyMember.Init(User.Identity.Name);
if (MyMember.ID_Member > 0)
{
if (Protocol == "ftp")
Connector = new FTPDirectory();
else if (Protocol == "sftp")
Connector = new SFTPDirectory();
else if (Protocol == "local")
Connector = new LocalDirectory();
if (Connector != null)
{
try
{
Connector.Connect(Host, Port, Username, Password, Fingerprint);
while (true)
{
Boolean Mod = false;
if (Directory.Length >= 2)
{
if (Directory.Substring(0, 2) == "//")
{
Directory = Directory.Substring(1);
Mod = true;
}
else if (Directory.Substring(0, 2) == "..")
{
Directory = Directory.Substring(2);
Mod = true;
}
}
else if (Directory.Length >= 3)
{
if (Directory.Substring(0, 3) == "/..")
{
Directory = Directory.Substring(3);
Mod = true;
}
}
if (!Mod)
break;
}
if (Directory.Length > 1 && Directory != "/")
{
if (Directory.Substring(0, 1) != "/")
Directory = "/" + Directory;
if (Directory.Substring(Directory.Length - 1) == "/")
Directory = Directory.Substring(0, Directory.Length - 1);
if (Directory.Substring(Directory.Length - 3) == "/..") // go one directory up
{
Directory = Directory.Substring(0, Directory.Length - 3);
Directory = Directory.Substring(0, Directory.LastIndexOf('/'));
}
}
if (Directory == "")
Directory = "/";
Connector.Info.CurrentDirectory = Connector.GetWorkingDirectory(Directory);
Connector.ListDirectory(Directory);
Connector.Disconnect();
}
catch (Exception ex)
{
Connector.Info.Error = ex.Message;
if (ex.InnerException != null)
Connector.Info.Error += '\n' + ex.InnerException.Message;
}
}
}
return Json((Connector != null) ? Connector.Info : null, JsonRequestBehavior.AllowGet);
}