//******************************************************************************************************
// FtpClient.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 05/22/2003 - J. Ritchie Carroll
// Generated original version of source code.
// 09/23/2008 - J. Ritchie Carroll
// Generated original version of source code.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 12/17/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
#region [ Contributor License Agreements ]
//*******************************************************************************************************
//
// Code based on the following project:
// http://www.codeproject.com/KB/IP/net_ftp_upload.aspx
//
// Copyright Alex Kwok & Uwe Keim
//
// The Code Project Open License (CPOL):
// http://www.codeproject.com/info/cpol10.aspx
//
//*******************************************************************************************************
#endregion
using System;
using System.ComponentModel;
using System.Drawing;
// This FTP library is based on a similar C# library found on "The Code Project" web site originally written by
// Alex Kwok (no license specified), then enhanced by Uwe Keim (licensed under The Code Project Open License).
// GSF translated the code into VB with most of classes being renamed (removed Ftp prefix) and the namespace was
// changed to GSF.Ftp. Many bug fixes, additions and modifications have been made to this code as well as extensive
// testing. Note worthy changes: converted the C# delegates to standard .NET events for ease of use, made the
// library work with IIS based FTP servers that were in Unix mode, added detailed file system information for FTP
// files and directories (size, timestamp, etc), converted FTP session into a component that could be dragged onto
// a design surface, created an FTP FileWatcher component and an FTP file system crawler based on this library.
// In 2008 we migrated the entire code set to C# and restored the original "Ftp" prefix to the classes for to
// satisfy uniqueness in type name constraint coming from code analysis.
namespace GSF.Net.Ftp
{
///
/// Represents a FTP session.
///
///
/// Creates a client connection to an FTP server for uploading or downloading files.
///
[ToolboxBitmap(typeof(FtpClient)), DefaultProperty("Server"), DefaultEvent("FileTransferProgress"), Description("Creates a client connection to an FTP server")]
public class FtpClient : Component
{
#region [ Members ]
// Events
///
/// Raised when file transfer begins.
///
///
/// is local filename,
/// is remote filename,
/// is file transfer direction.
///
public event EventHandler> BeginFileTransfer;
///
/// Raised when file transfer completes.
///
///
/// is local filename,
/// is remote filename,
/// is file transfer direction.
///
public event EventHandler> EndFileTransfer;
///
/// Raised as file transfer is progressing.
///
///
/// is current file transfer progress,
/// is file transfer direction.
///
public event EventHandler, TransferDirection>> FileTransferProgress;
///
/// Raised when ansynchronous file transfer process has completed (success or failure).
///
///
/// is result of asynchronous FTP transfer process.
///
public event EventHandler> FileTransferNotification;
///
/// Raised when FTP response has been received.
///
///
/// is received FTP response.
///
public event EventHandler> ResponseReceived;
///
/// Raised when FTP command has been sent.
///
///
/// is sent FTP command.
///
public event EventHandler> CommandSent;
// Fields
private bool m_caseInsensitive;
private IFtpSessionState m_currentState;
private int m_waitLockTimeOut;
private bool m_disposed;
#endregion
#region [ Constructors ]
///
/// Constructs a new FTP session using the default settings.
///
public FtpClient()
: this(false)
{
}
///
/// Constructs a new FTP session using the specified settings.
///
/// Set to true to not be case sensitive with FTP file and directory names.
public FtpClient(bool caseInsensitive)
{
m_caseInsensitive = caseInsensitive;
m_waitLockTimeOut = 10;
m_currentState = new FtpSessionDisconnected(this, m_caseInsensitive);
}
///
/// Initializes a new instance of the class.
///
/// object that contains the .
public FtpClient(IContainer container)
: this()
{
if ((object)container != null)
container.Add(this);
}
#endregion
#region [ Properties ]
///
/// Gets or sets FTP server name (DNS name or IP).
///
///
/// FTP server name should not be prefixed with FTP://.
///
[Browsable(true), Category("Configuration"), Description("Specify FTP server name (do not prefix with FTP://).")]
public string Server
{
get
{
return m_currentState.Server;
}
set
{
m_currentState.Server = value;
}
}
///
/// Gets or sets FTP case sensitivity of file and directory names.
///
///
/// Set to true to not be case sensitive with FTP file and directory names.
///
[Browsable(true), Category("Configuration"), Description("Set to True to not be case sensitive with FTP file names."), DefaultValue(false)]
public bool CaseInsensitive
{
get
{
return m_caseInsensitive;
}
set
{
m_caseInsensitive = value;
}
}
///
/// Gets or sets FTP server port to use, defaults to 21.
///
///
/// This only needs to be changed if the FTP server is established on a non-standard port number.
///
[Browsable(true), Category("Configuration"), Description("Specify FTP server port, if needed."), DefaultValue(21)]
public int Port
{
get
{
return m_currentState.Port;
}
set
{
m_currentState.Port = value;
}
}
///
/// Gets or sets current FTP session directory.
///
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public FtpDirectory CurrentDirectory
{
get
{
return m_currentState.CurrentDirectory;
}
set
{
m_currentState.CurrentDirectory = value;
}
}
///
/// Gets FTP session root directory entry.
///
[Browsable(false)]
public FtpDirectory RootDirectory
{
get
{
return m_currentState.RootDirectory;
}
}
///
/// Gets or sets maximum number of seconds to wait for read lock for files to be uploaded. Defaults to 10 seconds.
///
[Browsable(true), Category("Configuration"), Description("Specify the maximum number of seconds to wait for read lock for files to be uploaded."), DefaultValue(10)]
public int WaitLockTimeout
{
get
{
return m_waitLockTimeOut;
}
set
{
m_waitLockTimeOut = value;
}
}
///
/// Changes the current FTP session directory to the specified path.
///
/// New directory.
public void SetCurrentDirectory(string directoryPath)
{
if (!IsConnected)
throw new InvalidOperationException("You must be connected to the FTP server before you can set the current directory.");
if (directoryPath.Length > 0)
{
m_currentState.CurrentDirectory = new FtpDirectory((FtpSessionConnected)m_currentState, CaseInsensitive, directoryPath);
m_currentState.CurrentDirectory.Refresh();
}
}
///
/// Gets the current FTP control channel.
///
[Browsable(false)]
public FtpControlChannel ControlChannel
{
get
{
return m_currentState.ControlChannel;
}
}
///
/// Returns true if FTP session is currently connected.
///
[Browsable(false)]
public bool IsConnected
{
get
{
return (m_currentState is FtpSessionConnected);
}
}
///
/// Returns true if FTP session is currently busy.
///
[Browsable(false)]
public bool IsBusy
{
get
{
return m_currentState.IsBusy;
}
}
internal IFtpSessionState State
{
get
{
return m_currentState;
}
set
{
m_currentState = value;
}
}
#endregion
#region [ Methods ]
///
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected override void Dispose(bool disposing)
{
if (!m_disposed)
{
try
{
if (disposing)
{
if ((object)m_currentState != null)
m_currentState.Dispose();
m_currentState = null;
}
}
finally
{
m_disposed = true; // Prevent duplicate dispose.
base.Dispose(disposing); // Call base class Dispose().
}
}
}
///
/// Aborts current file transfer.
///
public void AbortTransfer()
{
m_currentState.AbortTransfer();
}
///
/// Connects to FTP server using specified credentials.
///
/// User name used to authenticate to FTP server.
/// Password used to authenticate to FTP server.
public void Connect(string userName, string password)
{
m_currentState.Connect(userName, password);
}
///
/// Closes current FTP session.
///
public void Close()
{
m_currentState.Close();
}
internal void OnResponseReceived(string response)
{
if ((object)ResponseReceived != null)
ResponseReceived(this, new EventArgs(response));
}
internal void OnCommandSent(string command)
{
if ((object)CommandSent != null)
CommandSent(this, new EventArgs(command));
}
internal void OnBeginFileTransfer(string localFileName, string remoteFileName, TransferDirection transferDirection)
{
if ((object)BeginFileTransfer != null)
BeginFileTransfer(this, new EventArgs(localFileName, remoteFileName, transferDirection));
}
internal void OnEndFileTransfer(string localFileName, string remoteFileName, TransferDirection transferDirection)
{
if ((object)EndFileTransfer != null)
EndFileTransfer(this, new EventArgs(localFileName, remoteFileName, transferDirection));
}
internal void OnFileTransferProgress(ProcessProgress fileTransferProgress, TransferDirection transferDirection)
{
if ((object)FileTransferProgress != null)
FileTransferProgress(this, new EventArgs, TransferDirection>(fileTransferProgress, transferDirection));
}
internal void OnFileTransferNotification(FtpAsyncResult transferResult)
{
if ((object)FileTransferNotification != null)
FileTransferNotification(this, new EventArgs(transferResult));
}
#endregion
}
}