public static List<BukkitPlayer> bukkitPlayers = new LinkedList<BukkitPlayer>(); static public CriticalSection csBukkitPlayers = new CriticalSection(); static public CriticalSection csIrcBans = new CriticalSection(); static public CriticalSection csIrcUsers = new CriticalSection(); public static SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"); public static List<IrcBan> ircBans = new ArrayList<IrcBan>(); public static Modes mode = Modes.STANDALONE; public static String msgIRCBan = "&e[IRC] {BannedUser} was banned by {BannedBy}"; public static String msgIRCBanDynmap = "{BannedUser} was banned by {BannedBy}"; public static String msgIRCKick = "&e[IRC] {KickedUser} was kicked by {KickedBy}"; public static String msgIRCKickDynmap = "{KickedUser} was kicked by {KickedBy}"; public static String msgIRCKickReason = "&e[IRC] {KickedUser} was kicked by {KickedBy} ({Reason})"; public static String msgIRCKickReasonDynmap = "{KickedUser} was kicked by {KickedBy} ({Reason})"; public static String msgIRCLeave = "&e[IRC] {User} left IRC"; public static String msgIRCLeaveDynmap = "{User} left IRC"; public static String msgIRCLeaveReason = "&e[IRC] {User} left IRC ({Reason})"; public static String msgIRCLeaveReasonDynmap = "{User} left IRC ({Reason})"; public static String serverUID; public static HashMap<String, IRCServer> servers = new HashMap<String, IRCServer>(); public final class Config {

	private static SimpleDateFormat dateFormat = new SimpleDateFormat(
			"EEE MMM dd HH:mm:ss yyyy");
	private static String serverCreationDate = dateFormat.format(new Date());
	private static String ircdOperPass = ""; // caching only
	private static BukkitIRCdPlugin plugin = BukkitIRCdPlugin.thePlugin;
	private static FileConfiguration config;

	private Config() {

	}

	/**
     Saves the configuration file.
	 */
	public static void saveConfiguration() {
		try {
			plugin.saveConfig();
			BukkitIRCdPlugin.log
			.info("[BukkitIRCd] Saved configuration file." +
					(isDebugModeEnabled() ? " Code BukkitIRCdPlugin742." :
							""));
		} catch (final Exception e) {
			BukkitIRCdPlugin.log
			.warning("[BukkitIRCd] Caught exception while writing settings to file: ");
			e.printStackTrace();
		}
	}

	/**
     Reloads the configuration file.
	 */
	public static void reloadConfiguration() {
		plugin.reloadConfig();

		loadConfiguration();
	}

	/**
     Loads the configuration.
	 */
	public static void loadConfiguration() {
		config = plugin.getConfig();
	}

	public static String getMode() {
		final String mode = "standalone";
		return config.getString("mode", mode);
	}

	public static void setMode(final String mode) {
		config.set("mode", mode);
	}

	public static SimpleDateFormat getDateFormat() {
		return dateFormat;
	}

	public static void setDateFormat(final SimpleDateFormat dateFormat) {
		Config.dateFormat = dateFormat;
	}

	public static String getServerCreationDate() {
		return serverCreationDate;
	}

	public static boolean isIrcdRedundantModes() {
		final boolean ircdRedundantModes = false;
		return config.getBoolean("redundant-modes", ircdRedundantModes);
	}

	public static void setIrcdRedundantModes(final boolean ircdRedundantModes) {
		config.set("redundant-modes", ircdRedundantModes);
	}

	public static int getIrcdPort() {
		final int ircdPort = 6667;
		return config.getInt("standalone.port", ircdPort);
	}

	public static void setIrcdPort(final int ircdPort) {
		config.set("standalone.port", ircdPort);
	}

	public static int getIrcdMaxConnections() {
		final int ircdMaxConnections = 1000;
		return config.getInt("standalone.max-connections", ircdMaxConnections);
	}

	public static void setIrcdMaxConnections(final int ircdMaxConnections) {
		config.set("standalone.max-connections", ircdMaxConnections);
	}

	public static int getIrcdPingInterval() {
		final int ircdPingInterval = 45;
		return config.getInt("standalone.ping-interval", ircdPingInterval);
	}

	public static void setIrcdPingInterval(final int ircdPingInterval) {
		config.set("standalone.ping-interval", ircdPingInterval);
	}

	public static int getIrcdPinkTimeoutInterval() {
		final int ircdPinkTimeoutInterval = 180;
		return config.getInt("standalone.timeout", ircdPinkTimeoutInterval);
	}

	public static void setIrcdPinkTimeoutInterval(
			final int ircdPinkTimeoutInterval) {
		config.set("standalone.timeout", ircdPinkTimeoutInterval);
	}

	public static int getIrcdMaxNickLength() {
		final int ircdMaxNickLength = 32;
		return config.getInt("standalone.max-nick-length", ircdMaxNickLength);
	}

	public static void setIrcdMaxNickLength(final int ircdMaxNickLength) {
		config.set("standalone.max-nick-length", ircdMaxNickLength);
	}

	public static String getIrcdChannel() {
		final String ircdChannel = "#minecraft";
		return config.getString("channel-name", ircdChannel);
	}

	public static void setIrcdChannel(final String ircdChannel) {
		config.set("channel-name", ircdChannel);
	}

	public static String getIrcdServerName() {
		final String ircdServerName = "BukkitIRCd";
		return config.getString("server-name", ircdServerName);
	}

	public static void setIrcdServerName(final String ircdServerName) {
		config.set("server-name", ircdServerName);
	}

	public static String getIrcdServerDescription() {
		final String ircdServerDescription = "Minecraft BukkitIRCd Server";
		return config.getString("server-description", ircdServerDescription);
	}

	public static void setIrcdServerDescription(
			final String ircdServerDescription) {
		config.set("server-description", ircdServerDescription);
	}

	public static String getIrcdServerHostName() {
		final String ircdServerHostName = "bukkitircd.localhost";
		return config.getString("server-host", ircdServerHostName);
	}

	public static void setIrcdServerHostName(final String ircdServerHostName) {
		config.set("server-host", ircdServerHostName);
	}

	public static String getIrcdIngameSuffix() {
		final String ircdIngameSuffix = "/minecraft";
		return config.getString("ingame-suffix", ircdIngameSuffix);
	}

	public static void setIrcdIngameSuffix(final String ircdIngameSuffix) {
		config.set("ingame-suffix", ircdIngameSuffix);
	}

	public static String getIrcdTopic() {
		final String ircdTopic = "Welcome to a Bukkit server!";
		return config.getString("standalone.channel-topic", ircdTopic)
				.replace("^K", (char) 3 + "").replace("^B", (char) 2 + "")
				.replace("^I", (char) 29 + "").replace("^O", (char) 15 + "")
				.replace("^U", (char) 31 + "");
	}

	public static void setIrcdTopic(final String ircdTopic) {
		config.set(
				"standalone.channel-topic",
				ircdTopic.replace("^K", (char) 3 + "")
				.replace("^B", (char) 2 + "")
				.replace("^I", (char) 29 + "")
				.replace("^O", (char) 15 + "")
				.replace("^U", (char) 31 + ""));
	}

	public static String getIrcdTopicSetBy() {
		return config.getString("standalone.channel-topic-set-by",
				getIrcdServerName());
	}

	public static void setIrcdTopicSetBy(final String ircdTopicSetBy) {
		config.set("standalone.channel-topic-set-by", ircdTopicSetBy);
	}

	public static long getIrcdTopicSetDate() {
		try {
			return BukkitIRCdPlugin.dateFormat.parse(config.getString("standalone.channel-topic-set-date", BukkitIRCdPlugin.dateFormat.format(System.currentTimeMillis() / 1000L))).getTime();
		} catch (ParseException e) {
			e.printStackTrace();
		}

		return (new Date()).getTime();
	}

	public static void setIrcdTopicSetDate(final long ircdTopicSetDate) {
		config.set("standalone.channel-topic-set-date", ircdTopicSetDate);
	}

	public static String getIrcdBantype() {
		final String ircdBantype = "ip";
		return config.getString("ban-type", ircdBantype);
	}

	public static void setIrcdBantype(final String ircdBantype) {
		config.set("ban-type", ircdBantype);
	}

	public static boolean isIrcdConvertColorCodes() {
		final boolean ircdConvertColorCodes = true;
		return config.getBoolean("convert-color-codes", ircdConvertColorCodes);
	}

	public static void setIrcdConvertColorCodes(final boolean ircdConvertColorCodes) {
		config.set("convert-color-codes", ircdConvertColorCodes);
	}

	public static boolean isIrcdHandleAmpersandColors() {
		final boolean ircdHandleAmpersandColors = true;
		return config.getBoolean("handle-ampersand-colors", ircdHandleAmpersandColors);
	}

	public static void setIrcdHandleAmpersandColors(final boolean ircdHandleAmpersandColors) {
		config.set("handle-ampersand-colors", ircdHandleAmpersandColors);
	}

	public static boolean isIrcdNoticesEnabled() {
		final boolean ircdNoticesEnabled = true;
		return config.getBoolean("enable-notices", ircdNoticesEnabled);
	}

	public static void setIrcdNoticesEnabled(final boolean ircdNoticesEnabled) {
		config.set("enable-notices", ircdNoticesEnabled);
	}

	public static String getIrcdOperUser() {
		final String ircdOperUser = "";
		return config.getString("standalone.oper-username", ircdOperUser);
	}

	public static void setIrcdOperUser(final String ircdOperUser) {
		config.set("standalone.oper-username", ircdOperUser);
	}

	public static String getIrcdOperPass() {
		if (!ircdOperPass.isEmpty()) {
			return ircdOperPass;
		}

		final String operpass = config.getString("standalone.oper-password",
				ircdOperPass);
		if (operpass.isEmpty()) {
			ircdOperPass = operpass;
		} else if (operpass.startsWith("~")) {
			ircdOperPass = operpass.substring(1);
		} else if (!operpass.isEmpty()) {
			ircdOperPass = Hash.compute(operpass, HashType.SHA_512);
		}
		return ircdOperPass;
	}

	public static void setIrcdOperPass(final String ircdOperPass) {
		config.set("standalone.oper-password", ircdOperPass);
	}

	public static String getIrcdOperModes() {
		final String ircdOperModes = "~&@%+";
		return config.getString("standalone.oper-modes", ircdOperModes);
	}

	public static void setIrcdOperModes(final String ircdOperModes) {
		config.set("standalone.oper-modes", ircdOperModes);
	}

	public static String getIrcdConsoleChannel() {
		final String ircdConsoleChannel = "#staff";
		return config.getString("console-channel-name", ircdConsoleChannel);
	}

	public static void setIrcdConsoleChannel(final String ircdConsoleChannel) {
		config.set("console-channel-name", ircdConsoleChannel);
	}

	public static String getIrcdIrcColors() {
		final String ircdIrcColors = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15";
		return config.getString("irc-colors", ircdIrcColors);
	}

	public static void setIrcdIrcColors(final String ircdIrcColors) {
		config.set("irc-colors", ircdIrcColors);
	}

	public static String getIrcdGameColors() {
		final String ircdGameColors = "0,f,1,2,c,4,5,6,e,a,3,b,9,d,8,7";
		return config.getString("game-colors", ircdGameColors);
	}

	public static void setIrcdGameColors(final String ircdGameColors) {
		config.set("game-colors", ircdGameColors);
	}

	public static boolean isIrcdColorDeathMessagesEnabled() {
		final boolean ircdColorDeathMessagesEnabled = false;
		return config.getBoolean("color-death-messages", ircdColorDeathMessagesEnabled);
	}

	public static void setIrcdColorDeathMessagesEnabled(final boolean ircdColorDeathMessagesEnabled) {
		config.set("color-death-messages", ircdColorDeathMessagesEnabled);
	}

	public static boolean isIrcdColorSayMessageEnabled() {
		final boolean ircdColorSayMessageEnabled = false;
		return config.getBoolean("color-say-messages", ircdColorSayMessageEnabled);
	}

	public static void setIrcdColorSayMessageEnabled(final boolean ircdColorSayMessageEnabled) {
		config.set("color-say-messages", ircdColorSayMessageEnabled);
	}

	public static boolean isIrcdBroadCastDeathMessages() {
		final boolean ircdBroadCastDeathMessages = true;
		return config.getBoolean("broadcast-death-messages",
				ircdBroadCastDeathMessages);
	}

	public static void setIrcdBroadCastDeathMessages(final boolean ircdBroadCastDeathMessages) {
		config.set("broadcast-death-messages", ircdBroadCastDeathMessages);
	}

	public static boolean isDebugModeEnabled() {
		final boolean debugModeEnabled = false;
		return config.getBoolean("debug-mode", debugModeEnabled);
	}

	public static void setDebugModeEnabled(final boolean debugModeEnabled) {
		config.set("debug-mode", debugModeEnabled);
	}
	public static boolean isIrcdIngameSuffixStripEnabled() {
		final boolean ircdIngameSuffixStripEnabled = true;
		return config.getBoolean("strip-ingame-suffix",
				ircdIngameSuffixStripEnabled);
	}

	public static void setIrcdIngameSuffixStripEnabled(final boolean ircdIngameSuffixStripEnabled) {
		config.set("strip-ingame-suffix", ircdIngameSuffixStripEnabled);
	}

	public static String getLinkRemoteHost() {
		final String linkRemoteHost = "localhost";
		return config.getString("inspircd.remote-host", linkRemoteHost);
	}

	public static void setLinkRemoteHost(final String linkRemoteHost) {
		config.set("inspircd.remote-host", linkRemoteHost);
	}

	public static int getLinkRemotePort() {
		final int linkRemotePort = 7000;
		return config.getInt("inspircd.remote-port", linkRemotePort);
	}

	public static void setLinkRemotePort(final int linkRemotePort) {
		config.set("inspircd.remote-port", linkRemotePort);
	}

	public static int getLinkLocalPort() {
		final int linkLocalPort = 7000;
		return config.getInt("inspircd.local-port", linkLocalPort);
	}

	public static void setLinkLocalPort(final int linkLocalPort) {
		config.set("inspircd.local-port", linkLocalPort);
	}

	public static boolean isLinkAutoconnect() {
		final boolean linkAutoconnect = true;
		return config.getBoolean("inspircd.auto-connect", linkAutoconnect);
	}

	public static void setLinkAutoconnect(final boolean linkAutoconnect) {
		config.set("inspircd.auto-connect", linkAutoconnect);
	}

	public static String getLinkName() {
		final String linkName = "irc.localhost";
		return config.getString("inspircd.link-name", linkName);
	}

	public static void setLinkName(final String linkName) {
		config.set("inspircd.link-name", linkName);
	}

	public static String getLinkConnectPassword() {
		final String linkConnectPassword = "test";
		return config.getString("inspircd.connect-password", linkConnectPassword);
	}

	public static void setLinkConnectPassword(final String linkConnectPassword) {
		config.set("inspircd.connect-password", linkConnectPassword);
	}

	public static String getLinkReceivePassword() {
		final String linkReceivePassword = "test";
		return config.getString("inspircd.receive-password", linkReceivePassword);
	}

	public static void setLinkReceivePassword(final String linkReceivePassword) {
		config.set("inspircd.receive-password", linkReceivePassword);
	}

	public static int getLinkPingInterval() {
		final int linkPingInterval = 60;
		return config.getInt("inspircd.ping-interval", linkPingInterval);
	}

	public static void setLinkPingInterval(final int linkPingInterval) {
		config.set("inspircd.ping-interval", linkPingInterval);
	}

	public static int getLinkTimeout() {
		final int linkTimeout = 180;
		return config.getInt("inspircd.timeout", linkTimeout);
	}

	public static void setLinkTimeout(final int linkTimeout) {
		config.set("inspircd.timeout", linkTimeout);
	}

	public static int getLinkDelay() {
		final int linkDelay = 60;
		return config.getInt("inspircd.connect-delay", linkDelay);
	}

	public static void setLinkDelay(final int linkDelay) {
		config.set("inspircd.connect-delay", linkDelay);
	}

	public static int getLinkServerID() {
		return config.getInt("inspircd.server-id", new Random().nextInt(900) + 100);
	}

	public static void setLinkServerID(final int linkServerID) {
		config.set("inspircd.server-id", linkServerID);
	}

	public static List<String> getKickCommands() {
		return config.getStringList("kick-commands");
	}

	public static void setKickCommands(final List<String> kickCommands) {
		config.set("kick-commands", kickCommands);
	}

	public static boolean isEnableRawSend() {
		final boolean enableRawSend = false;
		return config.getBoolean("enable-raw-send", enableRawSend);
	}

	public static void setEnableRawSend(final boolean enableRawSend) {
		config.set("enable-raw-send", enableRawSend);
	}

	public static String getHostMaskPrefix() {
		return config.getString("host-mask-prefix");
	}

	public static void setHostMaskPrefix(final String hostMaskPrefix) {
		config.set("host-mask-prefix", hostMaskPrefix);
	}

	public static String getHostMaskSuffix() {
		return config.getString("host-mask-suffix");
	}

	public static void setHostMaskSuffix(final String hostMaskSuffix) {
		config.set("host-mask-suffix", hostMaskSuffix);
	}

	public static String getHostMaskKey() {
		return config.getString("host-mask-key");
	}

	public static void setHostMaskKey(final String hostMaskKey) {
		config.set("host-mask-key", hostMaskKey);
	}

	public static boolean isUseHostMask() {
		return config.getBoolean("use-host-mask", false);
	}

	public static void setIsHostMask(final boolean useHostMask) {
		config.set("use-host-mask", useHostMask);
	}

	public static BukkitIRCdPlugin getPlugin() {
		return plugin;
	}

	public static void setPlugin(final BukkitIRCdPlugin plugin) {
		Config.plugin = plugin;
	}

	public static FileConfiguration getConfig() {
		return config;
	}

	public static void setConfig(final FileConfiguration config) {
		Config.config = config;
	}
} public class ChatUtils {
	static char IRC_Color = (char) 3; // ETX Control Code (^C)
	static char IRC_Bold = (char) 2; // STX Control Code (^B)
	static char IRC_Ital = (char) 29; // GS Control Code
	static char IRC_Under = (char) 31; // US Control Code (^_)
	static char IRC_Reset = (char) 15; // SI Control Code (^O)
	static char MC_Color = (char) 167; // Section Sign

	/**
     Strips IRC formatting codes.
     <p>
     @param input IRC Message being send to game
     <p>
     @return Stripped down message
	 */
	public static String stripIRCFormatting(String input) {

		String output = input.replaceAll("\u0003[0-9]{1,2}(,[0-9]{1,2})?", ""); // Remove IRC background color code
		output = output.replace(IRC_Reset + "", "");
		output = output.replace(IRC_Ital + "", "");
		output = output.replace(IRC_Bold + "", "");
		output = output.replace(IRC_Under + "", "");
		output = output.replace(IRC_Color + "", "");
		return output;
	}

	/**
     Converts colors in a string from Minecraft to IRC, or IRC to Minecraft if specified.
     <p>
     For Minecraft -> IRC, &colour codes are converted to the IRC format.
     <p>
     For IRC -> Minecraft, IRC codes are converted to Minecraft codes with the section sign.
     <p>
     @param input A string, usually a message, containing formatted text.
     @param fromIRCtoGame If true, the string was generated in IRC and needs to be formatted for Minecraft. If false, it was generated in Minecraft and needs to be formatted for IRC.
     <p>
     @return Converted message
	 */
	public static String convertColors(String input, boolean fromIRCtoGame) {

		String output = null;
		if (fromIRCtoGame) {
			if (!Config.isIrcdConvertColorCodes()) {
				return ChatUtils.stripIRCFormatting(input);
			}
			output = input.replaceAll("(\\d),\\d{1,2}", "$1"); // Remove IRC background color code

			output = output.replace(IRC_Reset + "", MC_Color + "r");
			output = output.replace(IRC_Ital + "", MC_Color + "o");
			output = output.replace(IRC_Bold + "", MC_Color + "l");
			output = output.replace(IRC_Under + "", MC_Color + "n");

			output = output.replace(IRC_Color + "01", MC_Color + "0"); // IRC Black to MC Black
			output = output.replace(IRC_Color + "02", MC_Color + "1");// IRC Dark Blue to MC Dark Blue
			output = output.replace(IRC_Color + "03", MC_Color + "2"); // IRC Dark Green to MC Dark Green
			output = output.replace(IRC_Color + "04", MC_Color + "c"); // IRC Red to MC Red
			output = output.replace(IRC_Color + "05", MC_Color + "4"); // IRC Dark Red to MC Dark Red
			output = output.replace(IRC_Color + "06", MC_Color + "5"); // IRC Purple to MC Purple
			output = output.replace(IRC_Color + "07", MC_Color + "6"); // IRC Dark Yellow to MC Gold
			output = output.replace(IRC_Color + "08", MC_Color + "e"); // IRC Yellow to MC Yellow
			output = output.replace(IRC_Color + "09", MC_Color + "a"); // IRC Light Green to MC Green
			output = output.replace(IRC_Color + "10", MC_Color + "3"); // IRC Teal to MC Dark Aqua
			output = output.replace(IRC_Color + "11", MC_Color + "b"); // IRC Cyan to MC Aqua
			output = output.replace(IRC_Color + "12", MC_Color + "9"); // IRC Light Blue to MC Blue
			output = output.replace(IRC_Color + "13", MC_Color + "d"); // IRC Light Purple to MC Pink
			output = output.replace(IRC_Color + "14", MC_Color + "8"); // IRC Grey to MC Dark Grey
			output = output.replace(IRC_Color + "15", MC_Color + "7"); // IRC Light Grey to MC Grey
			output = output.replace(IRC_Color + "00", MC_Color + "f"); // IRC White to MC White

			output = output.replace(IRC_Color + "1", MC_Color + "0"); // IRC Black to MC Black
			output = output.replace(IRC_Color + "2", MC_Color + "1");// IRC Dark Blue to MC Dark Blue
			output = output.replace(IRC_Color + "3", MC_Color + "2"); // IRC Dark Green to MC Dark Green
			output = output.replace(IRC_Color + "4", MC_Color + "c"); // IRC Red to MC Red
			output = output.replace(IRC_Color + "5", MC_Color + "4"); // IRC Dark Red to MC Dark Red
			output = output.replace(IRC_Color + "6", MC_Color + "5"); // IRC Purple to MC Purple
			output = output.replace(IRC_Color + "7", MC_Color + "6"); // IRC Dark Yellow to MC Gold
			output = output.replace(IRC_Color + "8", MC_Color + "e"); // IRC Yellow to MC Yellow
			output = output.replace(IRC_Color + "9", MC_Color + "a"); // IRC Light Green to MC Green
			output = output.replace(IRC_Color + "0", MC_Color + "f"); // IRC White to MC White

			output = output.replace(IRC_Color + "", ""); // Get rid of any remaining ETX Characters
			output = output.replace(IRC_Ital + "", ""); // Get rid of any remaining GS Characters
			output = output.replace(IRC_Bold + "", ""); // Get rid of any remaining STX Characters
			output = output.replace(IRC_Under + "", ""); // Get rid of any remaining US Characters

		} else {
			if (!Config.isIrcdConvertColorCodes()) {
				return ChatColor.stripColor(input);
			}
			if (Config.isIrcdHandleAmpersandColors()) {
				output = ChatColor.translateAlternateColorCodes('&', input);
			} else {
				output = input;
			}
			output = output.replace(MC_Color + "n", IRC_Under + "");
			output = output.replace(MC_Color + "o", IRC_Ital + "");
			output = output.replace(MC_Color + "l", IRC_Bold + "");
			output = output.replace(MC_Color + "r", IRC_Reset + "");
			output = output.replace(MC_Color + "m", ""); // IRC Does not have support for Strikethrough
			output = output.replace(MC_Color + "k", ""); // IRC Does not have support for Garbled Text
			output = output.replace(MC_Color + "0", IRC_Color + "01"); // Minecraft Black to IRC Black
			output = output.replace(MC_Color + "1", IRC_Color + "02"); // Minecraft Dark Blue to IRC Dark Blue
			output = output.replace(MC_Color + "2", IRC_Color + "03"); // Minecraft Dark Green to IRC Dark Green
			output = output.replace(MC_Color + "3", IRC_Color + "10"); // Minecraft Dark Aqua to IRC Teal
			output = output.replace(MC_Color + "4", IRC_Color + "05"); // Minecraft Dark Red to IRC Dark Red
			output = output.replace(MC_Color + "5", IRC_Color + "06"); // Minecraft Purple to IRC Purple
			output = output.replace(MC_Color + "6", IRC_Color + "07"); // Minecraft Gold to IRC Dark Yellow
			output = output.replace(MC_Color + "7", IRC_Color + "15"); // Minecraft Grey to IRC Light Grey
			output = output.replace(MC_Color + "8", IRC_Color + "14"); // Minecraft Dark Grey to IRC Grey
			output = output.replace(MC_Color + "9", IRC_Color + "12"); // Minecraft Blue to IRC Light Blue
			output = output.replace(MC_Color + "a", IRC_Color + "09"); // Minecraft Green to IRC Light Green
			output = output.replace(MC_Color + "b", IRC_Color + "11"); // Minecraft Aqua to IRC Cyan
			output = output.replace(MC_Color + "c", IRC_Color + "04"); // Minecraft Red to IRC Red
			output = output.replace(MC_Color + "d", IRC_Color + "13"); // Minecraft Light Purple to IRC Pink
			output = output.replace(MC_Color + "e", IRC_Color + "08"); // Minecraft Yellow to IRC Yellow
			output = output.replace(MC_Color + "f", IRC_Color + "00"); // Minecraft White to IRC White

		}

		return output;
	}

	/**
     Connects 'parts' of a String and prints them.
     <p>
     @param parts Incoming message
     <p>
     @return Whether the message was successfully sent.
	 */
	public static boolean println(String... parts) {
		final String line = ChatUtils.join(parts, " ", 0);
		if ((IRCd.server == null) || (!IRCd.server.isConnected()) || (IRCd.server.isClosed()) || (out == null)) {
			return false;
		}
		synchronized (csServer) {
			if (Config.isDebugModeEnabled()) {
				System.out.println("[BukkitIRCd]" + ChatColor.DARK_BLUE + "[<-] " + line);
			}
			out.println(line);
			return true;
		}
	}

	/**
     <p>
     @param text Text to be checked
     @param pattern	Regex pattern for matching
     <p>
     @return	Whether a match was found
	 */
	public static boolean wildCardMatch(String text, String pattern) {
		//add sentinel so don't need to worry about *'s at end of pattern
		text += '\0';
		pattern += '\0';

		int N = pattern.length();

		boolean[] states = new boolean[N + 1];
		boolean[] old = new boolean[N + 1];
		old[0] = true;

		for (int i = 0; i < text.length(); i++) {
			char c = text.charAt(i);
			states = new boolean[N + 1]; // initialized to false
			for (int j = 0; j < N; j++) {
				char p = pattern.charAt(j);

				// hack to handle *'s that match 0 characters
				if (old[j] && (p == '*')) {
					old[j + 1] = true;
				}

				if (old[j] && (p == c)) {
					states[j + 1] = true;
				}
				if (old[j] && (p == '?')) {
					states[j + 1] = true;
				}
				if (old[j] && (p == '*')) {
					states[j] = true;
				}
				if (old[j] && (p == '*')) {
					states[j + 1] = true;
				}
			}
			old = states;
		}
		return states[N];
	}

	// TODO Find out what this is supposed to be used for, as literally nothing uses it
	/**
     UNKNOWN
     <p>
     @param line
     <p>
     @return
	 */
	public static String[] split(String line) {
		String[] sp1 = line.split(" :", 2);
		String[] sp2 = sp1[0].split(" ");
		String[] res;
		if (!sp2[0].startsWith(":")) {
			res = new String[sp1.length + sp2.length];
			System.arraycopy(sp2, 0, res, 1, sp2.length);
		} else {
			res = new String[sp1.length + sp2.length - 1];
			System.arraycopy(sp2, 0, res, 0, sp2.length);
			res[0] = res[0].substring(1);
		}
		if (sp1.length == 2) {
			res[res.length - 1] = sp1[1];
		}
		return res;
	}

	/**
     Executes a Minecraft command asynchronously for the IRC staff channel.
     <p>
     @param command	The command that is to be run.
	 */
	public static void executeCommand(final String command) {
		new BukkitRunnable() {

			@Override
			public void run() {
				final Server server = Bukkit.getServer();
				try {
					final ServerCommandEvent commandEvent = new ServerCommandEvent(IRCd.commandSender, command);
					server.getPluginManager().callEvent(commandEvent);
					server.dispatchCommand(commandEvent.getSender(), commandEvent.getCommand());
					IRCd.commandSender.sendMessage(ChatColor.ITALIC + "" + ChatColor.GRAY + "[CONSOLE: Command executed.]");
				} catch (CommandException c) {
					Throwable e = c.getCause();

					IRCd.commandSender.sendMessage(ChatColor.RED + "Exception in command \"" + command + "\": " + e);
					if (Config.isDebugModeEnabled()) {
						for (final StackTraceElement s : e.getStackTrace()) {
							IRCd.commandSender.sendMessage(s.toString());
						}
					}
				} catch (Exception e) {
					IRCd.commandSender.sendMessage(ChatColor.RED + "&cException in command \"" + command + "\": " + e);

					if (Config.isDebugModeEnabled()) {
						for (final StackTraceElement s : e.getStackTrace()) {
							IRCd.commandSender.sendMessage(s.toString());
						}
					}
				}
			}
		}.runTask(BukkitIRCdPlugin.thePlugin);
	}

	/**
     UNKNOWN
     <p>
     @param strArray
     @param delimiter
     @param start
     <p>
     @return
	 */
	public static String join(String[] strArray, String delimiter, int start) {

		if (strArray.length <= start) {
			return "";
		}
		//Compute buffer length
		int size = delimiter.length() * (strArray.length - start - 1);
		for (final String s : strArray) {
			size += s.length();
		}

		final StringBuilder builder = new StringBuilder(size);
		builder.append(strArray[start]);
		for (int i = start + 1; i < strArray.length; i++) {
			builder.append(delimiter).append(strArray[i]);
		}

		return builder.toString();
	}

	/**
     Broadcasts a message to the game server asynchronously
     <p>
     @param msg	The message to be broadcast
     <p>
     @return true if able to schedule broadcast
	 */
	public static boolean broadcastMessage(final String msg) {

		try {
			new BukkitRunnable() {
				@Override
				public void run() {
					Bukkit.getServer().broadcastMessage(msg);
				}
			}.runTask(BukkitIRCdPlugin.thePlugin);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	/**
     Send a message to a player
     <p>
     @param player The recipient of the message.
     @param msg	The message to be sent
     <p>
     @return Whether the message was successfully sent
	 */
	public static boolean sendMessage(final String player, final String msg) {
		// TODO Replace .getPlayer as it seems to be Deprecated. 
		try {
			new BukkitRunnable() {
				@SuppressWarnings("deprecation")
				@Override
				public void run() {
					final Player p = Bukkit.getServer().getPlayer(player);
					if (p != null) {
						p.sendMessage(msg);
					}
				}
			}.runTask(BukkitIRCdPlugin.thePlugin);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

} public class MessageFormatter {
    
    public String chat(String input, String prefix, String user, String suffix, String reason, String message) {
		String output = input;
		output = output.replace("{User}", user);
		output = output.replace("{Prefix}", prefix);
		output = output.replace("{Suffix}", suffix);
		return output;
    }
    
    public static String joinIRC(String input, String prefix, String user, String suffix) {
		String output = input;
		output = output.replace("{Prefix}", prefix);
		output = output.replace("{User}", user);
		output = output.replace("{Suffix}", suffix);
		return output;
    }
    
    public static String changeNick(String input, String oldnick, String newnick, String prefix, String suffix) {
		String output = input;
		output = output.replace("{OldNick}", oldnick);
		output = output.replace("{NewNick}", newnick);
		output = output.replace("{Prefix}", prefix);
		output = output.replace("{Suffix}", suffix);
		return output;
    }
    
    public static String changeNickDynmap(String input, String oldnick, String newnick) {
		String output = input;
		output = output.replace("{OldNick}", oldnick);
		output = output.replace("{NewNick}", newnick);
		return output;
    }
    
    public static String sendMsg(String input, String prefix, String suffix, String user, String message) {
		String output = input;
		output = output.replace("{Prefix}", prefix);
		output = output.replace("{Suffix}", suffix);		
		output = output.replace("{User}", user);
		output = output.replace("{Message}", message);
		return output;
    }
    
    public static String ircleaveMsg(String input, String prefix, String suffix, String user, String reason) {
		String output = input;
		output = output.replace("{Prefix}", prefix);
		output = output.replace("{Suffix}", suffix);		
		output = output.replace("{User}", user);
		output = output.replace("{Reason}", reason);
		return output;
    }
    
    public static String ircleaveDynmapMsg(String input, String user, String reason) {
		String output = input;		
		output = output.replace("{User}", user);
		output = output.replace("{Reason}", reason);
		return output;
    }

    public static String playerMsg(String input, String count, String users) {
		String output = input;		
		output = output.replace("{Count}", count);
		output = output.replace("{Users}", users);
		return output;
    }
        
    public static String dynmapMsg(String input, String user, String message) {
		String output = input;		
		output = output.replace("{User}", user);
		output = output.replace("{Message}", message);
		return output;
    }    
      
    public static String banMsg(String input, String banneduser, String bannedby) {
		String output = input;
		output = output.replace("{BannedUser}", banneduser);
		output = output.replace("{BannedBy}", bannedby);		
		return output;
    }
    
    public static String kickMsg(String input, String kickedby, String kickeduser) {
		String output = input;
		output = output.replace("{KickedBy}", kickedby);
		output = output.replace("{KickedUser}", kickeduser);	
		return output;
    }
   
    public static String sendMsgList(String input, String count, String users) {
		String output = input;
		output = output.replace("{Count}", count);
		output = output.replace("{Users}", users);	
		return output;
    }    
    
    public static String kickMsgReason(String input, String kickedby, String kickeduser, String kickreason) {
		String output = input;
		output = output.replace("{KickedBy}", kickedby);
		output = output.replace("{KickedUser}", kickeduser);	
		output = output.replace("{Reason}", kickreason);
		return output;
    }
    
    public static String kickMsgDisplay(String input, String kickedby, String kickreason) {
		String output = input;
		output = output.replace("{KickedBy}", kickedby);	
		output = output.replace("{Reason}", kickreason);
		return output;
    }

    public static String delinkedMsg(String input, String linkname, String reason) {
		String output = input;
		output = output.replace("{LinkName}", linkname);	
		output = output.replace("{Reason}", reason);
		return output;
    }    
  
    public static String irckickMsgReason(String input, String kickedby, String kickeduser, String kickreason, String kickedprefix, String kickedsuffix, String kickerprefix, String kickersuffix) {
		String output = input;
		output = output.replace("{KickedBy}", kickedby);
		output = output.replace("{KickedUser}", kickeduser);	
		output = output.replace("{Reason}", kickreason);
		output = output.replace("{KickedPrefix}", kickedprefix);
		output = output.replace("{KickedSuffix}", kickedsuffix);	
		output = output.replace("{KickerPrefix}", kickerprefix);
		output = output.replace("{KickerSuffix}", kickersuffix);			
		return output;
    }  
    
    public static String irckickMsg(String input, String kickedby, String kickeduser, String kickedprefix, String kickedsuffix, String kickerprefix, String kickersuffix) {
		String output = input;
		output = output.replace("{KickedBy}", kickedby);
		output = output.replace("{KickedUser}", kickeduser);
		output = output.replace("{KickedPrefix}", kickedprefix);
		output = output.replace("{KickedSuffix}", kickedsuffix);	
		output = output.replace("{KickerPrefix}", kickerprefix);
		output = output.replace("{KickerSuffix}", kickersuffix);			
		return output;
    }    
} public class TimeUtils {

	public final static long ONE_SECOND = 1000;
	public final static long SECONDS = 60;

	public final static long ONE_MINUTE = ONE_SECOND * 60;
	public final static long MINUTES = 60;

	public final static long ONE_HOUR = ONE_MINUTE * 60;
	public final static long HOURS = 24;

	public final static long ONE_DAY = ONE_HOUR * 24;

	private TimeUtils() {
	}

	/**
     Converts time (in milliseconds) to human-readable format "<w> days, <x> hours, <y> minutes and (z) seconds"
	 */
	public static String millisToLongDHMS(long duration) {
		StringBuffer res = new StringBuffer();
		long temp = 0;
		if (duration >= ONE_SECOND) {
			temp = duration / ONE_DAY;
			if (temp > 0) {
				duration -= temp * ONE_DAY;
				res.append(temp).append(" day").append(temp > 1 ? "s" : "").append(duration >= ONE_MINUTE ? ", " : "");
			}

			temp = duration / ONE_HOUR;
			if (temp > 0) {
				duration -= temp * ONE_HOUR;
				res.append(temp).append(" hour").append(temp > 1 ? "s" : "").append(duration >= ONE_MINUTE ? ", " : "");
			}

			temp = duration / ONE_MINUTE;
			if (temp > 0) {
				duration -= temp * ONE_MINUTE;
				res.append(temp).append(" minute").append(temp > 1 ? "s" : "");
			}

			if (!res.toString().equals("") && duration >= ONE_SECOND) {
				res.append(" and ");
			}

			temp = duration / ONE_SECOND;
			if (temp > 0) {
				res.append(temp).append(" second").append(temp > 1 ? "s" : "");
			}
			return res.toString();
		} else {
			return "0 second";
		}
	}

	/**
     converts time (in milliseconds) to human-readable format "<dd:>hh:mm:ss"
	 */
	public static String millisToShortDHMS(long duration) {
		String res = "";
		duration /= ONE_SECOND;
		int seconds = (int) (duration % SECONDS);
		duration /= SECONDS;
		int minutes = (int) (duration % MINUTES);
		duration /= MINUTES;
		int hours = (int) (duration % HOURS);
		int days = (int) (duration / HOURS);
		if (days == 0) {
			res = String.format("%02d:%02d:%02d", hours, minutes, seconds);
		} else {
			res = String.format("%dd%02d:%02d:%02d", days, hours, minutes,
					seconds);
		}
		return res;
	}

}
import static com.Jdbye.BukkitIRCd.IRCd.bukkitPlayers;
import static com.Jdbye.BukkitIRCd.IRCd.channelTS;
import static com.Jdbye.BukkitIRCd.IRCd.csBukkitPlayers;
import static com.Jdbye.BukkitIRCd.IRCd.csIrcBans;
import static com.Jdbye.BukkitIRCd.IRCd.csIrcUsers;
import static com.Jdbye.BukkitIRCd.IRCd.dateFormat;
import static com.Jdbye.BukkitIRCd.IRCd.ircBans;
import static com.Jdbye.BukkitIRCd.IRCd.mode;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCBan;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCBanDynmap;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCKick;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCKickDynmap;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCKickReason;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCKickReasonDynmap;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCLeave;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCLeaveDynmap;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCLeaveReason;
import static com.Jdbye.BukkitIRCd.IRCd.msgIRCLeaveReasonDynmap;
import static com.Jdbye.BukkitIRCd.IRCd.serverUID;
import static com.Jdbye.BukkitIRCd.IRCd.servers;
import com.Jdbye.BukkitIRCd.Configuration.Config;
import com.Jdbye.BukkitIRCd.Utilities.ChatUtils;
import com.Jdbye.BukkitIRCd.Utilities.MessageFormatter;
import com.Jdbye.BukkitIRCd.Utilities.TimeUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.bukkit.ChatColor;
		}
		return false;
	}

	public static boolean removeIRCUsers(String reason) {
		synchronized (csIrcUsers) {
			if (mode == Modes.STANDALONE) {
				Iterator<ClientConnection> iter = clientConnections.iterator();
				while (iter.hasNext()) {
					ClientConnection processor = iter.next();
					if (processor.isIdented && processor.isNickSet) {
						if ((IRCd.isPlugin) &&
								(BukkitIRCdPlugin.thePlugin != null)) {
							BukkitIRCdPlugin.thePlugin
							.removeLastReceivedFrom(processor.nick);
							if (msgIRCLeave.length() > 0 && reason != null) {
								ChatUtils.broadcastMessage(MessageFormatter.ircleaveMsg(msgIRCLeaveReason, IRCFunctionality.getGroupSuffix(processor.modes), IRCFunctionality.getGroupPrefix(processor.modes), processor.nick, reason));
							}
							if ((BukkitIRCdPlugin.dynmap != null) &&
									(msgIRCLeaveDynmap.length() > 0)) {
								BukkitIRCdPlugin.dynmap.sendBroadcastToWeb("IRC", msgIRCLeaveDynmap.replace("%USER%", processor.nick));
							}
						}
					}
					iter.remove();
					if (processor.isConnected()) {
						processor.disconnect();
					}
					return true;
				}
			}
		}
		return false;
	}

	public static boolean removeIRCUsersBySID(String serverID) {
		if (mode != Modes.INSPIRCD) {
			return false;
		}
		IRCServer is = servers.get(serverID);
		if (is != null) {
			if (Config.isDebugModeEnabled()) {
				BukkitIRCdPlugin.log.info("[BukkitIRCd] Server " + serverID +
						" (" + is.host + ") delinked");
			}
			Iterator<Map.Entry<String, IRCUser>> iter = uid2ircuser.entrySet()
					.iterator();
			while (iter.hasNext()) {
				Map.Entry<String, IRCUser> entry = iter.next();
				String curUID = entry.getKey();
				IRCUser curUser = entry.getValue();
				if (curUID.startsWith(serverID)) {
					if (curUser.joined) {

						if (msgIRCLeaveReason.length() > 0) {
							ChatUtils.broadcastMessage(MessageFormatter.ircleaveMsg(msgIRCLeaveReason, IRCFunctionality.getGroupSuffix(curUser.getTextModes()), IRCFunctionality.getGroupPrefix(curUser.getTextModes()), curUser.nick, is.host + " split"));
						}
						if ((BukkitIRCdPlugin.dynmap != null) && (msgIRCLeaveReasonDynmap.length() > 0)) {
							BukkitIRCdPlugin.dynmap.sendBroadcastToWeb( "IRC", MessageFormatter.ircleaveDynmapMsg(msgIRCLeaveReasonDynmap, curUser.nick, is.host + " split"));
						}
					}
					iter.remove();
				}
			}
			servers.remove(serverID);
			for (String curSID : is.leaves) {
				removeIRCUsersBySID(curSID);
			}
			return true;
		}
		return false;
	}

	public static boolean kickBanIRCUser(IRCUser ircuser, String kickBannedBy, String kickBannedByHost, boolean isIngame) {
		return kickBanIRCUser(ircuser, kickBannedBy, kickBannedByHost, null, isIngame, Config.getIrcdBantype());
	}

	public static boolean kickBanIRCUser(IRCUser ircuser, String kickBannedBy, String kickBannedByHost, boolean isIngame, String banType) {
		return kickBanIRCUser(ircuser, kickBannedBy, kickBannedByHost, null, isIngame, banType);
	}

	public static boolean kickBanIRCUser(IRCUser ircuser, String kickBannedBy, String kickBannedByHost, String reason, boolean isIngame) {
		return kickBanIRCUser(ircuser, kickBannedBy, kickBannedByHost, null, isIngame, Config.getIrcdBantype());
	}

	public static boolean kickBanIRCUser(IRCUser ircuser, String kickBannedBy, String kickBannedByHost, String reason, boolean isIngame, String banType) {
		if (banType == null) {
			banType = Config.getIrcdBantype();
		}
		String split[] = kickBannedByHost.split("!")[1].split("@");
		String kickedByIdent = split[0];
		String kickedByHostname = split[1];
		return (banIRCUser(ircuser, kickBannedBy, kickBannedByHost, isIngame, banType) && kickIRCUser(ircuser, kickBannedBy, kickedByIdent, kickedByHostname, reason, isIngame));
	}

	public static boolean kickIRCUser(IRCUser ircuser, String kickedByNick, String kickedByIdent, String kickedByHost, boolean isIngame) {
		return kickIRCUser(ircuser, kickedByNick, kickedByIdent, kickedByHost, null, isIngame);
	}

	@SuppressWarnings("unchecked")
	public static boolean kickIRCUser(IRCUser ircuser, String kickedByNick,
			String kickedByIdent, String kickedByHost, String reason,
			boolean isIngame) {
		if (ircuser == null) {
			return false;
		}
		synchronized (csIrcUsers) {
			if (mode == Modes.STANDALONE) {
				ClientConnection processor;
				Iterator<ClientConnection> iter = clientConnections.iterator();
				while (iter.hasNext()) {
					processor = iter.next();
					if (processor.nick.equalsIgnoreCase(ircuser.nick)) {
						if (processor.isIdented && processor.isNickSet) {
							if ((IRCd.isPlugin) &&
									(BukkitIRCdPlugin.thePlugin != null)) {
								if (reason != null) {
									if (msgIRCKickReason.length() > 0) {
										ChatUtils.broadcastMessage(MessageFormatter.irckickMsgReason(msgIRCKickReason, kickedByNick, processor.nick, ChatUtils.convertColors(reason, true), IRCFunctionality.getGroupPrefix(processor.modes), IRCFunctionality.getGroupSuffix(processor.modes), IRCFunctionality.getGroupPrefix(getIRCUser(kickedByNick).getTextModes()), IRCFunctionality.getGroupSuffix(getIRCUser(kickedByNick).getTextModes())));
									}
									if ((BukkitIRCdPlugin.dynmap != null) && (msgIRCKickReasonDynmap.length() > 0)) {