add FTP handler + mime type guesser

This commit is contained in:
Yuki 2023-10-08 22:27:47 -04:00
parent e049b1a090
commit 1f901943e3
3 changed files with 122 additions and 3 deletions

View File

@ -1,5 +1,6 @@
using System.Text; using System.Text;
using System.Web; using System.Web;
using HeyRed.Mime;
namespace Shoko; namespace Shoko;
@ -13,17 +14,18 @@ class FileProtoHandler : ProtoHandler
public override void Load() public override void Load()
{ {
var file = HttpUtility.UrlDecode(new UriBuilder(URL).Path); var file = HttpUtility.UrlDecode(URL.AbsolutePath);
if(URL.Host.Length > 0) if(URL.Host.Length > 0)
file = "//" + URL.Host + file; file = "//" + URL.Host + file;
MediaType = "text/plain"; // TODO: magic numbers MediaType = "text/plain";
Status = "OK"; Status = "OK";
if(File.Exists(file)) if(File.Exists(file))
{ {
var stream = new FileStream(file, FileMode.Open); var stream = new FileStream(file, FileMode.Open);
MediaType = MimeGuesser.GuessMimeType(stream);
Content = stream; Content = stream;
} }
else if(Directory.Exists(file)) else if(Directory.Exists(file))

View File

@ -0,0 +1,116 @@
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()
{
}
}

View File

@ -1,5 +1,6 @@
using System.Reflection; using System.Reflection;
using System.Web; using System.Web;
using HeyRed.Mime;
namespace Shoko; namespace Shoko;
@ -16,10 +17,10 @@ class ResProtoHandler : ProtoHandler
var path = HttpUtility.HtmlDecode(new UriBuilder(URL).Path); var path = HttpUtility.HtmlDecode(new UriBuilder(URL).Path);
Status = "OK"; Status = "OK";
Loaded = true; Loaded = true;
MediaType = "text/plain";
try try
{ {
Content = Assembly.GetExecutingAssembly().GetManifestResourceStream(path); Content = Assembly.GetExecutingAssembly().GetManifestResourceStream(path);
MediaType = MimeGuesser.GuessMimeType(Content);
} }
catch catch
{ {