From f42ee695807913c8dd7439241b071d54d2b05a58 Mon Sep 17 00:00:00 2001 From: Michael Snyder Date: Sun, 19 Apr 2015 13:14:30 -0500 Subject: [PATCH] Just pushing some changes -webfront now displays player info and link to repz account -webfront shows ips for authed admin ( determined by ip ) -webfront now show chat and allows authed players to send ingame messages -fixed time span issue in webfront -fixed most recent ban always missing -fixed crash when RCON stops responding and removing a player -version on footer --- Admin/Database.cs | 56 ++++++++- Admin/Event.cs | 19 +++ Admin/Player.cs | 8 ++ Admin/Server.cs | 144 +++++++++++++++------ Admin/Utilities.cs | 11 +- Admin/WebFront.cs | 217 ++++++++++++++++++++++++-------- Admin/m2demo/admin/commands.gsc | 28 +++++ Admin/m2demo/admin/main.gsc | 7 ++ Admin/version.txt | 3 + Admin/webfront/bans.html | 11 +- Admin/webfront/header.html | 130 ++++++++++++++++++- Admin/webfront/main.html | 23 ++-- Admin/webfront/player.html | 15 ++- Admin/webfront/stats.html | 11 +- 14 files changed, 561 insertions(+), 122 deletions(-) diff --git a/Admin/Database.cs b/Admin/Database.cs index 53f6baad..0d3909fe 100644 --- a/Admin/Database.cs +++ b/Admin/Database.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Data.SQLite; using System.Data; +using System.Linq; using System.IO; using System.Collections; @@ -204,6 +205,44 @@ namespace IW4MAdmin return null; } + //get player by ip, (used for webfront) + public Player getPlayer(String IP) + { + String Query = String.Format("SELECT * FROM CLIENTS WHERE IP='{0}'", IP); + DataTable Result = GetDataTable(Query); + + if (Result != null && Result.Rows.Count > 0) + { + List lastKnown = new List(); + foreach (DataRow p in Result.Rows) + { + DateTime LC; + try + { + LC = DateTime.Parse(p["LastConnection"].ToString()); + lastKnown.Add(new Player(p["Name"].ToString(), p["npID"].ToString(), -1, (Player.Permission)(p["Level"]), Convert.ToInt32(p["Number"]), p["LastOffense"].ToString(), Convert.ToInt32((DateTime.Now - LC).TotalSeconds), p["IP"].ToString(), LC)); + } + + catch (Exception) + { + continue; + } + } + + if (lastKnown.Count > 0) + { + List Returning = lastKnown.OrderBy(t => t.Connections).ToList(); + return Returning[0]; + } + + else + return null; + } + + else + return null; + } + //Returns a list of players matching name parameter, null if no players found matching public List findPlayers(String name) { @@ -238,7 +277,7 @@ namespace IW4MAdmin //Returns any player with level 4 permissions, null if no owner found public Player getOwner() { - String Query = String.Format("SELECT * FROM CLIENTS WHERE Level >= '{0}'", 4); + String Query = String.Format("SELECT * FROM CLIENTS WHERE Level > '{0}'", 4); DataTable Result = GetDataTable(Query); if (Result != null && Result.Rows.Count > 0) @@ -270,6 +309,19 @@ namespace IW4MAdmin return Bans; } + //Returns all players with level > Flagged + public List getAdmins() + { + List Admins = new List(); + String Query = String.Format("SELECT * FROM CLIENTS WHERE LEVEL > '{0}'", 1); + DataTable Result = GetDataTable(Query); + + foreach (DataRow P in Result.Rows) + Admins.Add(new Player(P["Name"].ToString(), P["npID"].ToString(), (Player.Permission)P["Level"], P["IP"].ToString())); + + return Admins; + } + //Returns total number of player entries in database public int totalPlayers() { @@ -530,7 +582,7 @@ namespace IW4MAdmin public List findPlayers(String name) { - String Query = String.Format("SELECT * FROM ALIASES WHERE NAMES LIKE '%{0}%' LIMIT 8", name); + String Query = String.Format("SELECT * FROM ALIASES WHERE NAMES LIKE '%{0}%' LIMIT 15", name); DataTable Result = GetDataTable(Query); List players = new List(); diff --git a/Admin/Event.cs b/Admin/Event.cs index 510808fe..3d37cf19 100644 --- a/Admin/Event.cs +++ b/Admin/Event.cs @@ -5,6 +5,25 @@ using System.Text.RegularExpressions; namespace IW4MAdmin { + class Chat + { + public Chat ( Player O, String M, DateTime D) + { + Origin = O; + Message = M; + Time = D; + } + + public String timeString() + { + return Time.ToShortTimeString(); + } + + public Player Origin { get; private set; } + public String Message { get; private set; } + public DateTime Time { get; private set; } + } + class Event { public enum GType diff --git a/Admin/Player.cs b/Admin/Player.cs index 4713a3e4..6d6f5347 100644 --- a/Admin/Player.cs +++ b/Admin/Player.cs @@ -125,6 +125,14 @@ namespace IW4MAdmin LastConnection = DateTime.Now; } + public Player(string n, string id, Player.Permission P, String I) + { + Name = n; + npID = id; + Level = P; + IP = I; + } + public Player(string n, string id, int num, Player.Permission l, int cind, String lo, int con, String IP2) { Name = n; diff --git a/Admin/Server.cs b/Admin/Server.cs index e5e1e0c7..ab814c6b 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -38,6 +38,8 @@ namespace IW4MAdmin Reports = new List(); Skills = new Moserware.TrueSkill(); statusPlayers = new Dictionary(); + chatHistory = new List(); + lastWebChat = DateTime.Now; nextMessage = 0; initCommands(); initMacros(); @@ -148,6 +150,21 @@ namespace IW4MAdmin } } } + + bool checkClientStatus(Player P) + { + /* RCON.addRCON("admin_lastevent status;" + P.getID() + ";0;clean"); + Utilities.Wait(0.5); // give it time to update + String[] Status = RCON.addRCON("whoisdirty"); + + if (Status != null) + { + String GUID = Utilities.stripColors(Status[1].Split(new char[] { '\"' })[3]); + } + */ + + return true; + } //Add player object p to `players` list public bool addPlayer(Player P) @@ -205,10 +222,11 @@ namespace IW4MAdmin // and ips if (NewPlayer.Alias.getIPS().Find(i => i.Equals(P.getIP())) == null || P.getIP() == null || P.getIP() == String.Empty) { - NewPlayer.updateIP(P.getIP()); NewPlayer.Alias.addIP(P.getIP()); } + NewPlayer.updateIP(P.getIP()); + aliasDB.updatePlayer(NewPlayer.Alias); clientDB.updatePlayer(NewPlayer); @@ -268,6 +286,9 @@ namespace IW4MAdmin } } + //finally lets check their clean status :> + checkClientStatus(NewPlayer); + lock (players) { players[NewPlayer.getClientNum()] = null; // just in case we have shit in the way @@ -278,6 +299,10 @@ namespace IW4MAdmin #endif Log.Write("Client " + NewPlayer.getName() + " connecting...", Log.Level.Debug); // they're clean + if (chatHistory.Count > Math.Ceiling((double)clientnum / 2)) + chatHistory.RemoveAt(0); + chatHistory.Add(new Chat(NewPlayer, "CONNECTED", DateTime.Now)); + if (NewPlayer.getLevel() == Player.Permission.Flagged) ToAdmins("^1NOTICE: ^7Flagged player ^5" + NewPlayer.getName() + "^7 has joined!"); @@ -628,52 +653,53 @@ namespace IW4MAdmin private void pollServer() { int timesFailed = 0; + Dictionary toCheck = new Dictionary(); while (isRunning) { - lock (statusPlayers) - { - String[] Response = RCON.addRCON("status"); - if (Response != null) - statusPlayers = Utilities.playersFromStatus(Response); - } - - if (statusPlayers != null) + String[] Response = RCON.addRCON("status"); + if (Response != null) + toCheck = Utilities.playersFromStatus(Response); + + if (toCheck != null) { lastPoll = DateTime.Now; timesFailed = 0; - if (statusPlayers.Count != clientnum) + + if (toCheck != statusPlayers) { - lock (statusPlayers) + List toRemove = new List(); + lock (players) { - List toRemove = new List(); - lock (players) - { - foreach (Player P in players) - { - if (P == null) - continue; - - Player Matching; - statusPlayers.TryGetValue(P.getID(), out Matching); - if (Matching == null) // they are no longer with us - toRemove.Add(P); - } - - foreach (Player Removing in toRemove) // cuz cant modify collections - removePlayer(Removing.getClientNum()); - } - - foreach (var P in statusPlayers.Values) + foreach (Player P in players) { if (P == null) - { - Log.Write("Null player found in statusPlayers", Log.Level.Debug); continue; - } - if (!addPlayer(P)) - Log.Write("Error adding " + P.getName() + " at client slot #" + P.getClientNum(), Log.Level.Debug); + Player Matching; + toCheck.TryGetValue(P.getID(), out Matching); + if (Matching == null) // they are no longer with us + toRemove.Add(P); } + + foreach (Player Removing in toRemove) // cuz cant modify collections + removePlayer(Removing.getClientNum()); + } + + foreach (var P in toCheck.Values) + { + if (P == null) + { + Log.Write("Null player found in toCheck", Log.Level.Debug); + continue; + } + + if (!addPlayer(P)) + Log.Write("Error adding " + P.getName() + " at client slot #" + P.getClientNum(), Log.Level.Debug); + } + + lock (statusPlayers) + { + statusPlayers = toCheck; } } @@ -896,6 +922,10 @@ namespace IW4MAdmin return false; } + if (chatHistory.Count > Math.Ceiling(((double)clientnum - 1) / 2)) + chatHistory.RemoveAt(0); + chatHistory.Add(new Chat(E.Origin, "DISCONNECTED", DateTime.Now)); + removePlayer(E.Origin.getClientNum()); return true; } @@ -972,7 +1002,17 @@ namespace IW4MAdmin } if (E.Data.Substring(0, 1) != "!") // Not a command so who gives an F? + { + E.Data = Utilities.stripColors(Utilities.cleanChars(E.Data)); + if (E.Data.Length > 50) + E.Data = E.Data.Substring(0, 50) + "..."; + if (chatHistory.Count > Math.Ceiling((double)clientnum/2)) + chatHistory.RemoveAt(0); + + chatHistory.Add(new Chat(E.Origin, E.Data, DateTime.Now)); + return true; + } Command C = E.isValidCMD(commands); @@ -1105,7 +1145,19 @@ namespace IW4MAdmin if (B.getID() == Target.getID()) { clientDB.removeBan(Target.getID(), Target.getIP()); - Bans.Remove(B); + int position = Bans.IndexOf(B); + + + if (position > -1 && position < Bans.Count - 1) + { + Log.Write("Removing ban at index #" + position, Log.Level.Debug); + Bans.RemoveAt(position); + Bans[position] = null; + } + + else + Log.Write(position + " is an invalid ban index!", Log.Level.Debug); + Player P = clientDB.getPlayer(Target.getID(), -1); P.setLevel(Player.Permission.User); clientDB.updatePlayer(P); @@ -1172,6 +1224,24 @@ namespace IW4MAdmin RCON.addRCON("admin_lastevent alert;" + P.getID() + ";0;mp_killstreak_nuclearstrike"); } + public void webChat(Player P, String Message) + { + DateTime requestTime = DateTime.Now; + + if ((requestTime - lastWebChat).TotalSeconds > 1) + { + Broadcast("^1[WEBCHAT] ^5" + P.getName() + "^7 - " + Message); + if (chatHistory.Count > Math.Ceiling((double)clientnum / 2)) + chatHistory.RemoveAt(0); + + if (Message.Length > 50) + Message = Message.Substring(0, 50) + "..."; + + chatHistory.Add(new Chat(P, Utilities.stripColors(Message), DateTime.Now)); + lastWebChat = DateTime.Now; + } + } + //END //THIS IS BAD BECAUSE WE DON"T WANT EVERYONE TO HAVE ACCESS :/ @@ -1324,6 +1394,7 @@ namespace IW4MAdmin public String Gametype; public int totalKills = 0; public List Reports; + public List chatHistory; //Info private String IP; @@ -1342,6 +1413,7 @@ namespace IW4MAdmin private int maxClients; private Dictionary Macros; private Moserware.TrueSkill Skills; + private DateTime lastWebChat; //Will probably move this later diff --git a/Admin/Utilities.cs b/Admin/Utilities.cs index d050d0ff..5e55e94f 100644 --- a/Admin/Utilities.cs +++ b/Admin/Utilities.cs @@ -58,7 +58,7 @@ namespace IW4MAdmin public static String removeNastyChars(String str) { if (str != null) - return str.Replace("`", "").Replace("\\", "").Replace("\"", "").Replace("^", "").Replace(""", "''").Replace("&", "&").Replace("\"", "''"); + return str.Replace("`", "").Replace("\\", "").Replace("\"", "").Replace(""", "''").Replace("&", "&").Replace("\"", "''"); else return String.Empty; } @@ -78,6 +78,15 @@ namespace IW4MAdmin return lineNumber; } + public static String cleanChars(String S) + { + StringBuilder Cleaned = new StringBuilder(); + + foreach (char c in S) + if (c < 127 && c > 31 && c != 37 && c != 34 && c != 92) Cleaned.Append(c); + return Cleaned.ToString(); + } + public static String stripColors(String str) { return Regex.Replace(str, @"\^[0-9]", ""); diff --git a/Admin/WebFront.cs b/Admin/WebFront.cs index 60e28665..5a375320 100644 --- a/Admin/WebFront.cs +++ b/Admin/WebFront.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Web; using Kayak; using Kayak.Http; using System.Net; @@ -10,6 +11,23 @@ using System.Net; namespace IW4MAdmin_Web { + class Client + { + public Client ( WebFront.Page req, int cur, IDictionary inc, String D) + { + requestedPage = req; + requestedPageNumber = cur; + requestOrigin = inc; + requestData = D; + } + + 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; } + + } + class WebFront { public enum Page @@ -61,7 +79,7 @@ namespace IW4MAdmin_Web return output.ToString(); } - static public String parseMacros(String input, WebFront.Page Page, int Pagination, int server) + static public String parseMacros(String input, WebFront.Page Page, int server, int Pagination, bool logged, String Data) { StringBuilder buffer = new StringBuilder(); switch (input) @@ -116,15 +134,18 @@ namespace IW4MAdmin_Web {1} {2} {3} - Stats + Stats | Bans {5} -
-
", + ", Servers[i].getName(), Servers[i].getMap(), Servers[i].getClientNum() + "/" + Servers[i].getMaxClients(), IW4MAdmin.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": @@ -133,7 +154,7 @@ namespace IW4MAdmin_Web buffer.Append(""); int totalBans = IW4MAdmin.Program.Servers[0].Bans.Count; int range; - int start = Pagination*30 + 1; + int start = Pagination*30; cycleFix = 0; if (totalBans <= 30) @@ -192,8 +213,7 @@ namespace IW4MAdmin_Web buffer.Append(parsePagination(server, IW4MAdmin.Program.Servers[0].Bans.Count, 30, Pagination, "bans")); return buffer.ToString(); case "PAGE": - buffer.Append("
"); - + buffer.Append("
"); return buffer.ToString(); case "STATS": int totalStats = IW4MAdmin.Program.Servers[server].statDB.totalStats(); @@ -241,78 +261,130 @@ namespace IW4MAdmin_Web return buffer.ToString().Replace("{{TOP}}", (start + 1).ToString()); case "PLAYER": buffer.Append("
"); - IW4MAdmin.Player Player = IW4MAdmin.Program.Servers[server].clientDB.getPlayer(Pagination); + List matchingPlayers = new List(); - if (Player == null) + if (Data == null) + matchingPlayers.Add(IW4MAdmin.Program.Servers[server].clientDB.getPlayer(Pagination)); + else + { + var alias = IW4MAdmin.Program.Servers[server].aliasDB.findPlayers(Data); + + foreach (var a in alias) + { + var p = IW4MAdmin.Program.Servers[server].clientDB.getPlayer(a.getNumber()); + if (p != null) + { + List aliases = new List(); + IW4MAdmin.Program.Servers[server].getAliases(aliases, p); + + foreach (var pa in aliases) + { + if (!matchingPlayers.Exists(x => x.getDBID() == pa.getDBID())) + matchingPlayers.Add(pa); + } + } + } + } + + if (matchingPlayers == null) buffer.Append("
NameAliasesIPRatingLevelConnectionsLast SeenProfile
"); else { - buffer.Append(""); - StringBuilder str = new StringBuilder(); - List aliases = new List(); - IW4MAdmin.Program.Servers[server].getAliases(aliases, Player); + foreach (IW4MAdmin.Player Player in matchingPlayers) + { + if (Player == null) + continue; + + buffer.Append(""); + StringBuilder str = new StringBuilder(); + List aliases = new List(); + IW4MAdmin.Program.Servers[server].getAliases(aliases, Player); - foreach (IW4MAdmin.Player a in aliases) - str.AppendFormat("{0}
", a.getName()); + foreach (IW4MAdmin.Player a in aliases) + { + if (Data != null) + { + if (a.Alias.getNames().Exists(p => p.ToLower().Contains(Data.ToLower())) && a.getDBID() != Player.getDBID()) + { + str.AppendFormat("{0}
", a.getName()); + break; + } + } + else + str.AppendFormat("{0}
", a.getName()); + } - Player.stats = IW4MAdmin.Program.Servers[server].statDB.getStats(Player.getDBID()); - String Rating = String.Empty; + Player.stats = IW4MAdmin.Program.Servers[server].statDB.getStats(Player.getDBID()); + String Rating = String.Empty; - if (Player.stats == null) - Rating = "Not Available"; - else - Rating = Player.stats.Skill.ToString(); + if (Player.stats == null) + Rating = "Not Available"; + else + Rating = Player.stats.Skill.ToString(); - bool logged = false; - String IP; - if (logged) - IP = Player.getIP(); - else - IP = "XXX.XXX.XXX.XXX"; + StringBuilder IPs = new StringBuilder(); - Int64 forumID = Int64.Parse(Player.getID(), NumberStyles.AllowHexSpecifier); - forumID = forumID - 76561197960265728; + if (logged && Data == null) + { + foreach (IW4MAdmin.Player a in aliases) + { + foreach (String ip in a.Alias.getIPS()) + { + if (!IPs.ToString().Contains(ip)) + IPs.AppendFormat("{0}
", ip); + } + } - buffer.AppendFormat("{0}{1}{2}{3}{4}{5}{6} ago{8}", Player.getName(), str, IP, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName()); - buffer.Append(""); + } + else + IPs.Append("XXX.XXX.XXX.XXX"); + + Int64 forumID = Int64.Parse(Player.getID().Substring(0,16), NumberStyles.AllowHexSpecifier); + forumID = forumID - 76561197960265728; + + buffer.AppendFormat("{0}{1}{2}{3}{4}{5}{6} ago{8}", Player.getName(), str, IPs, Rating, IW4MAdmin.Utilities.nameHTMLFormatted(Player.getLevel()), Player.getConnections(), Player.getLastConnection(), forumID, Player.getName(), "/0/" + Player.getDBID() + "/?player"); + buffer.Append(""); + } + + buffer.Append(""); } return buffer.ToString(); - default: return input; } } - static public String findMacros(String input, int pageNumber, int server, WebFront.Page page) + static public String findMacros(String input, Client C, int server) { String output = input; - switch (page) + bool logged = IW4MAdmin.Program.Servers[server].clientDB.getAdmins().Exists(player => player.getIP() == C.requestOrigin["Host"].Split(':')[0]); + + if (logged) + Console.WriteLine(C.requestOrigin["Host"] + " is authed"); + else + Console.WriteLine(C.requestOrigin["Host"] + " is not authed"); + + switch (C.requestedPage) { case WebFront.Page.main: - output = output.Replace("{{SERVERS}}", parseMacros("SERVERS", page, pageNumber, server)); + 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", page, pageNumber, server)); + 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", page, pageNumber, server)); + 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", page, pageNumber, server)); + output = output.Replace("{{PLAYER}}", parseMacros("PLAYER", C.requestedPage, server, C.requestedPageNumber, logged, C.requestData)); 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("{{VERSION}}", IW4MAdmin.Program.Version.ToString()); - //output = output.Replace("{{PAGE}}", parseMacros("PAGE", page)); - //output = output.Replace("{{STATS}}", parseMacros("STATS", page)); return output; } @@ -337,6 +409,7 @@ namespace IW4MAdmin_Web { public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response) { + if (request.Uri.StartsWith("/")) { //Console.WriteLine("[WEBFRONT] Processing Request for " + request.Uri); @@ -354,7 +427,6 @@ namespace IW4MAdmin_Web String[] req = request.Path.Split(new char[] {'/'}, StringSplitOptions.RemoveEmptyEntries); - int server = 0; int page = 0; @@ -369,7 +441,8 @@ namespace IW4MAdmin_Web IW4MAdmin.file Bans = new IW4MAdmin.file("webfront\\bans.html"); var bans = Bans.getLines(); Bans.Close(); - body = Macro.findMacros((header + bans + footer), page, server, WebFront.Page.bans); + Client toSend = new Client(WebFront.Page.bans, page, request.Headers, null); + body = Macro.findMacros((header + bans + footer), toSend, server); } else if (request.QueryString == "stats") @@ -377,7 +450,8 @@ namespace IW4MAdmin_Web IW4MAdmin.file Stats = new IW4MAdmin.file("webfront\\stats.html"); var stats = Stats.getLines(); Stats.Close(); - body = Macro.findMacros(header + stats + footer, page, server, WebFront.Page.stats); + Client toSend = new Client(WebFront.Page.stats, page, request.Headers, null); + body = Macro.findMacros(header + stats + footer, toSend, server); } else if (request.QueryString == "player") @@ -385,7 +459,51 @@ namespace IW4MAdmin_Web IW4MAdmin.file Player = new IW4MAdmin.file("webfront\\player.html"); var player = Player.getLines(); Player.Close(); - body = Macro.findMacros(header + player + footer, page, server, WebFront.Page.player); + string Data; + if (req.Length > 2) + Data = req[2]; + else + Data = null; + Client toSend = new Client(WebFront.Page.player, page, request.Headers, Data); + body = Macro.findMacros(header + player + footer, toSend, server); + } + + else if (request.QueryString == "chat") + { + StringBuilder chatMessages = new StringBuilder(); +#if DEBUG + // if (IW4MAdmin.Program.Servers[server].chatHistory.Count < 8) + // IW4MAdmin.Program.Servers[server].chatHistory.Add(new IW4MAdmin.Chat(new IW4MAdmin.Player("TEST", "xuid", 0, 0), "TEST MESSAGE", DateTime.Now)); +#endif + String IP, Text; + if (req.Length > 3) + { + IP = req[2]; + Text = IW4MAdmin.Utilities.cleanChars(HttpUtility.UrlDecode(req[3])); + } + + else + { + IP = null; + Text = null; + } + + if (IP == null && IW4MAdmin.Program.Servers[server].getClientNum() > 0) + { + chatMessages.Append(""); + foreach (IW4MAdmin.Chat Message in IW4MAdmin.Program.Servers[server].chatHistory) + chatMessages.AppendFormat("", IW4MAdmin.Utilities.nameHTMLFormatted(Message.Origin), Message.Message, Message.timeString()); + chatMessages.Append("
{0}{1}{2}
"); + body = chatMessages.ToString(); + } + + else if (Text != null && Text.Length > 4) + { + IW4MAdmin.Player requestPlayer = IW4MAdmin.Program.Servers[server].clientDB.getPlayer(IP); + + if (requestPlayer != null) + IW4MAdmin.Program.Servers[server].webChat(requestPlayer, Text); + } } else @@ -393,7 +511,8 @@ namespace IW4MAdmin_Web IW4MAdmin.file Main = new IW4MAdmin.file("webfront\\main.html"); var main = Main.getLines(); Main.Close(); - body = Macro.findMacros(header + main + footer, 0, server, WebFront.Page.main); + Client toSend = new Client(WebFront.Page.main, page, request.Headers, null); + body = Macro.findMacros(header + main + footer, toSend, server); } IW4MAdmin.Program.Servers[server].Log.Write("Webfront processed request for " + request.Uri, IW4MAdmin.Log.Level.Debug); diff --git a/Admin/m2demo/admin/commands.gsc b/Admin/m2demo/admin/commands.gsc index 2b1364a2..64473af8 100644 --- a/Admin/m2demo/admin/commands.gsc +++ b/Admin/m2demo/admin/commands.gsc @@ -37,4 +37,32 @@ Tell(message, source) self iPrintLnBold("^1" + source.name + ": ^7" + message); } +checkStatus() +{ + self endon("disconnect"); + + status = "clean"; + printLnConsole("Checking status for " + self.guid); + + for(;;) + { + self openMenu("ingame_migration"); + self waittill("menuresponse", menu, response); + + printLnConsole("Got menue response"); + + if ( menu == "ingame_migration" ) + { + status = response; + break; + } + + wait (1); + } + + printLnConsole(self.name + "is" + response); + + if ( status == "dirty") + setDvar("whosisdirt", self.guid); +} diff --git a/Admin/m2demo/admin/main.gsc b/Admin/m2demo/admin/main.gsc index 708e95f8..a19fefeb 100644 --- a/Admin/m2demo/admin/main.gsc +++ b/Admin/m2demo/admin/main.gsc @@ -6,6 +6,10 @@ initIW4MAdmin() { Settings = LoadSettings(); setDvarIfUninitialized(Settings["dvar_prefix"] + "_lastevent", ""); // | COMMAND | ORIGIN npID | TARGET npID | OPT DATA + setDvarIfUninitialized("whoisdirty", ""); + + game["menu_huehue"] = "ingame_migration"; + precachemenu(game["menu_huehue"]); thread waitEvent(); level thread onPlayerConnect(); @@ -71,6 +75,9 @@ processEvent(event) case "tell": Target Tell(Data, Player); break; + case "status": + Player checkStatus(); + break; default: Player Tell("You entered an invalid command!"); } diff --git a/Admin/version.txt b/Admin/version.txt index 31e5c967..939bfebf 100644 --- a/Admin/version.txt +++ b/Admin/version.txt @@ -1,7 +1,10 @@ VERSION: 0.9 CHANGELOG: -webfront now displays player info and link to repz account +-webfront shows ips for authed admin ( determined by ip ) +-webfront now show chat and allows authed players to send ingame messages -fixed time span issue in webfront +-fixed most recent ban always missing -fixed crash when RCON stops responding and removing a player -version on footer diff --git a/Admin/webfront/bans.html b/Admin/webfront/bans.html index f63a2373..42c12395 100644 --- a/Admin/webfront/bans.html +++ b/Admin/webfront/bans.html @@ -1,6 +1,5 @@ - -
-
BANS
Back
-
- {{BANS}} -
\ No newline at end of file +
+
BANS
Back
+
+ {{BANS}} +
\ No newline at end of file diff --git a/Admin/webfront/header.html b/Admin/webfront/header.html index 2e03b302..bbf54337 100644 --- a/Admin/webfront/header.html +++ b/Admin/webfront/header.html @@ -4,7 +4,12 @@ {{TITLE}} - + + + + + diff --git a/Admin/webfront/main.html b/Admin/webfront/main.html index ca6d7c38..6e0c2082 100644 --- a/Admin/webfront/main.html +++ b/Admin/webfront/main.html @@ -1,9 +1,14 @@ - - -
-
IW4M Admin
- -

Currently Monitoring

-
- {{SERVERS}} -
\ No newline at end of file + +
+
IW4M Admin
+ +

Currently Monitoring

+
+ {{SERVERS}} +
\ No newline at end of file diff --git a/Admin/webfront/player.html b/Admin/webfront/player.html index 1d2afa61..3a9c50fb 100644 --- a/Admin/webfront/player.html +++ b/Admin/webfront/player.html @@ -1,8 +1,7 @@ - -
-
PLAYER
Back
-
-
-
- {{PLAYER}} -
\ No newline at end of file +
+
PLAYER
Back
+
+
+
+ {{PLAYER}} +
\ No newline at end of file diff --git a/Admin/webfront/stats.html b/Admin/webfront/stats.html index 71467450..9b285e93 100644 --- a/Admin/webfront/stats.html +++ b/Admin/webfront/stats.html @@ -1,6 +1,5 @@ - -
-
STATS
Back
-
- {{STATS}} -
\ No newline at end of file +
+
STATS
Back
+
+ {{STATS}} +
\ No newline at end of file