diff --git a/Protocols/SpartanProtoHandler.cs b/Protocols/SpartanProtoHandler.cs new file mode 100644 index 0000000..1f16a16 --- /dev/null +++ b/Protocols/SpartanProtoHandler.cs @@ -0,0 +1,81 @@ +using System.Net.Sockets; +using System.Text; +using System.Web; + +namespace Shoko; + +[Protocol("spartan")] +class SpartanProtoHandler : ProtoHandler +{ + public SpartanProtoHandler(Uri url) + { + URL = url; + } + + public override void Load() + { + var file = URL.AbsolutePath; + + if(!file.StartsWith("/")) file = "/"+file; + + var data = URL.Query; + if(data.StartsWith("?")) data.Remove(0,1); + + var query = Encoding.UTF8.GetBytes(data); + + var uri = Encoding.UTF8.GetBytes($"{URL.Host} {HttpUtility.UrlDecode(file)} {query.Length}\r\n"); + + var tcp = new TcpClient(URL.Host, URL.Port < 0 ? 300 : URL.Port); + + var stream = tcp.GetStream(); + stream.Write(uri); + if(query.Length > 0) + stream.Write(query); + + var reader = new StreamReader(stream); + var header = reader.ReadLine(); + + var meta = header.Split(" ", 2, StringSplitOptions.TrimEntries); + Status = meta[0]; + + MediaType = "text/plain"; + + if(Status.StartsWith('2')) + { + if(meta.Length > 1) + { + var dict = new Dictionary(); + var type = meta[1].Split(";", StringSplitOptions.TrimEntries).ToList(); + MediaType = type[0]; + + foreach (var item in type) + { + var val = item.Split("=", 2); + dict[val[0]] = val.Length > 1 ? val[1] : ""; + } + + MediaTypeParams = dict; + } + Content = stream; + } + else + { + byte[] content = new byte[]{}; + if(meta.Length > 1) + { + if(Status.StartsWith('3')) + { + meta[1] = "=> "+meta[1]; + MediaType = "text/gemini"; + } + content = Encoding.UTF8.GetBytes(meta[1]); + } + Content = new MemoryStream(content); + } + Loaded = true; + } + + public override void Render() + { + } +} \ No newline at end of file