Removed nugetSource from pipeline Removed more comments Created Static Classes for most DMO / Controller Classes Push ConfigurationManager.AppSettings to controller Align Tests with other Projects
1049 lines
32 KiB
C#
1049 lines
32 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Fab2ApprovalSystem.Misc;
|
|
|
|
public class FTP {
|
|
#region Public Variables
|
|
|
|
/// <summary>
|
|
/// IP address or hostname to connect to
|
|
/// </summary>
|
|
public string server;
|
|
|
|
/// <summary>
|
|
/// Username to login as
|
|
/// </summary>
|
|
public string user;
|
|
|
|
/// <summary>
|
|
/// Password for account
|
|
/// </summary>
|
|
public string pass;
|
|
|
|
/// <summary>
|
|
/// Port number the FTP server is listening on
|
|
/// </summary>
|
|
public int port;
|
|
|
|
/// <summary>
|
|
/// The timeout (miliseconds) for waiting on data to arrive
|
|
/// </summary>
|
|
public int timeout;
|
|
|
|
#endregion
|
|
|
|
#region Private Variables
|
|
|
|
private string messages; // server messages
|
|
private string responseStr; // server response if the user wants it.
|
|
private bool passive_mode; // #######################################
|
|
private long bytes_total; // upload/download info if the user wants it.
|
|
private long file_size; // gets set when an upload or download takes place
|
|
private Socket main_sock;
|
|
private IPEndPoint main_ipEndPoint;
|
|
private Socket listening_sock;
|
|
private Socket data_sock;
|
|
private IPEndPoint data_ipEndPoint;
|
|
private FileStream file;
|
|
private int response;
|
|
private string bucket;
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
public FTP() {
|
|
server = null;
|
|
user = null;
|
|
pass = null;
|
|
port = 21;
|
|
passive_mode = true;
|
|
main_sock = null;
|
|
main_ipEndPoint = null;
|
|
listening_sock = null;
|
|
data_sock = null;
|
|
data_ipEndPoint = null;
|
|
file = null;
|
|
bucket = "";
|
|
bytes_total = 0;
|
|
timeout = 10000; // 10 seconds
|
|
messages = "";
|
|
}
|
|
|
|
public FTP(string server, string user, string pass) {
|
|
this.server = server;
|
|
this.user = user;
|
|
this.pass = pass;
|
|
port = 21;
|
|
passive_mode = true;
|
|
main_sock = null;
|
|
main_ipEndPoint = null;
|
|
listening_sock = null;
|
|
data_sock = null;
|
|
data_ipEndPoint = null;
|
|
file = null;
|
|
bucket = "";
|
|
bytes_total = 0;
|
|
timeout = 10000; // 10 seconds
|
|
messages = "";
|
|
}
|
|
|
|
public FTP(string server, int port, string user, string pass) {
|
|
this.server = server;
|
|
this.user = user;
|
|
this.pass = pass;
|
|
this.port = port;
|
|
passive_mode = true;
|
|
main_sock = null;
|
|
main_ipEndPoint = null;
|
|
listening_sock = null;
|
|
data_sock = null;
|
|
data_ipEndPoint = null;
|
|
file = null;
|
|
bucket = "";
|
|
bytes_total = 0;
|
|
timeout = 10000; // 10 seconds
|
|
messages = "";
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Connection status to the server
|
|
/// </summary>
|
|
public bool IsConnected {
|
|
get {
|
|
if (main_sock != null)
|
|
return main_sock.Connected;
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Returns true if the message buffer has data in it
|
|
/// </summary>
|
|
public bool MessagesAvailable {
|
|
get {
|
|
if (messages.Length > 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Server messages if any, buffer is cleared after you access this property
|
|
/// </summary>
|
|
public string Messages {
|
|
get {
|
|
string tmp = messages;
|
|
messages = "";
|
|
return tmp;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// The response string from the last issued command
|
|
/// </summary>
|
|
public string ResponseString {
|
|
get {
|
|
return responseStr;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// The total number of bytes sent/recieved in a transfer
|
|
/// </summary>
|
|
public long BytesTotal // #######################################
|
|
{
|
|
get {
|
|
return bytes_total;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// The size of the file being downloaded/uploaded (Can possibly be 0 if no size is available)
|
|
/// </summary>
|
|
public long FileSize // #######################################
|
|
{
|
|
get {
|
|
return file_size;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// True: Passive mode [default]
|
|
/// False: Active Mode
|
|
/// </summary>
|
|
public bool PassiveMode // #######################################
|
|
{
|
|
get =>
|
|
passive_mode;
|
|
set =>
|
|
passive_mode = value;
|
|
}
|
|
|
|
private void Fail() {
|
|
Disconnect();
|
|
throw new Exception(responseStr);
|
|
}
|
|
|
|
private void SetBinaryMode(bool mode) {
|
|
if (mode)
|
|
SendCommand("TYPE I");
|
|
else
|
|
SendCommand("TYPE A");
|
|
|
|
ReadResponse();
|
|
if (response != 200)
|
|
Fail();
|
|
}
|
|
|
|
private void SendCommand(string command) {
|
|
byte[] cmd = Encoding.ASCII.GetBytes((command + "\r\n").ToCharArray());
|
|
|
|
#if (FTP_DEBUG)
|
|
if (command.Length > 3 && command.Substring(0, 4) == "PASS")
|
|
Console.WriteLine("\rPASS xxx");
|
|
else
|
|
Console.WriteLine("\r" + command);
|
|
#endif
|
|
|
|
main_sock.Send(cmd, cmd.Length, 0);
|
|
}
|
|
|
|
private void FillBucket() {
|
|
byte[] bytes = new byte[512];
|
|
long bytesgot;
|
|
int msecs_passed = 0; // #######################################
|
|
|
|
while (main_sock.Available < 1) {
|
|
System.Threading.Thread.Sleep(50);
|
|
msecs_passed += 50;
|
|
// this code is just a fail safe option
|
|
// so the code doesn't hang if there is
|
|
// no data comming.
|
|
if (msecs_passed > timeout) {
|
|
Disconnect();
|
|
throw new Exception("Timed out waiting on server to respond.");
|
|
}
|
|
}
|
|
|
|
while (main_sock.Available > 0) {
|
|
bytesgot = main_sock.Receive(bytes, 512, 0);
|
|
bucket += Encoding.ASCII.GetString(bytes, 0, (int)bytesgot);
|
|
// this may not be needed, gives any more data that hasn't arrived
|
|
// just yet a small chance to get there.
|
|
System.Threading.Thread.Sleep(50);
|
|
}
|
|
}
|
|
|
|
private string GetLineFromBucket() {
|
|
int i;
|
|
string buf = "";
|
|
|
|
if ((i = bucket.IndexOf('\n')) < 0) {
|
|
while (i < 0) {
|
|
FillBucket();
|
|
i = bucket.IndexOf('\n');
|
|
}
|
|
}
|
|
|
|
buf = bucket.Substring(0, i);
|
|
bucket = bucket.Substring(i + 1);
|
|
|
|
return buf;
|
|
}
|
|
|
|
// Any time a command is sent, use ReadResponse() to get the response
|
|
// from the server. The variable responseStr holds the entire string and
|
|
// the variable response holds the response number.
|
|
private void ReadResponse() {
|
|
string buf;
|
|
messages = "";
|
|
|
|
while (true) {
|
|
buf = GetLineFromBucket();
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine(buf);
|
|
#endif
|
|
// the server will respond with "000-Foo bar" on multi line responses
|
|
// "000 Foo bar" would be the last line it sent for that response.
|
|
// Better example:
|
|
// "000-This is a multiline response"
|
|
// "000-Foo bar"
|
|
// "000 This is the end of the response"
|
|
if (Regex.Match(buf, "^[0-9]+ ").Success) {
|
|
responseStr = buf;
|
|
response = int.Parse(buf.Substring(0, 3));
|
|
break;
|
|
} else
|
|
messages += Regex.Replace(buf, "^[0-9]+-", "") + "\n";
|
|
}
|
|
}
|
|
|
|
// if you add code that needs a data socket, i.e. a PASV or PORT command required,
|
|
// call this function to do the dirty work. It sends the PASV or PORT command,
|
|
// parses out the port and ip info and opens the appropriate data socket
|
|
// for you. The socket variable is private Socket data_socket. Once you
|
|
// are done with it, be sure to call CloseDataSocket()
|
|
private void OpenDataSocket() {
|
|
if (passive_mode) // #######################################
|
|
{
|
|
string[] pasv;
|
|
string server;
|
|
int port;
|
|
|
|
Connect();
|
|
SendCommand("PASV");
|
|
ReadResponse();
|
|
if (response != 227)
|
|
Fail();
|
|
|
|
try {
|
|
int i1, i2;
|
|
|
|
i1 = responseStr.IndexOf('(') + 1;
|
|
i2 = responseStr.IndexOf(')') - i1;
|
|
pasv = responseStr.Substring(i1, i2).Split(',');
|
|
} catch (Exception) {
|
|
Disconnect();
|
|
throw new Exception("Malformed PASV response: " + responseStr);
|
|
}
|
|
|
|
if (pasv.Length < 6) {
|
|
Disconnect();
|
|
throw new Exception("Malformed PASV response: " + responseStr);
|
|
}
|
|
|
|
server = string.Format("{0}.{1}.{2}.{3}", pasv[0], pasv[1], pasv[2], pasv[3]);
|
|
port = (int.Parse(pasv[4]) << 8) + int.Parse(pasv[5]);
|
|
|
|
try {
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Data socket: {0}:{1}", server, port);
|
|
#endif
|
|
CloseDataSocket();
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Creating socket...");
|
|
#endif
|
|
data_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Resolving host");
|
|
#endif
|
|
|
|
data_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Connecting..");
|
|
#endif
|
|
data_sock.Connect(data_ipEndPoint);
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Connected.");
|
|
#endif
|
|
} catch (Exception ex) {
|
|
throw new Exception("Failed to connect for data transfer: " + ex.Message);
|
|
}
|
|
} else // #######################################
|
|
{
|
|
Connect();
|
|
|
|
try {
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Data socket (active mode)");
|
|
#endif
|
|
CloseDataSocket();
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Creating listening socket...");
|
|
#endif
|
|
listening_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Binding it to local address/port");
|
|
#endif
|
|
// for the PORT command we need to send our IP address; let's extract it
|
|
// from the LocalEndPoint of the main socket, that's already connected
|
|
string sLocAddr = main_sock.LocalEndPoint.ToString();
|
|
int ix = sLocAddr.IndexOf(':');
|
|
if (ix < 0) {
|
|
throw new Exception("Failed to parse the local address: " + sLocAddr);
|
|
}
|
|
string sIPAddr = sLocAddr.Substring(0, ix);
|
|
// let the system automatically assign a port number (setting port = 0)
|
|
IPEndPoint localEP = new(IPAddress.Parse(sIPAddr), 0);
|
|
|
|
listening_sock.Bind(localEP);
|
|
sLocAddr = listening_sock.LocalEndPoint.ToString();
|
|
ix = sLocAddr.IndexOf(':');
|
|
if (ix < 0) {
|
|
throw new Exception("Failed to parse the local address: " + sLocAddr);
|
|
}
|
|
int nPort = int.Parse(sLocAddr.Substring(ix + 1));
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Listening on {0}:{1}", sIPAddr, nPort);
|
|
#endif
|
|
// start to listen for a connection request from the host (note that
|
|
// Listen is not blocking) and send the PORT command
|
|
listening_sock.Listen(1);
|
|
string sPortCmd = string.Format("PORT {0},{1},{2}",
|
|
sIPAddr.Replace('.', ','),
|
|
nPort / 256, nPort % 256);
|
|
SendCommand(sPortCmd);
|
|
ReadResponse();
|
|
if (response != 200)
|
|
Fail();
|
|
} catch (Exception ex) {
|
|
throw new Exception("Failed to connect for data transfer: " + ex.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ConnectDataSocket() // #######################################
|
|
{
|
|
if (data_sock != null) // already connected (always so if passive mode)
|
|
return;
|
|
|
|
try {
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Accepting the data connection.");
|
|
#endif
|
|
data_sock = listening_sock.Accept(); // Accept is blocking
|
|
listening_sock.Close();
|
|
listening_sock = null;
|
|
|
|
if (data_sock == null) {
|
|
throw new Exception("Winsock error: " +
|
|
Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error()));
|
|
}
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Connected.");
|
|
#endif
|
|
} catch (Exception ex) {
|
|
throw new Exception("Failed to connect for data transfer: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void CloseDataSocket() {
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Attempting to close data channel socket...");
|
|
#endif
|
|
if (data_sock != null) {
|
|
if (data_sock.Connected) {
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Closing data channel socket!");
|
|
#endif
|
|
data_sock.Close();
|
|
#if (FTP_DEBUG)
|
|
Console.WriteLine("Data channel socket closed!");
|
|
#endif
|
|
}
|
|
data_sock = null;
|
|
}
|
|
|
|
data_ipEndPoint = null;
|
|
}
|
|
/// <summary>
|
|
/// Closes all connections to the ftp server
|
|
/// </summary>
|
|
public void Disconnect() {
|
|
CloseDataSocket();
|
|
|
|
if (main_sock != null) {
|
|
if (main_sock.Connected) {
|
|
SendCommand("QUIT");
|
|
main_sock.Close();
|
|
}
|
|
main_sock = null;
|
|
}
|
|
|
|
if (file != null)
|
|
file.Close();
|
|
|
|
main_ipEndPoint = null;
|
|
file = null;
|
|
}
|
|
/// <summary>
|
|
/// Connect to a ftp server
|
|
/// </summary>
|
|
/// <param name="server">IP or hostname of the server to connect to</param>
|
|
/// <param name="port">Port number the server is listening on</param>
|
|
/// <param name="user">Account name to login as</param>
|
|
/// <param name="pass">Password for the account specified</param>
|
|
public void Connect(string server, int port, string user, string pass) {
|
|
this.server = server;
|
|
this.user = user;
|
|
this.pass = pass;
|
|
this.port = port;
|
|
|
|
Connect();
|
|
}
|
|
/// <summary>
|
|
/// Connect to a ftp server
|
|
/// </summary>
|
|
/// <param name="server">IP or hostname of the server to connect to</param>
|
|
/// <param name="user">Account name to login as</param>
|
|
/// <param name="pass">Password for the account specified</param>
|
|
public void Connect(string server, string user, string pass) {
|
|
this.server = server;
|
|
this.user = user;
|
|
this.pass = pass;
|
|
|
|
Connect();
|
|
}
|
|
/// <summary>
|
|
/// Connect to an ftp server
|
|
/// </summary>
|
|
public void Connect() {
|
|
if (server == null)
|
|
throw new Exception("No server has been set.");
|
|
if (user == null)
|
|
throw new Exception("No username has been set.");
|
|
|
|
if (main_sock != null)
|
|
if (main_sock.Connected)
|
|
return;
|
|
|
|
main_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
main_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);
|
|
|
|
try {
|
|
main_sock.Connect(main_ipEndPoint);
|
|
} catch (Exception ex) {
|
|
throw new Exception(ex.Message);
|
|
}
|
|
|
|
ReadResponse();
|
|
if (response != 220)
|
|
Fail();
|
|
|
|
SendCommand("USER " + user);
|
|
ReadResponse();
|
|
|
|
switch (response) {
|
|
case 331:
|
|
if (pass == null) {
|
|
Disconnect();
|
|
throw new Exception("No password has been set.");
|
|
}
|
|
SendCommand("PASS " + pass);
|
|
ReadResponse();
|
|
if (response != 230)
|
|
Fail();
|
|
break;
|
|
case 230:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
/// <summary>
|
|
/// Retrieves a list of files from the ftp server
|
|
/// </summary>
|
|
/// <returns>An ArrayList of files</returns>
|
|
public ArrayList List() {
|
|
byte[] bytes = new byte[512];
|
|
string file_list = "";
|
|
long bytesgot = 0;
|
|
int msecs_passed = 0;
|
|
ArrayList list = new();
|
|
|
|
Connect();
|
|
OpenDataSocket();
|
|
SendCommand("LIST");
|
|
ReadResponse();
|
|
|
|
// FILIPE MADUREIRA.
|
|
// Added response 125
|
|
switch (response) {
|
|
case 125:
|
|
case 150:
|
|
break;
|
|
default:
|
|
CloseDataSocket();
|
|
throw new Exception(responseStr);
|
|
}
|
|
ConnectDataSocket(); // #######################################
|
|
|
|
while (data_sock.Available < 1) {
|
|
System.Threading.Thread.Sleep(50);
|
|
msecs_passed += 50;
|
|
// this code is just a fail safe option
|
|
// so the code doesn't hang if there is
|
|
// no data comming.
|
|
if (msecs_passed > (timeout / 10)) {
|
|
// FILIPE MADUREIRA.
|
|
// If there are no files to list it gives timeout.
|
|
// So I wait less time and if no data is received, means that there are no files
|
|
break; // Maybe there are no files
|
|
}
|
|
}
|
|
|
|
while (data_sock.Available > 0) {
|
|
bytesgot = data_sock.Receive(bytes, bytes.Length, 0);
|
|
file_list += Encoding.ASCII.GetString(bytes, 0, (int)bytesgot);
|
|
System.Threading.Thread.Sleep(50); // *shrug*, sometimes there is data comming but it isn't there yet.
|
|
}
|
|
|
|
CloseDataSocket();
|
|
|
|
ReadResponse();
|
|
if (response != 226)
|
|
throw new Exception(responseStr);
|
|
|
|
foreach (string f in file_list.Split('\n')) {
|
|
if (f.Length > 0 && !Regex.Match(f, "^total").Success)
|
|
list.Add(f.Substring(0, f.Length - 1));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
/// <summary>
|
|
/// Gets a file list only
|
|
/// </summary>
|
|
/// <returns>ArrayList of files only</returns>
|
|
public ArrayList ListFiles() {
|
|
ArrayList list = new();
|
|
|
|
foreach (string f in List()) {
|
|
// FILIPE MADUREIRA
|
|
if ((f.Length > 0)) {
|
|
if ((f[0] != 'd') && (f.ToUpper().IndexOf("<DIR>") < 0))
|
|
list.Add(f);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a directory list only
|
|
/// </summary>
|
|
/// <returns>ArrayList of directories only</returns>
|
|
public ArrayList ListDirectories() {
|
|
ArrayList list = new();
|
|
|
|
foreach (string f in List()) {
|
|
// FILIPE MADUREIRA
|
|
// In Windows servers it is identified by <DIR>
|
|
if (f.Length > 0) {
|
|
if ((f[0] == 'd') || (f.ToUpper().IndexOf("<DIR>") >= 0))
|
|
list.Add(f);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
/// <summary>
|
|
/// Returns the 'Raw' DateInformation in ftp format. (YYYYMMDDhhmmss). Use GetFileDate to return a DateTime object as a better option.
|
|
/// </summary>
|
|
/// <param name="fileName">Remote FileName to Query</param>
|
|
/// <returns>Returns the 'Raw' DateInformation in ftp format</returns>
|
|
public string GetFileDateRaw(string fileName) {
|
|
Connect();
|
|
|
|
SendCommand("MDTM " + fileName);
|
|
ReadResponse();
|
|
if (response != 213) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
|
|
return (responseStr.Substring(4));
|
|
}
|
|
/// <summary>
|
|
/// GetFileDate will query the ftp server for the date of the remote file.
|
|
/// </summary>
|
|
/// <param name="fileName">Remote FileName to Query</param>
|
|
/// <returns>DateTime of the Input FileName</returns>
|
|
public DateTime GetFileDate(string fileName) =>
|
|
ConvertFTPDateToDateTime(GetFileDateRaw(fileName));
|
|
|
|
private DateTime ConvertFTPDateToDateTime(string input) {
|
|
if (input.Length < 14)
|
|
throw new ArgumentException("Input Value for ConvertFTPDateToDateTime method was too short.");
|
|
|
|
// YYYYMMDDhhmmss":
|
|
int year = Convert.ToInt16(input.Substring(0, 4));
|
|
int month = Convert.ToInt16(input.Substring(4, 2));
|
|
int day = Convert.ToInt16(input.Substring(6, 2));
|
|
int hour = Convert.ToInt16(input.Substring(8, 2));
|
|
int min = Convert.ToInt16(input.Substring(10, 2));
|
|
int sec = Convert.ToInt16(input.Substring(12, 2));
|
|
|
|
return new DateTime(year, month, day, hour, min, sec);
|
|
}
|
|
/// <summary>
|
|
/// Get the working directory on the ftp server
|
|
/// </summary>
|
|
/// <returns>The working directory</returns>
|
|
public string GetWorkingDirectory() {
|
|
// PWD - print working directory
|
|
Connect();
|
|
SendCommand("PWD");
|
|
ReadResponse();
|
|
|
|
if (response != 257)
|
|
throw new Exception(responseStr);
|
|
|
|
string pwd;
|
|
try {
|
|
pwd = responseStr.Substring(responseStr.IndexOf("\"", 0) + 1);
|
|
pwd = pwd.Substring(0, pwd.LastIndexOf("\""));
|
|
pwd = pwd.Replace("\"\"", "\""); // directories with quotes in the name come out as "" from the server
|
|
} catch (Exception ex) {
|
|
throw new Exception("Uhandled PWD response: " + ex.Message);
|
|
}
|
|
|
|
return pwd;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Change to another directory on the ftp server
|
|
/// </summary>
|
|
/// <param name="path">Directory to change to</param>
|
|
public void ChangeDir(string path) {
|
|
Connect();
|
|
SendCommand("CWD " + path);
|
|
ReadResponse();
|
|
if (response != 250) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Create a directory on the ftp server
|
|
/// </summary>
|
|
/// <param name="dir">Directory to create</param>
|
|
public void MakeDir(string dir) {
|
|
Connect();
|
|
SendCommand("MKD " + dir);
|
|
ReadResponse();
|
|
|
|
switch (response) {
|
|
case 257:
|
|
case 250:
|
|
break;
|
|
default:
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Remove a directory from the ftp server
|
|
/// </summary>
|
|
/// <param name="dir">Name of directory to remove</param>
|
|
public void RemoveDir(string dir) {
|
|
Connect();
|
|
SendCommand("RMD " + dir);
|
|
ReadResponse();
|
|
if (response != 250) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Remove a file from the ftp server
|
|
/// </summary>
|
|
/// <param name="filename">Name of the file to delete</param>
|
|
public void RemoveFile(string filename) {
|
|
Connect();
|
|
SendCommand("DELE " + filename);
|
|
ReadResponse();
|
|
if (response != 250) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Rename a file on the ftp server
|
|
/// </summary>
|
|
/// <param name="oldfilename">Old file name</param>
|
|
/// <param name="newfilename">New file name</param>
|
|
public void RenameFile(string oldfilename, string newfilename) // #######################################
|
|
{
|
|
Connect();
|
|
SendCommand("RNFR " + oldfilename);
|
|
ReadResponse();
|
|
if (response != 350) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
} else {
|
|
SendCommand("RNTO " + newfilename);
|
|
ReadResponse();
|
|
if (response != 250) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Get the size of a file (Provided the ftp server supports it)
|
|
/// </summary>
|
|
/// <param name="filename">Name of file</param>
|
|
/// <returns>The size of the file specified by filename</returns>
|
|
public long GetFileSize(string filename) {
|
|
Connect();
|
|
SendCommand("SIZE " + filename);
|
|
ReadResponse();
|
|
if (response != 213) {
|
|
#if (FTP_DEBUG)
|
|
Console.Write("\r" + responseStr);
|
|
#endif
|
|
throw new Exception(responseStr);
|
|
}
|
|
|
|
return long.Parse(responseStr.Substring(4));
|
|
}
|
|
/// <summary>
|
|
/// Open an upload with no resume if it already exists
|
|
/// </summary>
|
|
/// <param name="filename">File to upload</param>
|
|
public void OpenUpload(string filename) =>
|
|
OpenUpload(filename, filename, false);
|
|
|
|
/// <summary>
|
|
/// Open an upload with no resume if it already exists
|
|
/// </summary>
|
|
/// <param name="filename">Local file to upload (Can include path to file)</param>
|
|
/// <param name="remotefilename">Filename to store file as on ftp server</param>
|
|
public void OpenUpload(string filename, string remotefilename) =>
|
|
OpenUpload(filename, remotefilename, false);
|
|
|
|
/// <summary>
|
|
/// Open an upload with resume support
|
|
/// </summary>
|
|
/// <param name="filename">Local file to upload (Can include path to file)</param>
|
|
/// <param name="resume">Attempt resume if exists</param>
|
|
public void OpenUpload(string filename, bool resume) =>
|
|
OpenUpload(filename, filename, resume);
|
|
|
|
/// <summary>
|
|
/// Open an upload with resume support
|
|
/// </summary>
|
|
/// <param name="filename">Local file to upload (Can include path to file)</param>
|
|
/// <param name="remote_filename">Filename to store file as on ftp server</param>
|
|
/// <param name="resume">Attempt resume if exists</param>
|
|
public void OpenUpload(string filename, string remote_filename, bool resume) {
|
|
Connect();
|
|
SetBinaryMode(true);
|
|
OpenDataSocket();
|
|
|
|
bytes_total = 0;
|
|
|
|
try {
|
|
file = new FileStream(filename, FileMode.Open);
|
|
} catch (Exception ex) {
|
|
file = null;
|
|
throw new Exception(ex.Message);
|
|
}
|
|
|
|
file_size = file.Length;
|
|
|
|
if (resume) {
|
|
long size = GetFileSize(remote_filename);
|
|
SendCommand("REST " + size);
|
|
ReadResponse();
|
|
if (response == 350)
|
|
file.Seek(size, SeekOrigin.Begin);
|
|
}
|
|
|
|
SendCommand("STOR " + remote_filename);
|
|
ReadResponse();
|
|
|
|
switch (response) {
|
|
case 125:
|
|
case 150:
|
|
break;
|
|
default:
|
|
file.Close();
|
|
file = null;
|
|
throw new Exception(responseStr);
|
|
}
|
|
ConnectDataSocket(); // #######################################
|
|
|
|
return;
|
|
}
|
|
/// <summary>
|
|
/// Download a file with no resume
|
|
/// </summary>
|
|
/// <param name="filename">Remote file name</param>
|
|
public void OpenDownload(string filename) =>
|
|
OpenDownload(filename, filename, false);
|
|
|
|
/// <summary>
|
|
/// Download a file with optional resume
|
|
/// </summary>
|
|
/// <param name="filename">Remote file name</param>
|
|
/// <param name="resume">Attempt resume if file exists</param>
|
|
public void OpenDownload(string filename, bool resume) =>
|
|
OpenDownload(filename, filename, resume);
|
|
|
|
/// <summary>
|
|
/// Download a file with no attempt to resume
|
|
/// </summary>
|
|
/// <param name="filename">Remote filename</param>
|
|
/// <param name="localfilename">Local filename (Can include path to file)</param>
|
|
public void OpenDownload(string filename, string localfilename) =>
|
|
OpenDownload(filename, localfilename, false);
|
|
|
|
/// <summary>
|
|
/// Open a file for download
|
|
/// </summary>
|
|
/// <param name="remote_filename">The name of the file on the FTP server</param>
|
|
/// <param name="local_filename">The name of the file to save as (Can include path to file)</param>
|
|
/// <param name="resume">Attempt resume if file exists</param>
|
|
public void OpenDownload(string remote_filename, string local_filename, bool resume) {
|
|
Connect();
|
|
SetBinaryMode(true);
|
|
|
|
bytes_total = 0;
|
|
|
|
try {
|
|
file_size = GetFileSize(remote_filename);
|
|
} catch {
|
|
file_size = 0;
|
|
}
|
|
|
|
if (resume && File.Exists(local_filename)) {
|
|
try {
|
|
file = new FileStream(local_filename, FileMode.Open);
|
|
} catch (Exception ex) {
|
|
file = null;
|
|
throw new Exception(ex.Message);
|
|
}
|
|
|
|
SendCommand("REST " + file.Length);
|
|
ReadResponse();
|
|
if (response != 350)
|
|
throw new Exception(responseStr);
|
|
file.Seek(file.Length, SeekOrigin.Begin);
|
|
bytes_total = file.Length;
|
|
} else {
|
|
try {
|
|
file = new FileStream(local_filename, FileMode.Create);
|
|
} catch (Exception ex) {
|
|
file = null;
|
|
throw new Exception(ex.Message);
|
|
}
|
|
}
|
|
|
|
OpenDataSocket();
|
|
SendCommand("RETR " + remote_filename);
|
|
ReadResponse();
|
|
|
|
switch (response) {
|
|
case 125:
|
|
case 150:
|
|
break;
|
|
default:
|
|
file.Close();
|
|
file = null;
|
|
throw new Exception(responseStr);
|
|
}
|
|
ConnectDataSocket(); // #######################################
|
|
|
|
return;
|
|
}
|
|
/// <summary>
|
|
/// Upload the file, to be used in a loop until file is completely uploaded
|
|
/// </summary>
|
|
/// <returns>Bytes sent</returns>
|
|
public long DoUpload() {
|
|
byte[] bytes = new byte[512];
|
|
long bytes_got;
|
|
|
|
try {
|
|
bytes_got = file.Read(bytes, 0, bytes.Length);
|
|
bytes_total += bytes_got;
|
|
data_sock.Send(bytes, (int)bytes_got, 0);
|
|
|
|
if (bytes_got <= 0) {
|
|
// the upload is complete or an error occured
|
|
file.Close();
|
|
file = null;
|
|
|
|
CloseDataSocket();
|
|
ReadResponse();
|
|
switch (response) {
|
|
case 226:
|
|
case 250:
|
|
break;
|
|
default:
|
|
throw new Exception(responseStr);
|
|
}
|
|
|
|
SetBinaryMode(false);
|
|
}
|
|
} catch (Exception ex) {
|
|
file.Close();
|
|
file = null;
|
|
CloseDataSocket();
|
|
ReadResponse();
|
|
SetBinaryMode(false);
|
|
throw;
|
|
}
|
|
|
|
return bytes_got;
|
|
}
|
|
/// <summary>
|
|
/// Download a file, to be used in a loop until the file is completely downloaded
|
|
/// </summary>
|
|
/// <returns>Number of bytes recieved</returns>
|
|
public long DoDownload() {
|
|
byte[] bytes = new byte[512];
|
|
long bytes_got;
|
|
|
|
try {
|
|
bytes_got = data_sock.Receive(bytes, bytes.Length, 0);
|
|
|
|
if (bytes_got <= 0) {
|
|
// the download is done or an error occured
|
|
CloseDataSocket();
|
|
file.Close();
|
|
file = null;
|
|
|
|
ReadResponse();
|
|
switch (response) {
|
|
case 226:
|
|
case 250:
|
|
break;
|
|
default:
|
|
throw new Exception(responseStr);
|
|
}
|
|
|
|
SetBinaryMode(false);
|
|
|
|
return bytes_got;
|
|
}
|
|
|
|
file.Write(bytes, 0, (int)bytes_got);
|
|
bytes_total += bytes_got;
|
|
} catch (Exception ex) {
|
|
CloseDataSocket();
|
|
file.Close();
|
|
file = null;
|
|
ReadResponse();
|
|
SetBinaryMode(false);
|
|
throw;
|
|
}
|
|
|
|
return bytes_got;
|
|
}
|
|
} |