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 async Task 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(); await stream.WriteAsync(uri); if(query.Length > 0) await stream.WriteAsync(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 = await Download(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); } OnLoaded(); } public override void Render() { } }