Files
mapo-iob-libs/EgwProxy.Ftp/Manager.cs
T
Samuele Locatelli a2171e643d Aggiunta proxy iniziale:
- FTP
- Gomba
- Icoel
- MultiCcn
- OSAI
- SqlDB
2024-12-23 09:01:29 +01:00

530 lines
18 KiB
C#

using FluentFTP;
using NLog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
namespace EgwProxy.Ftp
{
/// <summary>
/// Client per operazioni FTP, basato su FluentFTP: https://github.com/robinrodricks/FluentFTP https://github.com/robinrodricks/FluentFTP/wiki/Quick-Start-Example
/// </summary>
public class Manager
{
#region Public Constructors
/// <summary>
/// Inizializzazione di oggetto per comunicazione FTP
/// </summary>
/// <param name="server"></param>
/// <param name="userName"></param>
/// <param name="passwd"></param>
/// <param name="rawCert"></param>
/// <param name="skipCert"></param>
public Manager(string server, string userName, string passwd, string rawCert, bool skipCert)
{
_server = server;
_userName = userName;
_passwd = passwd;
_skipCert = skipCert;
_rawCert = rawCert;
if (!string.IsNullOrEmpty(server))
{
// se ho user/pwd è autenticato...
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(passwd))
{
client = new FtpClient(server, userName, passwd);
}
//.. altrimenti anonimo...
else
{
client = new FtpClient(server);
}
client.Config.RetryAttempts = 3;
IsConfigured = true;
}
}
#endregion Public Constructors
#region Public Properties
public bool IsConfigured { get; set; } = false;
#endregion Public Properties
#region Public Methods
/// <summary>
/// Creazione directory remota
/// </summary>
/// <param name="remoteDir">Nome directory remota da creare (ad es: @"/public_html/videos")</param>
public bool CreateDir(string remoteDir)
{
bool answ = false;
try
{
tryConnect();
// upload della folder + files, cancellazione extra files = mirroring
answ = client.CreateDirectory(remoteDir);
}
catch (Exception exc)
{
Log.Error($"Eccezione in CreateDir{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Eliminazionedirectory remota
/// </summary>
/// <param name="remoteDir">Nome directory remota da eliminare</param>
public bool DeleteDir(string remoteDir)
{
bool answ = false;
try
{
tryConnect();
// Elimina folder
client.DeleteDirectory(remoteDir);
answ = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione in DeleteDir{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Eliminazione file remoto
/// </summary>
/// <param name="remoteFile">Nome file remoto da eliminare</param>
public bool DeleteFile(string remoteFile)
{
bool answ = false;
tryConnect();
try
{
// Elimina folder
client.DeleteFile(remoteFile);
answ = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione in DeleteFile{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Eliminazione lista di files remoti
/// </summary>
/// <param name="remFileList">Lista file remoti da eliminare</param>
public int DeleteFileList(List<string> remFileList)
{
int numDone = 0;
tryConnect();
try
{
foreach (var remoteFile in remFileList)
{
// Elimina folder
client.DeleteFile(remoteFile);
// verifico se sia presente...
bool fExist = client.FileExists(remoteFile);
if (!fExist)
{
numDone++;
}
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in DeleteFileList{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return numDone;
}
/// <summary>
/// Verifica esistenza directory su server FTP remoto
/// </summary>
/// <param name="remotePath">Percorso remoto da testare (ad es "/htdocs/extras/")</param>
/// <returns></returns>
public bool DirExists(string remotePath)
{
bool answ = false;
try
{
tryConnect();
answ = client.DirectoryExists(remotePath);
}
catch (Exception exc)
{
Log.Error($"Eccezione in DirExists{Environment.NewLine}{exc}");
}
// c chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Verifica esistenza file su server FTP remoto
/// </summary>
/// <param name="remotePath">Percorso remoto da testare (ad es "/htdocs/big2.txt")</param>
/// <returns></returns>
public bool FileExists(string remotePath)
{
bool answ = false;
try
{
tryConnect();
answ = client.FileExists(remotePath);
}
catch (Exception exc)
{
Log.Error($"Eccezione in FileExists{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Scaricamento intera directory, modalità MIRROR
/// </summary>
/// <param name="localDir">Path directory da inviare (ad es:@"C:\website\videos\")</param>
/// <param name="remoteDir">Nome remoto file per caricamento (ad es: @"/public_html/videos")</param>
/// <param name="syncMode">Modalità di sync (default = mirror)</param>
public bool GetDir(string localDir, string remoteDir, FtpFolderSyncMode syncMode = FtpFolderSyncMode.Mirror)
{
bool answ = false;
try
{
tryConnect();
// download della folder secondo modalità sync
var result = client.DownloadDirectory(localDir, remoteDir, syncMode);
//answ = (result != null && result.Count > 0);
answ = result != null && result.Where(x => !x.IsSuccess).Count() == 0;
}
catch (Exception exc)
{
Log.Error($"Eccezione in GetDir{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Download singolo file
/// </summary>
/// <param name="fileName">Path locale del file da inviare (ad es: @"C:\MyVideo.mp4")</param>
/// <param name="remoteName">NOme remoto file per caricamento (ad es: "/htdocs/MyVideo.mp4")</param>
public bool GetFile(string fileName, string remoteName)
{
bool answ = false;
try
{
tryConnect();
// effettuo caricamento puntuale
var result = client.DownloadFile(fileName, remoteName);
answ = result == FtpStatus.Success;
}
catch (Exception exc)
{
Log.Error($"Eccezione in GetFile{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Mostra contenuto directory remota
/// </summary>
/// <param name="remoteDir">Nome directory remota da leggere con (ad es: @"/public_html/videos")</param>
/// <param name="recurse">Indica se fare search ricorsivo</param>
public List<FtpListItem> GetRemoteList(string remoteDir, bool recurse)
{
List<FtpListItem> answ = new List<FtpListItem>();
try
{
tryConnect();
// recupero listing remoto directory
FtpListItem[] dirContent;
if (recurse)
{
dirContent = client.GetListing(remoteDir, FtpListOption.Recursive);
}
else
{
dirContent = client.GetListing(remoteDir);
}
answ = dirContent.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione in GetRemoteList{Environment.NewLine}{exc}");
}
client.Disconnect();
// chiudo!
return answ;
}
/// <summary>
/// Mostra contenuto directory remota
/// </summary>
/// <param name="remoteDir">Nome directory remota da leggere (ad es: @"/public_html/videos")</param>
/// <param name="recurse">Indica se fare search ricorsivo</param>
public List<string> ListDir(string remoteDir, bool recurse)
{
List<string> answ = new List<string>();
try
{
tryConnect();
// upload della folder + files, cancellazione extra files = mirroring
FtpListItem[] dirContent;
if (recurse)
{
dirContent = client.GetListing(remoteDir, FtpListOption.Recursive);
}
else
{
dirContent = client.GetListing(remoteDir);
}
answ = dirContent.Select(x => $"{x.Type} - {x.Name}").ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione in ListDir{Environment.NewLine}{exc}");
}
client.Disconnect();
// chiudo!
return answ;
}
/// <summary>
/// Caricamento intera directory, modalità MIRROR
/// </summary>
/// <param name="localDir">Path directory da inviare (ad es:@"C:\website\videos\")</param>
/// <param name="remoteDir">Nome remoto file per caricamento (ad es: @"/public_html/videos")</param>
/// <param name="syncMode">Modalità di sync (default = mirror)</param>
public List<FtpResult> MirrorLocalDir(string localDir, string remoteDir, FtpFolderSyncMode syncMode = FtpFolderSyncMode.Mirror)
{
List<FtpResult> jobResult = new List<FtpResult>();
try
{
tryConnect();
jobResult = client.UploadDirectory(localDir, remoteDir, syncMode);
//answ = (result != null && result.Count > 0);
}
catch (Exception exc)
{
Log.Error($"Eccezione in MirrorLocalDir{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return jobResult;
}
/// <summary>
/// Scaricamento intera directory, modalità MIRROR, con restituzione elenco esiti
/// </summary>
/// <param name="localDir">Path directory da inviare (ad es:@"C:\website\videos\")</param>
/// <param name="remoteDir">Nome remoto file per caricamento (ad es: @"/public_html/videos")</param>
/// <param name="syncMode">Modalità di sync (default = mirror)</param>
public List<FtpResult> MirrorRemoteDir(string localDir, string remoteDir, FtpFolderSyncMode syncMode = FtpFolderSyncMode.Mirror)
{
List<FtpResult> jobResult = new List<FtpResult>();
try
{
tryConnect();
jobResult = client.DownloadDirectory(localDir, remoteDir, syncMode);
}
catch (Exception exc)
{
Log.Error($"Eccezione in mirrorRemoteDir{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return jobResult;
}
/// <summary>
/// Caricamento intera directory, modalità MIRROR
/// </summary>
/// <param name="localDir">Path directory da inviare (ad es:@"C:\website\videos\")</param>
/// <param name="remoteDir">Nome remoto file per caricamento (ad es: @"/public_html/videos")</param>
/// <param name="syncMode">Modalità di sync (default = mirror)</param>
public bool SendDir(string localDir, string remoteDir, FtpFolderSyncMode syncMode = FtpFolderSyncMode.Mirror)
{
bool answ = false;
try
{
tryConnect();
//var result = client.UploadDirectory(localDir, remoteDir, FtpFolderSyncMode.Mirror, FtpRemoteExists.OverwriteInPlace, FtpVerify.Retry);
// upload della folder + files, cancellazione extra files = mirroring
var result = client.UploadDirectory(localDir, remoteDir, syncMode);
//answ = (result != null && result.Count > 0);
answ = result != null && result.Where(x => !x.IsSuccess).Count() == 0;
}
catch (Exception exc)
{
Log.Error($"Eccezione in SendDir{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Caricamento singolo file
/// </summary>
/// <param name="fileName">Path locale del file da inviare (ad es: @"C:\MyVideo.mp4")</param>
/// <param name="remoteName">NOme remoto file per caricamento (ad es: "/htdocs/MyVideo.mp4")</param>
public bool SendFile(string fileName, string remoteName)
{
bool answ = false;
try
{
tryConnect();
tryConnect();
// effettuo caricamento puntuale
var result = client.UploadFile(fileName, remoteName);
answ = result == FtpStatus.Success;
// se insuccesso --> controllo se ci sia file...
if (!answ)
{
answ = FileExists(remoteName);
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in SendFile{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Verifica connessione con server FTP remoto
/// </summary>
/// <returns></returns>
public bool ServerOk()
{
bool answ = false;
try
{
tryConnect();
answ = client.IsConnected;
}
catch (Exception exc)
{
Log.Error($"Eccezione in ServerOk{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
/// <summary>
/// Restituisce tipo server remoto
/// </summary>
/// <returns></returns>
public string ServerType()
{
string answ = "";
try
{
tryConnect();
FtpServer srvType = client.ServerType;
answ = $"{srvType}";
}
catch (Exception exc)
{
Log.Error($"Eccezione in ServerType{Environment.NewLine}{exc}");
}
// chiudo!
client.Disconnect();
return answ;
}
#endregion Public Methods
#region Protected Fields
protected bool _skipCert = false;
#endregion Protected Fields
#region Protected Properties
protected string _passwd { get; set; } = "";
protected string _rawCert { get; set; } = "";
protected string _server { get; set; } = "";
protected string _userName { get; set; } = "";
#endregion Protected Properties
#region Private Fields
private static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Private Properties
private FtpClient client { get; set; } = new FtpClient();
#endregion Private Properties
#region Private Methods
private void Client_ValidateCertificate(FluentFTP.Client.BaseClient.BaseFtpClient control, FtpSslValidationEventArgs e)
{
if (e.PolicyErrors == SslPolicyErrors.None || _skipCert || e.Certificate.GetRawCertDataString() == _rawCert)
{
e.Accept = true;
}
else
{
Log.Error($"{e.PolicyErrors}");
Log.Error($"Cert:{Environment.NewLine}{e.Certificate}");
Log.Error($"RawString:{Environment.NewLine}{e.Certificate.GetRawCertDataString()}");
throw new Exception($"{e.PolicyErrors}{Environment.NewLine}{e.Certificate.GetRawCertDataString()}");
}
}
private void tryConnect()
{
// connect to the server and automatically detect working FTP settings
if (!client.IsConnected)
{
var profiles = client.AutoDetect(true, true);
#if false
// if any profiles are found, print the code to the console
if (profiles.Count > 0)
{
var code = profiles[0].ToCode();
Console.WriteLine(code);
}
#endif
client.ValidateCertificate += Client_ValidateCertificate;
client.AutoConnect();
}
}
#endregion Private Methods
}
}