Advertisement
Guest User

Untitled

a guest
Sep 22nd, 2017
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 36.33 KB | None | 0 0
  1. /*
  2.  * IRClib -- A Java Internet Relay Chat library -- class IRCConnection
  3.  * Copyright (C) 2002 - 2006 Christoph Schwering <schwering@gmail.com>
  4.  *
  5.  * This library and the accompanying materials are made available under the
  6.  * terms of the
  7.  *  - GNU Lesser General Public License,
  8.  *  - Apache License, Version 2.0 and
  9.  *  - Eclipse Public License v1.0.
  10.  * This library is distributed in the hope that it will be useful, but WITHOUT
  11.  * ANY WARRANTY.
  12.  */
  13.  
  14. package org.schwering.irc.lib;
  15.  
  16. import java.io.BufferedReader;
  17. import java.io.IOException;
  18. import java.io.InputStreamReader;
  19. import java.io.OutputStreamWriter;
  20. import java.io.PrintWriter;
  21. import java.net.Socket;
  22. import java.net.SocketException;
  23.  
  24. /**
  25.  * Creates a new connection to an IRC server. It's the main class of the
  26.  * IRClib, the point everything starts.
  27.  * <p>
  28.  * The following sample code tries to establish an IRC connection to an
  29.  * IRC server:
  30.  * <p>
  31.  * <hr /><pre>
  32.  * /&#42;
  33.  *  &#42; The following code of a class which imports org.schwering.irc.lib.*
  34.  *  &#42; prepares an IRC connection and then tries to establish the connection.
  35.  *  &#42; The server is "irc.somenetwork.com", the default portrange (6667 and
  36.  *  &#42; 6669) is set, no password is used (null). The nickname is "Foo" and
  37.  *  &#42; the realname is "Mr. Foobar". The username "foobar".
  38.  *  &#42; Because of setDaemon(true), the JVM exits even if this thread is
  39.  *  &#42; running.
  40.  *  &#42; An instance of the class MyListener which must implement
  41.  *  &#42; IRCActionListener is added as only event-listener for the connection.
  42.  *  &#42; The connection is told to parse out mIRC color codes and to enable
  43.  *  &#42; automatic PING? PONG! replies.
  44.  *  &#42;/
  45.  * IRCConnection conn = new IRCConnection(
  46.  *                            "irc.somenetwork.com",
  47.  *                            6667,
  48.  *                            6669,
  49.  *                            null,
  50.  *                            "Foo",
  51.  *                            "Mr. Foobar",
  52.  *                            "foo@bar.com"
  53.  *                          );
  54.  *
  55.  * conn.addIRCEventListener(new MyListener());
  56.  * conn.setDaemon(true);
  57.  * conn.setColors(false);
  58.  * conn.setPong(true);
  59.  *
  60.  * try {
  61.  *   conn.connect(); // Try to connect!!! Don't forget this!!!
  62.  * } catch (IOException ioexc) {
  63.  *   ioexc.printStackTrace();
  64.  * }
  65.  * </pre><hr />
  66.  * <p>
  67.  * The serverpassword isn't needed in most cases. You can give
  68.  * <code>null</code> or <code>""</code> instead as done in this example.
  69.  * @author Christoph Schwering <schwering@gmail.com>
  70.  * @version 3.05
  71.  * @see IRCEventListener
  72.  * @see IRCParser
  73.  * @see IRCUtil
  74.  * @see SSLIRCConnection
  75.  */
  76. public class IRCConnection implements Runnable {
  77.        
  78.  
  79.     /**
  80.      * Records data usage for in and out of IRCConnection.
  81.      */
  82.     private long data_in = 0;
  83.     private long data_out = 0;
  84.     private Thread thread;
  85.    
  86.     /**
  87.      * This <code>Socket</code> is a connection to the IRC server.
  88.      */
  89.     private Socket socket;
  90.    
  91.     /**
  92.      * This is like a UNIX-runlevel. Its value indicates the level of the
  93.      * <code>IRCConnection</code> object. <code>0</code> means that the object
  94.      * has not yet been connected, <code>1</code> means that it's connected but
  95.      * not registered, <code>2</code> means that it's connected and registered
  96.      * but still waiting to receive the nickname the first time, <code>3</code>
  97.      * means that it's connected and registered, and <code>-1</code> means that
  98.      * it was connected but is disconnected.
  99.      * Therefore the defaultvalue is <code>0</code>.
  100.      */
  101.     protected byte level = 0;
  102.    
  103.     /**
  104.      * The host of the IRC server.
  105.      */
  106.     protected String host;
  107.    
  108.     /**
  109.      * The <code>int[]</code> contains all ports to which we are going to try to
  110.      * connect. This can be a portrange from port 6667 to 6669, for example.
  111.      */
  112.     protected int[] ports;
  113.    
  114.     /**
  115.      * The <code>BufferedReader</code> receives Strings from the IRC server.
  116.      */
  117.     private volatile BufferedReader in;
  118.    
  119.     /**
  120.      * The <code>PrintWriter</code> sends Strings to the IRC server.
  121.      */
  122.     private PrintWriter out;
  123.    
  124.     /**
  125.      * The <code>String</code> contains the name of the character encoding used
  126.      * to talk to the server. This can be ISO-8859-1 or UTF-8 for example. The
  127.      * default is ISO-8859-1.
  128.      */
  129.     protected String encoding = "ISO-8859-1";
  130.    
  131.     /**
  132.      * This array contains <code>IRCEventListener</code> objects.
  133.      */
  134.     private IRCEventListener[] listeners = new IRCEventListener[0];
  135.    
  136.     /**
  137.      * This <code>int</code> is the connection's timeout in milliseconds. It's
  138.      * used in the <code>Socket.setSoTimeout</code> method. The default is
  139.      * <code>1000 * 60 * 15</code> millis which are 15 minutes.
  140.      */
  141.     private int timeout = 1000 * 60 * 15;
  142.    
  143.     /**
  144.      * This <code>boolean</code> stands for enabled (<code>true</code>) or
  145.      * disabled (<code>false</code>) ColorCodes.<br />Default is enabled
  146.      * (<code>false</code>).
  147.      */
  148.     private boolean colorsEnabled = false;
  149.    
  150.     /**
  151.      * This <code>boolean</code> stands for enabled or disabled automatic PING?
  152.      * PONG! support. <br />It means, that if the server asks with PING for the
  153.      * ping, the PONG is automatically sent. Default is automatic PONG enabled
  154.      * (<code>true</code>).
  155.      */
  156.     private boolean pongAutomatic = true;
  157.    
  158.     /**
  159.      * The password, which is needed to get access to the IRC server.
  160.      */
  161.     private String pass;
  162.    
  163.     /**
  164.      * The user's nickname, which is indispensably to connect.
  165.      */
  166.     private String nick;
  167.    
  168.     /**
  169.      * The user's realname, which is indispensably to connect.
  170.      */
  171.     private String realname;
  172.    
  173.     /**
  174.      * The user's username, which is indispensable to connect.
  175.      */
  176.     private String username;
  177.    
  178. // ------------------------------
  179.    
  180.     /**
  181.      * Creates a new IRC connection. <br />
  182.      * The difference to the other constructor is, that it transmits the ports in
  183.      * an <code>int[]</code>. Thus, also ports like 1024, 2048, 6667 and
  184.      * 6669 can be selected.<br /><br />
  185.      * The constructor prepares a new IRC connection which can be really started
  186.      * by invoking the <code>connect</code> method. Before invoking it, you should
  187.      * set the <code>IRCEventListener</code> and other settings.<br />
  188.      * Note that you do not need to set a password to connect to the large public
  189.      * IRC networks like QuakeNet, EFNet etc. To use no password in your IRC
  190.      * connection, use <code>""</code> or <code>null</code> for the password
  191.      * argument in the constructor.
  192.      * @param host The hostname of the server we want to connect to.
  193.      * @param ports The portrange to which we want to connect.
  194.      * @param pass The password of the IRC server. If your server isn't
  195.      *             secured by a password (that's normal), use
  196.      *             <code>null</code> or <code>""</code>.
  197.      * @param nick The nickname for the connection. Is used to register the
  198.      *             connection.
  199.      * @param username The username. Is used to register the connection.
  200.      * @param realname The realname. Is used to register the connection.
  201.      * @throws IllegalArgumentException If the <code>host</code> or
  202.      *                                  <code>ports</code> is <code>null</code> or
  203.      *                                  <code>ports</code>' length is
  204.      *                                  <code>0</code>.
  205.      * @see #connect()
  206.      */
  207.     public IRCConnection(String host, int[] ports, String pass, String nick,
  208.             String username, String realname) {
  209.         if (host == null || ports == null || ports.length == 0)
  210.             throw new IllegalArgumentException("Host and ports may not be null.");
  211.         this.host = host;
  212.         this.ports = ports;
  213.         this.pass = (pass != null && pass.length() == 0) ? null : pass;
  214.         this.nick = nick;
  215.         this.username = username;
  216.         this.realname = realname;
  217.     }
  218.    
  219. // ------------------------------
  220.    
  221.     /**
  222.      * Creates a new IRC connection. <br />
  223.      * The difference to the other constructor is, that it transmits the ports as
  224.      * two <code>int</code>s. Thus, only a portrange from port <code>x</code> to
  225.      * port <code>y</code> like from port 6667 to 6669 can be selected.<br />
  226.      * <br />
  227.      * The constructor prepares a new IRC connection which can be really started
  228.      * by invoking the <code>connect</code> method. Before invoking it, you should
  229.      * set the <code>IRCEventListener</code> and other settings.<br />
  230.      * Note that you do not need to set a password to connect to the large public
  231.      * IRC networks like QuakeNet, EFNet etc. To use no password in your IRC
  232.      * connection, use <code>""</code> or <code>null</code> for the password
  233.      * argument in the constructor.
  234.      * @param host The hostname of the server we want to connect to.
  235.      * @param portMin The beginning of the port range we are going to connect
  236.      *                to.
  237.      * @param portMax The ending of the port range we are going to connect to.
  238.      * @param pass The password of the IRC server. If your server isn't
  239.      *             secured by a password (that's normal), use
  240.      *             <code>null</code> or <code>""</code>.
  241.      * @param nick The nickname for the connection. Is used to register the
  242.      *             connection.
  243.      * @param username The username. Is used to register the connection.
  244.      * @param realname The realname. Is used to register the connection.
  245.      * @throws IllegalArgumentException If the <code>host</code> is
  246.      *                                  <code>null</code>.
  247.      * @see #connect()
  248.      */
  249.     public IRCConnection(String host, int portMin, int portMax, String pass,
  250.             String nick, String username, String realname) {
  251.         this(host, portRangeToArray(portMin, portMax), pass, nick, username,
  252.                 realname);
  253.     }
  254.    
  255. // ------------------------------
  256.    
  257.     /**
  258.      * Converts a portrange which starts with a given <code>int</code> and ends
  259.      * with a given <code>int</code> into an array which contains all
  260.      * <code>int</code>s from the beginning to the ending (including beginning
  261.      * and ending).<br />
  262.      * If <code>portMin > portMax</code>, the portrange is turned arount
  263.      * automatically.
  264.      * @param portMin The beginning port of the portrange.
  265.      * @param portMax The ending port of the portrange.
  266.      */
  267.     private static int[] portRangeToArray(int portMin, int portMax) {
  268.         if (portMin > portMax) {
  269.             int tmp = portMin;
  270.             portMin = portMax;
  271.             portMax = tmp;
  272.         }
  273.         int[] ports = new int[portMax - portMin + 1];
  274.         for (int i = 0; i < ports.length; i++)
  275.             ports[i] = portMin + i;
  276.         return ports;
  277.     }
  278.    
  279. // ------------------------------
  280.    
  281.     /**
  282.      * Establish a connection to the server. <br />
  283.      * This method must be invoked to start a connection; the constructor doesn't
  284.      * do that!<br />
  285.      * It tries all set ports until one is open. If all ports fail it throws an
  286.      * <code>IOException</code>.<br />
  287.      * You can invoke <code>connect</code> only one time.
  288.      * @throws IOException If an I/O error occurs.
  289.      * @throws SocketException If the <code>connect</code> method was already
  290.      *                         invoked.
  291.      * @see #isConnected()
  292.      * @see #doQuit()
  293.      * @see #doQuit(String)
  294.      * @see #close()
  295.      */
  296.     public void connect() throws IOException {
  297.         if (level != 0) // otherwise disconnected or connect
  298.             throw new SocketException("Socket closed or already open ("+ level +")");
  299.         IOException exception = null;
  300.         Socket s = null;
  301.         for (int i = 0; i < ports.length && s == null; i++) {
  302.             try {
  303.                 s = new Socket(host, ports[i]);
  304.                 exception = null;
  305.             } catch (IOException exc) {
  306.                 if (s != null)
  307.                     s.close();
  308.                 s = null;
  309.                 exception = exc;
  310.             }
  311.         }
  312.         if (exception != null)
  313.             throw exception; // connection wasn't successful at any port
  314.        
  315.         prepare(s);
  316.     }
  317.    
  318. // ------------------------------
  319.    
  320.     /**
  321.      * Invoked by the <code>connect</code> method, this method prepares the
  322.      * connection. <br />
  323.      * It initializes the class-vars for the inputstream and the outputstream of
  324.      * the socket, starts the registration of at the IRC server by calling
  325.      * <code>register()</code> and starts the receiving of lines from the server
  326.      * by starting the thread with the <code>start</code> method.<br /><br />
  327.      * This method must be protected, because it is used by extending classes,
  328.      * which override the <code>connect</code> method.
  329.      * @param s The socket which is used for the connection.
  330.      * @throws IOException If an I/O error occurs.
  331.      * @see #connect()
  332.      * @see #run()
  333.      */
  334.     protected void prepare(Socket s) throws IOException {
  335.         if (s == null)
  336.             throw new SocketException("Socket s is null, not connected");
  337.         socket = s;
  338.         level = 1;
  339.         s.setSoTimeout(timeout);
  340.         in  = new BufferedReader(new InputStreamReader(s.getInputStream(),
  341.                 encoding));
  342.         out = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),
  343.                 encoding));
  344.         thread = new Thread(this);
  345.         thread.start();
  346.         register();
  347.     }
  348.    
  349. // ------------------------------
  350.    
  351.     /**
  352.      * Registers the connection with the IRC server. <br />
  353.      * In fact, it sends a password (if set, else nothing), the nickname and the
  354.      * user, the realname and the host which we're connecting to.<br />
  355.      * The action synchronizes <code>code> so that no important messages
  356.      * (like the first PING) come in before this registration is finished.<br />
  357.      * The <code>USER</code> command's format is:<br /><code>
  358.      * <username> <localhost> <irchost> <realname>
  359.      * </code>
  360.      */
  361.     private void register() {
  362.         if (pass != null)
  363.             send("PASS "+ pass);
  364.         send("NICK "+ nick);
  365.         send("USER "+ username +" "+ host
  366.                 +" bla :"+ realname);
  367.     }
  368.    
  369. // ------------------------------
  370.    
  371.     /**
  372.      * The <code>Thread</code> is started by the <code>connect</code> method.
  373.      * It's task is to receive strings from the IRC server and hand them over
  374.      * to the <code>get</code> method.
  375.      */
  376.     public void run() {
  377.         try {
  378.             String line;
  379.             while (!thread.isInterrupted()) {
  380.                 line = in.readLine();
  381.                 if (line != null) {
  382.                     data_in += (line).getBytes("ISO-8859-1").length;
  383.                     get(line); }
  384.                 else {
  385.                     close(); }
  386.             }
  387.         } catch (IOException exc) {
  388.             close();
  389.         }
  390.     }
  391.    
  392. // ------------------------------
  393.    
  394.     /**
  395.      * Sends a String to the server.
  396.      * You should use this method only, if you must do it. For most purposes,
  397.      * there are <code>do*</code> methods (like <code>doJoin</code>). A carriage
  398.      * return line feed (<code>\r\n</code>) is appended automatically.
  399.      * @param line The line which should be send to the server without the
  400.      *             trailing carriage return line feed (<code>\r\n</code>).
  401.      */
  402.     public void send(String line) {
  403.         try {
  404.             out.write(line +"\r\n");
  405.             data_out += (line+"\r\n").getBytes("ISO-8859-1").length;
  406.             out.flush();
  407.             if (level == 1) { // not registered
  408.                 IRCParser p = new IRCParser(line);
  409.                 if (p.getCommand().equalsIgnoreCase("NICK"))
  410.                     nick = p.getParameter(1).trim();
  411.             }
  412.         } catch (Exception exc) {
  413.             exc.printStackTrace();
  414.         }
  415.     }
  416.    
  417. // ------------------------------
  418.    
  419.     /**
  420.      * Just parses a String given as the only argument with the help of the
  421.      * <code>IRCParser</code> class. Then it controls the command and fires events
  422.      * through the <code>IRCEventListener</code>.<br />
  423.      * @param line The line which is sent from the server.
  424.      */
  425.     private synchronized void get(String line) {
  426.         IRCParser p;
  427.         try {
  428.             p = new IRCParser(line, colorsEnabled);
  429.         } catch (Exception exc) {
  430.             return;
  431.         }
  432.         String command = p.getCommand();
  433.         int reply; // 3-digit reply will be parsed in the later if-condition
  434.        
  435.         if (command.equalsIgnoreCase("PRIVMSG")) { // MESSAGE
  436.            
  437.             IRCUser user = p.getUser();
  438.             String middle = p.getMiddle();
  439.             String trailing = p.getTrailing();
  440.             for (int i = 0; i < listeners.length; i++)
  441.                 listeners[i].onPrivmsg(middle, user, trailing);
  442.            
  443.         } else if (command.equalsIgnoreCase("MODE")) { // MODE
  444.            
  445.             String chan = p.getParameter(1);
  446.             if (IRCUtil.isChan(chan)) {
  447.                 IRCUser user = p.getUser();
  448.                 String param2 = p.getParameter(2);
  449.                 String paramsFrom3 = p.getParametersFrom(3);
  450.                 for (int i = 0; i < listeners.length; i++)
  451.                     listeners[i].onMode(chan, user,
  452.                             new IRCModeParser(param2, paramsFrom3));
  453.             } else {
  454.                 IRCUser user = p.getUser();
  455.                 String paramsFrom2 = p.getParametersFrom(2);
  456.                 for (int i = 0; i < listeners.length; i++)
  457.                     listeners[i].onMode(user, chan, paramsFrom2);
  458.             }
  459.            
  460.         } else if (command.equalsIgnoreCase("PING")) { // PING
  461.            
  462.             String ping = p.getTrailing(); // no int cause sometimes it's text
  463.             if (pongAutomatic)
  464.                 doPong(ping);
  465.             else
  466.                 for (int i = 0; i < listeners.length; i++)
  467.                     listeners[i].onPing(ping);
  468.            
  469.             if (level == 1) { // not registered
  470.                 level = 2; // first PING received -> connection
  471.                 for (int i = 0; i < listeners.length; i++)
  472.                     listeners[i].onRegistered();
  473.             }
  474.            
  475.         } else if (command.equalsIgnoreCase("JOIN")) { // JOIN
  476.            
  477.             IRCUser user = p.getUser();
  478.             String trailing = p.getTrailing();
  479.             for (int i = 0; i < listeners.length; i++)
  480.                 listeners[i].onJoin(trailing, user);
  481.            
  482.         } else if (command.equalsIgnoreCase("NICK")) { // NICK
  483.            
  484.             IRCUser user = p.getUser();
  485.             String changingNick = p.getNick();
  486.             String newNick = p.getTrailing();
  487.             if (changingNick.equalsIgnoreCase(nick))
  488.                 nick = newNick;
  489.             for (int i = 0; i < listeners.length; i++)
  490.                 listeners[i].onNick(user, newNick);
  491.            
  492.         } else if (command.equalsIgnoreCase("QUIT")) { // QUIT
  493.            
  494.             IRCUser user = p.getUser();
  495.             String trailing = p.getTrailing();
  496.             for (int i = 0; i < listeners.length; i++)
  497.                 listeners[i].onQuit(user, trailing);
  498.            
  499.         } else if (command.equalsIgnoreCase("PART")) { // PART
  500.            
  501.             IRCUser user = p.getUser();
  502.             String chan = p.getParameter(1);
  503.             String msg = p.getParameterCount() > 1 ? p.getTrailing() : "";
  504.             // not logic: "PART :#zentrum" is without msg, "PART #zentrum :cjo all"
  505.             // is with msg. so we cannot use getMiddle and getTrailing :-/
  506.             for (int i = 0; i < listeners.length; i++)
  507.                 listeners[i].onPart(chan, user, msg);
  508.            
  509.         } else if (command.equalsIgnoreCase("NOTICE")) { // NOTICE
  510.            
  511.             IRCUser user = p.getUser();
  512.             String middle = p.getMiddle();
  513.             String trailing = p.getTrailing();
  514.             for (int i = 0; i < listeners.length; i++)
  515.                 listeners[i].onNotice(middle, user, trailing);
  516.            
  517.         } else if ((reply = IRCUtil.parseInt(command)) >= 1 && reply < 400) { // RPL
  518.            
  519.             String potNick = p.getParameter(1);
  520.             if ((level == 1 || level == 2) && nick.length() > potNick.length() &&
  521.                     nick.substring(0, potNick.length()).equalsIgnoreCase(potNick)) {
  522.                 nick = potNick;
  523.                 if (level == 2)
  524.                     level = 3;
  525.             }
  526.            
  527.             if (level == 1) { // not registered
  528.                 level = 2; // if first PING wasn't received, we're
  529.                 for (int i = 0; i < listeners.length; i++)
  530.                     listeners[i].onRegistered(); // connected now for sure
  531.             }
  532.            
  533.             String middle = p.getMiddle();
  534.             String trailing = p.getTrailing();
  535.             for (int i = 0; i < listeners.length; i++)
  536.                 listeners[i].onReply(reply, middle, trailing);
  537.            
  538.         } else if (reply >= 400 && reply < 600) { // ERROR
  539.            
  540.             String trailing = p.getTrailing();
  541.             for (int i = 0; i < listeners.length; i++)
  542.                 listeners[i].onError(reply, trailing);
  543.            
  544.         } else if (command.equalsIgnoreCase("KICK")) { // KICK
  545.            
  546.             IRCUser user = p.getUser();
  547.             String param1 = p.getParameter(1);
  548.             String param2 = p.getParameter(2);
  549.             String msg = (p.getParameterCount() > 2) ? p.getTrailing() : "";
  550.             for (int i = 0; i < listeners.length; i++)
  551.                 listeners[i].onKick(param1, user, param2, msg);
  552.            
  553.         } else if (command.equalsIgnoreCase("INVITE")) { // INVITE
  554.            
  555.             IRCUser user = p.getUser();
  556.             String middle = p.getMiddle();
  557.             String trailing = p.getTrailing();
  558.             for (int i = 0; i < listeners.length; i++)
  559.                 listeners[i].onInvite(trailing, user, middle);
  560.            
  561.         } else if (command.equalsIgnoreCase("TOPIC")) { // TOPIC
  562.            
  563.             IRCUser user = p.getUser();
  564.             String middle = p.getMiddle();
  565.             String trailing = p.getTrailing();
  566.             for (int i = 0; i < listeners.length; i++)
  567.                 listeners[i].onTopic(middle, user, trailing);
  568.            
  569.         } else if (command.equalsIgnoreCase("ERROR")) { // ERROR
  570.            
  571.             String trailing = p.getTrailing();
  572.             for (int i = 0; i < listeners.length; i++)
  573.                 listeners[i].onError(trailing);
  574.            
  575.         } else { // OTHER
  576.            
  577.             String prefix = p.getPrefix();
  578.             String middle = p.getMiddle();
  579.             String trailing = p.getTrailing();
  580.             for (int i = 0; i < listeners.length; i++)
  581.                 listeners[i].unknown(prefix, command, middle, trailing);
  582.            
  583.         }
  584.     }
  585.  
  586.     public void sleep(int a) {
  587.         try {
  588.             //thread.sleep(a); 
  589.         } catch (Exception e) { e.printStackTrace(); }
  590.     }
  591.    
  592. // ------------------------------
  593.    
  594.     /**
  595.      * Close down the connection brutally. <br />
  596.      * It does *NOT* send the proper IRC command <code>QUIT</code>. You should
  597.      * always use the <code>doQuit</code> methods or <code>send("QUIT")</code>
  598.      * instead of this method. <br />
  599.      * You should use this method to close down the connection only when the IRC
  600.      * server doesn't react to the <code>QUIT</code> command.
  601.      * @see #connect()
  602.      * @see #doQuit
  603.      * @see #doQuit(String)
  604.      */
  605.     public synchronized void close() {
  606.         try {
  607.             if (!thread.isInterrupted()) {
  608.                 System.out.println("Interrupting thread...");
  609.                 thread.interrupt(); }
  610.         } catch (Exception exc) {
  611.             exc.printStackTrace();
  612.         }
  613.         try {
  614.             if (socket != null) {
  615.                 System.out.println("Closing socket...");
  616.                 socket.close(); }
  617.         } catch (Exception exc) {
  618.             exc.printStackTrace();
  619.         }
  620.         try {
  621.             if (out != null) {
  622.                 System.out.println("Closing out stream...");
  623.                 out.close(); }
  624.         } catch (Exception exc) {
  625.             exc.printStackTrace();
  626.         }
  627.         try {
  628.             if (in != null) {
  629.                 System.out.println("Closing in stream...");
  630.                 in.close(); }
  631.         } catch (Exception exc) {
  632.             exc.printStackTrace();
  633.         }
  634.         if (this.level != 0) {
  635.             System.out.println("Setting level to 0...");
  636.             this.level = 0;
  637.             for (int i = 0; i < listeners.length; i++) {
  638.                 System.out.println("Doing listener");
  639.                 listeners[i].onDisconnected(); }
  640.         }
  641.         socket = null;
  642.         in = null;
  643.         out = null;
  644.         //listeners = new IRCEventListener[0];
  645.     }
  646.    
  647. // ------------------------------
  648.    
  649.     /**
  650.      * Adds a new {@link org.schwering.irc.lib.IRCEventListener} which listens
  651.      * for actions coming from the IRC server.
  652.      * @param l An instance of the
  653.      *          {@link org.schwering.irc.lib.IRCEventListener} interface.
  654.      * @throws IllegalArgumentException If <code>listener</code> is
  655.      *                                  <code>null</code>.
  656.      */
  657.     public synchronized void addIRCEventListener(IRCEventListener l) {
  658.         if (l == null)
  659.             throw new IllegalArgumentException("Listener is null.");
  660.         int len = listeners.length;
  661.         IRCEventListener[] oldListeners = listeners;
  662.         listeners = new IRCEventListener[len + 1];
  663.         System.arraycopy(oldListeners, 0, listeners, 0, len);
  664.         listeners[len] = l;
  665.     }
  666.    
  667. // ------------------------------
  668.    
  669.     /**
  670.      * Removes the first occurence of the given
  671.      * {@link org.schwering.irc.lib.IRCEventListener} from the listener-vector.
  672.      * @param l An instance of the
  673.      *          {@link org.schwering.irc.lib.IRCEventListener} interface.
  674.      * @return <code>true</code> if the listener was successfully removed;
  675.      *         <code>false</code> if it was not found.
  676.      */
  677.     public synchronized boolean removeIRCEventListener(IRCEventListener l) {
  678.         if (l == null)
  679.             return false;
  680.         int index = -1;
  681.         for (int i = 0; i < listeners.length; i++)
  682.             if (listeners[i].equals(l)) {
  683.                 index = i;
  684.                 break;
  685.             }
  686.         if (index == -1)
  687.             return false;
  688.         listeners[index] = null;
  689.         int len = listeners.length - 1;
  690.         IRCEventListener[] newListeners = new IRCEventListener[len];
  691.         for (int i = 0, j = 0; i < len; j++)
  692.             if (listeners[j] != null)
  693.                 newListeners[i++] = listeners[j];
  694.         listeners = newListeners;
  695.         return true;
  696.     }
  697.    
  698. // ------------------------------
  699.    
  700.     /**
  701.      * Enables or disables the mIRC colorcodes.
  702.      * @param colors <code>true</code> to enable, <code>false</code> to disable
  703.      *               colors.
  704.      */
  705.     public void setColors(boolean colors) {
  706.         colorsEnabled = colors;
  707.     }
  708.    
  709. // ------------------------------
  710.    
  711.     /**
  712.      * Enables or disables the automatic PING? PONG! support.
  713.      * @param pong <code>true</code> to enable automatic <code>PONG</code>
  714.      *             reply, <code>false</code> makes the class fire
  715.      *             <code>onPing</code> events.
  716.      */
  717.     public void setPong(boolean pong) {
  718.         pongAutomatic = pong;
  719.     }
  720.    
  721. // ------------------------------
  722.    
  723.     /**
  724.      * Changes the character encoding used to talk to the server.
  725.      * This can be ISO-8859-1 or UTF-8 for example.
  726.      * This property must be set before a call to the <code>connect()</code>
  727.      * method.
  728.      * @param encoding
  729.      */
  730.     public void setEncoding(String encoding) {
  731.         this.encoding   = encoding;
  732.     }
  733.    
  734. // ------------------------------
  735.    
  736.     /**
  737.      * Sets the connection's timeout in milliseconds. <br />
  738.      * The default is <code>1000 * 60 15</code> millis which are 15 minutes.
  739.      */
  740.     public void setTimeout(int millis) {
  741.         if (socket != null)
  742.             try {
  743.                 socket.setSoTimeout(millis);
  744.             } catch (IOException exc) {
  745.                 exc.printStackTrace();
  746.             }
  747.             timeout = millis;
  748.     }
  749.    
  750. // ------------------------------
  751.    
  752.     /**
  753.      * Tells whether there's a connection to the IRC network or not. <br />
  754.      * If <code>connect</code> wasn't called yet, it returns <code>false</code>.
  755.      * @return The status of the connection; <code>true</code> if it's connected.
  756.      * @see #connect()
  757.      * @see #doQuit()
  758.      * @see #doQuit(String)
  759.      * @see #close()
  760.      */
  761.     public boolean isConnected() {
  762.         return level >= 1;
  763.     }
  764.    
  765. // ------------------------------
  766.    
  767.     /**
  768.      * Returns the nickname of this instance.
  769.      * @return The nickname.
  770.      */
  771.     public String getNick() {
  772.         return nick;
  773.     }
  774.    
  775. // ------------------------------
  776.    
  777.     /**
  778.      * Returns the realname of this instance.
  779.      * @return The realname.
  780.      */
  781.     public String getRealname() {
  782.         return realname;
  783.     }
  784.    
  785. // ------------------------------
  786.    
  787.     /**
  788.      * Returns the username of this instance.
  789.      * @return The username.
  790.      */
  791.     public String getUsername() {
  792.         return username;
  793.     }
  794.    
  795. // ------------------------------
  796.    
  797.     /**
  798.      * Returns the server of this instance.
  799.      * @return The server's hostname.
  800.      */
  801.     public String getHost() {
  802.         return host;
  803.     }
  804.    
  805. // ------------------------------
  806.    
  807.     /**
  808.      * Returns the password of this instance. If no password is set,
  809.      * <code>null</code> is returned.
  810.      * @return The password. If no password is set, <code>null</code> is
  811.      *         returned.
  812.      */
  813.     public String getPassword() {
  814.         return pass;
  815.     }
  816.    
  817. // ------------------------------
  818.    
  819.     /**
  820.      * Returns all ports to which the <code>IRCConnection</code> is going to try
  821.      * or has tried to connect to.
  822.      * @return The ports in an <code>int[]</code> array.
  823.      */
  824.     public int[] getPorts() {
  825.         return ports;
  826.     }  
  827.    
  828. // ------------------------------
  829.    
  830.     /**
  831.      * Returns the port to which the <code>IRCConnection</code> connected, or
  832.      * <code>0</code> if the connection failed or wasn't tried yet.
  833.      * @return The port to which the <code>IRCConnection</code>, or
  834.      *         <code>0</code> if the connection failed or wasn't tried yet.
  835.      */
  836.     public int getPort() {
  837.         return (socket != null) ? socket.getPort() : 0;
  838.     }
  839.    
  840. // ------------------------------
  841.    
  842.     /**
  843.      * Indicates whether colors are stripped out or not.
  844.      * @return <code>true</code> if colors are disabled.
  845.      */
  846.     public boolean getColors() {
  847.         return colorsEnabled;
  848.     }
  849.    
  850. // ------------------------------
  851.    
  852.     /**
  853.      * Indicates whether automatic PING? PONG! is enabled or not.
  854.      * @return <code>true</code> if PING? PONG! is done automatically.
  855.      */
  856.     public boolean getPong() {
  857.         return pongAutomatic;
  858.     }
  859.    
  860. // ------------------------------
  861.    
  862.     /**
  863.      * Returns the encoding of the socket.
  864.      * @return The socket's encoding.
  865.      */
  866.     public String getEncoding() {
  867.         return encoding;
  868.     }
  869.    
  870. // ------------------------------
  871.    
  872.     /**
  873.      * Returns the timeout of the socket. <br />
  874.      * If an error occurs, which is never the case, <code>-1</code> is returned.
  875.      * @return The timeout.
  876.      */
  877.     public int getTimeout() {
  878.         if (socket != null)
  879.             try {
  880.                 return socket.getSoTimeout();
  881.             } catch (IOException exc) {
  882.                 exc.printStackTrace();
  883.                 return -1;
  884.             }
  885.             else
  886.                 return timeout;
  887.     }
  888.    
  889. // ------------------------------
  890.    
  891.     /**
  892.      * Generates a <code>String</code> with some information about the instance of
  893.      * <code>IRCConnection</code>.
  894.      * Its format is: <code>
  895.      * classname[host,portMin,portMax,username,nick,realname,pass,connected]
  896.      * </code>.
  897.      * @return A <code>String</code> with information about the instance.
  898.      */
  899.     public String toString() {
  900.         return getClass().getName() +"["+ host +","+ getPort() +","+ username +","+
  901.         nick +","+ realname +","+ pass +","+ isConnected() +"]";
  902.     }
  903.    
  904. // ------------------------------
  905.    
  906.     /**
  907.      * Removes away message.
  908.      */
  909.     public void doAway() {
  910.         send("AWAY");
  911.     }  
  912.    
  913. // ------------------------------
  914.    
  915.     /**
  916.      * Sets away message.
  917.      * @param msg The away message.
  918.      */
  919.     public void doAway(String msg) {
  920.         send("AWAY :"+ msg);
  921.     }  
  922.    
  923. // ------------------------------
  924.    
  925.     /**
  926.      * Invites a user to a channel.
  927.      * @param nick The nickname of the user who should be invited.
  928.      * @param chan The channel the user should be invited to.
  929.      */
  930.     public void doInvite(String nick, String chan) {
  931.         send("INVITE "+ nick +" "+ chan);
  932.     }  
  933.    
  934. // ------------------------------
  935.    
  936.     /**
  937.      * Checks if one or more nicks are used on the server.
  938.      * @param nick The nickname of the user we search for.
  939.      */
  940.     public void doIson(String nick) {
  941.         send("ISON "+ nick);
  942.     }  
  943.    
  944. // ------------------------------
  945.    
  946.     /**
  947.      * Joins a channel without a key.
  948.      * @param chan The channel which is to join.
  949.      */
  950.     public void doJoin(String chan) {
  951.         send("JOIN "+ chan);
  952.     }  
  953.    
  954. // ------------------------------
  955.    
  956.     /**
  957.      * Joins a channel with a key.
  958.      * @param chan The channel which is to join.
  959.      * @param key The key of the channel.
  960.      */
  961.     public void doJoin(String chan, String key) {
  962.         send("JOIN "+ chan +" "+ key);
  963.     }  
  964.    
  965. // ------------------------------
  966.    
  967.     /**
  968.      * Kicks a user from a channel.
  969.      * @param chan The channel somebody should be kicked from.
  970.      * @param nick The nickname of the user who should be kicked.
  971.      */
  972.     public void doKick(String chan, String nick) {
  973.         send("KICK "+ chan +" "+ nick);
  974.     }
  975.    
  976. // ------------------------------
  977.    
  978.     /**
  979.      * Kicks a user from a channel with a comment.
  980.      * @param chan The channel somebody should be kicked from.
  981.      * @param nick The nickname of the user who should be kicked.
  982.      * @param msg The optional kickmessage.
  983.      */
  984.     public void doKick(String chan, String nick, String msg) {
  985.         send("KICK "+ chan +" "+ nick +" :"+ msg);
  986.     }  
  987.    
  988. // ------------------------------
  989.    
  990.     /**
  991.      * Lists all channels with their topic and status.
  992.      */
  993.     public void doList() {
  994.         send("LIST");
  995.     }  
  996.    
  997. // ------------------------------
  998.    
  999.     /**
  1000.      * Lists channel(s) with their topic and status.
  1001.      * @param chan The channel the <code>LIST</code> refers to.
  1002.      */
  1003.     public void doList(String chan) {
  1004.         send("LIST "+ chan);
  1005.     }  
  1006.    
  1007. // ------------------------------
  1008.    
  1009.     /**
  1010.      * Lists all visible users.
  1011.      */
  1012.     public void doNames() {
  1013.         send("NAMES");
  1014.     }  
  1015.    
  1016. // ------------------------------
  1017.    
  1018.     /**
  1019.      * Lists all visible users of (a) channel(s).
  1020.      * @param chan The channel the <code>NAMES</code> command is refering to.
  1021.      */
  1022.     public void doNames(String chan) {
  1023.         send("NAMES "+ chan);
  1024.     }  
  1025.    
  1026. // ------------------------------
  1027.    
  1028.     /**
  1029.      * Sends a message to a person or a channel.
  1030.      * @param target The nickname or channel the message should be sent to.
  1031.      * @param msg The message which should be transmitted.
  1032.      */
  1033.     public void doPrivmsg(String target, String msg) {
  1034.         send("PRIVMSG "+ target +" :"+ msg);
  1035.     }
  1036.    
  1037. // ------------------------------
  1038.    
  1039.     /**
  1040.      * Requests a Reply 324 for the modes of a given channel.
  1041.      * @param chan The channel the <code>MODE</code> request is refering to.
  1042.      */
  1043.     public void doMode(String chan) {
  1044.         send("MODE "+ chan);
  1045.     }
  1046.    
  1047. // ------------------------------
  1048.    
  1049.     /**
  1050.      * Sends a mode to the server. <br />
  1051.      * The first argument is a nickname (user-mode) or a channel (channel-mode).
  1052.      * <code>String mode</code> must contain the operators (+/-), the modes
  1053.      * (o/v/i/k/l/p/s/w) and the possibly values (nicks/banmask/limit/key).
  1054.      * @param target The nickname or channel of the user whose modes will be
  1055.      *               changed.
  1056.      * @param mode The new modes.
  1057.      */
  1058.     public void doMode(String target, String mode) {
  1059.         send("MODE "+ target +" "+ mode);
  1060.     }
  1061.    
  1062. // ------------------------------
  1063.    
  1064.     /**
  1065.      * Changes the nickname.
  1066.      * @param nick The new nickname.
  1067.      */
  1068.     public void doNick(String nick) {
  1069.         send("NICK "+ nick);
  1070.     }  
  1071.    
  1072. // ------------------------------
  1073.    
  1074.     /**
  1075.      * Notices a message to a person or a channel.
  1076.      * @param target The nickname or channel (group) the message should be
  1077.      *               sent to.
  1078.      * @param msg The message which should be transmitted.
  1079.      */
  1080.     public void doNotice(String target, String msg) {
  1081.         send("NOTICE "+ target +" :"+ msg);
  1082.     }
  1083.    
  1084. // ------------------------------
  1085.    
  1086.     /**
  1087.      * Parts from a given channel.
  1088.      * @param chan The channel you want to part from.
  1089.      */
  1090.     public void doPart(String chan) {
  1091.         send("PART "+ chan);
  1092.     }
  1093.    
  1094. // ------------------------------
  1095.    
  1096.     /**
  1097.      * Parts from a given channel with a given parg-msg.
  1098.      * @param chan The channel you want to part from.
  1099.      * @param msg The optional partmessage.
  1100.      */
  1101.     public void doPart(String chan, String msg) {
  1102.         send("PART "+ chan +" :"+ msg);
  1103.     }
  1104.    
  1105. // ------------------------------
  1106.    
  1107.     /**
  1108.      * Quits from the IRC server with a quit-msg.
  1109.      * @param ping The ping which was received in <code>onPing</code>. It's a
  1110.      *             <code>String</code>, because sometimes on some networks
  1111.      *             the server-hostname (for example splatterworld.quakenet.org) is
  1112.      *             given as parameter which would throw an Exception if we
  1113.      *             gave the ping as long.
  1114.      */
  1115.     public void doPong(String ping) {
  1116.         send("PONG :"+ ping);
  1117.     }
  1118.    
  1119. // ------------------------------
  1120.    
  1121.     /**
  1122.      * Quits from the IRC server.
  1123.      * Calls the <code>disconnect</code>-method which does the work actually.
  1124.      * @see #isConnected()
  1125.      * @see #connect()
  1126.      * @see #doQuit(String)
  1127.      * @see #close()
  1128.      */
  1129.     public void doQuit() {
  1130.         send("QUIT");
  1131.     }
  1132.    
  1133. // ------------------------------
  1134.    
  1135.     /**
  1136.      * Quits from the IRC server with a quit-msg.
  1137.      * Calls the <code>disconnect</code>-method which does the work actually.
  1138.      * @param msg The optional quitmessage.
  1139.      * @see #isConnected()
  1140.      * @see #connect()
  1141.      * @see #doQuit()
  1142.      * @see #close()
  1143.      */
  1144.     public void doQuit(String msg) {
  1145.         send("QUIT :"+ msg);
  1146.     }
  1147.    
  1148. // ------------------------------
  1149.    
  1150.     /**
  1151.      * Requests the topic of a chan. The topic is given in a numeric reply.
  1152.      * @param chan The channel which topic should be requested.
  1153.      */
  1154.     public void doTopic(String chan) {
  1155.         send("TOPIC "+ chan);
  1156.     }  
  1157.    
  1158. // ------------------------------
  1159.    
  1160.     /**
  1161.      * Changes the topic of a chan.
  1162.      * @param chan The channel which topic is changed.
  1163.      * @param topic The new topic.
  1164.      */
  1165.     public void doTopic(String chan, String topic) {
  1166.         send("TOPIC "+ chan +" :"+ topic);
  1167.     }  
  1168.    
  1169. // ------------------------------
  1170.    
  1171.     /**
  1172.      * Requests information about users matching the given criteric,
  1173.      * for example a channel they are on.
  1174.      * @param criteric The criterics of the <code>WHO</code> query.
  1175.      */
  1176.     public void doWho(String criteric) {
  1177.         send("WHO "+ criteric);
  1178.     }  
  1179.    
  1180. // ------------------------------
  1181.    
  1182.     /**
  1183.      * Requires information about an existing user.
  1184.      * @param nick The nickname of the user the query is refering to.
  1185.      */
  1186.     public void doWhois(String nick) {
  1187.         send("WHOIS "+ nick);
  1188.     }  
  1189.    
  1190. // ------------------------------
  1191.    
  1192.     /**
  1193.      * Requires host-information about a user, who is not connected anymore.
  1194.      * @param nick The nickname of the user the query is refering to.
  1195.      */
  1196.     public void doWhowas(String nick) {
  1197.         send("WHOWAS "+ nick);
  1198.     }
  1199.    
  1200. // ------------------------------
  1201.    
  1202.     /**
  1203.      * Requires host-information about up to 5 users which must be listed and
  1204.      * divided by spaces.
  1205.      * @param nick The nickname of the user the query is refering to.
  1206.      */
  1207.     public void doUserhost(String nick) {
  1208.         send("USERHOST "+ nick);
  1209.     }
  1210.    
  1211.     public long getDataReceived() {
  1212.         return data_in;
  1213.     }
  1214.    
  1215.     public long getDataSent() {
  1216.         return data_out;
  1217.     }  
  1218. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement