SuperDesign/Source/RySmartEditor/FTP/FTP_FtpWeb.cs
zilinsoft 993f1ca1a9 ### 2024-12-20 星期五更新
------
#### SuperDesign    V3.0.2412.2001
- *.[新增]新增程序更新日志设置和自动发布功能。
- *.[修复]修复Post数据格式不正确时双击文本框会导致软件闪退的BUG。
2024-12-20 08:15:19 +08:00

460 lines
18 KiB
C#

using GameBackup3H3.DbOp;
using ryCommon;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using WinSCP;
#pragma warning disable CA1031 // 不捕获常规异常类型
namespace FTPop
{
/// <summary>
/// FTP管理
/// </summary>
public class FTPFtpWeb : IFTP, IDisposable
{
private bool disposed = false;
string ftpURI;
public string CurRemoteFolder { get; private set; } = "";
FTPInfo _ftpinfo;
private Encoding GetEncoding()
{
if (_ftpinfo.Encoding == "UTF8")
{ return Encoding.UTF8; }
else
{ return Encoding.GetEncoding(_ftpinfo.Encoding); }
}
private static bool OnCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
/* Console.WriteLine("Server Certificate Issued To: {0}", certificate.GetName());
Console.WriteLine("Server Certificate Issued By: {0}", certificate.GetIssuerName());
// Return true if there are no policy errors
// The certificate can also be manually verified to
//make sure it meets your specific // policies by
// interrogating the x509Certificate object.
if (errors != SslPolicyErrors.None)
{
Console.WriteLine("Server Certificate Validation Error");
Console.WriteLine(errors.ToString());
return false;
}
else
{
Console.WriteLine("No Certificate Validation Errors");
return true;
}*/
return true; //所有證書都合法
}
private void ShowCertificateInfo(X509Certificate remoteCertificate, bool verbose)
{
//Console.WriteLine("Certficate Information for:/n{0}/n", remoteCertificate.GetName());
//Console.WriteLine("Valid From: /n{0}", remoteCertificate.GetEffectiveDateString());
//Console.WriteLine("Valid To: /n{0}", remoteCertificate.GetExpirationDateString());
//Console.WriteLine("Certificate Format: /n{0}/n", remoteCertificate.GetFormat());
//Console.WriteLine("Issuer Name: /n{0}", remoteCertificate.GetIssuerName());
//if (verbose)
//{
// Console.WriteLine("Serial Number: /n{0}", remoteCertificate.GetSerialNumberString());
// Console.WriteLine("Hash: /n{0}", remoteCertificate.GetCertHashString());
// Console.WriteLine("Key Algorithm: /n{0}", remoteCertificate.GetKeyAlgorithm());
// Console.WriteLine("Key Algorithm Parameters: /n{0}", remoteCertificate.GetKeyAlgorithmParametersString());
// Console.WriteLine("Public Key: /n{0}", remoteCertificate.GetPublicKeyString());
//}
}
private void showSslInfo(string serverName, SslStream sslStream, bool verbose)
{
ShowCertificateInfo(sslStream.RemoteCertificate, verbose);
Console.WriteLine("/n/nSSL Connect Report for : {0}/n", serverName);
Console.WriteLine("Is Authenticated: {0}", sslStream.IsAuthenticated);
Console.WriteLine("Is Encrypted: {0}", sslStream.IsEncrypted);
Console.WriteLine("Is Signed: {0}", sslStream.IsSigned);
Console.WriteLine("Is Mutually Authenticated: {0}/n", sslStream.IsMutuallyAuthenticated);
Console.WriteLine("Hash Algorithm: {0}", sslStream.HashAlgorithm);
Console.WriteLine("Hash Strength: {0}", sslStream.HashStrength);
Console.WriteLine("Cipher Algorithm: {0}", sslStream.CipherAlgorithm);
Console.WriteLine("Cipher Strength: {0}/n", sslStream.CipherStrength);
Console.WriteLine("Key Exchange Algorithm: {0}", sslStream.KeyExchangeAlgorithm);
Console.WriteLine("Key Exchange Strength: {0}/n", sslStream.KeyExchangeStrength);
Console.WriteLine("SSL Protocol: {0}", sslStream.SslProtocol);
}
private X509CertificateCollection _clientCertificates = new X509CertificateCollection();
private void AppendText(string text, Color color)
{
}
/// <summary>
/// 打开FTP
/// </summary>
/// <param name="ftpinfo"></param>
public int Open(FTPInfo ftpinfo)
{
if(ftpinfo==null)
{
return -1;
}
_ftpinfo = ftpinfo;
AppendText("Status : Connected to " + ftpinfo.IP + "\n", Color.Red);
InitWorkingDirectory();
return 1;
}
private bool InitWorkingDirectory()
{
ftpURI = "ftp://" + _ftpinfo.IP+":"+_ftpinfo.Port + "/";
return true;
}
/// <summary>
/// 关闭FTP
/// </summary>
/// <returns></returns>
public int Close()
{
return 1;
}
int delCount = 0;
public int ReTryCount { get; set; } = 2;
/// <summary>
/// 移除文件
/// </summary>
/// <param name="remotePath"></param>
/// <returns></returns>
public int RemoveFiles(string remotePath)
{
InitWorkingDirectory();
try
{
string uri = ftpURI + remotePath;
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(_ftpinfo.UserName, _ftpinfo.Pwd);
reqFTP.KeepAlive = false;
reqFTP.Timeout = 3000;
reqFTP.Method = WebRequestMethods.Ftp.DeleteFile;
ServicePoint currentServicePoint = reqFTP.ServicePoint;
currentServicePoint.ConnectionLimit = 1024;
string result = String.Empty;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
long size = response.ContentLength;
Stream datastream = response.GetResponseStream();
StreamReader sr = new StreamReader(datastream);
result = sr.ReadToEnd();
sr.Close();
datastream.Close();
response.Close();
delCount = 0;
return 1;
}
catch (Exception ex)
{
delCount++;
if (delCount <= ReTryCount)
{
return RemoveFiles(remotePath);
}
else
{
delCount = 0;
}
AppendText("Delete Error --> " + ex.Message + " 文件名:" + remotePath, Color.Red);
//Insert_Standard_ErrorLog.Insert("FtpWeb", "Delete Error --> " + ex.Message + " 文件名:" + fileName);
return -1;
}
}
/// <summary>
/// 移动文件
/// </summary>
/// <param name="fromPath"></param>
/// <param name="toPath"></param>
/// <returns></returns>
public int MoveFile(string fromPath, string toPath)
{
FtpWebRequest reqFTP;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fromPath));
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.RenameTo = toPath;
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.Timeout = 10000;
reqFTP.Credentials = new NetworkCredential(_ftpinfo.UserName, _ftpinfo.Pwd);
ServicePoint currentServicePoint = reqFTP.ServicePoint;
currentServicePoint.ConnectionLimit = 1024;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
ftpStream.Close();
response.Close();
}
catch (Exception)
{
return -1;
}
return 1;
}
/// <summary>
/// 文件是否存在
/// </summary>
/// <param name="remotePath"></param>
/// <returns></returns>
public bool FileExists(string remotePath)
{
long Filesize = FileSize(remotePath);
return Filesize>0;
}
/// <summary>
/// 文件大小
/// </summary>
/// <param name="remotePath"></param>
/// <returns></returns>
public Int64 FileSize(string remotePath)
{
FtpWebRequest reqFTP;
long fileSize;
try
{
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + remotePath));
reqFTP.Method = WebRequestMethods.Ftp.GetFileSize;
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.Timeout = 10000;
reqFTP.Credentials = new NetworkCredential(_ftpinfo.UserName, _ftpinfo.Pwd);
ServicePoint currentServicePoint = reqFTP.ServicePoint;
currentServicePoint.ConnectionLimit = 1024;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
fileSize = response.ContentLength;
ftpStream.Close();
response.Close();
}
catch (Exception)
{
return -1;
}
return fileSize;
}
/// <summary>
/// 文件最后修改时间
/// </summary>
/// <param name="remotePath"></param>
/// <returns></returns>
public DateTime FileLastWriteTime(string remotePath)
{
return new DateTime(2000, 1, 1);
}
/// <summary>
/// 文件信息
/// </summary>
/// <param name="remotePath"></param>
/// <returns></returns>
public RemoteFileInfo GetFileInfo(string remotePath)
{
return new RemoteFileInfo();
}
/// <summary>
/// 显示文件夹列表
/// </summary>
/// <param name="CurFolder"></param>
/// <returns></returns>
public List<RemoteFileInfo> ListDirectory(string CurFolder)
{
InitWorkingDirectory();
var list = new List<RemoteFileInfo>();
try
{
string regex =
@"^" + //# Start of line
@"(?<dir>[\-ld])" + //# File size
@"(?<permission>[\-rwx]{9})" + //# Whitespace \n
@"\s+" + //# Whitespace \n
@"(?<filecode>\d+)" +
@"\s+" + //# Whitespace \n
@"(?<owner>\w+)" +
@"\s+" + //# Whitespace \n
@"(?<group>\w+)" +
@"\s+" + //# Whitespace \n
@"(?<size>\d+)" +
@"\s+" + //# Whitespace \n
@"(?<month>\w{3})" + //# Month (3 letters) \n
@"\s+" + //# Whitespace \n
@"(?<day>\d{1,2})" + //# Day (1 or 2 digits) \n
@"\s+" + //# Whitespace \n
@"(?<timeyear>[\d:]{4,5})" + //# Time or year \n
@"\s+" + //# Whitespace \n
@"(?<filename>(.*))" + //# Filename \n
@"$"; //# End of line
StringBuilder result = new StringBuilder();
FtpWebRequest ftp;
ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + CurFolder));
ftp.Credentials = new NetworkCredential(_ftpinfo.UserName, _ftpinfo.Pwd);
ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
ftp.KeepAlive = false;
ftp.Timeout = 10000;
if (_ftpinfo.Encrypt > 0)
{
ServicePointManager.ServerCertificateValidationCallback = new
System.Net.Security.RemoteCertificateValidationCallback(OnCertificateValidation);
ftp.ClientCertificates = new X509CertificateCollection();
ftp.AuthenticationLevel = AuthenticationLevel.MutualAuthRequested;
ftp.ImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
ftp.EnableSsl = true;
}
WebResponse response = ftp.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), GetEncoding());
string line = reader.ReadLine();
while (line != null)
{
var split = new Regex(regex).Match(line);
string dir = split.Groups["dir"].ToString();
string filename = split.Groups["filename"].ToString();
var size = split.Groups["size"].ToString();
bool isDirectory = !string.IsNullOrWhiteSpace(dir) && dir.Equals("d", StringComparison.OrdinalIgnoreCase);
list.Add(new RemoteFileInfo()
{
FullName = CurFolder.TrimEnd('/') +"/"+ filename,
IsDirectory = isDirectory,
Name = filename,
Length = size.ToInt64(),
LastWriteTime = (split.Groups["timeyear"].ToString() + " " + split.Groups["month"].ToString() + " " + split.Groups["day"].ToString()).ToDateTime()
}) ;
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
result.Remove(result.ToString().LastIndexOf("\n", StringComparison.OrdinalIgnoreCase), 1);
reader.Close();
response.Close();
}
catch (Exception)
{
return list;
}
return list;
}
/// <summary>
/// 上传
/// </summary>
/// <param name="localPath"></param>
/// <param name="remotePath"></param>
/// <returns></returns>
public int Upload(string localPath, string remotePath)
{
FileInfo fileInf = new FileInfo(localPath);
string uri = ftpURI + remotePath;
FtpWebRequest reqFTP;
reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));
reqFTP.Credentials = new NetworkCredential(_ftpinfo.UserName, _ftpinfo.Pwd);
reqFTP.KeepAlive = true;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = fileInf.Length;
reqFTP.EnableSsl = true;
ServicePoint currentServicePoint = reqFTP.ServicePoint;
currentServicePoint.ConnectionLimit = 1024;
int buffLength = 2048;
byte[] buff = new byte[buffLength];
int contentLen;
FileStream fs = fileInf.OpenRead();
Int64 upload_size = 0;
try
{
Stream strm = reqFTP.GetRequestStream();
contentLen = fs.Read(buff, 0, buffLength);
while (contentLen != 0)
{
double process = upload_size / (double)fileInf.Length;
if (process > 1) { process = 1; }
var progress = new FileTransferProgressEventArgs()
{
Cancel = false,
LocalPath = localPath,
FileProgress = process,
};
FileTransferProgress?.Invoke(this, progress);
if (progress.Cancel) { break; }
upload_size += buffLength;
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, buffLength);
}
strm.Close();
fs.Close();
var progress2 = new FileTransferProgressEventArgs()
{
Cancel = false,
LocalPath = localPath,
FileProgress = 1,
IsComplete=true
};
FileTransferProgress?.Invoke(this, progress2);
return 1;
}
catch (Exception ex)
{
ErrorMsg = ex.Message;
return -1;
}
}
public string ErrorMsg { get; set; } = "";
/// <summary>
/// 文件传输事件
/// </summary>
public event FileTransferProgressEventHandler FileTransferProgress;
~FTPFtpWeb()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
Close();
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
}
// Release unmanaged resources. If disposing is false,
// only the following code is executed.
// Note that this is not thread safe.
// Another thread could start disposing the object
// after the managed resources are disposed,
// but before the disposed flag is set to true.
// If thread safety is necessary, it must be
// implemented by the client.
}
disposed = true;
}
}
}