diff --git a/Admin/Application.csproj b/Admin/Application.csproj index cbcfcd4d..2e92bb4b 100644 --- a/Admin/Application.csproj +++ b/Admin/Application.csproj @@ -367,8 +367,8 @@ copy /Y "$(ProjectDir)lib\Kayak.dll" "$(SolutionDir)BUILD\lib" xcopy /Y /I /E "$(ProjectDir)webfront\*" "$(SolutionDir)BUILD\Webfront" xcopy /Y /I /E "$(SolutionDir)Admin\Config\*" "$(SolutionDir)BUILD\Config" -if $(ConfigurationName) == Release-Nightly powershell.exe -file "$(SolutionDir)DEPLOY\publish_nightly.ps1" 1.5 -if $(ConfigurationName) == Release-Stable powershell.exe -file "$(SolutionDir)DEPLOY\publish_stable.ps1" 1.5 +if $(ConfigurationName) == Release-Nightly powershell.exe -file "$(SolutionDir)DEPLOY\publish_nightly.ps1" 1.6 +if $(ConfigurationName) == Release-Stable powershell.exe -file "$(SolutionDir)DEPLOY\publish_stable.ps1" 1.6 diff --git a/Admin/Kayak.cs b/Admin/Kayak.cs index e7450073..cf60b3c0 100644 --- a/Admin/Kayak.cs +++ b/Admin/Kayak.cs @@ -37,19 +37,19 @@ namespace IW4MAdmin class Request : IHttpRequestDelegate { - public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response, string IP) + public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response) { var logger = ApplicationManager.GetInstance().GetLogger(); - logger.WriteInfo($"HTTP request {request.Path}"); - logger.WriteInfo($"QueryString: {request.QueryString}"); - logger.WriteInfo($"IP: {IP}"); + logger.WriteDebug($"HTTP request {request.Path}"); + logger.WriteDebug($"QueryString: {request.QueryString}"); + logger.WriteDebug($"IP: {request.IPAddress}"); NameValueCollection querySet = new NameValueCollection(); if (request.QueryString != null) - querySet = System.Web.HttpUtility.ParseQueryString(SharedLibrary.Utilities.StripIllegalCharacters(request.QueryString)); + querySet = System.Web.HttpUtility.ParseQueryString(request.QueryString); - querySet.Set("IP", IP); + querySet.Set("IP", request.IPAddress); try { diff --git a/Admin/Main.cs b/Admin/Main.cs index 42437535..74840b39 100644 --- a/Admin/Main.cs +++ b/Admin/Main.cs @@ -15,7 +15,7 @@ namespace IW4MAdmin static void Main(string[] args) { - Version = 1.5; + Version = 1.6; handler = new ConsoleEventDelegate(OnProcessExit); SetConsoleCtrlHandler(handler, true); diff --git a/Admin/Server.cs b/Admin/Server.cs index fe3dfa9a..796882cc 100644 --- a/Admin/Server.cs +++ b/Admin/Server.cs @@ -257,11 +257,33 @@ namespace IW4MAdmin E.Target = Players[cNum]; } + List matchingPlayers; + if (E.Target == null) // Find active player including quotes (multiple words) - E.Target = GetClientByName(E.Data.Trim()); + { + matchingPlayers = GetClientByName(E.Data.Trim()); + if (matchingPlayers.Count > 1) + { + await E.Origin.Tell("Multiple players match that name"); + throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} had multiple players found for {C.Name}"); + } + else if (matchingPlayers.Count == 1) + E.Target = matchingPlayers.First(); + } if (E.Target == null) // Find active player as single word - E.Target = GetClientByName(Args[0]); + { + matchingPlayers = GetClientByName(Args[0]); + if (matchingPlayers.Count > 1) + { + await E.Origin.Tell("Multiple players match that name"); + foreach (var p in matchingPlayers) + await E.Origin.Tell($"[^3{p.ClientID}^7] {p.Name}"); + throw new SharedLibrary.Exceptions.CommandException($"{E.Origin} had multiple players found for {C.Name}"); + } + else if (matchingPlayers.Count == 1) + E.Target = matchingPlayers.First(); + } if (E.Target == null && C.RequiresTarget) { @@ -600,7 +622,7 @@ namespace IW4MAdmin else // Not a command { - E.Data = E.Data.StripColors().CleanChars(); + E.Data = E.Data.StripColors(); // this should not be done for all messages. //if (E.Data.Length > 50) // E.Data = E.Data.Substring(0, 50) + "..."; diff --git a/Admin/lib/Kayak.dll b/Admin/lib/Kayak.dll index d9eb6a3c..14936579 100644 Binary files a/Admin/lib/Kayak.dll and b/Admin/lib/Kayak.dll differ diff --git a/Admin/lib/SharedLibrary.dll b/Admin/lib/SharedLibrary.dll index ebce2c11..c5e9a3db 100644 Binary files a/Admin/lib/SharedLibrary.dll and b/Admin/lib/SharedLibrary.dll differ diff --git a/Admin/version.txt b/Admin/version.txt index 70869f2a..2dd3dcfb 100644 --- a/Admin/version.txt +++ b/Admin/version.txt @@ -1,4 +1,13 @@ -Version 1.5 +Version 1.6: +CHANGELOG: +-got rid of pesky "error on character" message +-optimizations to commands +-report reason doesn't truncate if there's a space in the target name +-If multiple matches are found when finding a player, a list of matches is shown +-"special" characters are allowed in names and messages +-prune command demotes inactive admins (defaults to 30 days if no days are specified) + +Version 1.5 CHANGELOG: -added back player history graphs (past 12 hours every 15 minutes) -fixed issue with configurationmanager files and threading @@ -8,7 +17,7 @@ CHANGELOG: -started working on more advanced statistics -all chat is stored -word cloud displays most commonly used words on the server --fixed misc issuess +-fixed misc issues VERSION 1.4 CHANGELOG: @@ -27,7 +36,6 @@ CHANGELOG: -webfront playerlist level colors are hidden to non admin users -tempban length can now be specified (m, h, d, y) - VERSION 1.3 CHANGELOG: -complete rewrite of lots of parts diff --git a/Admin/webfront/main.css b/Admin/webfront/main.css index 6f7f4403..9eb8edd4 100644 --- a/Admin/webfront/main.css +++ b/Admin/webfront/main.css @@ -25,7 +25,7 @@ div#content .serverTitle { width: calc( 100% / 3); background-color: #007ACC; } div#content .serverPlayers { text-align: right; width: calc( 100% / 3); background-color: #007ACC; } div#content .serverMap { text-align: center; width: calc( 100% / 3); background-color: #007ACC; } div#content .serverPlayerList {float: right; margin: 0.5em; } -div#content .serverChatList { float: left; margin: 0.5em } +div#content .serverChatList { float: left; margin: 0.5em; max-width: 60%; overflow:hidden } div#content .playerName { font-size: 1.1vw; color: rgba(78, 140, 77, 0.64); width: 10em; text-align: right; } div#content .playerName:hover { color: rgb(0, 122, 204) !important; } div#content .chatPlayerName { font-weight: bold; font-size: 1.1vw; color:#fff; padding-right: 0.5em; opacity: 0.5; } @@ -60,7 +60,7 @@ div#content .hiddenWrapper { color: #007ACC;} div#content #consoleWrap { width: 60%; margin: 0 auto; } div#content #console { padding: 1em; height: 35vh; background-color: #181818; } -div#content #consoleWrap .search { width: calc(80% - 10px); } +div#content #consoleWrap .search { width: calc(80% - 10px); float: left; } div#consoleWrap .playerSearchWrap input[type="text"]:focus, select:focus { border-width: 0; outline: none; } div#consoleWrap .playerSearchWrap { margin: 0 !important; width: 100%; } div#consoleWrap .searchButton { width: calc(20% - 10px); } diff --git a/Plugins/SimpleStats/Plugin.cs b/Plugins/SimpleStats/Plugin.cs index 5d03b9f6..534a4f15 100644 --- a/Plugins/SimpleStats/Plugin.cs +++ b/Plugins/SimpleStats/Plugin.cs @@ -16,7 +16,7 @@ namespace StatsPlugin new CommandArgument() { Name = "player", - Required = true + Required = false } }) { } @@ -100,6 +100,39 @@ namespace StatsPlugin } } + public class CPruneAdmins : Command + { + public CPruneAdmins() : base("prune", "demote any admins that have not connected recently (defaults to 30 days)", "p", Player.Permission.Owner, false, new CommandArgument[] + { + new CommandArgument() + { + Name = "inactive days", + Required = false + } + }) + { } + + public override async Task ExecuteAsync(Event E) + { + int inactiveDays = 30; + + try + { + inactiveDays = Int32.Parse(E.Data); + if (inactiveDays < 1) + throw new FormatException(); + } + + catch (FormatException) + { + await E.Origin.Tell("Invalid number of inactive days"); + } + + E.Owner.Manager.GetClientDatabase().PruneAdmins(inactiveDays); + + } + } + /// /// Each server runs from the same plugin ( for easier reloading and reduced memory usage ). /// So, to have multiple stat tracking, we must store a stat struct for each server @@ -420,7 +453,7 @@ namespace StatsPlugin // calculate the players Score Per Minute for the current session double SessionSPM = curServer.Kills[P.ClientID] * 100 / Math.Max(1, newPlayTime); // calculate how much the KDR should way - // 0.81829 is a Eddie-Generated number that weights the KDR nicely + // 1.637 is a Eddie-Generated number that weights the KDR nicely double KDRWeight = Math.Round(Math.Pow(DisconnectingPlayerStats.KDR, 1.637 / Math.E), 3); double SPMWeightAgainstAverage; @@ -428,7 +461,6 @@ namespace StatsPlugin SPMWeightAgainstAverage = (DisconnectingPlayerStats.scorePerMinute == 1) ? 1 : SessionSPM / DisconnectingPlayerStats.scorePerMinute; // calculate the weight of the new play time againmst lifetime playtime - // double SPMAgainstPlayWeight = newPlayTime / Math.Min(600, DisconnectingPlayerStats.TotalPlayTime + newPlayTime); // calculate the new weight against average times the weight against play time double newSkillFactor = SPMWeightAgainstAverage * SPMAgainstPlayWeight * SessionSPM; @@ -436,7 +468,7 @@ namespace StatsPlugin // if the weight is greater than 1, add, else subtract DisconnectingPlayerStats.scorePerMinute += (SPMWeightAgainstAverage >= 1) ? newSkillFactor : -newSkillFactor; - DisconnectingPlayerStats.Skill = DisconnectingPlayerStats.scorePerMinute * KDRWeight / 10; + DisconnectingPlayerStats.Skill = DisconnectingPlayerStats.scorePerMinute * KDRWeight * 10; DisconnectingPlayerStats.TotalPlayTime += newPlayTime; curServer.playerStats.UpdateStats(P, DisconnectingPlayerStats); diff --git a/Plugins/Tests/Plugin.cs b/Plugins/Tests/Plugin.cs index 1e04e73c..c743a2fa 100644 --- a/Plugins/Tests/Plugin.cs +++ b/Plugins/Tests/Plugin.cs @@ -42,10 +42,11 @@ namespace IW4MAdmin.Plugins #endregion #region PLUGIN_INFO + Console.WriteLine("|Name |Alias|Description |Requires Target|Syntax |Required Level|"); + Console.WriteLine("|--------------| -----| --------------------------------------------------------| -----------------| -------------| ----------------|"); foreach (var command in S.Manager.GetCommands().OrderByDescending(c => c.Permission).ThenBy(c => c.Name)) { - //|Name|Alias|Description|Requires Target|Syntax|Required Level| - Console.WriteLine($"|{command.Name}|{command.Alias}|{command.Description}|{command.RequiresTarget}|{command.Syntax.Substring(8)}|{command.Permission}|"); + Console.WriteLine($"|{command.Name}|{command.Alias}|{command.Description}|{command.RequiresTarget}|{command.Syntax.Substring(8).EscapeMarkdown()}|{command.Permission}|"); } #endregion } @@ -62,7 +63,7 @@ namespace IW4MAdmin.Plugins { var rand = new Random(); int index = rand.Next(0, 17); - var p = new Player($"Test_{index}", $"_test{index}", index, (int)Player.Permission.User) + var p = new Player($"?!'\"\"'<>Test_{index}", $"_test{index}", index, (int)Player.Permission.User) { Ping = 1 }; diff --git a/README.md b/README.md index 87927160..78cdbdb8 100644 --- a/README.md +++ b/README.md @@ -37,49 +37,49 @@ _If you wish to customize your experience of IW4MAdmin, the following configurat ___ ### Commands -|Name |Alias|Description |Requires Target|Arguments |Required Level| -|--------------|-----|--------------------------------------------------------|---------------|---------------|--------------| -|disabletrusted|dt|disable trusted player group for the server|False|0|Owner| -|enabletrusted|et|enable trusted player group for the server|False|0|Owner| -|quit|q|quit IW4MAdmin|False|0|Owner| -|rcon|rcon|send rcon command to server|False|1|Owner| -|setlevel|sl|set player to specified administration level|True|2|Owner| -|ban|b|permanently ban a player from the server|True|2|SeniorAdmin| -|find|f|find player in database|False|1|SeniorAdmin| -|fredisable|frd|disable fast restarting at the end of a map|False|0|SeniorAdmin| -|frenable|fre|enable fast restarting at the end of a map|False|0|SeniorAdmin| -|unban|ub|unban player by database id|True|1|SeniorAdmin| -|map|m|change to specified map|False|1|Administrator| -|maprotate|mr|cycle to the next map in rotation|False|0|Administrator| -|mask|hide|hide your online presence from online admin list|False|0|Administrator| -|plugins|p|view all loaded plugins|False|0|Administrator| -|alias|known|get past aliases and ips of a player|True|1|Moderator| -|baninfo|bi|get information about a ban for a player|True|1|Moderator| -|fastrestart|fr|fast restart current map|False|0|Moderator| -|findall|fa|find a player by their aliase(s)|False|1|Moderator| -|flag|fp|flag a suspicious player and announce to admins on join|True|2|Moderator| -|list|l|list active clients|False|0|Moderator| -|reports|reps|get most recent reports|False|0|Moderator| -|say|s|broadcast message to all players|False|1|Moderator| -|tempban|tb|temporarily ban a player for for specified time (defaults to 1 hour)|True|2|Moderator| -|uptime|up|get current application running time|False|0|Moderator| -|usage|us|get current application memory usage|False|0|Moderator| -|kick|k|kick a player by name|True|2|Trusted| -|warn|w|warn player for infringing rules|True|2|Trusted| -|warnclear|wc|remove all warning for a player|True|1|Trusted| -|admins|a|list currently connected admins|False|0|User| -|getexternalip|ip|view your external IP address|False|0|User| -|help|h|list all available commands|False|0|User| -|owner|o|claim ownership of the server|False|0|User| -|privatemessage|pm|send message to other player|True|2|User| -|report|rep|report a player for suspicious behaivor|True|2|User| -|resetstats|rs|reset your stats to factory-new|False|0|User| -|rules|r|list server rules|False|0|User| -|stats|xlrstats|view your stats|False|0|User| -|topstats|ts|view the top 5 players on this server|False|0|User| -|vote|v|vote for the next map|False|1|User| -|votecancel|vc|cancel your vote for the next map|False|0|User| -|whoami|who|give information about yourself|False|0|User| +|Name |Alias|Description |Requires Target|Syntax |Required Level| +|--------------| -----| --------------------------------------------------------| -----------------| -------------| ----------------| +|disabletrusted|dt|disable trusted player group for the server|False|!dt |Owner| +|enabletrusted|et|enable trusted player group for the server|False|!et |Owner| +|prune|p|demote any admins that have not connected recently (defaults to 30 days)|False|!p \|Owner| +|quit|q|quit IW4MAdmin|False|!q |Owner| +|rcon|rcon|send rcon command to server|False|!rcon \|Owner| +|reload|rl|reload configuration files|False|!rl |Owner| +|setlevel|sl|set player to specified administration level|True|!sl \ \|Owner| +|ban|b|permanently ban a player from the server|True|!b \ \|SeniorAdmin| +|fredisable|frd|disable fast restarting at the end of a map|False|!frd |SeniorAdmin| +|frenable|fre|enable fast restarting at the end of a map|False|!fre |SeniorAdmin| +|unban|ub|unban player by database id|True|!ub \|SeniorAdmin| +|find|f|find player in database|False|!f \|Administrator| +|findall|fa|find a player by their aliase(s)|False|!fa \|Administrator| +|map|m|change to specified map|False|!m \|Administrator| +|maprotate|mr|cycle to the next map in rotation|False|!mr |Administrator| +|plugins|p|view all loaded plugins|False|!p |Administrator| +|alias|known|get past aliases and ips of a player|True|!known \|Moderator| +|baninfo|bi|get information about a ban for a player|True|!bi \|Moderator| +|fastrestart|fr|fast restart current map|False|!fr |Moderator| +|flag|fp|flag a suspicious player and announce to admins on join|True|!fp \ \|Moderator| +|list|l|list active clients|False|!l |Moderator| +|reports|reps|get or clear recent reports|False|!reps \|Moderator| +|say|s|broadcast message to all players|False|!s \|Moderator| +|tempban|tb|temporarily ban a player for specified time (defaults to 1 hour)|True|!tb \ \ \|Moderator| +|uptime|up|get current application running time|False|!up |Moderator| +|usage|us|get current application memory usage|False|!us |Moderator| +|kick|k|kick a player by name|True|!k \ \|Trusted| +|warn|w|warn player for infringing rules|True|!w \ \|Trusted| +|warnclear|wc|remove all warning for a player|True|!wc \|Trusted| +|admins|a|list currently connected admins|False|!a |User| +|getexternalip|ip|view your external IP address|False|!ip |User| +|help|h|list all available commands|False|!h \|User| +|privatemessage|pm|send message to other player|True|!pm \ \|User| +|report|rep|report a player for suspicious behavior|True|!rep \ \|User| +|resetstats|rs|reset your stats to factory-new|False|!rs |User| +|rules|r|list server rules|False|!r |User| +|stats|xlrstats|view your stats|False|!xlrstats \|User| +|topstats|ts|view the top 5 players on this server|False|!ts |User| +|vote|v|vote for the next map|False|!v \|User| +|votecancel|vc|cancel your vote for the next map|False|!vc |User| +|whoami|who|give information about yourself.|False|!who |User| #### Player Identification All players are identified 4 seperate ways @@ -159,13 +159,14 @@ ___ **Commands added by this plugin** -|Name |Alias|Description |Requires Target|Arguments |Required Level| -|--------------|-----|--------------------------------------------------------|---------------|---------------|--------------| -|disabletrusted|dt|disable trusted player group for the server|False|0|Owner| -|enabletrusted|et|enable trusted player group for the server|False|0|Owner| -|resetstats|rs|reset your stats to factory-new|False|0|User| -|stats|xlrstats|view your stats|False|0|User| -|topstats|ts|view the top 5 players on this server|False|0|User| +|Name |Alias|Description |Requires Target|Syntax |Required Level| +|--------------| -----| --------------------------------------------------------| -----------------| -------------| ----------------| +|disabletrusted|dt|disable trusted player group for the server|False|!dt |Owner| +|enabletrusted|et|enable trusted player group for the server|False|!et |Owner| +|prune|p|demote any admins that have not connected recently (defaults to 30 days)|False|!p \|Owner| +|resetstats|rs|reset your stats to factory-new|False|!rs |User| +|stats|xlrstats|view your stats|False|!xlrstats \|User| +|topstats|ts|view the top 5 players on this server|False|!ts |User| - To qualify for top stats, a player must meet the following criteria * `Skill` > 10 diff --git a/SharedLibrary/Commands/NativeCommands.cs b/SharedLibrary/Commands/NativeCommands.cs index ea4a50e5..66fc515b 100644 --- a/SharedLibrary/Commands/NativeCommands.cs +++ b/SharedLibrary/Commands/NativeCommands.cs @@ -151,7 +151,7 @@ namespace SharedLibrary.Commands }, new CommandArgument() { - Name = "duration (m|d|w|y|)", + Name = "duration (m|h|d|w|y)", Required = true, }, new CommandArgument() @@ -193,8 +193,8 @@ namespace SharedLibrary.Commands }, new CommandArgument() { - Name = "reason", - Required = true + Name = "reason", + Required = true } }) { } @@ -247,7 +247,7 @@ namespace SharedLibrary.Commands public override async Task ExecuteAsync(Event E) { - String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientID, E.Origin.NetworkID, E.Origin.DatabaseID, SharedLibrary.Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IP); + String You = String.Format("{0} [^3#{1}^7] {2} [^3@{3}^7] [{4}^7] IP: {5}", E.Origin.Name, E.Origin.ClientID, E.Origin.NetworkID, E.Origin.DatabaseID, Utilities.ConvertLevelToColor(E.Origin.Level), E.Origin.IP); await E.Origin.Tell(You); } } @@ -663,8 +663,9 @@ namespace SharedLibrary.Commands public class CReload : Command { - public CReload() : - base("reload", "reload configuration files", "rl", Player.Permission.Owner, false) { } + public CReload() : + base("reload", "reload configuration files", "rl", Player.Permission.Owner, false) + { } public override async Task ExecuteAsync(Event E) { @@ -755,14 +756,14 @@ namespace SharedLibrary.Commands if (E.Target.Level > E.Origin.Level) { - await E.Origin.Tell("You cannot report " + E.Target.Name); + await E.Origin.Tell($"You cannot report {E.Target.Name}"); return; } E.Data = E.Data.RemoveWords(1); E.Owner.Reports.Add(new Report(E.Target, E.Origin, E.Data)); - await E.Origin.Tell("Successfully reported " + E.Target.Name); + await E.Origin.Tell($"Successfully reported {E.Target.Name}"); await E.Owner.ExecuteEvent(new Event(Event.GType.Report, E.Data, E.Origin, E.Target, E.Owner)); await E.Owner.ToAdmins(String.Format("^5{0}^7->^1{1}^7: {2}", E.Origin.Name, E.Target.Name, E.Data)); } @@ -831,8 +832,8 @@ namespace SharedLibrary.Commands { new CommandArgument() { - Name = "player", - Required = true + Name = "player", + Required = true } }) { } diff --git a/SharedLibrary/Database.cs b/SharedLibrary/Database.cs index d3582d65..65265b63 100644 --- a/SharedLibrary/Database.cs +++ b/SharedLibrary/Database.cs @@ -564,7 +564,7 @@ namespace SharedLibrary { Dictionary newPlayer = new Dictionary { - { "Name", Utilities.StripIllegalCharacters(P.Name) }, + { "Name", P.Name }, { "npID", P.NetworkID }, { "Level", (int)P.Level }, { "LastOffense", "" }, @@ -596,12 +596,17 @@ namespace SharedLibrary } + public void PruneAdmins(int inactiveDays) + { + ExecuteNonQuery($"UPDATE CLIENTS SET Level={(int)Player.Permission.User} WHERE LastConnection < '{Utilities.DateTimeSQLite(DateTime.Now.AddDays(-inactiveDays))}'"); + } + //Add specified ban to database public void AddPenalty(Penalty B) { Dictionary newBan = new Dictionary { - { "Reason", Utilities.StripIllegalCharacters(B.Reason) }, + { "Reason", B.Reason }, { "npID", B.OffenderID }, { "bannedByID", B.PenaltyOriginID }, { "IP", B.IP }, @@ -712,7 +717,7 @@ namespace SharedLibrary Dictionary newPlayer = new Dictionary { { "Number", Alias.Number }, - { "NAMES", Utilities.StripIllegalCharacters(String.Join(";", Alias.Names)) }, + { "NAMES", String.Join(";", Alias.Names) }, { "IPS", String.Join(";", Alias.IPS) } }; Insert("ALIASES", newPlayer); diff --git a/SharedLibrary/Event.cs b/SharedLibrary/Event.cs index a071d1fe..b19dad0d 100644 --- a/SharedLibrary/Event.cs +++ b/SharedLibrary/Event.cs @@ -29,10 +29,10 @@ namespace SharedLibrary { Type = Ty; Version = V; - Message = M; + Message = System.Web.HttpUtility.HtmlEncode(M); Title = T; - Origin = O; - Target = Ta; + Origin = System.Web.HttpUtility.HtmlEncode(O); + Target = System.Web.HttpUtility.HtmlEncode(Ta); ID = Math.Abs(DateTime.Now.GetHashCode()); } @@ -124,7 +124,7 @@ namespace SharedLibrary { Regex rgx = new Regex("[^a-zA-Z0-9 -! -_]"); string message = rgx.Replace(line[4], ""); - return new Event(GType.Say, Utilities.StripIllegalCharacters(message).StripColors(), SV.ParseClientFromString(line, 2), null, SV) { Message = Utilities.StripIllegalCharacters(message).StripColors() }; + return new Event(GType.Say, message.StripColors(), SV.ParseClientFromString(line, 2), null, SV) { Message = message }; } if (removeTime.Contains("ScriptKill")) diff --git a/SharedLibrary/Penalty.cs b/SharedLibrary/Penalty.cs index 93e77e5d..e2b5627e 100644 --- a/SharedLibrary/Penalty.cs +++ b/SharedLibrary/Penalty.cs @@ -7,7 +7,7 @@ namespace SharedLibrary { public Penalty(Type BType, String Reas, String TargID, String From, DateTime time, String ip, DateTime exp) { - Reason = Reas.CleanChars().StripColors(); + Reason = Reas.StripColors(); OffenderID = TargID; PenaltyOriginID = From; When = time; diff --git a/SharedLibrary/Server.cs b/SharedLibrary/Server.cs index e74504e6..b83ddb44 100644 --- a/SharedLibrary/Server.cs +++ b/SharedLibrary/Server.cs @@ -91,12 +91,19 @@ namespace SharedLibrary /// /// Player name to search for /// Matching player if found - public Player GetClientByName(String pName) + public List GetClientByName(String pName) { string[] QuoteSplit = pName.Split('"'); + bool literal = false; if (QuoteSplit.Length > 1) + { pName = QuoteSplit[1]; - return Players.FirstOrDefault(p => p != null && p.Name.ToLower().Contains(pName.ToLower())); + literal = true; + } + if (literal) + return Players.Where(p => p != null && p.Name.ToLower().Equals(pName.ToLower())).ToList(); + + return Players.Where(p => p != null && p.Name.ToLower().Contains(pName.ToLower())).ToList(); } /// diff --git a/SharedLibrary/SharedLibrary.csproj b/SharedLibrary/SharedLibrary.csproj index 76563899..77a372a3 100644 --- a/SharedLibrary/SharedLibrary.csproj +++ b/SharedLibrary/SharedLibrary.csproj @@ -75,6 +75,7 @@ ..\packages\System.Data.SQLite.Core.1.0.105.1\lib\net45\System.Data.SQLite.dll True + diff --git a/SharedLibrary/Utilities.cs b/SharedLibrary/Utilities.cs index 95d0c1f2..7b801cf6 100644 --- a/SharedLibrary/Utilities.cs +++ b/SharedLibrary/Utilities.cs @@ -80,27 +80,6 @@ namespace SharedLibrary return Player.Permission.Banned; } - public static String StripIllegalCharacters(String str) - { - if (str != null) - return str.Replace("`", "").Replace("\\", "").Replace("\"", "").Replace(""", "").Replace("&", "&").Replace("\"", "''").Replace("'", "").Replace("?", ""); - - else - return String.Empty; - } - - public static String CleanChars(this string S) - { - if (S == null) - return ""; - - 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(); - } - /// /// Remove all IW Engine color codes /// @@ -314,5 +293,10 @@ namespace SharedLibrary return "1 hour"; } + + public static string EscapeMarkdown(this string markdownString) + { + return markdownString.Replace("<", "\\<").Replace(">", "\\>").Replace("|", "\\|"); + } } }