private void SetPlayerInfoText(PlayerInfo info) { textBox1.Text = ""; PlayerLabel.Text = player.Name; SetTextRankColor(Color.GetName(player.Rank.Color)); if (info.LastIP.Equals(System.Net.IPAddress.None)) { textBox1.Text += String.Format("About {0}&S: Never seen before.\r\n", info.ClassyName); } else { if (info != null) { TimeSpan idle = info.PlayerObject.IdleTime; if (info.IsHidden) { if (idle.TotalMinutes > 2) { if (player.Can(Permission.ViewPlayerIPs)) { textBox1.Text += String.Format("About {0}&S: HIDDEN from {1} (idle {2})\r\n", info.ClassyName, info.LastIP, idle.ToMiniString()); } else { textBox1.Text += String.Format("About {0}&S: HIDDEN (idle {1})\r\n", info.ClassyName, idle.ToMiniString()); } } else { if (player.Can(Permission.ViewPlayerIPs)) { textBox1.Text += String.Format("About {0}&S: HIDDEN. Online from {1}\r\n", info.ClassyName, info.LastIP); } else { textBox1.Text += String.Format("About {0}&S: HIDDEN.\r\n", info.ClassyName); } } } else { if (idle.TotalMinutes > 1) { if (player.Can(Permission.ViewPlayerIPs)) { textBox1.Text += String.Format("About {0}&S: Online now from {1} (idle {2})\r\n", info.ClassyName, info.LastIP, idle.ToMiniString()); } else { textBox1.Text += String.Format("About {0}&S: Online now (idle {1})\r\n", info.ClassyName, idle.ToMiniString()); } } else { if (player.Can(Permission.ViewPlayerIPs)) { textBox1.Text += String.Format("About {0}&S: Online now from {1}\r\n", info.ClassyName, info.LastIP); } else { textBox1.Text += String.Format("About {0}&S: Online now.\r\n", info.ClassyName); } } } } else { if (player.Can(Permission.ViewPlayerIPs)) { if (info.LeaveReason != LeaveReason.Unknown) { textBox1.Text += String.Format("About {0}&S: Last seen {1} ago from {2} ({3}).\r\n", info.ClassyName, info.TimeSinceLastSeen.ToMiniString(), info.LastIP, info.LeaveReason); } else { textBox1.Text += String.Format("About {0}&S: Last seen {1} ago from {2}.\r\n", info.ClassyName, info.TimeSinceLastSeen.ToMiniString(), info.LastIP); } } else { if (info.LeaveReason != LeaveReason.Unknown) { textBox1.Text += String.Format("About {0}&S: Last seen {1} ago ({2}).\r\n", info.ClassyName, info.TimeSinceLastSeen.ToMiniString(), info.LeaveReason); } else { textBox1.Text += String.Format("About {0}&S: Last seen {1} ago.\r\n", info.ClassyName, info.TimeSinceLastSeen.ToMiniString()); } } } // Show login information textBox1.Text += String.Format(" Logged in {0} time(s) since {1:d MMM yyyy}.\r\n", info.TimesVisited, info.FirstLoginDate); } if (info.IsFrozen) { textBox1.Text += String.Format(" Frozen {0} ago by {1}\r\n", info.TimeSinceFrozen.ToMiniString(), info.FrozenByClassy); } if (info.IsMuted) { textBox1.Text += String.Format(" Muted for {0} by {1}\r\n", info.TimeMutedLeft.ToMiniString(), info.MutedByClassy); float blocks = ((info.BlocksBuilt + info.BlocksDrawn) - info.BlocksDeleted); if (blocks < 0) { textBox1.Text += String.Format(" &CWARNING! {0}&S has deleted more than built!\r\n", info.ClassyName); //<---- GlennMR on Au70 Galaxy } } // Show ban information IPBanInfo ipBan = IPBanList.Get(info.LastIP); switch (info.BanStatus) { case BanStatus.Banned: if (ipBan != null) { textBox1.Text += String.Format(" Account and IP are &CBANNED&S. See &H/BanInfo\r\n"); } else { textBox1.Text += String.Format(" Account is &CBANNED&S. See &H/BanInfo\r\n"); } break; case BanStatus.IPBanExempt: if (ipBan != null) { textBox1.Text += String.Format(" IP is &CBANNED&S, but account is exempt. See &H/BanInfo\r\n"); } else { textBox1.Text += String.Format(" IP is not banned, and account is exempt. See &H/BanInfo\r\n"); } break; case BanStatus.NotBanned: if (ipBan != null) { textBox1.Text += String.Format(" IP is &CBANNED&S. See &H/BanInfo\r\n"); } break; } if (!info.LastIP.Equals(System.Net.IPAddress.None)) { // Show alts List <PlayerInfo> altNames = new List <PlayerInfo>(); int bannedAltCount = 0; foreach (PlayerInfo playerFromSameIP in PlayerDB.FindPlayers(info.LastIP)) { if (playerFromSameIP == info) { continue; } altNames.Add(playerFromSameIP); if (playerFromSameIP.IsBanned) { bannedAltCount++; } } // Stats if (info.BlocksDrawn > 500000000) { textBox1.Text += String.Format(" Built {0} and deleted {1} blocks, drew {2}M blocks, wrote {3} messages.\r\n", info.BlocksBuilt, info.BlocksDeleted, info.BlocksDrawn / 1000000, info.MessagesWritten); } else if (info.BlocksDrawn > 500000) { textBox1.Text += String.Format(" Built {0} and deleted {1} blocks, drew {2}K blocks, wrote {3} messages.\r\n", info.BlocksBuilt, info.BlocksDeleted, info.BlocksDrawn / 1000, info.MessagesWritten); } else if (info.BlocksDrawn > 0) { textBox1.Text += String.Format(" Built {0} and deleted {1} blocks, drew {2} blocks, wrote {3} messages.\r\n", info.BlocksBuilt, info.BlocksDeleted, info.BlocksDrawn, info.MessagesWritten); } else { textBox1.Text += String.Format(" Built {0} and deleted {1} blocks, wrote {2} messages.\r\n", info.BlocksBuilt, info.BlocksDeleted, info.MessagesWritten); } // More stats if (info.TimesBannedOthers > 0 || info.TimesKickedOthers > 0 || info.PromoCount > 0) { textBox1.Text += String.Format(" Kicked {0}, Promoted {1} and banned {2} players.\r\n", info.TimesKickedOthers, info.PromoCount, info.TimesBannedOthers); } if (info.TimesKicked > 0) { if (info.LastKickDate != DateTime.MinValue) { textBox1.Text += String.Format(" Got kicked {0} times. Last kick {1} ago by {2}\r\n", info.TimesKicked, info.TimeSinceLastKick.ToMiniString(), info.LastKickByClassy); } else { textBox1.Text += String.Format(" Got kicked {0} times.\r\n", info.TimesKicked); } if (info.LastKickReason != null) { textBox1.Text += String.Format(" Kick reason: {0}\r\n", info.LastKickReason); } } // Promotion/demotion if (info.PreviousRank == null) { if (info.RankChangedBy == null) { textBox1.Text += String.Format(" Rank is {0}&S (default).\r\n", info.Rank.ClassyName); } else { textBox1.Text += String.Format(" Promoted to {0}&S by {1}&S {2} ago.\r\n", info.Rank.ClassyName, info.RankChangedByClassy, info.TimeSinceRankChange.ToMiniString()); if (info.RankChangeReason != null) { textBox1.Text += String.Format(" Promotion reason: {0}\r\n", info.RankChangeReason); } } } else if (info.PreviousRank <= info.Rank) { textBox1.Text += String.Format(" Promoted from {0}&S to {1}&S by {2}&S {3} ago.\r\n", info.PreviousRank.ClassyName, info.Rank.ClassyName, info.RankChangedByClassy, info.TimeSinceRankChange.ToMiniString()); if (info.RankChangeReason != null) { textBox1.Text += String.Format(" Promotion reason: {0}\r\n", info.RankChangeReason); } } else { textBox1.Text += String.Format(" Demoted from {0}&S to {1}&S by {2}&S {3} ago.\r\n", info.PreviousRank.ClassyName, info.Rank.ClassyName, info.RankChangedByClassy, info.TimeSinceRankChange.ToMiniString()); if (info.RankChangeReason != null) { textBox1.Text += String.Format(" Demotion reason: {0}\r\n", info.RankChangeReason); } } if (!info.LastIP.Equals(System.Net.IPAddress.None)) { // Time on the server TimeSpan totalTime = info.TotalTime; totalTime = totalTime.Add(info.TimeSinceLastLogin); textBox1.Text += String.Format(" Spent a total of {0:F1} hours ({1:F1} minutes) here.\r\n", totalTime.TotalHours, totalTime.TotalMinutes); } textBox1.Text = Color.StripColors(textBox1.Text); } }
/// <summary> Bans given IP address and all accounts on that IP. All players from IP are kicked. /// Throws PlayerOpException on problems. </summary> /// <param name="targetAddress"> IP address that is being banned. </param> /// <param name="player"> Player who is banning. </param> /// <param name="reason"> Reason for ban. May be empty, if permitted by server configuration. </param> /// <param name="announce"> Whether ban should be publicly announced on the server. </param> /// <param name="raiseEvents"> Whether AddingIPBan, AddedIPBan, BanChanging, and BanChanged events should be raised. </param> public static void BanAll([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason, bool announce, bool raiseEvents) { if (targetAddress == null) { throw new ArgumentNullException("targetAddress"); } if (player == null) { throw new ArgumentNullException("player"); } if (reason != null && reason.Trim().Length == 0) { reason = null; } if (!player.Can(Permission.Ban, Permission.BanIP, Permission.BanAll)) { PlayerOpException.ThrowPermissionMissing(player, null, "ban-all", Permission.Ban, Permission.BanIP, Permission.BanAll); } // Check if player is trying to ban self if (targetAddress.Equals(player.IP) && !player.IsSuper()) { PlayerOpException.ThrowCannotTargetSelf(player, null, "ban-all"); } // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255) if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any)) { PlayerOpException.ThrowInvalidIP(player, null, targetAddress); } // Check if any high-ranked players use this address PlayerInfo[] allPlayersOnIP = PlayerDB.FindPlayers(targetAddress); PlayerInfo infoWhomPlayerCantBan = allPlayersOnIP.FirstOrDefault(info => !player.Can(Permission.Ban, info.Rank)); if (infoWhomPlayerCantBan != null) { PlayerOpException.ThrowPermissionLimitIP(player, infoWhomPlayerCantBan, targetAddress); } PlayerOpException.CheckBanReason(reason, player, null, false); bool somethingGotBanned = false; // Ban the IP if (!Contains(targetAddress)) { IPBanInfo banInfo = new IPBanInfo(targetAddress, null, player.Name, reason); if (Add(banInfo, raiseEvents)) { Logger.Log(LogType.UserActivity, "{0} banned {1} (BanAll {1}). Reason: {2}", player.Name, targetAddress, reason ?? ""); // Announce ban on the server if (announce) { var can = Server.Players.Can(Permission.ViewPlayerIPs); can.Message("&W{0} was banned by {1}", MessageType.Announcement, targetAddress, player.ClassyName); var cant = Server.Players.Cant(Permission.ViewPlayerIPs); cant.Message("&WAn IP was banned by {0}", MessageType.Announcement, player.ClassyName); } somethingGotBanned = true; } } // Ban individual players foreach (PlayerInfo targetAlt in allPlayersOnIP) { if (targetAlt.BanStatus != BanStatus.NotBanned) { continue; } // Raise PlayerInfo.BanChanging event PlayerInfoBanChangingEventArgs e = new PlayerInfoBanChangingEventArgs(targetAlt, player, false, reason, announce); if (raiseEvents) { PlayerInfo.RaiseBanChangingEvent(e); if (e.Cancel) { continue; } reason = e.Reason; } // Do the ban if (targetAlt.ProcessBan(player, player.Name, reason)) { if (raiseEvents) { PlayerInfo.RaiseBanChangedEvent(e); } // Log and announce ban Logger.Log(LogType.UserActivity, "{0} banned {1} (BanAll {2}). Reason: {3}", player.Name, targetAlt.Name, targetAddress, reason ?? ""); if (announce) { Server.Message("&WPlayer {0}&W was banned by {1}&W (BanAll)", targetAlt.ClassyName, player.ClassyName); } somethingGotBanned = true; } } // If no one ended up getting banned, quit here if (!somethingGotBanned) { PlayerOpException.ThrowNoOneToBan(player, null, targetAddress); } // Announce BanAll reason towards the end of all bans if (announce && ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null) { Server.Message("&WBanAll reason: {0}", reason); } // Kick all players from IP Player[] targetsOnline = Server.Players.FromIP(targetAddress).ToArray(); if (targetsOnline.Length <= 0) { return; } var kickReason = reason != null ? $"Banned by {player.Name}: {reason}" : $"Banned by {player.Name}"; foreach (var t in targetsOnline) { t.Kick(kickReason, LeaveReason.BanAll); } }
/// <summary> Unbans given IP address and all accounts on that IP. Throws PlayerOpException on problems. </summary> /// <param name="targetAddress"> IP address that is being unbanned. </param> /// <param name="player"> Player who is unbanning. </param> /// <param name="reason"> Reason for unban. May be null or empty, if permitted by server configuration. </param> /// <param name="announce"> Whether unban should be publicly announced on the server. </param> /// <param name="raiseEvents"> Whether RemovingIPBan, RemovedIPBan, BanChanging, and BanChanged events should be raised. </param> public static void UnbanAll([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason, bool announce, bool raiseEvents) { if (targetAddress == null) { throw new ArgumentNullException("targetAddress"); } if (player == null) { throw new ArgumentNullException("player"); } if (reason != null && reason.Trim().Length == 0) { reason = null; } if (!player.Can(Permission.Ban, Permission.BanIP, Permission.BanAll)) { PlayerOpException.ThrowPermissionMissing(player, null, "unban-all", Permission.Ban, Permission.BanIP, Permission.BanAll); } // Check if player is trying to unban self if (targetAddress.Equals(player.IP) && !player.IsSuper()) { PlayerOpException.ThrowCannotTargetSelf(player, null, "unban-all"); } // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255) if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any)) { PlayerOpException.ThrowInvalidIP(player, null, targetAddress); } PlayerOpException.CheckBanReason(reason, player, null, true); bool somethingGotUnbanned = false; // Unban the IP if (Contains(targetAddress)) { if (Remove(targetAddress, raiseEvents)) { Logger.Log(LogType.UserActivity, "{0} unbanned {1} (UnbanAll {1}). Reason: {2}", player.Name, targetAddress, reason ?? ""); // Announce unban on the server if (announce) { var can = Server.Players.Can(Permission.ViewPlayerIPs); can.Message("&W{0} was unbanned by {1}", 0, targetAddress, player.ClassyName); var cant = Server.Players.Cant(Permission.ViewPlayerIPs); cant.Message("&WAn IP was unbanned by {0}", 0, player.ClassyName); } somethingGotUnbanned = true; } } // Unban individual players PlayerInfo[] allPlayersOnIP = PlayerDB.FindPlayers(targetAddress); foreach (PlayerInfo targetAlt in allPlayersOnIP) { if (targetAlt.BanStatus != BanStatus.Banned) { continue; } // Raise PlayerInfo.BanChanging event PlayerInfoBanChangingEventArgs e = new PlayerInfoBanChangingEventArgs(targetAlt, player, true, reason, announce); if (raiseEvents) { PlayerInfo.RaiseBanChangingEvent(e); if (e.Cancel) { continue; } reason = e.Reason; } // Do the ban if (targetAlt.ProcessUnban(player.Name, reason)) { if (raiseEvents) { PlayerInfo.RaiseBanChangedEvent(e); } // Log and announce ban Logger.Log(LogType.UserActivity, "{0} unbanned {1} (UnbanAll {2}). Reason: {3}", player.Name, targetAlt.Name, targetAddress, reason ?? ""); if (announce) { Server.Message("&WPlayer {0}&W was unbanned by {1}&W (UnbanAll)", targetAlt.ClassyName, player.ClassyName); } somethingGotUnbanned = true; } } // If no one ended up getting unbanned, quit here if (!somethingGotUnbanned) { PlayerOpException.ThrowNoOneToUnban(player, null, targetAddress); } // Announce UnbanAll reason towards the end of all unbans if (announce && ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null) { Server.Message("&WUnbanAll reason: {0}", reason); } }
/// <summary> Bans given IP address. All players from IP are kicked. If an associated PlayerInfo is known, /// use a different overload of this method instead. Throws PlayerOpException on problems. </summary> /// <param name="targetAddress"> IP address that is being banned. </param> /// <param name="player"> Player who is banning. </param> /// <param name="reason"> Reason for ban. May be empty, if permitted by server configuration. </param> /// <param name="announce"> Whether ban should be publicly announced on the server. </param> /// <param name="raiseEvents"> Whether AddingIPBan and AddedIPBan events should be raised. </param> public static void BanIP([NotNull] this IPAddress targetAddress, [NotNull] Player player, [CanBeNull] string reason, bool announce, bool raiseEvents) { if (targetAddress == null) { throw new ArgumentNullException("targetAddress"); } if (player == null) { throw new ArgumentNullException("player"); } if (reason != null && reason.Trim().Length == 0) { reason = null; } // Check if player can ban IPs in general if (!player.Can(Permission.Ban, Permission.BanIP)) { PlayerOpException.ThrowPermissionMissing(player, null, "IP-ban", Permission.Ban, Permission.BanIP); } // Check if a non-bannable address was given (0.0.0.0 or 255.255.255.255) if (targetAddress.Equals(IPAddress.None) || targetAddress.Equals(IPAddress.Any)) { PlayerOpException.ThrowInvalidIP(player, null, targetAddress); } // Check if player is trying to ban self if (targetAddress.Equals(player.IP) && !player.IsSuper()) { PlayerOpException.ThrowCannotTargetSelf(player, null, "IP-ban"); } // Check if target is already banned IPBanInfo existingBan = Get(targetAddress); if (existingBan != null) { string msg; if (player.Can(Permission.ViewPlayerIPs)) { msg = String.Format("IP address {0} is already banned.", targetAddress); } else { msg = String.Format("Given IP address is already banned."); } string colorMsg = "&S" + msg; throw new PlayerOpException(player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg); } // Check if any high-ranked players use this address PlayerInfo infoWhomPlayerCantBan = PlayerDB.FindPlayers(targetAddress) .FirstOrDefault(info => !player.Can(Permission.Ban, info.Rank)); if (infoWhomPlayerCantBan != null) { PlayerOpException.ThrowPermissionLimitIP(player, infoWhomPlayerCantBan, targetAddress); } PlayerOpException.CheckBanReason(reason, player, null, false); // Actually ban IPBanInfo banInfo = new IPBanInfo(targetAddress, null, player.Name, reason); bool result = Add(banInfo, raiseEvents); if (result) { Logger.Log(LogType.UserActivity, "{0} banned {1} (BanIP {1}). Reason: {2}", player.Name, targetAddress, reason ?? ""); if (announce) { // Announce ban on the server var can = Server.Players.Can(Permission.ViewPlayerIPs); can.Message("&W{0} was banned by {1}", 0, targetAddress, player.ClassyName); var cant = Server.Players.Cant(Permission.ViewPlayerIPs); cant.Message("&WAn IP was banned by {0}", 0, player.ClassyName); if (ConfigKey.AnnounceKickAndBanReasons.Enabled() && reason != null) { Server.Message("&WBanIP reason: {0}", reason); } } // Kick all players connected from address string kickReason; if (reason != null) { kickReason = String.Format("IP-Banned by {0}: {1}", player.Name, reason); } else { kickReason = String.Format("IP-Banned by {0}", player.Name); } foreach (Player other in Server.Players.FromIP(targetAddress)) { if (other.Info.BanStatus != BanStatus.IPBanExempt) { other.Kick(kickReason, LeaveReason.BanIP); // TODO: check side effects of not using DoKick } } } else { // address is already banned string msg; if (player.Can(Permission.ViewPlayerIPs)) { msg = String.Format("{0} is already banned.", targetAddress); } else { msg = "Given IP address is already banned."; } string colorMsg = "&S" + msg; throw new PlayerOpException(player, null, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg); } }