//****************************************************************************************************** // 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; using System.Net; // 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 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 asynchronous 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_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) { CaseInsensitive = caseInsensitive; WaitLockTimeout = 10; State = new FtpSessionDisconnected(this, CaseInsensitive); } /// /// Initializes a new instance of the class. /// /// object that contains the . public FtpClient(IContainer container) : this() { 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 => State.Server; set => State.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; set; } /// /// 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 => State.Port; set => State.Port = value; } /// /// Gets or sets the timeout, in milliseconds, for /// read and write operations, defaults to 30 seconds. /// [Browsable(true), Category("Configuration"), Description("Specify FTP server read/write timeout, if needed."), DefaultValue(30000)] public int Timeout { get => State.Timeout; set => State.Timeout = value; } /// /// Gets or sets the passive/active mode of the server. /// [Browsable(true), Category("Configuration"), Description("Specify passive/active mode of FTP server."), DefaultValue(true)] public bool Passive { get => State.Passive; set => State.Passive = value; } /// /// Gets or sets the IP address to send with the PORT command. /// [Browsable(true), Category("Configuration"), Description("Specify IP address to send with PORT command."), DefaultValue(null)] public string ActiveAddress { get => State.ActiveAddress.ToString(); set => State.ActiveAddress = IPAddress.TryParse(value, out IPAddress address) ? address : null; } /// /// Gets or sets the minimum value in the range of ports /// used when listening for connections in active mode. /// [Browsable(true), Category("Configuration"), Description("Specify minimum port in range of active ports."), DefaultValue(0)] public int MinActivePort { get => State.MinActivePort; set => State.MinActivePort = value; } /// /// Gets or sets the maximum value in the range of ports /// used when listening for connections in active mode. /// [Browsable(true), Category("Configuration"), Description("Specify maximum port in range of active ports."), DefaultValue(0)] public int MaxActivePort { get => State.MaxActivePort; set => State.MaxActivePort = value; } /// /// Gets or sets current FTP session directory. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public FtpDirectory CurrentDirectory { get => State.CurrentDirectory; set => State.CurrentDirectory = value; } /// /// Gets FTP session root directory entry. /// [Browsable(false)] public FtpDirectory RootDirectory => State.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; set; } /// /// 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) return; State.CurrentDirectory = new FtpDirectory((FtpSessionConnected)State, CaseInsensitive, directoryPath); State.CurrentDirectory.Refresh(); } /// /// Gets the current FTP control channel. /// [Browsable(false)] public FtpControlChannel ControlChannel => State.ControlChannel; /// /// Returns true if FTP session is currently connected. /// [Browsable(false)] public bool IsConnected => State is FtpSessionConnected; /// /// Returns true if FTP session is currently busy. /// [Browsable(false)] public bool IsBusy => State.IsBusy; internal IFtpSessionState State { get; set; } #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) return; try { if (!disposing) return; State?.Dispose(); State = null; } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } /// /// Aborts current file transfer. /// public void AbortTransfer() { State.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) { State.Connect(userName, password); } /// /// Closes current FTP session. /// public void Close() { State.Close(); } internal void OnResponseReceived(string response) { ResponseReceived?.Invoke(this, new EventArgs(response)); } internal void OnCommandSent(string command) { CommandSent?.Invoke(this, new EventArgs(command)); } internal void OnBeginFileTransfer(string localFileName, string remoteFileName, TransferDirection transferDirection) { BeginFileTransfer?.Invoke(this, new EventArgs(localFileName, remoteFileName, transferDirection)); } internal void OnEndFileTransfer(string localFileName, string remoteFileName, TransferDirection transferDirection) { EndFileTransfer?.Invoke(this, new EventArgs(localFileName, remoteFileName, transferDirection)); } internal void OnFileTransferProgress(ProcessProgress fileTransferProgress, TransferDirection transferDirection) { FileTransferProgress?.Invoke(this, new EventArgs, TransferDirection>(fileTransferProgress, transferDirection)); } internal void OnFileTransferNotification(FtpAsyncResult transferResult) { FileTransferNotification?.Invoke(this, new EventArgs(transferResult)); } #endregion } }