using System; using System.Collections.Generic; using System.Linq; using System.Text; using Kayak; using Kayak.Http; using System.Net; namespace IW4MAdmin_Web { class WebFront { public enum Page { main, stats, bans } public WebFront() { } public void Init() { webSchedule = KayakScheduler.Factory.Create(new SchedulerDelegate()); webServer = KayakServer.Factory.CreateHttp(new RequestDelegate(), webSchedule); using (webServer.Listen(new IPEndPoint(IPAddress.Any, 1624))) { // runs scheduler on calling thread. this method will block until // someone calls Stop() on the scheduler. webSchedule.Start(); } } private IScheduler webSchedule; private IServer webServer; } static class Macro { static public String parsePagination(int server, int totalItems, int itemsPerPage, int currentPage, String Page) { StringBuilder output = new StringBuilder(); output.Append("
"); if ( currentPage > 0) output.AppendFormat("PREV", server, currentPage - 1, Page); double totalPages = Math.Ceiling(((float)totalItems / itemsPerPage)); output.Append("" + (currentPage + 1) + "/" + totalPages + ""); if ((currentPage + 1) < totalPages) output.AppendFormat("NEXT", server, currentPage + 1, Page); output.Append("
"); return output.ToString(); } static public String parseMacros(String input, WebFront.Page Page, int Pagination, int server) { StringBuilder buffer = new StringBuilder(); switch (input) { case "SERVERS": var Servers = IW4MAdmin.Program.Servers; for (int i = 0; i < Servers.Count; i++) { StringBuilder players = new StringBuilder(); if (Servers[i].getClientNum() < 1) players.Append("No Players"); else { int count = 0; foreach (IW4MAdmin.Player P in Servers[i].statusPlayers.Values) { if (count > 0 && count % 6 == 0) players.Append(""); players.AppendFormat("{0}", P.getName()); count++; } } buffer.AppendFormat(@"
{0} {1} {2} {3} Stats Bans
{5}

", Servers[i].getName(), Servers[i].getMap(), Servers[i].getClientNum() + "/" + Servers[i].getMaxClients(), IW4MAdmin.Utilities.gametypeLocalized(Servers[i].getGametype()), i, players.ToString()); } return buffer.ToString(); case "TITLE": return "IW4M Administration"; case "BANS": buffer.Append(""); int totalBans = IW4MAdmin.Program.Servers[0].Bans.Count; int range; int start = Pagination*30 + 1; int cycleFix = 0; if (totalBans <= 30) range = totalBans - 1; else if ((totalBans - start) < 30) range = (totalBans - start); else range = 30; List Bans = new List(); if (totalBans > 0) Bans = IW4MAdmin.Program.Servers[0].Bans.GetRange(start, range); else Bans.Add(new IW4MAdmin.Ban("No Bans", "0", "0", DateTime.Now, "")); buffer.Append("

{{TIME}}


"); if (Bans[0] != null) buffer = buffer.Replace("{{TIME}}", "From " + IW4MAdmin.Utilities.timePassed(Bans[0].getTime()) + " ago" + " — " + totalBans + " total"); for (int i = 0; i < Bans.Count; i++) { if (Bans[i] == null) continue; IW4MAdmin.Player P = IW4MAdmin.Program.Servers[0].clientDB.getPlayer(Bans[i].getID(), -1); IW4MAdmin.Player B = IW4MAdmin.Program.Servers[0].clientDB.getPlayer(Bans[i].getBanner(), -1); if (P == null) P = new IW4MAdmin.Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, ""); if (B == null) B = new IW4MAdmin.Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, ""); if (P.getLastO() == String.Empty) P.LastOffense = "Evade"; if (P != null && B != null) { if (B.getID() == P.getID()) B.updateName("IW4MAdmin"); // shh it will all be over soon String Prefix; if (cycleFix % 2 == 0) Prefix = "class=row-grey"; else Prefix = "class=row-white"; buffer.AppendFormat("", P.getName(), P.getLastO(), IW4MAdmin.Utilities.nameHTMLFormatted(B), Bans[i].getWhen(), Prefix); cycleFix++; } } buffer.Append("
NameOffenseBanned ByTime
{0}{1}{2}{3}

"); buffer.Append(parsePagination(server, IW4MAdmin.Program.Servers[0].Bans.Count, 30, Pagination, "bans")); return buffer.ToString(); case "PAGE": buffer.Append("
"); return buffer.ToString(); case "STATS": int totalStats = IW4MAdmin.Program.Servers[server].statDB.totalStats(); buffer.Append("

Starting at #{{TOP}}


"); buffer.Append(""); start = Pagination*30; if (totalStats <= 30) range = totalStats - 1; else if ((totalStats - start) < 30 ) range = (totalStats - start); else range = 30; List Stats = IW4MAdmin.Program.Servers[server].statDB.getMultipleStats(start, range); buffer.Append(""); cycleFix = 0; for (int i = 0; i < totalStats; i++) { if (i >= Stats.Count -1 || Stats[i] == null ) continue; IW4MAdmin.Player P = IW4MAdmin.Program.Servers[server].clientDB.getPlayer(Stats[i].statIndex); if (P == null) continue; P.stats = Stats[i]; if (P.stats != null) { String Prefix; if (cycleFix % 2 == 0) Prefix = "class=row-grey"; else Prefix = "class=row-white"; buffer.AppendFormat("", P.getName(), P.stats.Kills, P.stats.Deaths, P.stats.KDR, P.stats.Skill, Prefix); cycleFix++; } } buffer.Append("
NameKillsDeathsKDRRating
{0}{1}{2}{3}{4}

"); buffer.Append(parsePagination(server, totalStats, 30, Pagination, "stats")); return buffer.ToString().Replace("{{TOP}}", (start + 1).ToString()); default: return input; } } static public String findMacros(String input, int pageNumber, int server, WebFront.Page page) { String output = input; switch (page) { case WebFront.Page.main: output = output.Replace("{{SERVERS}}", parseMacros("SERVERS", page, pageNumber, server)); break; case WebFront.Page.bans: output = output.Replace("{{BANS}}", parseMacros("BANS", page, pageNumber, server)); break; case WebFront.Page.stats: output = output.Replace("{{STATS}}", parseMacros("STATS", page, pageNumber, server)); break; } //output = output.Replace("{{PAGE}}", parseMacros("PAGE", page, pageNumber, server)); //output = output.Replace("{{SERVERS}}", parseMacros("SERVERS", 0)); //output = output.Replace("{{BANS}}", parseMacros("BANS", page)); output = output.Replace("{{TITLE}}", "IW4M Administration"); //output = output.Replace("{{PAGE}}", parseMacros("PAGE", page)); //output = output.Replace("{{STATS}}", parseMacros("STATS", page)); return output; } } class SchedulerDelegate : ISchedulerDelegate { public void OnException(IScheduler scheduler, Exception e) { Console.WriteLine(e.InnerException.Message); Console.Write(e.InnerException); e.DebugStackTrace(); } public void OnStop(IScheduler scheduler) { } } class RequestDelegate : IHttpRequestDelegate { public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response) { if (request.Uri.StartsWith("/")) { Console.WriteLine("[WEBFRONT] Processing Request for " + request.Uri); var body = String.Empty; if (request.Uri.StartsWith("/")) { IW4MAdmin.file Header = new IW4MAdmin.file("webfront\\header.html"); var header = Header.getLines(); Header.Close(); String[] req = request.Path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries); int server = 0; int page = 0; if (req.Length > 1) { Int32.TryParse(req[0], out server); Int32.TryParse(req[1], out page); } if (request.QueryString == "bans") { IW4MAdmin.file Bans = new IW4MAdmin.file("webfront\\bans.html"); var bans = Bans.getLines(); Bans.Close(); body = Macro.findMacros((header + bans), page, server, WebFront.Page.bans); } else if (request.QueryString == "stats") { IW4MAdmin.file Stats = new IW4MAdmin.file("webfront\\stats.html"); var stats = Stats.getLines(); Stats.Close(); body = Macro.findMacros(header + stats, page, server, WebFront.Page.stats); } else { IW4MAdmin.file Main = new IW4MAdmin.file("webfront\\main.html"); var main = Main.getLines(); Main.Close(); body = Macro.findMacros(header + main, 0, server, WebFront.Page.main); } } /*var body = string.Format( "Uri: {0}\r\nPath: {1}\r\nQuery:{2}\r\nFragment: {3}\r\n", request.Uri, request.Path, request.QueryString, request.Fragment);*/ var headers = new HttpResponseHead() { Status = "200 OK", Headers = new Dictionary() { { "Content-Type", "text/html" }, { "Content-Length", body.Length.ToString() }, } }; response.OnResponse(headers, new BufferedProducer(body)); } else { var responseBody = "The resource you requested ('" + request.Uri + "') could not be found."; var headers = new HttpResponseHead() { Status = "404 Not Found", Headers = new Dictionary() { { "Content-Type", "text/text" }, { "Content-Length", responseBody.Length.ToString() } } }; var body = new BufferedProducer(responseBody); response.OnResponse(headers, body); } } class BufferedProducer : IDataProducer { ArraySegment data; public BufferedProducer(string data) : this(data, Encoding.UTF8) { } public BufferedProducer(string data, Encoding encoding) : this(encoding.GetBytes(data)) { } public BufferedProducer(byte[] data) : this(new ArraySegment(data)) { } public BufferedProducer(ArraySegment data) { this.data = data; } public IDisposable Connect(IDataConsumer channel) { // null continuation, consumer must swallow the data immediately. channel.OnData(data, null); channel.OnEnd(); return null; } } class BufferedConsumer : IDataConsumer { List> buffer = new List>(); Action resultCallback; Action errorCallback; public BufferedConsumer(Action resultCallback, Action errorCallback) { this.resultCallback = resultCallback; this.errorCallback = errorCallback; } public bool OnData(ArraySegment data, Action continuation) { // since we're just buffering, ignore the continuation. buffer.Add(data); return false; } public void OnError(Exception error) { errorCallback(error); } public void OnEnd() { // turn the buffer into a string. var str = buffer .Select(b => Encoding.UTF8.GetString(b.Array, b.Offset, b.Count)) .Aggregate((result, next) => result + next); resultCallback(str); } } } }