/* Copyright (c) 2006, J.P. Trosclair
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Based on FTPFactory.cs code, pretty much a complete re-write with FTPFactory.cs
* as a reference.
*
***********************
* Authors of this code:
***********************
* J.P. Trosclair (jptrosclair@judelawfirm.com)
* Filipe Madureira (filipe_madureira@hotmail.com)
* Carlo M. Andreoli (cmandreoli@numericaprogetti.it)
* Sloan Holliday (sloan@ipass.net)
* Johann Pascher (johann.pascher@gmail.com)
*
***********************
* FTPFactory.cs was written by Jaimon Mathew (jaimonmathew@rediffmail.com)
* and modified by Dan Rolander (Dan.Rolander@marriott.com),
* Johann Pascher (johann.pascher@gmail.com)
* http://www.csharphelp.com/archives/archive9.html
***********************
*
* ** DO NOT ** contact the authors of FTPFactory.cs about problems with this code. It
* is not their responsibility. Only contact people listed as authors of THIS CODE.
*
* Any bug fixes or additions to the code will be properly credited to the author.
*
* BUGS: There probably are plenty. If you fix one, please email me with info
* about the bug and the fix, code is welcome.
*
* All calls to the ftplib functions should be:
*
* try
* {
* // ftplib function call
* }
* catch(Exception ex)
* {
* // error handeler
* }
*
* If you add to the code please make use of OpenDataSocket(), CloseDataSocket(), and
* ReadResponse() appropriately. See the comments above each for info about using them.
*
* The Fail() function terminates the entire connection. Only call it on critical errors.
* Non critical errors should NOT close the connection.
* All errors should throw an exception of type Exception with the response string from
* the server as the message.
*
* See the simple ftp client for examples on using this class
*/
//#define FTP_DEBUG
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
namespace FTPLib
{
public class FTP
{
#region Public Variables
///
/// IP address or hostname to connect to
///
public string server;
///
/// Username to login as
///
public string user;
///
/// Password for account
///
public string pass;
///
/// Port number the FTP server is listening on
///
public int port;
///
/// The timeout (miliseconds) for waiting on data to arrive
///
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
///
/// Constructor
///
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 = "";
}
///
/// Constructor
///
/// Server to connect to
/// Account to login as
/// Account password
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 = "";
}
///
/// Constructor
///
/// Server to connect to
/// Port server is listening on
/// Account to login as
/// Account password
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
///
/// Connection status to the server
///
public bool IsConnected
{
get
{
if (main_sock != null)
return main_sock.Connected;
return false;
}
}
///
/// Returns true if the message buffer has data in it
///
public bool MessagesAvailable
{
get
{
if(messages.Length > 0)
return true;
return false;
}
}
///
/// Server messages if any, buffer is cleared after you access this property
///
public string Messages
{
get
{
string tmp = messages;
messages = "";
return tmp;
}
}
///
/// The response string from the last issued command
///
public string ResponseString
{
get
{
return responseStr;
}
}
///
/// The total number of bytes sent/recieved in a transfer
///
public long BytesTotal // #######################################
{
get
{
return bytes_total;
}
}
///
/// The size of the file being downloaded/uploaded (Can possibly be 0 if no size is available)
///
public long FileSize // #######################################
{
get
{
return file_size;
}
}
///
/// True: Passive mode [default]
/// False: Active Mode
///
public bool PassiveMode // #######################################
{
get
{
return 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();
}
public void SetCommand(string command)
{
SendCommand(command);
ReadResponse();
Console.WriteLine("\r\n--> " + command);
Console.WriteLine(responseStr);
}
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(500);
msecs_passed += 50;
Console.Write(".");
// 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();
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)
System.Net.IPEndPoint localEP = new IPEndPoint(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;
}
///
/// Closes all connections to the ftp server
///
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;
}
///
/// Connect to a ftp server
///
/// IP or hostname of the server to connect to
/// Port number the server is listening on
/// Account name to login as
/// Password for the account specified
public void Connect(string server, int port, string user, string pass)
{
this.server = server;
this.user = user;
this.pass = pass;
this.port = port;
Connect();
}
///
/// Connect to a ftp server
///
/// IP or hostname of the server to connect to
/// Account name to login as
/// Password for the account specified
public void Connect(string server, string user, string pass)
{
this.server = server;
this.user = user;
this.pass = pass;
Connect();
}
///
/// Connect to an ftp server
///
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;
}
///
/// Retrieves a list of files from the ftp server
///
/// An ArrayList of files
public ArrayList List()
{
Byte[] bytes = new Byte[512];
string file_list = "";
long bytesgot = 0;
int msecs_passed = 0;
ArrayList list = new ArrayList();
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))
{
//CloseDataSocket();
//throw new Exception("Timed out waiting on server to respond.");
//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;
}
///
/// Gets a file list only
///
/// ArrayList of files only
public ArrayList ListFiles()
{
ArrayList list = new ArrayList();
foreach(string f in List())
{
//FILIPE MADUREIRA
//In Windows servers it is identified by
if ((f.Length > 0))
{
if ((f[0] != 'd') && (f.ToUpper().IndexOf("") < 0))
list.Add(f);
}
}
return list;
}
///
/// Gets a directory list only
///
/// ArrayList of directories only
public ArrayList ListDirectories()
{
ArrayList list = new ArrayList();
foreach(string f in List())
{
//FILIPE MADUREIRA
//In Windows servers it is identified by
if (f.Length > 0)
{
if ((f[0] == 'd') || (f.ToUpper().IndexOf("") >= 0))
list.Add(f);
}
}
return list;
}
///
/// Puts the 'Raw' DateInformation in ftp format.
///
/// Local FileName to Query
/// Local FileName to Query
/// Puts the 'Raw' DateInformation in ftp format
public string PutFileDateRaw(string MDTType, string fileName)
{
Connect();
SendCommand( MDTType + " " + fileName);
ReadResponse();
if (response != 213)
{
//#if (FTP_DEBUG)
Console.Write("\r" + responseStr);
//#endif
throw new Exception(responseStr);
}
return (this.responseStr.Substring(4));
}
///
/// Returns the 'Raw' DateInformation in ftp format. (YYYYMMDDhhmmss). Use GetFileDate to return a DateTime object as a better option.
///
/// Remote FileName to Query
/// Returns the 'Raw' DateInformation in ftp format
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 (this.responseStr.Substring(4));
}
///
/// GetFileDate will query the ftp server for the date of the remote file.
///
/// Remote FileName to Query
/// DateTime of the Input FileName
public DateTime GetFileDate(string fileName)
{
return 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);
}
///
/// Get the working directory on the ftp server
///
/// The working directory
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);//5);
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;
}
///
/// Change to another directory on the ftp server
///
/// Directory to change to
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);
}
}
///
/// Create a directory on the ftp server
///
/// Directory to create
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);
}
}
///
/// Remove a directory from the ftp server
///
/// Name of directory to remove
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);
}
}
///
/// Remove a file from the ftp server
///
/// Name of the file to delete
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);
}
}
///
/// Rename a file on the ftp server
///
/// Old file name
/// New file name
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);
}
}
}
///
/// Get the size of a file (Provided the ftp server supports it)
///
/// Name of file
/// The size of the file specified by filename
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 Int64.Parse(responseStr.Substring(4));
}
//------------------------------------------------------------------------------------------------------------------
///
/// Open an upload with no resume if it already exists
///
/// File to upload
public void OpenUploadM(string filename)
{
OpenUploadM(filename, filename, false);
}
///
/// Open an upload with no resume if it already exists
///
/// Local file to upload (Can include path to file)
/// Filename to store file as on ftp server
public void OpenUploadM(string filename, string remotefilename)
{
OpenUploadM(filename, remotefilename, false);
}
///
/// Open an upload with resume support
///
/// Local file to upload (Can include path to file)
/// Attempt resume if exists
public void OpenUploadM(string filename, bool resume)
{
OpenUploadM(filename, filename, resume);
}
///
/// Open an upload with resume support
///
/// Local file to upload (Can include path to file)
/// Filename to store file as on ftp server
/// Attempt resume if exists
public void OpenUploadM(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;
SetCommand("STOR " + remote_filename);
switch(response)
{
case 125:
case 150:
break;
default:
file.Close();
file = null;
throw new Exception(responseStr);
}
ConnectDataSocket(); // #######################################
return;
}
///----------------------------
///
/// Open an upload with no resume if it already exists
///
/// File to upload
public void OpenUpload(string filename)
{
OpenUpload(filename, filename, false);
}
///
/// Open an upload with no resume if it already exists
///
/// Local file to upload (Can include path to file)
/// Filename to store file as on ftp server
public void OpenUpload(string filename, string remotefilename)
{
OpenUpload(filename, remotefilename, false);
}
///
/// Open an upload with resume support
///
/// Local file to upload (Can include path to file)
/// Attempt resume if exists
public void OpenUpload(string filename, bool resume)
{
OpenUpload(filename, filename, resume);
}
///
/// Open an upload with resume support
///
/// Local file to upload (Can include path to file)
/// Filename to store file as on ftp server
/// Attempt resume if exists
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;
SendCommand("STOR " + remote_filename);
ReadResponse();
switch (response)
{
case 125:
case 150:
break;
default:
file.Close();
file = null;
throw new Exception(responseStr);
}
ConnectDataSocket(); // #######################################
return;
}
///
/// Download a file with no resume
///
/// Remote file name
public void OpenDownload(string filename)
{
OpenDownload(filename, filename, false);
}
///
/// Download a file with optional resume
///
/// Remote file name
/// Attempt resume if file exists
public void OpenDownload(string filename, bool resume)
{
OpenDownload(filename, filename, resume);
}
///
/// Download a file with no attempt to resume
///
/// Remote filename
/// Local filename (Can include path to file)
public void OpenDownload(string filename, string localfilename)
{
OpenDownload(filename, localfilename, false);
}
///
/// Open a file for download
///
/// The name of the file on the FTP server
/// The name of the file to save as (Can include path to file)
/// Attempt resume if file exists
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;
}
///
/// Upload the file, to be used in a loop until file is completely uploaded
///
/// Bytes sent
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 ex;
}
return bytes_got;
}
///
/// Download a file, to be used in a loop until the file is completely downloaded
///
/// Number of bytes recieved
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 ex;
}
return bytes_got;
}
}
}