Browse Source

add .irclib

Andrew Dolgov 5 years ago
parent
commit
06fb4066fb

+ 1194 - 0
daemon/src/org/fox/ttirc/irclib/IRCConnection.java

@@ -0,0 +1,1194 @@
+/*
+ * IRClib -- A Java Internet Relay Chat library -- class IRCConnection
+ * Copyright (C) 2002 - 2006 Christoph Schwering <[email protected]>
+ * 
+ * This library and the accompanying materials are made available under the
+ * terms of the
+ * 	- GNU Lesser General Public License,
+ * 	- Apache License, Version 2.0 and
+ * 	- Eclipse Public License v1.0.
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY.
+ */
+
+package org.fox.ttirc.irclib;
+
+import java.io.*;
+import java.net.Socket;
+import java.net.SocketException;
+
+/**
+ * Creates a new connection to an IRC server. It's the main class of the
+ * IRClib, the point everything starts.
+ * <p>
+ * The following sample code tries to establish an IRC connection to an 
+ * IRC server:
+ * <p>
+ * <hr /><pre>
+ * /&#42; 
+ *  &#42; The following code of a class which imports org.schwering.irc.lib.*
+ *  &#42; prepares an IRC connection and then tries to establish the connection.
+ *  &#42; The server is "irc.somenetwork.com", the default portrange (6667 and 
+ *  &#42; 6669) is set, no password is used (null). The nickname is "Foo" and 
+ *  &#42; the realname is "Mr. Foobar". The username "foobar".
+ *  &#42; Because of setDaemon(true), the JVM exits even if this thread is 
+ *  &#42; running.
+ *  &#42; An instance of the class MyListener which must implement 
+ *  &#42; IRCActionListener is added as only event-listener for the connection. 
+ *  &#42; The connection is told to parse out mIRC color codes and to enable
+ *  &#42; automatic PING? PONG! replies.
+ *  &#42;/
+ * IRCConnection conn = new IRCConnection(
+ *                            "irc.somenetwork.com", 
+ *                            6667, 
+ *                            6669, 
+ *                            null, 
+ *                            "Foo", 
+ *                            "Mr. Foobar", 
+ *                            "[email protected]" 
+ *                          ); 
+ * 
+ * conn.addIRCEventListener(new MyListener()); 
+ * conn.setDaemon(true);
+ * conn.setColors(false); 
+ * conn.setPong(true); 
+ * 
+ * try {
+ *   conn.connect(); // Try to connect!!! Don't forget this!!!
+ * } catch (IOException ioexc) {
+ *   ioexc.printStackTrace(); 
+ * }
+ * </pre><hr />
+ * <p>
+ * The serverpassword isn't needed in most cases. You can give 
+ * <code>null</code> or <code>""</code> instead as done in this example.
+ * @author Christoph Schwering &lt;[email protected]&gt;
+ * @version 3.05
+ * @see IRCEventListener
+ * @see IRCParser
+ * @see IRCUtil
+ * @see SSLIRCConnection
+ */
+public class IRCConnection extends Thread {
+	
+	/** 
+	 * This <code>Socket</code> is a connection to the IRC server. 
+	 */
+	private Socket socket;
+	
+	/**
+	 * This is like a UNIX-runlevel. Its value indicates the level of the 
+	 * <code>IRCConnection</code> object. <code>0</code> means that the object 
+	 * has not yet been connected, <code>1</code> means that it's connected but 
+	 * not registered, <code>2</code> means that it's connected and registered 
+	 * but still waiting to receive the nickname the first time, <code>3</code> 
+	 * means that it's connected and registered, and <code>-1</code> means that 
+	 * it was connected but is disconnected. 
+	 * Therefore the defaultvalue is <code>0</code>.
+	 */
+	protected byte level = 0;
+	
+	/** 
+	 * The host of the IRC server. 
+	 */
+	protected String host;
+	
+	/** 
+	 * The <code>int[]</code> contains all ports to which we are going to try to
+	 * connect. This can be a portrange from port 6667 to 6669, for example.
+	 */
+	protected int[] ports;
+	
+	/** 
+	 * The <code>BufferedReader</code> receives Strings from the IRC server. 
+	 */
+	private volatile BufferedReader in;
+	
+	/** 
+	 * The <code>PrintWriter</code> sends Strings to the IRC server. 
+	 */
+	private PrintWriter out;
+	
+	/**
+	 * The <code>String</code> contains the name of the character encoding used
+	 * to talk to the server. This can be ISO-8859-1 or UTF-8 for example. The
+	 * default is ISO-8859-1.
+	 */
+	protected String encoding = "ISO-8859-1";
+	
+	/**
+	 * This array contains <code>IRCEventListener</code> objects.
+	 */
+	private IRCEventListener[] listeners = new IRCEventListener[0];
+	
+	/** 
+	 * This <code>int</code> is the connection's timeout in milliseconds. It's 
+	 * used in the <code>Socket.setSoTimeout</code> method. The default is 
+	 * <code>1000 * 60 * 15</code> millis which are 15 minutes. 
+	 */
+	private int timeout = 1000 * 60 * 15;
+	
+	/** 
+	 * This <code>boolean</code> stands for enabled (<code>true</code>) or 
+	 * disabled (<code>false</code>) ColorCodes.<br />Default is enabled 
+	 * (<code>false</code>).
+	 */
+	private boolean colorsEnabled = false;
+	
+	/** 
+	 * This <code>boolean</code> stands for enabled or disabled automatic PING? 
+	 * PONG! support. <br />It means, that if the server asks with PING for the 
+	 * ping, the PONG is automatically sent. Default is automatic PONG enabled 
+	 * (<code>true</code>). 
+	 */
+	private boolean pongAutomatic = true;
+	
+	/** 
+	 * The password, which is needed to get access to the IRC server. 
+	 */
+	private String pass;
+	
+	/** 
+	 * The user's nickname, which is indispensably to connect. 
+	 */
+	private String nick;
+	
+	/** 
+	 * The user's realname, which is indispensably to connect. 
+	 */
+	private String realname;
+	
+	/** 
+	 * The user's username, which is indispensable to connect. 
+	 */
+	private String username;
+	
+// ------------------------------
+	
+	/**
+	 * Creates a new IRC connection. <br />
+	 * The difference to the other constructor is, that it transmits the ports in
+	 * an <code>int[]</code>. Thus, also ports like 1024, 2048, 6667 and 
+	 * 6669 can be selected.<br /><br />
+	 * The constructor prepares a new IRC connection which can be really started 
+	 * by invoking the <code>connect</code> method. Before invoking it, you should
+	 * set the <code>IRCEventListener</code> and other settings.<br />
+	 * Note that you do not need to set a password to connect to the large public
+	 * IRC networks like QuakeNet, EFNet etc. To use no password in your IRC
+	 * connection, use <code>""</code> or <code>null</code> for the password
+	 * argument in the constructor.
+	 * @param host The hostname of the server we want to connect to.
+	 * @param ports The portrange to which we want to connect.
+	 * @param pass The password of the IRC server. If your server isn't 
+	 *             secured by a password (that's normal), use 
+	 *             <code>null</code> or <code>""</code>.
+	 * @param nick The nickname for the connection. Is used to register the 
+	 *             connection. 
+	 * @param username The username. Is used to register the connection. 
+	 * @param realname The realname. Is used to register the connection. 
+	 * @throws IllegalArgumentException If the <code>host</code> or 
+	 *                                  <code>ports</code> is <code>null</code> or
+	 *                                  <code>ports</code>' length is 
+	 *                                  <code>0</code>.
+	 * @see #connect()
+	 */
+	public IRCConnection(String host, int[] ports, String pass, String nick, 
+			String username, String realname) {
+		if (host == null || ports == null || ports.length == 0) 
+			throw new IllegalArgumentException("Host and ports may not be null."); 
+		this.host = host;
+		this.ports = ports;
+		this.pass = (pass != null && pass.length() == 0) ? null : pass;
+		this.nick = nick;
+		this.username = username;
+		this.realname = realname;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Creates a new IRC connection. <br />
+	 * The difference to the other constructor is, that it transmits the ports as
+	 * two <code>int</code>s. Thus, only a portrange from port <code>x</code> to
+	 * port <code>y</code> like from port 6667 to 6669 can be selected.<br />
+	 * <br />
+	 * The constructor prepares a new IRC connection which can be really started 
+	 * by invoking the <code>connect</code> method. Before invoking it, you should
+	 * set the <code>IRCEventListener</code> and other settings.<br />
+	 * Note that you do not need to set a password to connect to the large public
+	 * IRC networks like QuakeNet, EFNet etc. To use no password in your IRC
+	 * connection, use <code>""</code> or <code>null</code> for the password
+	 * argument in the constructor.
+	 * @param host The hostname of the server we want to connect to.
+	 * @param portMin The beginning of the port range we are going to connect 
+	 *                to.
+	 * @param portMax The ending of the port range we are going to connect to.
+	 * @param pass The password of the IRC server. If your server isn't 
+	 *             secured by a password (that's normal), use 
+	 *             <code>null</code> or <code>""</code>.
+	 * @param nick The nickname for the connection. Is used to register the 
+	 *             connection. 
+	 * @param username The username. Is used to register the connection. 
+	 * @param realname The realname. Is used to register the connection. 
+	 * @throws IllegalArgumentException If the <code>host</code> is 
+	 *                                  <code>null</code>.
+	 * @see #connect()
+	 */
+	public IRCConnection(String host, int portMin, int portMax, String pass, 
+			String nick, String username, String realname) {
+		this(host, portRangeToArray(portMin, portMax), pass, nick, username, 
+				realname);
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Converts a portrange which starts with a given <code>int</code> and ends 
+	 * with a given <code>int</code> into an array which contains all 
+	 * <code>int</code>s from the beginning to the ending (including beginning
+	 * and ending).<br />
+	 * If <code>portMin > portMax</code>, the portrange is turned arount 
+	 * automatically.
+	 * @param portMin The beginning port of the portrange.
+	 * @param portMax The ending port of the portrange.
+	 */
+	private static int[] portRangeToArray(int portMin, int portMax) {
+		if (portMin > portMax) {
+			int tmp = portMin;
+			portMin = portMax;
+			portMax = tmp;
+		}
+		int[] ports = new int[portMax - portMin + 1];
+		for (int i = 0; i < ports.length; i++)
+			ports[i] = portMin + i;
+		return ports;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Establish a connection to the server. <br />
+	 * This method must be invoked to start a connection; the constructor doesn't 
+	 * do that!<br />
+	 * It tries all set ports until one is open. If all ports fail it throws an 
+	 * <code>IOException</code>.<br />
+	 * You can invoke <code>connect</code> only one time.
+	 * @throws IOException If an I/O error occurs. 
+	 * @throws SocketException If the <code>connect</code> method was already
+	 *                         invoked.
+	 * @see #isConnected()
+	 * @see #doQuit()
+	 * @see #doQuit(String)
+	 * @see #close()
+	 */
+	public void connect() throws IOException {
+		if (level != 0) // otherwise disconnected or connect
+			throw new SocketException("Socket closed or already open ("+ level +")");
+		IOException exception = null;
+		Socket s = null;
+		for (int i = 0; i < ports.length && s == null; i++) {
+			try {
+				s = new Socket(host, ports[i]);
+				exception = null; 
+			} catch (IOException exc) {
+				if (s != null)
+					s.close();
+				s = null;
+				exception = exc; 
+			}
+		}
+		if (exception != null) 
+			throw exception; // connection wasn't successful at any port
+		
+		prepare(s);
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Invoked by the <code>connect</code> method, this method prepares the 
+	 * connection. <br />
+	 * It initializes the class-vars for the inputstream and the outputstream of 
+	 * the socket, starts the registration of at the IRC server by calling 
+	 * <code>register()</code> and starts the receiving of lines from the server 
+	 * by starting the thread with the <code>start</code> method.<br /><br />
+	 * This method must be protected, because it is used by extending classes,
+	 * which override the <code>connect</code> method. 
+	 * @param s The socket which is used for the connection.
+	 * @throws IOException If an I/O error occurs.
+	 * @see #connect()
+	 * @see #run()
+	 */
+	protected void prepare(Socket s) throws IOException {
+		if (s == null)
+			throw new SocketException("Socket s is null, not connected");
+		socket = s;
+		level = 1;
+		s.setSoTimeout(timeout);
+		in  = new BufferedReader(new InputStreamReader(s.getInputStream(), 
+				encoding));
+		out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(), 
+				encoding));
+		start();
+		register();
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Registers the connection with the IRC server. <br />
+	 * In fact, it sends a password (if set, else nothing), the nickname and the 
+	 * user, the realname and the host which we're connecting to.<br />
+	 * The action synchronizes <code>code> so that no important messages 
+	 * (like the first PING) come in before this registration is finished.<br />
+	 * The <code>USER</code> command's format is:<br /><code>
+	 * &lt;username&gt; &lt;localhost&gt; &lt;irchost&gt; &lt;realname&gt;
+	 * </code>
+	 */
+	private void register() {
+		if (pass != null)
+			send("PASS "+ pass); 
+		send("NICK "+ nick); 
+		send("USER "+ username +" "+ socket.getLocalAddress() +" "+ host 
+				+" :"+ realname); 
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * The <code>Thread</code> is started by the <code>connect</code> method.
+	 * It's task is to receive strings from the IRC server and hand them over 
+	 * to the <code>get</code> method.
+	 */
+	public void run() {
+		try {
+			String line;
+			while (!isInterrupted()) {
+				line = in.readLine();
+				if (line != null)
+					get(line);
+				else
+					close();
+			}
+		} catch (IOException exc) {
+			close();
+		}
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Sends a String to the server. 
+	 * You should use this method only, if you must do it. For most purposes, 
+	 * there are <code>do*</code> methods (like <code>doJoin</code>). A carriage 
+	 * return line feed (<code>\r\n</code>) is appended automatically.
+	 * @param line The line which should be send to the server without the 
+	 *             trailing carriage return line feed (<code>\r\n</code>).
+	 */
+	public void send(String line) {
+		try {
+			out.write(line +"\r\n");
+			out.flush();
+			if (level == 1) { // not registered
+				IRCParser p = new IRCParser(line);
+				if (p.getCommand().equalsIgnoreCase("NICK"))
+					nick = p.getParameter(1).trim();
+			}
+		} catch (Exception exc) {
+			exc.printStackTrace();
+		}
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Just parses a String given as the only argument with the help of the 
+	 * <code>IRCParser</code> class. Then it controls the command and fires events
+	 * through the <code>IRCEventListener</code>.<br />
+	 * @param line The line which is sent from the server.
+	 */
+	private synchronized void get(String line) {
+		IRCParser p;
+		try {
+			p = new IRCParser(line, colorsEnabled);
+		} catch (Exception exc) {
+			return;
+		}
+		String command = p.getCommand();
+		int reply; // 3-digit reply will be parsed in the later if-condition
+		
+		if (command.equalsIgnoreCase("PRIVMSG")) { // MESSAGE
+			
+			IRCUser user = p.getUser();
+			String middle = p.getMiddle();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onPrivmsg(middle, user, trailing);
+			
+		} else if (command.equalsIgnoreCase("MODE")) { // MODE
+			
+			String chan = p.getParameter(1);
+			if (IRCUtil.isChan(chan)) {
+				IRCUser user = p.getUser();
+				String param2 = p.getParameter(2);
+				String paramsFrom3 = p.getParametersFrom(3);
+				for (int i = listeners.length - 1; i >= 0; i--)
+					listeners[i].onMode(chan, user,
+							new IRCModeParser(param2, paramsFrom3));
+			} else {
+				IRCUser user = p.getUser();
+				String paramsFrom2 = p.getParametersFrom(2);
+				for (int i = listeners.length - 1; i >= 0; i--)
+					listeners[i].onMode(user, chan, paramsFrom2);
+			}
+			
+		} else if (command.equalsIgnoreCase("PING")) { // PING
+			
+			String ping = p.getTrailing(); // no int cause sometimes it's text
+			if (pongAutomatic)
+				doPong(ping);
+			else
+				for (int i = listeners.length - 1; i >= 0; i--)
+					listeners[i].onPing(ping);
+			
+			if (level == 1) { // not registered
+				level = 2; // first PING received -> connection
+				for (int i = listeners.length - 1; i >= 0; i--)
+					listeners[i].onRegistered();
+			}
+			
+		} else if (command.equalsIgnoreCase("JOIN")) { // JOIN
+			
+			IRCUser user = p.getUser();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onJoin(trailing, user);
+			
+		} else if (command.equalsIgnoreCase("NICK")) { // NICK
+			
+			IRCUser user = p.getUser();
+			String changingNick = p.getNick();
+			String newNick = p.getTrailing();
+			if (changingNick.equalsIgnoreCase(nick))
+				nick = newNick;
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onNick(user, newNick);
+			
+		} else if (command.equalsIgnoreCase("QUIT")) { // QUIT
+			
+			IRCUser user = p.getUser();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onQuit(user, trailing);
+			
+		} else if (command.equalsIgnoreCase("PART")) { // PART
+			
+			IRCUser user = p.getUser();
+			String chan = p.getParameter(1);
+			String msg = p.getParameterCount() > 1 ? p.getTrailing() : "";
+			// not logic: "PART :#zentrum" is without msg, "PART #zentrum :cjo all"
+			// is with msg. so we cannot use getMiddle and getTrailing :-/
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onPart(chan, user, msg);
+			
+		} else if (command.equalsIgnoreCase("NOTICE")) { // NOTICE
+			
+			IRCUser user = p.getUser();
+			String middle = p.getMiddle();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onNotice(middle, user, trailing);
+			
+		} else if ((reply = IRCUtil.parseInt(command)) >= 1 && reply < 400) { // RPL
+			
+			String potNick = p.getParameter(1);
+
+			// what the fuck? -fox
+			/*if ((level == 1 || level == 2) && nick.length() > potNick.length() &&
+					nick.substring(0, potNick.length()).equalsIgnoreCase(potNick)) {
+				nick = potNick;
+				if (level == 2)
+					level = 3;
+			}*/
+
+			// lets trust server RPL_WELCOME which tells us our nick			
+			if ((level == 1 || level == 2 || reply == 1)) {
+				nick = potNick;
+				if (level == 2)
+					level = 3;
+			}
+
+			// lets fire onregistered when we're actually registered i.e. received RPL_WELCOME
+			// unlike just taking a random RPL which might be sent before 001 -fox
+			if (reply == 1) { // RPL_WELCOME
+				level = 2; // if first PING wasn't received, we're
+				for (int i = listeners.length - 1; i >= 0; i--)
+					listeners[i].onRegistered(); // connected now for sure
+			}
+			
+			String middle = p.getMiddle();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onReply(reply, middle, trailing);
+			
+		} else if (reply >= 400 && reply < 600) { // ERROR
+			
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onError(reply, trailing);
+			
+		} else if (command.equalsIgnoreCase("KICK")) { // KICK
+			
+			IRCUser user = p.getUser();
+			String param1 = p.getParameter(1);
+			String param2 = p.getParameter(2);
+			String msg = (p.getParameterCount() > 2) ? p.getTrailing() : "";
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onKick(param1, user, param2, msg);
+			
+		} else if (command.equalsIgnoreCase("INVITE")) { // INVITE
+			
+			IRCUser user = p.getUser();
+			String middle = p.getMiddle();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onInvite(trailing, user, middle);
+			
+		} else if (command.equalsIgnoreCase("TOPIC")) { // TOPIC
+			
+			IRCUser user = p.getUser();
+			String middle = p.getMiddle();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onTopic(middle, user, trailing);
+			
+		} else if (command.equalsIgnoreCase("ERROR")) { // ERROR
+			
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onError(trailing);
+			
+		} else { // OTHER
+			
+			String prefix = p.getPrefix();
+			String middle = p.getMiddle();
+			String trailing = p.getTrailing();
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].unknown(prefix, command, middle, trailing);
+			
+		}
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Close down the connection brutally. <br />
+	 * It does *NOT* send the proper IRC command <code>QUIT</code>. You should 
+	 * always use the <code>doQuit</code> methods or <code>send("QUIT")</code> 
+	 * instead of this method. <br />
+	 * You should use this method to close down the connection only when the IRC
+	 * server doesn't react to the <code>QUIT</code> command.
+	 * @see #connect()
+	 * @see #doQuit
+	 * @see #doQuit(String)
+	 */
+	public synchronized void close() {
+		try {
+			if (!isInterrupted())
+				interrupt();
+		} catch (Exception exc) {
+			exc.printStackTrace();
+		}
+		try {
+			if (socket != null)
+				socket.close();
+		} catch (Exception exc) {
+			exc.printStackTrace();
+		}
+		try {
+			if (out != null)
+				out.close();
+		} catch (Exception exc) {
+			exc.printStackTrace();
+		}
+		try {
+			if (in != null)
+				in.close();
+		} catch (Exception exc) {
+			exc.printStackTrace();
+		}
+		if (this.level != -1) {
+			this.level = -1;
+			for (int i = listeners.length - 1; i >= 0; i--)
+				listeners[i].onDisconnected(); 
+		}
+		socket = null;
+		in = null;
+		out = null;
+		listeners = new IRCEventListener[0];
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Adds a new {@link IRCEventListener} which listens
+	 * for actions coming from the IRC server. 
+	 * @param l An instance of the 
+	 *          {@link IRCEventListener} interface.
+	 * @throws IllegalArgumentException If <code>listener</code> is 
+	 *                                  <code>null</code>.
+	 */
+	public synchronized void addIRCEventListener(IRCEventListener l) {
+		if (l == null)
+			throw new IllegalArgumentException("Listener is null.");
+		int len = listeners.length;
+		IRCEventListener[] oldListeners = listeners;
+		listeners = new IRCEventListener[len + 1];
+		System.arraycopy(oldListeners, 0, listeners, 0, len);
+		listeners[len] = l;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Removes the first occurence of the given 
+	 * {@link IRCEventListener} from the listener-vector.
+	 * @param l An instance of the 
+	 *          {@link IRCEventListener} interface.
+	 * @return <code>true</code> if the listener was successfully removed;
+	 *         <code>false</code> if it was not found.
+	 */
+	public synchronized boolean removeIRCEventListener(IRCEventListener l) {
+		if (l == null)
+			return false;
+		int index = -1;
+		for (int i = 0; i < listeners.length; i++)
+			if (listeners[i].equals(l)) {
+				index = i;
+				break;
+			}
+		if (index == -1)
+			return false;
+		listeners[index] = null;
+		int len = listeners.length - 1;
+		IRCEventListener[] newListeners = new IRCEventListener[len];
+		for (int i = 0, j = 0; i < len; j++)
+			if (listeners[j] != null)
+				newListeners[i++] = listeners[j];
+		listeners = newListeners;
+		return true;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Enables or disables the mIRC colorcodes. 
+	 * @param colors <code>true</code> to enable, <code>false</code> to disable 
+	 *               colors. 
+	 */
+	public void setColors(boolean colors) {
+		colorsEnabled = colors;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Enables or disables the automatic PING? PONG! support. 
+	 * @param pong <code>true</code> to enable automatic <code>PONG</code> 
+	 *             reply, <code>false</code> makes the class fire 
+	 *             <code>onPing</code> events.
+	 */
+	public void setPong(boolean pong) {
+		pongAutomatic = pong;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Changes the character encoding used to talk to the server. 
+	 * This can be ISO-8859-1 or UTF-8 for example.
+	 * This property must be set before a call to the <code>connect()</code> 
+	 * method.
+	 * @param encoding 
+	 */
+	public void setEncoding(String encoding) {
+		this.encoding	= encoding;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Sets the connection's timeout in milliseconds. <br />
+	 * The default is <code>1000 * 60 15</code> millis which are 15 minutes. 
+	 */
+	public void setTimeout(int millis) {
+		if (socket != null)
+			try {
+				socket.setSoTimeout(millis);
+			} catch (IOException exc) {
+				exc.printStackTrace();
+			}
+			timeout = millis;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Tells whether there's a connection to the IRC network or not. <br />
+	 * If <code>connect</code> wasn't called yet, it returns <code>false</code>.
+	 * @return The status of the connection; <code>true</code> if it's connected. 
+	 * @see #connect()
+	 * @see #doQuit()
+	 * @see #doQuit(String)
+	 * @see #close()
+	 */
+	public boolean isConnected() {
+		return level >= 1;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Returns the nickname of this instance. 
+	 * @return The nickname.
+	 */
+	public String getNick() {
+		return nick;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Returns the realname of this instance. 
+	 * @return The realname.
+	 */
+	public String getRealname() {
+		return realname;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Returns the username of this instance. 
+	 * @return The username.
+	 */
+	public String getUsername() {
+		return username;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Returns the server of this instance. 
+	 * @return The server's hostname.
+	 */
+	public String getHost() {
+		return host;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Returns the password of this instance. If no password is set, 
+	 * <code>null</code> is returned.
+	 * @return The password. If no password is set, <code>null</code> is
+	 *         returned.
+	 */
+	public String getPassword() {
+		return pass;
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Returns all ports to which the <code>IRCConnection</code> is going to try
+	 * or has tried to connect to.
+	 * @return The ports in an <code>int[]</code> array.
+	 */
+	public int[] getPorts() {
+		return ports;
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Returns the port to which the <code>IRCConnection</code> connected, or 
+	 * <code>0</code> if the connection failed or wasn't tried yet.
+	 * @return The port to which the <code>IRCConnection</code>, or 
+	 *         <code>0</code> if the connection failed or wasn't tried yet.
+	 */
+	public int getPort() {
+		return (socket != null) ? socket.getPort() : 0;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Indicates whether colors are stripped out or not.
+	 * @return <code>true</code> if colors are disabled.
+	 */
+	public boolean getColors() {
+		return colorsEnabled;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Indicates whether automatic PING? PONG! is enabled or not.
+	 * @return <code>true</code> if PING? PONG! is done automatically.
+	 */
+	public boolean getPong() {
+		return pongAutomatic;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Returns the encoding of the socket. 
+	 * @return The socket's encoding.
+	 */
+	public String getEncoding() {
+		return encoding;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Returns the timeout of the socket. <br />
+	 * If an error occurs, which is never the case, <code>-1</code> is returned.
+	 * @return The timeout.
+	 */
+	public int getTimeout() {
+		if (socket != null)
+			try {
+				return socket.getSoTimeout();
+			} catch (IOException exc) {
+				exc.printStackTrace();
+				return -1;
+			}
+			else 
+				return timeout;
+	}
+	
+// ------------------------------
+	
+	/**
+	 * Generates a <code>String</code> with some information about the instance of
+	 * <code>IRCConnection</code>.
+	 * Its format is: <code>
+	 * classname[host,portMin,portMax,username,nick,realname,pass,connected]
+	 * </code>.
+	 * @return A <code>String</code> with information about the instance.
+	 */
+	public String toString() {
+		return getClass().getName() +"["+ host +","+ getPort() +","+ username +","+ 
+		nick +","+ realname +","+ pass +","+ isConnected() +"]";
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Removes away message. 
+	 */
+	public void doAway() {
+		send("AWAY");
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Sets away message. 
+	 * @param msg The away message.
+	 */
+	public void doAway(String msg) {
+		send("AWAY :"+ msg);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Invites a user to a channel. 
+	 * @param nick The nickname of the user who should be invited. 
+	 * @param chan The channel the user should be invited to.
+	 */
+	public void doInvite(String nick, String chan) {
+		send("INVITE "+ nick +" "+ chan);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Checks if one or more nicks are used on the server. 
+	 * @param nick The nickname of the user we search for.
+	 */
+	public void doIson(String nick) {
+		send("ISON "+ nick);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Joins a channel without a key. 
+	 * @param chan The channel which is to join.
+	 */
+	public void doJoin(String chan) {
+		send("JOIN "+ chan);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Joins a channel with a key. 
+	 * @param chan The channel which is to join.
+	 * @param key The key of the channel.
+	 */
+	public void doJoin(String chan, String key) {
+		send("JOIN "+ chan +" "+ key);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Kicks a user from a channel. 
+	 * @param chan The channel somebody should be kicked from. 
+	 * @param nick The nickname of the user who should be kicked. 
+	 */
+	public void doKick(String chan, String nick) {
+		send("KICK "+ chan +" "+ nick);
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Kicks a user from a channel with a comment. 
+	 * @param chan The channel somebody should be kicked from.
+	 * @param nick The nickname of the user who should be kicked.
+	 * @param msg The optional kickmessage.
+	 */
+	public void doKick(String chan, String nick, String msg) {
+		send("KICK "+ chan +" "+ nick +" :"+ msg);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Lists all channels with their topic and status. 
+	 */
+	public void doList() {
+		send("LIST");
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Lists channel(s) with their topic and status. 
+	 * @param chan The channel the <code>LIST</code> refers to.
+	 */
+	public void doList(String chan) {
+		send("LIST "+ chan);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Lists all visible users.
+	 */
+	public void doNames() {
+		send("NAMES");
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Lists all visible users of (a) channel(s). 
+	 * @param chan The channel the <code>NAMES</code> command is refering to.
+	 */
+	public void doNames(String chan) {
+		send("NAMES "+ chan);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Sends a message to a person or a channel. 
+	 * @param target The nickname or channel the message should be sent to.
+	 * @param msg The message which should be transmitted.
+	 */
+	public void doPrivmsg(String target, String msg) {
+		send("PRIVMSG "+ target +" :"+ msg);
+	} 
+	
+// ------------------------------
+	
+	/** 
+	 * Requests a Reply 324 for the modes of a given channel. 
+	 * @param chan The channel the <code>MODE</code> request is refering to.
+	 */
+	public void doMode(String chan) {
+		send("MODE "+ chan);
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Sends a mode to the server. <br />
+	 * The first argument is a nickname (user-mode) or a channel (channel-mode). 
+	 * <code>String mode</code> must contain the operators (+/-), the modes 
+	 * (o/v/i/k/l/p/s/w) and the possibly values (nicks/banmask/limit/key). 
+	 * @param target The nickname or channel of the user whose modes will be 
+	 *               changed.
+	 * @param mode The new modes.
+	 */
+	public void doMode(String target, String mode) {
+		send("MODE "+ target +" "+ mode);
+	} 
+	
+// ------------------------------
+	
+	/** 
+	 * Changes the nickname. 
+	 * @param nick The new nickname.
+	 */
+	public void doNick(String nick) {
+		send("NICK "+ nick);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Notices a message to a person or a channel. 
+	 * @param target The nickname or channel (group) the message should be 
+	 *               sent to.
+	 * @param msg The message which should be transmitted.
+	 */
+	public void doNotice(String target, String msg) {
+		send("NOTICE "+ target +" :"+ msg);
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Parts from a given channel. 
+	 * @param chan The channel you want to part from.
+	 */
+	public void doPart(String chan) {
+		send("PART "+ chan);
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Parts from a given channel with a given parg-msg. 
+	 * @param chan The channel you want to part from.
+	 * @param msg The optional partmessage.
+	 */
+	public void doPart(String chan, String msg) {
+		send("PART "+ chan +" :"+ msg);
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Quits from the IRC server with a quit-msg.
+	 * @param ping The ping which was received in <code>onPing</code>. It's a 
+	 *             <code>String</code>, because sometimes on some networks 
+	 *             the server-hostname (for example splatterworld.quakenet.org) is
+	 *             given as parameter which would throw an Exception if we 
+	 *             gave the ping as long.
+	 */
+	public void doPong(String ping) {
+		send("PONG :"+ ping);
+	} 
+	
+// ------------------------------
+	
+	/** 
+	 * Quits from the IRC server. 
+	 * Calls the <code>disconnect</code>-method which does the work actually. 
+	 * @see #isConnected() 
+	 * @see #connect()
+	 * @see #doQuit(String)
+	 * @see #close()
+	 */
+	public void doQuit() {
+		send("QUIT"); 
+	} 
+	
+// ------------------------------
+	
+	/** 
+	 * Quits from the IRC server with a quit-msg. 
+	 * Calls the <code>disconnect</code>-method which does the work actually. 
+	 * @param msg The optional quitmessage.
+	 * @see #isConnected() 
+	 * @see #connect()
+	 * @see #doQuit()
+	 * @see #close()
+	 */
+	public void doQuit(String msg) {
+		send("QUIT :"+ msg); 
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Requests the topic of a chan. The topic is given in a numeric reply. 
+	 * @param chan The channel which topic should be requested. 
+	 */
+	public void doTopic(String chan) {
+		send("TOPIC "+ chan);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Changes the topic of a chan. 
+	 * @param chan The channel which topic is changed. 
+	 * @param topic The new topic.
+	 */
+	public void doTopic(String chan, String topic) {
+		send("TOPIC "+ chan +" :"+ topic);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Requests information about users matching the given criteric, 
+	 * for example a channel they are on. 
+	 * @param criteric The criterics of the <code>WHO</code> query.
+	 */
+	public void doWho(String criteric) {
+		send("WHO "+ criteric);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Requires information about an existing user. 
+	 * @param nick The nickname of the user the query is refering to.
+	 */
+	public void doWhois(String nick) {
+		send("WHOIS "+ nick);
+	}  
+	
+// ------------------------------
+	
+	/** 
+	 * Requires host-information about a user, who is not connected anymore. 
+	 * @param nick The nickname of the user the query is refering to.
+	 */
+	public void doWhowas(String nick) {
+		send("WHOWAS "+ nick);
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Requires host-information about up to 5 users which must be listed and 
+	 * divided by spaces. 
+	 * @param nick The nickname of the user the query is refering to.
+	 */
+	public void doUserhost(String nick) {
+		send("USERHOST "+ nick);
+	}
+}

+ 1402 - 0
daemon/src/org/fox/ttirc/irclib/IRCConstants.java

@@ -0,0 +1,1402 @@
+package org.fox.ttirc.irclib;
+
+/**
+ * Contains constants: reply codes, error codes and mIRC color codes.
+ * @author Christoph Schwering &lt;[email protected]&gt;
+ * @since 1.10
+ * @version 1.00
+ * @see IRCEventListener#onError(int, String)
+ * @see IRCEventListener#onReply(int, String, String)
+ */
+public interface IRCConstants {
+	
+	/**
+	 * Usually the first replies when you're connected.
+	 */
+	public static final int RPL_WELCOME = 001;
+	
+	/**
+	 * Usually the first replies when you're connected.
+	 */
+	public static final int RPL_YOURHOST = 002;
+	
+	/**
+	 * Usually the first replies when you're connected.
+	 */
+	public static final int RPL_CREATED = 003;
+	
+	/**
+	 * Usually the first replies when you're connected.
+	 */
+	public static final int RPL_MYINFO = 004;
+	
+	/**
+	 * Usually the first replies when you're connected.
+	 */
+	public static final int RPL_ISUPPORT = 005;
+	
+	
+	/**
+	 * Used to indicate the nickname parameter supplied to 
+	 * a command is currently unused.
+	 */
+	public static final int ERR_NOSUCHNICK = 401;
+	
+	/**
+	 * Format: "&lt;server name&gt; No such server". <br />
+	 * Used to indicate the server name given currently
+	 * doesn't exist.
+	 */
+	public static final int ERR_NOSUCHSERVER = 402;
+	
+	/**
+	 * Format: "&lt;channel name&gt; No such channel". <br />
+	 * Used to indicate the given channel name is invalid.
+	 */
+	public static final int ERR_NOSUCHCHANNEL = 403;
+	
+	/**
+	 * Format: "&lt;channel name&gt; Cannot send to channel". <br />
+	 * Sent to a user who is either (a) not on a channel
+	 * which is mode +n or (b) not a chanop (or mode +v) on
+	 * a channel which has mode +m set and is trying to send
+	 * a PRIVMSG message to that channel.
+	 */
+	public static final int ERR_CANNOTSENDTOCHAN = 404;
+	
+	/**
+	 * Format: "&lt;channel name&gt; You have joined too many
+	 * channels". <br />
+	 * Sent to a user when they have joined the maximum
+	 * number of allowed channels and they try to join
+	 * another channel.
+	 */
+	public static final int ERR_TOOMANYCHANNELS = 405;
+	
+	/**
+	 * Format: "&lt;nickname&gt; There was no such nickname". <br />
+	 * Returned by WHOWAS to indicate there is no history
+	 * information for that nickname.
+	 */
+	public static final int ERR_WASNOSUCHNICK = 406;
+	
+	
+	/**
+	 * Format: "&lt;target&gt; Duplicate recipients. No message delivered". <br />
+	 * Returned to a client which is attempting to send a PRIVMSG/NOTICE using 
+	 * the [email protected] destination format and for a [email protected] which has several 
+	 * occurrences.
+	 */
+	public static final int ERR_TOOMANYTARGETS = 407;
+	
+	/**
+	 * Format: "No origin specified". <br />
+	 * PING or PONG message missing the originator parameter
+	 * which is required since these commands must work
+	 * without valid prefixes.
+	 */
+	public static final int ERR_NOORIGIN = 409;
+	
+	/**
+	 * Format: "No recipient given (&lt;command&gt;)".
+	 */
+	public static final int ERR_NORECIPIENT = 411;
+	
+	/**
+	 * Format: "No text to send". <br />
+	 * 412 - 414 are returned by PRIVMSG to indicate that
+	 * the message wasn't delivered for some reason.
+	 * ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+	 * are returned when an invalid use of
+	 * "PRIVMSG $&lt;server&gt;" or "PRIVMSG #&lt;host&gt;" is attempted.
+	 */
+	public static final int ERR_NOTEXTTOSEND = 412;
+	
+	/**
+	 * Format: "&lt;mask&gt; No toplevel domain specified". <br />
+	 * 412 - 414 are returned by PRIVMSG to indicate that
+	 * the message wasn't delivered for some reason.
+	 * ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+	 * are returned when an invalid use of
+	 * "PRIVMSG $&lt;server&gt;" or "PRIVMSG #&lt;host&gt;" is attempted.
+	 */
+	public static final int ERR_NOTOPLEVEL = 413;
+	
+	/**
+	 * Format: "&lt;mask&gt; Wildcard in toplevel domain". <br />
+	 * 412 - 414 are returned by PRIVMSG to indicate that
+	 * the message wasn't delivered for some reason.
+	 * ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
+	 * are returned when an invalid use of
+	 * "PRIVMSG $&lt;server&gt;" or "PRIVMSG #&lt;host&gt;" is attempted.
+	 */
+	public static final int ERR_WILDTOPLEVEL = 414;
+	
+	/**
+	 * Format: "&lt;command&gt; Unknown command". <br />
+	 * Returned to a registered client to indicate that the
+	 * command sent is unknown by the server.
+	 */
+	public static final int ERR_UNKNOWNCOMMAND = 421;
+	
+	/**
+	 * Format: "MOTD File is missing". <br />
+	 * Server's MOTD file could not be opened by the server.
+	 */
+	public static final int ERR_NOMOTD = 422;
+	
+	/**
+	 * Format: "&lt;server&gt; No administrative info available". <br />
+	 * Returned by a server in response to an ADMIN message
+	 * when there is an error in finding the appropriate
+	 * information.
+	 */
+	public static final int ERR_NOADMININFO = 423;
+	
+	/**
+	 * Format: "File error doing &lt;file op&gt; on &lt;file&gt;". <br />
+	 * Generic error message used to report a failed file
+	 * operation during the processing of a message.
+	 */
+	public static final int ERR_FILEERROR = 424;
+	
+	/**
+	 * Format: "No nickname given". <br />
+	 * Returned when a nickname parameter expected for a
+	 * command and isn't found.
+	 */
+	public static final int ERR_NONICKNAMEGIVEN = 431;
+	
+	/**
+	 * Format: "&lt;nick&gt; Erroneus nickname". <br />
+	 * Returned after receiving a NICK message which contains
+	 * characters which do not fall in the defined set.  See
+	 * section x.x.x for details on valid nicknames.
+	 */
+	public static final int ERR_ERRONEUSNICKNAME = 432;
+	
+	/**
+	 * Format: "&lt;nick&gt; Nickname is already in use". <br />
+	 * Returned when a NICK message is processed that results
+	 * in an attempt to change to a currently existing
+	 * nickname.
+	 */
+	public static final int ERR_NICKNAMEINUSE = 433;
+	
+	/**
+	 * Format: "&lt;nick&gt; Nickname collision KILL". <br />
+	 * Returned by a server to a client when it detects a
+	 * nickname collision (registered of a NICK that
+	 * already exists by another server).
+	 */
+	public static final int ERR_NICKCOLLISION = 436;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;channel&gt; They aren't on that channel". <br />
+	 * Returned by the server to indicate that the target
+	 * user of the command is not on the given channel.
+	 */
+	public static final int ERR_USERNOTINCHANNEL = 441;
+	
+	/**
+	 * Format: "&lt;channel&gt; You're not on that channel". <br />
+	 * Returned by the server whenever a client tries to
+	 * perform a channel effecting command for which the
+	 * client isn't a member.
+	 */
+	public static final int ERR_NOTONCHANNEL = 442;
+	
+	/**
+	 * Format: "&lt;user&gt; &lt;channel&gt; is already on channel". <br />
+	 * Returned when a client tries to invite a user to a
+	 * channel they are already on.
+	 */
+	public static final int ERR_USERONCHANNEL = 443;
+	
+	/**
+	 * Format: "&lt;user&gt; User not logged in". <br />
+	 * Returned by the summon after a SUMMON command for a
+	 * user was unable to be performed since they were not
+	 * logged in.
+	 */
+	public static final int ERR_NOLOGIN = 444;
+	
+	/**
+	 * Format: "SUMMON has been disabled". <br />
+	 * Returned as a response to the SUMMON command.  Must be
+	 * returned by any server which does not implement it.
+	 */
+	public static final int ERR_SUMMONDISABLED = 445;
+	
+	/**
+	 * Format: "USERS has been disabled". <br />
+	 * Returned as a response to the USERS command.  Must be
+	 * returned by any server which does not implement it.
+	 */
+	public static final int ERR_USERSDISABLED = 446;
+	
+	/**
+	 * Format: "You have not registered". <br /> 
+	 * Returned by the server to indicate that the client
+	 * must be registered before the server will allow it
+	 * to be parsed in detail.
+	 */
+	public static final int ERR_NOTREGISTERED = 451;
+	
+	/**
+	 * Format: "&lt;command&gt; Not enough parameters". <br />
+	 * Returned by the server by numerous commands to
+	 * indicate to the client that it didn't supply enough
+	 * parameters.
+	 */
+	public static final int ERR_NEEDMOREPARAMS = 461;
+	
+	/**
+	 * Format: "You may not reregister". <br />
+	 * Returned by the server to any link which tries to
+	 * change part of the registered details (such as
+	 * password or user details from second USER message).
+	 */
+	public static final int ERR_ALREADYREGISTRED = 462;
+	
+	/**
+	 * Format: "Your host isn't among the privileged". <br />
+	 * Returned to a client which attempts to register with
+	 * a server which does not been setup to allow
+	 * connections from the host the attempted connection
+	 * is tried.
+	 */
+	public static final int ERR_NOPERMFORHOST = 463;
+	
+	/**
+	 * Format: "Password incorrect". <br />
+	 * Returned to indicate a failed attempt at registering
+	 * a connection for which a password was required and
+	 * was either not given or incorrect.
+	 */
+	public static final int ERR_PASSWDMISMATCH = 464;
+	
+	/**
+	 * Format: "You are banned from this server". <br />
+	 * Returned after an attempt to connect and register
+	 * yourself with a server which has been setup to
+	 * explicitly deny connections to you.
+	 */
+	public static final int ERR_YOUREBANNEDCREEP = 465;
+	
+	/**
+	 * Format: "&lt;channel&gt; Channel key already set".
+	 */
+	public static final int ERR_KEYSET = 467;
+	
+	/**
+	 * Format:  "&lt;channel&gt; Cannot join channel (+l)".
+	 */
+	public static final int ERR_CHANNELISFULL = 471;
+	
+	/**
+	 * Format:  "&lt;char&gt; is unknown mode char to me".
+	 */
+	public static final int ERR_UNKNOWNMODE = 472;
+	
+	/**
+	 * Format: "&lt;channel&gt; Cannot join channel (+i)".
+	 */
+	public static final int ERR_INVITEONLYCHAN = 473;
+	
+	/**
+	 * Format:  "&lt;channel&gt; Cannot join channel (+b)".
+	 */
+	public static final int ERR_BANNEDFROMCHAN = 474;
+	
+	/**
+	 * Format:  "&lt;channel&gt; Cannot join channel (+k)".
+	 */
+	public static final int ERR_BADCHANNELKEY = 475;
+	
+	/**
+	 * Format:  "Permission Denied- You're not an IRC operator".
+	 * Any command requiring operator privileges to operate
+	 * must return this error to indicate the attempt was
+	 * unsuccessful.
+	 */
+	public static final int ERR_NOPRIVILEGES = 481;
+	
+	/**
+	 * Format: "&lt;channel&gt; You're not channel operator". <br />
+	 * Any command requiring 'chanop' privileges (such as
+	 * MODE messages) must return this error if the client
+	 * making the attempt is not a chanop on the specified
+	 * channel.
+	 */
+	public static final int ERR_CHANOPRIVSNEEDED = 482;
+	
+	/**
+	 * Format: "You cant kill a server!". <br />
+	 * Any attempts to use the KILL command on a server
+	 * are to be refused and this error returned directly
+	 * to the client.
+	 */
+	public static final int ERR_CANTKILLSERVER = 483;
+	
+	/**
+	 * Format: "No O-lines for your host". <br />
+	 * If a client sends an OPER message and the server has
+	 * not been configured to allow connections from the
+	 * client's host as an operator, this error must be
+	 * returned.
+	 */
+	public static final int ERR_NOOPERHOST = 491;
+	
+	/**
+	 * Format: "Unknown MODE flag". <br />
+	 * Returned by the server to indicate that a MODE
+	 * message was sent with a nickname parameter and that
+	 * the a mode flag sent was not recognized.
+	 */
+	public static final int ERR_UMODEUNKNOWNFLAG = 501;
+	
+	/**
+	 * Format: "Cant change mode for other users". <br />
+	 * Error sent to any user trying to view or change the
+	 * user mode for a user other than themselves.
+	 */
+	public static final int ERR_USERSDONTMATCH = 502;
+	
+	/**
+	 * Dummy reply number. Not used.
+	 */
+	public static final int RPL_NONE = 300;
+	
+	/**
+	 * Format: "[&lt;reply&gt;{&lt;space&gt;&lt;reply&gt;}]". <br />
+	 * Reply format used by USERHOST to list replies to
+	 * the query list.  The reply string is composed as
+	 * follows:<br />
+	 * &lt;reply&gt; ::= &lt;nick&gt;['*'] '=' &lt;'+'|'-'&gt;&lt;hostname&gt;
+	 * <br />
+	 * The '*' indicates whether the client has registered
+	 * as an Operator.  The '-' or '+' characters represent
+	 * whether the client has set an AWAY message or not
+	 * respectively.
+	 */
+	public static final int RPL_USERHOST = 302;
+	
+	/**
+	 * Format: "[&lt;nick&gt; {&lt;space&gt;&lt;nick&gt;}]". <br />
+	 * Reply format used by ISON to list replies to the
+	 * query list.
+	 */
+	public static final int RPL_ISON = 303;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;away message&gt;".
+	 */
+	public static final int RPL_AWAY = 301;
+	
+	/**
+	 * Format: "You are no longer marked as being away".
+	 */
+	public static final int RPL_UNAWAY = 305;
+	
+	/**
+	 * Format: "You have been marked as being away". <br />
+	 * These replies are used with the AWAY command (if
+	 * allowed).  RPL_AWAY is sent to any client sending a
+	 * PRIVMSG to a client which is away.  RPL_AWAY is only
+	 * sent by the server to which the client is connected.
+	 * Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
+	 * client removes and sets an AWAY message.
+	 */
+	public static final int RPL_NOWAWAY = 306;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;user&gt; &lt;host&gt; * :&lt;real name&gt;".
+	 * <br />
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	public static final int RPL_WHOISUSER = 311;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;server&gt; &lt;server info&gt;". <br />
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	public static final int RPL_WHOISSERVER = 312;
+	
+	/**
+	 * Format: "&lt;nick&gt; is an IRC operator". <br />
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	public static final int RPL_WHOISOPERATOR = 313;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;integer&gt; seconds idle". <br />
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	public static final int RPL_WHOISIDLE = 317;
+	
+	/**
+	 * Format: "&lt;nick&gt; End of /WHOIS list". <br />
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	public static final int RPL_ENDOFWHOIS = 318;
+	
+	/**
+	 * Format: "&lt;nick&gt; {[@|+]&lt;channel&gt;&lt;space&gt;}". <br />
+	 * Replies 311 - 313, 317 - 319 are all replies
+	 * generated in response to a WHOIS message.  Given that
+	 * there are enough parameters present, the answering
+	 * server must either formulate a reply out of the above
+	 * numerics (if the query nick is found) or return an
+	 * error reply.  The '*' in RPL_WHOISUSER is there as
+	 * the literal character and not as a wild card.  For
+	 * each reply set, only RPL_WHOISCHANNELS may appear
+	 * more than once (for long lists of channel names).
+	 * The '@' and '+' characters next to the channel name
+	 * indicate whether a client is a channel operator or
+	 * has been granted permission to speak on a moderated
+	 * channel.  The RPL_ENDOFWHOIS reply is used to mark
+	 * the end of processing a WHOIS message.
+	 */
+	public static final int RPL_WHOISCHANNELS = 319;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;user&gt; &lt;host&gt; * &lt;real name&gt;".
+	 */
+	public static final int RPL_WHOWASUSER = 314;
+	
+	/**
+	 * Format: "&lt;nick&gt; End of WHOWAS". <br />
+	 * When replying to a WHOWAS message, a server must use
+	 * the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
+	 * ERR_WASNOSUCHNICK for each nickname in the presented
+	 * list.  At the end of all reply batches, there must
+	 * be RPL_ENDOFWHOWAS (even if there was only one reply
+	 * and it was an error).
+	 */
+	public static final int RPL_ENDOFWHOWAS = 369;
+	
+	/**
+	 * Format: "Channel Users  Name". <br />
+	 * Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
+	 * the start, actual replies with data and end of the
+	 * server's response to a LIST command.  If there are
+	 * no channels available to return, only the start
+	 * and end reply must be sent.
+	 */
+	public static final int RPL_LISTSTART = 321;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;# visible&gt; &lt;topic&gt;". <br />
+	 * Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
+	 * the start, actual replies with data and end of the
+	 * server's response to a LIST command.  If there are
+	 * no channels available to return, only the start
+	 * and end reply must be sent.
+	 */
+	public static final int RPL_LIST = 322;
+	
+	/**
+	 * Format: "End of /LIST". <br />
+	 * Replies RPL_LISTSTART, RPL_LIST, RPL_LISTEND mark
+	 * the start, actual replies with data and end of the
+	 * server's response to a LIST command.  If there are
+	 * no channels available to return, only the start
+	 * and end reply must be sent.
+	 */
+	public static final int RPL_LISTEND = 323;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;mode&gt; &lt;mode params&gt;". <br />
+	 */
+	public static final int RPL_CHANNELMODEIS = 324;
+	
+	/**
+	 * Format: "&lt;nick&gt; &lt;authname&gt; is authed as"<br />
+	 * This is part of /WHOIS on many servers which provide bots to authenticate.
+	 */
+	public static final int RPL_AUTHNAME = 333;
+	
+	/**
+	 * Format: "&lt;channel&gt; No topic is set". <br />
+	 * When sending a TOPIC message to determine the
+	 * channel topic, one of two replies is sent.  If
+	 * the topic is set, RPL_TOPIC is sent back else
+	 * public static final int RPL_NOTOPIC.
+	 */
+	public static final int RPL_NOTOPIC = 331;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;topic&gt;". <br />
+	 * When sending a TOPIC message to determine the
+	 * channel topic, one of two replies is sent.  If
+	 * the topic is set, RPL_TOPIC is sent back else
+	 * public static final int RPL_NOTOPIC.
+	 */
+	public static final int RPL_TOPIC = 332;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;nick-who-set-topic&gt; &lt;seconds&gt;".
+	 * The seconds are not milliseconds; just multiply it with 1000 and then 
+	 * format a date with it.
+	 */
+	public static final int RPL_TOPICINFO = 333;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;nick&gt;". <br />
+	 * Returned by the server to indicate that the
+	 * attempted INVITE message was successful and is
+	 * being passed onto the end client.
+	 */
+	public static final int RPL_INVITING = 341;
+	
+	/**
+	 * Format: "&lt;user&gt; Summoning user to IRC". <br />
+	 * Returned by a server answering a SUMMON message to
+	 * indicate that it is summoning that user.
+	 */
+	public static final int RPL_SUMMONING = 342;
+	
+	/**
+	 * Format: "&lt;version&gt;.&lt;debuglevel&gt; &lt;server&gt; 
+	 * &lt;comments&gt;". <br />
+	 * Reply by the server showing its version details.
+	 * The &lt;version&gt; is the version of the software being
+	 * used (including any patchlevel revisions) and the
+	 * &lt;debuglevel&gt; is used to indicate if the server is
+	 * running in "debug mode". <br />
+	 * The "comments" field may contain any comments about
+	 * the version or further version details.
+	 */
+	public static final int RPL_VERSION = 351;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;user&gt; &lt;host&gt; &lt;server&gt; 
+	 * &lt;nick&gt; &lt;H|G&gt;[*][@|+] &lt;hopcount&gt; &lt;real name&gt;". <br />
+	 * The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+	 * to answer a WHO message.  The RPL_WHOREPLY is only
+	 * sent if there is an appropriate match to the WHO
+	 * query.  If there is a list of parameters supplied
+	 * with a WHO message, a RPL_ENDOFWHO must be sent
+	 * after processing each list item with &lt;name&gt; being
+	 * the item.
+	 */
+	public static final int RPL_WHOREPLY = 352;
+	
+	/**
+	 * Format: "&lt;name&gt; End of /WHO list". <br />
+	 * The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
+	 * to answer a WHO message.  The RPL_WHOREPLY is only
+	 * sent if there is an appropriate match to the WHO
+	 * query.  If there is a list of parameters supplied
+	 * with a WHO message, a RPL_ENDOFWHO must be sent
+	 * after processing each list item with &lt;name&gt; being
+	 * the item.
+	 */
+	public static final int RPL_ENDOFWHO = 315;
+	
+	/**
+	 * Format: "&lt;channel&gt; [[@|+]&lt;nick&gt; [[@|+]&lt;nick&gt; 
+	 * [...]]]". <br />
+	 * To reply to a NAMES message, a reply pair consisting
+	 * of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+	 * server back to the client.  If there is no channel
+	 * found as in the query, then only RPL_ENDOFNAMES is
+	 * returned.  The exception to this is when a NAMES
+	 * message is sent with no parameters and all visible
+	 * channels and contents are sent back in a series of
+	 * RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+	 * the end.
+	 */
+	public static final int RPL_NAMREPLY = 353;
+	
+	/**
+	 * Format: "&lt;channel&gt; End of /NAMES list". <br />
+	 * To reply to a NAMES message, a reply pair consisting
+	 * of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
+	 * server back to the client.  If there is no channel
+	 * found as in the query, then only RPL_ENDOFNAMES is
+	 * returned.  The exception to this is when a NAMES
+	 * message is sent with no parameters and all visible
+	 * channels and contents are sent back in a series of
+	 * RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
+	 * the end.
+	 */
+	public static final int RPL_ENDOFNAMES = 366;
+	
+	/**
+	 * Format: "&lt;mask&gt; &lt;server&gt; &lt;hopcount&gt; &lt;server info&gt;".
+	 * <br />
+	 * In replying to the LINKS message, a server must send
+	 * replies back using the RPL_LINKS numeric and mark the
+	 * end of the list using an RPL_ENDOFLINKS reply.
+	 */
+	public static final int RPL_LINKS = 364;
+	
+	/**
+	 * Format: "&lt;mask&gt; End of /LINKS list". <br />
+	 * In replying to the LINKS message, a server must send
+	 * replies back using the RPL_LINKS numeric and mark the
+	 * end of the list using an RPL_ENDOFLINKS reply.
+	 */
+	public static final int RPL_ENDOFLINKS = 365;
+	
+	/**
+	 * Format: "&lt;channel&gt; &lt;banid&gt;". <br />
+	 * When listing the active 'bans' for a given channel,
+	 * a server is required to send the list back using the
+	 * RPL_BANLIST and RPL_ENDOFBANLIST messages.  A separate
+	 * RPL_BANLIST is sent for each active banid.  After the
+	 * banids have been listed (or if none present) a
+	 * RPL_ENDOFBANLIST must be sent.
+	 */
+	public static final int RPL_BANLIST = 367;
+	
+	/**
+	 * Format: "&lt;channel&gt; End of channel ban list". <br />
+	 * When listing the active 'bans' for a given channel,
+	 * a server is required to send the list back using the
+	 * RPL_BANLIST and RPL_ENDOFBANLIST messages.  A separate
+	 * RPL_BANLIST is sent for each active banid.  After the
+	 * banids have been listed (or if none present) a
+	 * RPL_ENDOFBANLIST must be sent.
+	 */
+	public static final int RPL_ENDOFBANLIST = 368;
+	
+	/**
+	 * Format: "&lt;string&gt;". <br />
+	 * A server responding to an INFO message is required to
+	 * send all its 'info' in a series of RPL_INFO messages
+	 * with a RPL_ENDOFINFO reply to indicate the end of the
+	 * replies.
+	 */
+	public static final int RPL_INFO = 371;
+	
+	
+	/**
+	 * Format: "End of /INFO list". <br />
+	 * A server responding to an INFO message is required to
+	 * send all its 'info' in a series of RPL_INFO messages
+	 * with a RPL_ENDOFINFO reply to indicate the end of the
+	 * replies.
+	 */
+	public static final int RPL_ENDOFINFO = 374;
+	
+	/**
+	 * Format: "- &lt;server&gt; Message of the day - ". <br />
+	 * When responding to the MOTD message and the MOTD file
+	 * is found, the file is displayed line by line, with
+	 * each line no longer than 80 characters, using
+	 * RPL_MOTD format replies.  These should be surrounded
+	 * by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+	 * RPL_ENDOFMOTD (after).
+	 */
+	public static final int RPL_MOTDSTART = 375;
+	
+	/**
+	 * Format: "- &lt;text&gt;". <br />
+	 * When responding to the MOTD message and the MOTD file
+	 * is found, the file is displayed line by line, with
+	 * each line no longer than 80 characters, using
+	 * RPL_MOTD format replies.  These should be surrounded
+	 * by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+	 * RPL_ENDOFMOTD (after).
+	 */
+	public static final int RPL_MOTD = 372;
+	
+	/**
+	 * Format: "End of /MOTD command". <br />
+	 * When responding to the MOTD message and the MOTD file
+	 * is found, the file is displayed line by line, with
+	 * each line no longer than 80 characters, using
+	 * RPL_MOTD format replies.  These should be surrounded
+	 * by a RPL_MOTDSTART (before the RPL_MOTDs) and an
+	 * RPL_ENDOFMOTD (after).
+	 */
+	public static final int RPL_ENDOFMOTD = 376;
+	
+	/**
+	 * Format: "You are now an IRC operator". <br />
+	 * RPL_YOUREOPER is sent back to a client which has
+	 * just successfully issued an OPER message and gained
+	 * operator status.
+	 */
+	public static final int RPL_YOUREOPER = 381;
+	
+	/**
+	 * Format: "&lt;config file&gt; Rehashing". <br />
+	 * If the REHASH option is used and an operator sends
+	 * a REHASH message, an RPL_REHASHING is sent back to
+	 * the operator.
+	 */
+	public static final int RPL_REHASHING = 382;
+	
+	/**
+	 * Format: "&lt;server&gt; &lt;string showing server's local time&gt;". <br />
+	 * When replying to the TIME message, a server must send
+	 * the reply using the RPL_TIME format above.  The string
+	 * showing the time need only contain the correct day and
+	 * time there.  There is no further requirement for the
+	 * time string.
+	 */
+	public static final int RPL_TIME = 391;
+	
+	/**
+	 * Format: "UserID   Terminal  Host". <br />
+	 * If the USERS message is handled by a server, the
+	 * replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+	 * RPL_NOUSERS are used.  RPL_USERSSTART must be sent
+	 * first, following by either a sequence of RPL_USERS
+	 * or a single RPL_NOUSER.  Following this is
+	 * RPL_ENDOFUSERS.
+	 */
+	public static final int RPL_USERSSTART = 392;
+	
+	/**
+	 * Format: "%-8s %-9s %-8s". <br />
+	 * If the USERS message is handled by a server, the
+	 * replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+	 * RPL_NOUSERS are used.  RPL_USERSSTART must be sent
+	 * first, following by either a sequence of RPL_USERS
+	 * or a single RPL_NOUSER.  Following this is
+	 * RPL_ENDOFUSERS.
+	 */
+	public static final int RPL_USERS = 393;
+	
+	/**
+	 * Format: "End of users". <br />
+	 * If the USERS message is handled by a server, the
+	 * replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+	 * RPL_NOUSERS are used.  RPL_USERSSTART must be sent
+	 * first, following by either a sequence of RPL_USERS
+	 * or a single RPL_NOUSER.  Following this is
+	 * RPL_ENDOFUSERS.
+	 */
+	public static final int RPL_ENDOFUSERS = 394;
+	
+	/**
+	 * Format: "Nobody logged in". <br />
+	 * If the USERS message is handled by a server, the
+	 * replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
+	 * RPL_NOUSERS are used.  RPL_USERSSTART must be sent
+	 * first, following by either a sequence of RPL_USERS
+	 * or a single RPL_NOUSER.  Following this is
+	 * RPL_ENDOFUSERS.
+	 */
+	public static final int RPL_NOUSERS = 395;
+	
+	/**
+	 * Format: "Link &lt;version & debug level&gt; &lt;destination&gt; 
+	 * &lt;next server&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACELINK = 200;
+	
+	/**
+	 * Format: "Try. &lt;class&gt; &lt;server&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACECONNECTING = 201;
+	
+	/**
+	 * Format: "H.S. &lt;class&gt; &lt;server&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACEHANDSHAKE = 202;
+	
+	/**
+	 * Format: "???? &lt;class&gt; [&lt;client IP address in dot form&gt;]". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACEUNKNOWN = 203;
+	
+	/**
+	 * Format: "Oper &lt;class&gt; &lt;nick&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACEOPERATOR = 204;
+	
+	/**
+	 * Format: "User &lt;class&gt; &lt;nick&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACEUSER = 205;
+	
+	/**
+	 * Format: "Serv &lt;class&gt; &lt;int&gt;S &lt;int&gt;C &lt;server&gt;
+	 * &lt;nick!user|*!*&gt;@&lt;host|server&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACESERVER = 206;
+	
+	/**
+	 * Format: "&lt;newtype&gt; 0 &lt;client name&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACENEWTYPE = 208;
+	
+	/**
+	 * Format: "File &lt;logfile&gt; &lt;debug level&gt;". <br />
+	 * The RPL_TRACE* are all returned by the server in
+	 * response to the TRACE message.  How many are
+	 * returned is dependent on the the TRACE message and
+	 * whether it was sent by an operator or not.  There
+	 * is no predefined order for which occurs first.
+	 * Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
+	 * RPL_TRACEHANDSHAKE are all used for connections
+	 * which have not been fully established and are either
+	 * unknown, still attempting to connect or in the
+	 * process of completing the 'server handshake'.
+	 * RPL_TRACELINK is sent by any server which handles
+	 * a TRACE message and has to pass it on to another
+	 * server.  The list of RPL_TRACELINKs sent in
+	 * response to a TRACE command traversing the IRC
+	 * network should reflect the actual connectivity of
+	 * the servers themselves along that path.
+	 * RPL_TRACENEWTYPE is to be used for any connection
+	 * which does not fit in the other categories but is
+	 * being displayed anyway.
+	 */
+	public static final int RPL_TRACELOG = 261;
+	
+	/**
+	 * Format: "&lt;linkname&gt; &lt;sendq&gt; &lt;sent messages&gt; 
+	 * &lt;sent bytes&gt; &lt;received messages&gt; 
+	 * &lt;received bytes&gt; &lt;time open&gt;".
+	 */
+	public static final int RPL_STATSLINKINFO = 211;
+	
+	/**
+	 * Format: "&lt;command&gt; &lt;count&gt;".
+	 */
+	public static final int RPL_STATSCOMMANDS = 212;
+	
+	/**
+	 * Format: "C &lt;host&gt; * &lt;name&gt; &lt;port&gt; &lt;class&gt;".
+	 */
+	public static final int RPL_STATSCLINE = 213;
+	
+	/**
+	 * Format: "N &lt;host&gt; * &lt;name&gt; &lt;port&gt; &lt;class&gt;".
+	 */
+	public static final int RPL_STATSNLINE = 214;
+	
+	/**
+	 * Format: "I &lt;host&gt; * &lt;host&gt; &lt;port&gt; &lt;class&gt;".
+	 */
+	public static final int RPL_STATSILINE = 215;
+	
+	/**
+	 * Format: "K &lt;host&gt; * &lt;username&gt; &lt;port&gt; &lt;class&gt;".
+	 */
+	public static final int RPL_STATSKLINE = 216;
+	
+	/**
+	 * Format: "Y &lt;class&gt; &lt;ping frequency&gt; &lt;connect 
+	 * frequency&gt; &lt;max sendq&gt;".
+	 */
+	public static final int RPL_STATSYLINE = 218;
+	
+	/**
+	 * Format: "&lt;stats letter&gt; End of /STATS report".
+	 */
+	public static final int RPL_ENDOFSTATS = 219;
+	
+	/**
+	 * Format: "L &lt;hostmask&gt; * &lt;servername&gt; &lt;maxdepth&gt;".
+	 */
+	public static final int RPL_STATSLLINE = 241;
+	
+	/**
+	 * Format: "Server Up %d days %d:%02d:%02d".
+	 */
+	public static final int RPL_STATSUPTIME = 242;
+	
+	/**
+	 * Format: "O &lt;hostmask&gt; * &lt;name&gt;"
+	 */
+	public static final int RPL_STATSOLINE = 243;
+	
+	/**
+	 * Format: "H &lt;hostmask&gt; * &lt;servername&gt;".
+	 */
+	public static final int RPL_STATSHLINE = 244;
+	
+	/**
+	 * Format: "&lt;user mode string&gt;". <br />
+	 * To answer a query about a client's own mode,
+	 * RPL_UMODEIS is sent back.
+	 */
+	public static final int RPL_UMODEIS = 221;
+	
+	/**
+	 * Format:   "There are &lt;integer&gt; users and &lt;integer&gt; 
+	 * invisible on &lt;integer&gt; servers". <br />
+	 * In processing an LUSERS message, the server
+	 * sends a set of replies from RPL_LUSERCLIENT,
+	 * RPL_LUSEROP, RPL_USERUNKNOWN,
+	 * RPL_LUSERCHANNELS and RPL_LUSERME.  When
+	 * replying, a server must send back
+	 * RPL_LUSERCLIENT and RPL_LUSERME.  The other
+	 * replies are only sent back if a non-zero count
+	 * is found for them.
+	 */
+	public static final int RPL_LUSERCLIENT = 251;
+	
+	/**
+	 * Format: "&lt;integer&gt; operator(s) online". <br />
+	 * In processing an LUSERS message, the server
+	 * sends a set of replies from RPL_LUSERCLIENT,
+	 * RPL_LUSEROP, RPL_USERUNKNOWN,
+	 * RPL_LUSERCHANNELS and RPL_LUSERME.  When
+	 * replying, a server must send back
+	 * RPL_LUSERCLIENT and RPL_LUSERME.  The other
+	 * replies are only sent back if a non-zero count
+	 * is found for them.
+	 */
+	public static final int RPL_LUSEROP = 252;
+	
+	/**
+	 * Format: "&lt;integer&gt; unknown connection(s)". <br />
+	 * In processing an LUSERS message, the server
+	 * sends a set of replies from RPL_LUSERCLIENT,
+	 * RPL_LUSEROP, RPL_USERUNKNOWN,
+	 * RPL_LUSERCHANNELS and RPL_LUSERME.  When
+	 * replying, a server must send back
+	 * RPL_LUSERCLIENT and RPL_LUSERME.  The other
+	 * replies are only sent back if a non-zero count
+	 * is found for them.
+	 */
+	public static final int RPL_LUSERUNKNOWN = 253;
+	
+	/**
+	 * Format: "&lt;integer&gt; channels formed". <br />
+	 * In processing an LUSERS message, the server
+	 * sends a set of replies from RPL_LUSERCLIENT,
+	 * RPL_LUSEROP, RPL_USERUNKNOWN,
+	 * RPL_LUSERCHANNELS and RPL_LUSERME.  When
+	 * replying, a server must send back
+	 * RPL_LUSERCLIENT and RPL_LUSERME.  The other
+	 * replies are only sent back if a non-zero count
+	 * is found for them.
+	 */
+	public static final int RPL_LUSERCHANNELS = 254;
+	
+	/**
+	 * Format: "I have &lt;integer&gt; clients and &lt;integer&gt; 
+	 * servers". <br />
+	 * In processing an LUSERS message, the server
+	 * sends a set of replies from RPL_LUSERCLIENT,
+	 * RPL_LUSEROP, RPL_USERUNKNOWN,
+	 * RPL_LUSERCHANNELS and RPL_LUSERME.  When
+	 * replying, a server must send back
+	 * RPL_LUSERCLIENT and RPL_LUSERME.  The other
+	 * replies are only sent back if a non-zero count
+	 * is found for them.
+	 */
+	public static final int RPL_LUSERME = 255;
+	
+	/**
+	 * Format: "&lt;server&gt; Administrative info". <br />
+	 * When replying to an ADMIN message, a server
+	 * is expected to use replies RLP_ADMINME
+	 * through to RPL_ADMINEMAIL and provide a text
+	 * message with each.  For RPL_ADMINLOC1 a
+	 * description of what city, state and country
+	 * the server is in is expected, followed by
+	 * details of the university and department
+	 * (RPL_ADMINLOC2) and finally the administrative
+	 * contact for the server (an email address here
+	 * is required) in RPL_ADMINEMAIL.
+	 */
+	public static final int RPL_ADMINME = 256;
+	
+	/**
+	 * Format: "&lt;admin info&gt;". <br />
+	 * When replying to an ADMIN message, a server
+	 * is expected to use replies RLP_ADMINME
+	 * through to RPL_ADMINEMAIL and provide a text
+	 * message with each.  For RPL_ADMINLOC1 a
+	 * description of what city, state and country
+	 * the server is in is expected, followed by
+	 * details of the university and department
+	 * (RPL_ADMINLOC2) and finally the administrative
+	 * contact for the server (an email address here
+	 * is required) in RPL_ADMINEMAIL.
+	 */
+	public static final int RPL_ADMINLOC1 = 257;
+	
+	/**
+	 * Format: "&lt;admin info&gt;". <br />
+	 * When replying to an ADMIN message, a server
+	 * is expected to use replies RLP_ADMINME
+	 * through to RPL_ADMINEMAIL and provide a text
+	 * message with each.  For RPL_ADMINLOC1 a
+	 * description of what city, state and country
+	 * the server is in is expected, followed by
+	 * details of the university and department
+	 * (RPL_ADMINLOC2) and finally the administrative
+	 * contact for the server (an email address here
+	 * is required) in RPL_ADMINEMAIL.
+	 */
+	public static final int RPL_ADMINLOC2 = 258;
+	
+	/**
+	 * Format: "&lt;admin info&gt;". <br />
+	 * When replying to an ADMIN message, a server
+	 * is expected to use replies RLP_ADMINME
+	 * through to RPL_ADMINEMAIL and provide a text
+	 * message with each.  For RPL_ADMINLOC1 a
+	 * description of what city, state and country
+	 * the server is in is expected, followed by
+	 * details of the university and department
+	 * (RPL_ADMINLOC2) and finally the administrative
+	 * contact for the server (an email address here
+	 * is required) in RPL_ADMINEMAIL.
+	 */
+	public static final int RPL_ADMINEMAIL = 259;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_TRACECLASS = 209;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_STATSQLINE = 217;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_SERVICEINFO = 231;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_ENDOFSERVICES = 232;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_SERVICE = 233;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_SERVLIST = 234;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_SERVLISTEND = 235;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_WHOISCHANOP = 316;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_KILLDONE = 361;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_CLOSING = 362;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_CLOSEEND = 363;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_INFOSTART = 373;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int RPL_MYPORTIS = 384;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int ERR_YOUWILLBEBANNED = 466;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int ERR_BADCHANMASK = 476;
+	
+	/**
+	 * This numeric is no longer in use, reserved for future planned use or
+	 * anything else.
+	 */
+	public static final int ERR_NOSERVICEHOST = 492;
+	
+	/** 
+	 * This is part of the mIRC code and shows that a color-code starts / ends. 
+	 * Here it is as the ASCII decimal int 3. 
+	 */
+	public static final char COLOR_INDICATOR = 3; // ASCII code
+	
+	/** 
+	 * This is part of the mIRC code and shows that bold starts / ends.
+	 * Here it is as the ASCII decimal int 32. 
+	 */
+	public static final char BOLD_INDICATOR = 31; // ASCII code
+	
+	/**
+	 * This is part of the mIRC code and shows that bold starts / ends.
+	 * Here it is as the ASCII decimal int 2. 
+	 */ 
+	public static final char UNDERLINE_INDICATOR = 2; // ASCII code
+	
+	/**
+	 * This is part of the mIRC code and shows that bold, underline and colors 
+	 * end. 
+	 * Here it is as the ASCII decimal int 15. 
+	 */
+	public static final char COLOR_END_INDICATOR = 15; // ASCII code
+	
+	/**
+	 * This is part of the mIRC code and indicates that the client's colors are 
+	 * reversed (background -&gt; foreground and foreground -&gt; background).
+	 * Here it is as the ASCII decimal int 1. 
+	 */ 
+	public static final char COLOR_REVERSE_INDICATOR = 22; // ASCII code
+	
+	/**
+	 * This is part of the mIRC code and shows that a PRIVMSG is an ACTION 
+	 * (<code>/me</code>).
+	 * Here it is as the ASCII decimal int 22. 
+	 */ 
+	public static final char ACTION_INDICATOR = 1; // ASCII code
+}

+ 301 - 0
daemon/src/org/fox/ttirc/irclib/IRCEventAdapter.java

@@ -0,0 +1,301 @@
+/*
+ * IRClib -- A Java Internet Relay Chat library -- class IRCEventAdapter
+ * Copyright (C) 2002 - 2006 Christoph Schwering <[email protected]>
+ * 
+ * This library and the accompanying materials are made available under the
+ * terms of the
+ * 	- GNU Lesser General Public License,
+ * 	- Apache License, Version 2.0 and
+ * 	- Eclipse Public License v1.0.
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY.
+ */
+
+package org.fox.ttirc.irclib;
+
+/**
+ * Adapts the events of the <code>IRCEventListener</code> interface.
+ * <p>
+ * Supported events:
+ * <ul>
+ * <li>Connect</li>
+ * <li>Disconnect</li>
+ * <li>Error</li>
+ * <li>Invite</li>
+ * <li>Join</li>
+ * <li>Kick</li>
+ * <li>Private Message</li>
+ * <li>Mode (Chan)</li>
+ * <li>Mode (User)</li>
+ * <li>Nick</li>
+ * <li>Notice</li>
+ * <li>Numeric Reply</li>
+ * <li>Numeric Error</li>
+ * <li>Part</li>
+ * <li>Ping</li>
+ * <li>Quit</li>
+ * <li>Topic</li>
+ * </ul>
+ * <p>
+ * For other, unkown events there's the <code>unknown</code>-method.
+ * @author Christoph Schwering &lt;[email protected]&gt;
+ * @version 1.63
+ * @see IRCEventListener
+ */
+public class IRCEventAdapter implements IRCEventListener {
+	
+	/** 
+	 * The default and only constructor does nothing. 
+	 */
+	public IRCEventAdapter() {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when the own connection is successfully established. 
+	 * This is the case when the first PING? is received. <br />
+	 * This happens between the connection is opened with a socket and the 
+	 * connection is registered: The client sends his information to the server 
+	 * (nickname, username). The server says hello to you by sending you 
+	 * some <code>NOTICE</code>s. And if your nickname is invalid or in use or 
+	 * anything else is wrong with your nickname, it asks you for a new one.
+	 */
+	public void onRegistered() {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when the own connection is broken.
+	 */
+	public void onDisconnected() {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when an <code>ERROR</code> command is received.
+	 * @param msg The message of the error.
+	 */
+	public void onError(String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when a numeric error is received.
+	 * The server often sends numeric errors (wrong nickname etc.). 
+	 * The <code>msg</code>'s format is different for every reply. All replies'
+	 * formats are described in the {@link IRCUtil}.
+	 * @param num The identifier (usually a 3-digit number).
+	 * @param msg The message of the error.
+	 */
+	public void onError(int num, String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody is invited to a channel.
+	 * @param chan The channel the user is invited to.
+	 * @param user The user who invites another. Contains nick, username and host.
+	 * @param passiveNick The nickname of the user who is invited by another user 
+	 *                    (passive).
+	 */
+	public void onInvite(String chan, IRCUser user, String passiveNick) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody joins a channel.
+	 * @param chan The channel the person joins.
+	 * @param user The user who joins. Contains nick, username and host.
+	 */
+	public void onJoin(String chan, IRCUser user) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody is kicked from a channel.
+	 * @param chan The channel somebody is kicked from.
+	 * @param user The user who kicks another user from a channel. 
+	 *             Contains nick, username and host.
+	 * @param passiveNick The nickname of the user who is kicked from a channel 
+	 *                    (passive).
+	 * @param msg The message the active user has set. This is <code>""</code> if 
+	 *            no message was set.
+	 */
+	public void onKick(String chan, IRCUser user, String passiveNick, 
+			String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when an operator changes the modes of a channel. 
+	 * For example, he can set somebody as an operator, too, or take him the 
+	 * oper-status. 
+	 * Also keys, moderated and other channelmodes are fired here.
+	 * @param chan The channel in which the modes are changed. 
+	 * @param user The user who changes the modes. 
+	 *             Contains nick, username and host.
+	 * @param modeParser The <code>IRCModeParser</code> object which contains the 
+	 *                   parsed information about the modes which are changed. 
+	 */
+	public void onMode(String chan, IRCUser user, IRCModeParser modeParser) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody changes somebody's usermodes. 
+	 * Note that this event is not fired when a channel-mode is set, for example
+	 * when someone sets another user as operator or the mode moderated.
+	 * @param user The user who changes the modes of another user or himself. 
+	 *             Contains nick, username and host.
+	 * @param passiveNick The nickname of the person whose modes are changed by 
+	 *                    another user or himself. 
+	 * @param mode The changed modes which are set.
+	 */
+	public void onMode(IRCUser user, String passiveNick, String mode) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody changes his nickname successfully.
+	 * @param user The user who changes his nickname. 
+	 *             Contains nick, username and host.
+	 * @param newNick The new nickname of the user who changes his nickname.
+	 */
+	public void onNick(IRCUser user, String newNick) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody sends a <code>NOTICE</code> to a user or a group. 
+	 * @param target The channel or nickname the user sent a <code>NOTICE</code> 
+	 *               to.
+	 * @param user The user who notices another person or a group. 
+	 *             Contains nick, username and host.
+	 * @param msg The message.
+	 */
+	public void onNotice(String target, IRCUser user, String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody parts from a channel.
+	 * @param chan The channel somebody parts from.
+	 * @param user The user who parts from a channel. 
+	 *             Contains nick, username and host.
+	 * @param msg The part-message which is optionally. 
+	 *            If it's empty, msg is <code>""</code>.
+	 */
+	public void onPart(String chan, IRCUser user, String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when a <code>PING</code> comes in. 
+	 * The IRC server tests in different periods if the client is still there by 
+	 * sending PING &lt;ping&gt;. The client must response PONG &lt;ping&gt;.
+	 * @param ping The ping which is received from the server.
+	 */
+	public void onPing(String ping) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when a user sends a <code>PRIVMSG</code> to a user or to a
+	 * group.
+	 * @param target The channel or nickname the user sent a <code>PRIVMSG</code> 
+	 *               to.
+	 * @param user The user who sent the <code>PRIVMSG</code>. 
+	 *             Contains nick, username and host.
+	 * @param msg The message the user transmits.
+	 */
+	public void onPrivmsg(String target, IRCUser user, String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when somebody quits from the network.
+	 * @param user The user who quits. Contains nick, username and host.
+	 * @param msg The optional message. <code>""</code> if no message is set by 
+	 *            the user.
+	 */
+	public void onQuit(IRCUser user, String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when a numeric reply is received. 
+	 * For example, <code>WHOIS</code> queries are answered by the server with 
+	 * numeric replies. 
+	 * The <code>msg</code>'s format is different for every reply. All replies'
+	 * formats are described in the {@link IRCUtil}.
+	 * The first word in the <code>value</code> is always your own nickname! 
+	 * @param num The numeric reply. 
+	 * @param value The first part of the message.
+	 * @param msg The main part of the message.
+	 */
+	public void onReply(int num, String value, String msg) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * Fired when the topic is changed by operators. 
+	 * Note that the topic is given as a numeric reply fired in 
+	 * <code>onReply</code> when you join a channel.
+	 * @param chan The channel where the topic is changed. 
+	 * @param user The user who changes the topic. 
+	 *             Contains nick, username and host.
+	 * @param topic The new topic.
+	 */
+	public void onTopic(String chan, IRCUser user, String topic) {
+		// nothing
+	}
+	
+// ------------------------------
+	
+	/** 
+	 * This event is fired when the incoming line can not be identified as a known
+	 * event.
+	 * @param prefix The prefix of the incoming line.
+	 * @param command The command of the incoming line.
+	 * @param middle The part until the colon (<code>:</code>).
+	 * @param trailing The part behind the colon (<code>:</code>).
+	 */
+	public void unknown(String prefix, String command, String middle,
+			String trailing) {
+		// nothing
+	}
+}

+ 264 - 0
daemon/src/org/fox/ttirc/irclib/IRCEventListener.java

@@ -0,0 +1,264 @@
+/*
+ * IRClib -- A Java Internet Relay Chat library -- class IRCEventListener
+ * Copyright (C) 2002 - 2006 Christoph Schwering <[email protected]>
+ * 
+ * This library and the accompanying materials are made available under the
+ * terms of the
+ * 	- GNU Lesser General Public License,
+ * 	- Apache License, Version 2.0 and
+ * 	- Eclipse Public License v1.0.
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY.
+ */
+
+package org.fox.ttirc.irclib;
+
+import java.util.EventListener;
+
+/**
+ * Used as listener for incoming events like messages.
+ * <p>
+ * The <code>IRCEventListener</code> is used by the 
+ * <code>IRCConnection.addEventListener(IRCEventListener)</code> method to add
+ * a listener which listens to the connection for incoming IRC events like 
+ * <code>PRIVMSG<