shoko/Protocols/FtpProtoHandler.cs

116 lines
3.5 KiB
C#

using System.Net;
using System.Text;
using FluentFTP;
using HeyRed.Mime;
namespace Shoko;
[Protocol("ftp")]
[Protocol("ftps")]
class FtpProtoHandler : ProtoHandler
{
public FtpProtoHandler(Uri url)
{
URL = url;
}
public override void Load()
{
var file = URL.AbsolutePath;
var conn = new FtpClient
{
Host = URL.Host,
Port = URL.Port
};
if (URL.UserInfo.Length > 0)
{
var userinfo = URL.UserInfo.Split(":",2);
var user = userinfo[0];
var pass = userinfo.Length > 1 ? userinfo[1] : "";
conn.Credentials = new NetworkCredential(user, pass);
}
if(URL.Scheme == "ftps")
{
conn.Config.EncryptionMode = FtpEncryptionMode.Explicit;
conn.Config.ValidateAnyCertificate = true;
}
conn.Config.LogToConsole = true;
conn.Config.LogHost = true;
conn.Config.LogUserName = true;
conn.Config.LogPassword = true;
conn.Connect();
MediaType = "text/plain"; // TODO: magic numbers
Status = "OK";
var info = conn.GetObjectInfo(file);
if(info is not null)
{
switch(info.Type)
{
case FtpObjectType.File:
//Content = conn.OpenRead(file);
if(conn.DownloadBytes(out byte[] bytes, info.FullName))
{
Content = new MemoryStream(bytes);
MediaType = MimeGuesser.GuessMimeType(Content);
}
break;
case FtpObjectType.Directory:
MediaType = "text/gemini";
var entries = conn.GetListing(info.FullName);
var str = "# "+file+"\r\n";
foreach(var entry in entries)
{
var path = entry.Name;
if(entry.Type == FtpObjectType.Directory) path += "/";
var target = new Uri(URL, path).ToString();
if(entry.Type == FtpObjectType.Link) target = new Uri(URL, info.LinkTarget).ToString();
str += string.Format("=>{0} {1}\r\n", target, path);
}
Content = new MemoryStream(Encoding.UTF8.GetBytes(str));
break;
case FtpObjectType.Link:
MediaType = "text/gemini";
Content = new MemoryStream(Encoding.UTF8.GetBytes("=>"+new Uri(URL, info.LinkTarget).ToString()));
break;
}
}
else
{
if(conn.DirectoryExists(file))
{
MediaType = "text/gemini";
var entries = conn.GetListing(file);
var str = "# "+file+"\r\n";
foreach(var entry in entries)
{
var path = entry.Name;
if(entry.Type == FtpObjectType.Directory) path += "/";
str += string.Format("=>{0} {1}\r\n", new Uri(URL, path).ToString(), path);
}
Content = new MemoryStream(Encoding.UTF8.GetBytes(str));
}
else
{
Content = new MemoryStream(Encoding.UTF8.GetBytes("file not found"));
Status = "not found";
}
}
Loaded = true;
}
public override void Render()
{
}
}