#define ENABLED_CRAP_CODE_THAT_NEEDS_TO_BE_REWRITTEN using System; using System.Globalization; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using Kayak; using Kayak.Http; using System.Net; using SharedLibrary; using IW4MAdmin; #if ENABLED_CRAP_CODE_THAT_NEEDS_TO_BE_REWRITTEN namespace IW4MAdmin_Web { class Client { public Client ( WebFront.Page req, int cur, IDictionary inc, String D, Player P) { requestedPage = req; requestedPageNumber = cur; requestOrigin = inc; requestData = D; playerRequesting = P; } public WebFront.Page requestedPage { get; private set; } public int requestedPageNumber { get; private set; } public IDictionary requestOrigin { get; private set; } public String requestData { get; private set; } public Player playerRequesting { get; private set; } } class WebFront { private Server[] Servers; public enum Page { main, stats, bans, player } public WebFront() { Servers = Program.getServers(); } 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(); } } public 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 server, int Pagination, bool logged, String Data) { StringBuilder buffer = new StringBuilder(); Server[] Servers= Program.getServers(); switch (input) { case "SERVERS": int cycleFix = 0; for (int i = 0; i < Servers.Count(); i++) { if (Program.getServers()[i] == null) continue; StringBuilder players = new StringBuilder(); if (Servers[i].getClientNum() < 1) players.Append("

No Players

"); else { int count = 0; double currentPlayers = Servers[i].statusPlayers.Count; foreach (Player P in Servers[i].getPlayers()) { if (P == null) continue; if (count % 2 == 0) { switch (cycleFix) { case 0: players.Append(""); cycleFix = 1; break; case 1: players.Append(""); cycleFix = 0; break; } } players.AppendFormat("{2}", i, P.databaseID, SharedLibrary.Utilities.nameHTMLFormatted(P)); if (count % 2 != 0) { players.Append(""); } count++; } } buffer.AppendFormat(@"
{0} {1} {2} {3} Stats Bans History
{5}
", Servers[i].getName(), Servers[i].getMap(), Servers[i].getClientNum() + "/" + Servers[i].getMaxClients(), SharedLibrary.Utilities.gametypeLocalized(Servers[i].getGametype()), i, players.ToString()); buffer.AppendFormat("
", i, '\"'); if (Servers[i].getClientNum() > 0) buffer.AppendFormat("
", i, '\"'); buffer.Append("
"); } return buffer.ToString(); case "TITLE": return "IW4M Administration"; case "BANS": buffer.Append(""); int totalBans = Program.getServers()[0].Bans.Count; int range; int start = Pagination*30; 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 = Program.getServers()[0].Bans.GetRange(start, range).OrderByDescending(x => x.When).ToList(); else Bans.Add(new Ban("No Bans", "0", "0", DateTime.Now, "")); buffer.Append("

{{TIME}}


"); if (Bans[0] != null) buffer = buffer.Replace("{{TIME}}", "From " + SharedLibrary.Utilities.timePassed(Bans[0].When) + " ago" + " — " + totalBans + " total"); for (int i = 0; i < Bans.Count; i++) { if (Bans[i] == null) continue; Player P = Program.getServers()[0].clientDB.getPlayer(Bans[i].npID, -1); Player B = Program.getServers()[0].clientDB.getPlayer(Bans[i].bannedByID, -1); if (P == null) P = new Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, ""); if (B == null) B = new Player("Unknown", "n/a", 0, 0, 0, "Unknown", 0, ""); if (P.lastOffense == String.Empty) P.lastOffense = "Evade"; if (P != null && B != null) { if (B.npID == P.npID) 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"; String Link = "/" + server + "/" + P.databaseID + "/userip/?player"; buffer.AppendFormat("", P.Name, P.lastOffense, SharedLibrary.Utilities.nameHTMLFormatted(B), Bans[i].getWhen(), Prefix, Link); cycleFix++; } } buffer.Append("
NameOffenseBanned ByTime
{0}{1}{2}{3}

"); buffer.Append(parsePagination(server, Servers[0].Bans.Count, 30, Pagination, "bans")); return buffer.ToString(); case "PAGE": buffer.Append("
"); return buffer.ToString(); case "STATS": int totalStats = 0; 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 = Servers[server].statDB.getMultipleStats(start, range).OrderByDescending(x => x.Skill).ToList(); buffer.Append(""); cycleFix = 0; /*for (int i = 0; i < totalStats; i++) { if (i >= Stats.Count -1 || Stats[i] == null ) continue; Player P = 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"; String Link = "/" + server + "/" + P.databaseID + "/userip/?player"; buffer.AppendFormat("", P.Name, P.stats.Kills, P.stats.Deaths, P.stats.KDR, P.stats.Skill, Prefix, Link); 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()); case "PLAYER": buffer.Append(""); List matchingPlayers = new List(); if (Data == null) matchingPlayers.Add(Servers[server].clientDB.getPlayer(Pagination)); else { var alias = Servers[server].aliasDB.findPlayers(Data); foreach (var a in alias) { var p = Servers[server].clientDB.getPlayer(a.getNumber()); if (p != null) { List aliases = new List(); Servers[server].getAliases(aliases, p); foreach (var pa in aliases) { if (!matchingPlayers.Exists(x => x.databaseID == pa.databaseID)) matchingPlayers.Add(pa); } } } } if (matchingPlayers == null) buffer.Append("
NameAliasesIPRatingLevelConnectionsLast SeenProfile
"); else { foreach (Player Player in matchingPlayers) { if (Player == null) continue; buffer.Append(""); StringBuilder str = new StringBuilder(); List aliases = new List(); Servers[server].getAliases(aliases, Player); foreach (Player a in aliases) { if (Data != null) { if (a.Alias.getNames().Exists(p => p.ToLower().Contains(Data.ToLower())) && a.databaseID != Player.databaseID) { str.AppendFormat("{0}
", a.Name); break; } } else str.AppendFormat("{0}
", a.Name); } StringBuilder IPs = new StringBuilder(); if (logged) { foreach (Player a in aliases) { foreach (String ip in a.Alias.getIPS()) { if (!IPs.ToString().Contains(ip)) IPs.AppendFormat("{0}
", ip); } } } else IPs.Append("XXX.XXX.XXX.XXX"); Int64 forumID = 0; if (Player.npID.Length == 16) { forumID = Int64.Parse(Player.npID.Substring(0, 16), NumberStyles.AllowHexSpecifier); forumID = forumID - 76561197960265728; } String Screenshot = String.Empty; if (logged) Screenshot = String.Format("
", forumID, Player.Name); buffer.AppendFormat("{0}{10}{1}{2}{3}{4}{5}{6} ago{8}", Player.Name, str, IPs, 0, SharedLibrary.Utilities.nameHTMLFormatted(Player), Player.Connections, Player.getLastConnection(), forumID, Player.Name, "/0/" + Player.databaseID + "/userip/?player", Screenshot); buffer.Append(""); } buffer.Append(""); } return buffer.ToString(); default: return input; } } static public String findMacros(String input, Client C, int server) { String output = input; bool logged = Program.getServers()[server].clientDB.getAdmins().Exists(player => player.IP == C.requestOrigin["Host"].Split(':')[0]); switch (C.requestedPage) { case WebFront.Page.main: output = output.Replace("{{SERVERS}}", parseMacros("SERVERS", C.requestedPage, server, C.requestedPageNumber, logged, C.requestData)); break; case WebFront.Page.bans: output = output.Replace("{{BANS}}", parseMacros("BANS", C.requestedPage, server, C.requestedPageNumber, logged, C.requestData)); break; case WebFront.Page.stats: output = output.Replace("{{STATS}}", parseMacros("STATS", C.requestedPage, server, C.requestedPageNumber, logged, C.requestData)); break; case WebFront.Page.player: output = output.Replace("{{PLAYER}}", parseMacros("PLAYER", C.requestedPage, server, C.requestedPageNumber, (C.playerRequesting.Level > Player.Permission.Flagged), C.requestData)); break; } output = output.Replace("{{TITLE}}", "IW4M Administration"); output = output.Replace("{{VERSION}}", Program.Version.ToString()); return output; } } class SchedulerDelegate : ISchedulerDelegate { public void OnException(IScheduler scheduler, Exception e) { //Program.getManager().mainLog.Write(e.InnerException.Message); //Console.Write(e.InnerException); // e.DebugStackTrace(); Program.getManager().mainLog.Write("Web front encountered an error!"); } public void OnStop(IScheduler scheduler) { } } class RequestDelegate : IHttpRequestDelegate { public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response) { String type = "text/html"; if (request.Uri.StartsWith("/")) { //Program.getManager().mainLog.Write("[WEBFRONT] Processing Request for " + request.Uri); var body = String.Empty; if (request.Uri.StartsWith("/")) { IFile Header = new IFile("webfront\\header.html"); var header = Header.getLines(); Header.Close(); IFile Footer = new IFile("webfront\\footer.html"); var footer = Footer.getLines(); Footer.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 (Program.getServers().Length < 1) { body = "

IT SEEMS LIKE THERE ARE NO LONGER ANY SERVERS BEING MONITORED!

"; } else if (request.QueryString == "bans") { IFile Bans = new IFile("webfront\\bans.html"); var bans = Bans.getLines(); Bans.Close(); Client toSend = new Client(WebFront.Page.bans, page, request.Headers, null, null); body = Macro.findMacros((header + bans + footer), toSend, server); } else if (request.QueryString == "stats") { IFile Stats = new IFile("webfront\\stats.html"); var stats = Stats.getLines(); Stats.Close(); Client toSend = new Client(WebFront.Page.stats, page, request.Headers, null, null); body = Macro.findMacros(header + stats + footer, toSend, server); } else if (request.QueryString == "playerhistory") { //type = "text/plain"; if (Program.getServers().Length < server) return; StringBuilder test = new StringBuilder(); test.Append("
"); test.Append(""); IFile Graph = new IFile("webfront\\graph.html"); var graph = Graph.getLines(); Graph.Close(); body = test.ToString() + graph ; } else if (request.QueryString == "player") { IFile Player = new IFile("webfront\\player.html"); var player = Player.getLines(); Player.Close(); String Data = null, IP = null, ID = null; if (req.Length > 3) { ID = req[1]; IP = req[2]; Data = req[3]; } else if (req.Length >2) { ID = req[1]; IP = req[2]; } if (Program.getServers().Length < server) return; Player P = Program.getServers()[server].clientDB.getPlayer(IP); if (P == null) P = new Player("Guest", "Guest", 0, 0); Client toSend = new Client(WebFront.Page.player, page, request.Headers, Data, P); body = Macro.findMacros(header + player + footer, toSend, server); } else if (request.QueryString == "chat") { StringBuilder chatMessages = new StringBuilder(); #if DEBUG // if (Program.Servers[server].chatHistory.Count < 8) // Program.Servers[server].chatHistory.Add(new Chat(new Player("TEST", "xuid", 0, 0), "TEST MESSAGE", DateTime.Now)); #endif if (Program.getServers().Length < server) return; String IP, Text; if (req.Length > 3) { IP = req[2]; Text = SharedLibrary.Utilities.cleanChars(HttpUtility.UrlDecode(req[3])); } else { IP = null; Text = null; } if (IP == null && Program.getServers()[server].getClientNum() > 0) { chatMessages.Append(""); foreach (Chat Message in Program.getServers()[server].chatHistory) chatMessages.AppendFormat("", SharedLibrary.Utilities.nameHTMLFormatted(Message.Origin), Message.Message, Message.timeString()); chatMessages.Append("
{0}{1}{2}
"); body = chatMessages.ToString(); } else if (Text != null && Text.Length > 4) { Player requestPlayer = Program.getServers()[server].clientDB.getPlayer(IP); if (requestPlayer != null) Program.getServers()[server].webChat(requestPlayer, Text); } } else if (request.QueryString == "pubbans") { type = "text/plain"; StringBuilder banTXT = new StringBuilder(); banTXT.AppendFormat("===========================================\nIW4M ADMIN PUBLIC BAN LIST\nGENERATED {0}\nIP---GUID---REASON---TIME\n===========================================\n", DateTime.Now.ToString()); foreach (Ban B in Program.getServers()[0].Bans) { if (B.IP != null && B.IP != String.Empty && B.Reason != null && B.Reason != String.Empty) banTXT.AppendFormat("{0}---{1}---{2}---{3}\n", B.IP, B.npID, B.Reason.Trim(), Math.Round((B.When-DateTime.MinValue).TotalSeconds, 0)); } body = banTXT.ToString(); } else { IFile Main = new IFile("webfront\\main.html"); var main = Main.getLines(); Main.Close(); Client toSend = new Client(WebFront.Page.main, page, request.Headers, null, null); body = Macro.findMacros(header + main + footer, toSend, server); } //Program.getServers()[server].Log.Write("Webfront processed request for " + request.Uri, Log.Level.Debug); } var headers = new HttpResponseHead() { Status = "200 OK", Headers = new Dictionary() { { "Content-Type", type }, { "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", type }, { "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); } } } } #endif