/// <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>
/// <exception cref="ArgumentNullException"> targetAddress or player is null. </exception>
/// <exception cref="PlayerOpException"> Permission or configuration issues arise, or if everyone has already been banned. </exception>
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;
lock ( BanListLock ) {
CheckIfLoaded();
// 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}", targetAddress, player.ClassyName);
var cant = Server.Players.Cant(Permission.ViewPlayerIPs);
cant.Message("&WAn IP was banned by {0}", 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)
{
string kickReason;
if (reason != null)
{
kickReason = String.Format("Banned by {0}: {1}", player.Name, reason);
}
else
{
kickReason = String.Format("Banned by {0}", player.Name);
}
for (int i = 0; i < targetsOnline.Length; i++)
{
if (targetsOnline[i].Info.BanStatus != BanStatus.IPBanExempt)
{
targetsOnline[i].Kick(kickReason, LeaveReason.BanAll);
}
}
}
}