1 /*****************************************************/
2 /* This java file is a part of the */
4 /* - Plouf's Java IRC Client - */
6 /* Copyright (C) 2002 - 2005 Philippe Detournay */
8 /* All contacts : theplouf@yahoo.com */
10 /* PJIRC is free software; you can redistribute */
11 /* it and/or modify it under the terms of the GNU */
12 /* General Public License as published by the */
13 /* Free Software Foundation; version 2 or later of */
16 /* PJIRC is distributed in the hope that it will */
17 /* be useful, but WITHOUT ANY WARRANTY; without */
18 /* even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
20 /* General Public License for more details. */
22 /* You should have received a copy of the GNU */
23 /* General Public License along with PJIRC; if */
24 /* not, write to the Free Software Foundation, */
25 /* Inc., 59 Temple Place, Suite 330, Boston, */
26 /* MA 02111-1307 USA */
28 /*****************************************************/
32 import irc.dcc.prv.DCCChatServer;
33 import irc.dcc.prv.DCCFileHandler;
36 import java.util.Date;
37 import java.util.Enumeration;
38 import java.util.Hashtable;
39 import java.util.Vector;
42 * FirstLineFilter, used to handle CTCP codes.
44 class FirstLineFilter {
45 private IRCServer _server;
46 private IRCConfiguration _ircConfiguration;
47 private ServerManager _mgr;
50 * Create a new FirstLineFilter
56 public FirstLineFilter(IRCServer serv, ServerManager mgr, IRCConfiguration config) {
57 _ircConfiguration = config;
63 * Release this object.
65 public void release() {
71 * Perform any needed action from a channel message.
79 * @return true if message was handled, false otherwise.
81 public boolean performFromChannelMessage(String channel, String nick, String msg) {
82 if (!msg.startsWith("\1"))
85 msg = msg.substring(1);
86 msg = msg.substring(0, msg.length() - 1);
89 int pos = msg.indexOf(' ');
91 cmd = msg.toLowerCase(java.util.Locale.ENGLISH);
93 cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH);
94 param = msg.substring(pos + 1);
97 if (cmd.equals("action")) {
98 Channel c = _server.getChannel(channel, false);
100 c.action(nick, param);
101 } else if (cmd.equals("sound")) {
102 _ircConfiguration.getAudioConfiguration().play(param);
103 _server.sendStatusMessage("\2\3" + "4" + "[" + nick + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + "]");
109 * Perform any needed action from a nick message.
115 * @return true if message was handled, false otherwise.
117 public boolean performFromNickMessage(String nick, String msg) {
118 if (!msg.startsWith("\1"))
121 msg = msg.substring(1);
122 msg = msg.substring(0, msg.length() - 1);
125 int pos = msg.indexOf(' ');
127 cmd = msg.toLowerCase(java.util.Locale.ENGLISH);
129 cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH);
130 param = msg.substring(pos + 1);
134 if (cmd.equals("action")) {
136 Query q = _server.getQuery(nick, false);
138 q.action(nick, param);
139 } else if (cmd.equals("version")) {
140 String data = "PJIRC " + _ircConfiguration.getVersion();
141 _server.execute("NOTICE " + nick + " :\1VERSION " + data + "\1");
142 } else if (cmd.equals("ping")) {
143 _server.execute("NOTICE " + nick + " :\1PING " + param + "\1");
144 } else if (cmd.equals("time")) {
145 String data = new Date().toString();
146 _server.execute("NOTICE " + nick + " :\1TIME " + data + "\1");
147 } else if (cmd.equals("finger")) {
148 String data = _ircConfiguration.getS("fingerreply");
149 _server.execute("NOTICE " + nick + " :\1FINGER " + data + "\1");
150 } else if (cmd.equals("userinfo")) {
151 String data = _ircConfiguration.getS("userinforeply");
152 _server.execute("NOTICE " + nick + " :\1USERINFO " + data + "\1");
153 } else if (cmd.equals("clientinfo")) {
154 String data = "This client is a Java application supporting the following CTCP tags : ACTION VERSION PING TIME FINGER USERINFO CLIENTINFO SOUND DCC";
155 _server.execute("NOTICE " + nick + " :\1CLIENTINFO " + data + "\1");
156 } else if (cmd.equals("sound")) {
157 _ircConfiguration.getAudioConfiguration().play(param);
158 } else if (cmd.equals("dcc")) {
159 StringParser sp = new StringParser();
160 String[] args = sp.parseString(param.toLowerCase(java.util.Locale.ENGLISH));
161 if (args.length >= 2) {
162 if (args[0].equals("chat") && args[1].equals("chat") && _ircConfiguration.getB("allowdccchat")) {
163 if (args.length >= 4) {
164 boolean bres = false;
165 Object[] res = _server.specialRequest("DCCChatRequest", new Object[] { nick });
166 for (int i = 0; i < res.length; i++)
167 if (((Boolean) res[i]).booleanValue())
172 DCCChatServer cserver = new DCCChatServer(_ircConfiguration, _server.getNick(), nick);
173 cserver.openActive(args[2], args[3]);
174 _mgr.newServer(cserver, false);
175 } catch (Throwable ex) {
176 ex.printStackTrace();
181 if (args[0].equals("send") && _ircConfiguration.getB("allowdccfile")) {
182 if (args.length >= 5) {
183 String fname = args[1];
185 String port = args[3];
186 String size = args[4];
187 Object[] res = _server.specialRequest("DCCFileRequest", new Object[] { nick, fname, new Integer(size) });
190 dest = (File) res[0];
193 DCCFileHandler handler = new DCCFileHandler(_ircConfiguration, nick, dest);
194 handler.receive(ip, port, size);
195 _mgr.newServer(handler, false);
196 } catch (Throwable ex) {
197 ex.printStackTrace();
205 _server.sendStatusMessage("\2\3" + "4" + "[" + nick + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + "]");
210 * Perform any needed action from a notice message.
216 * @return true if message was handled, false otherwise.
218 public boolean performFromNotice(String nick, String msg) {
219 if (!msg.startsWith("\1"))
222 msg = msg.substring(1);
223 msg = msg.substring(0, msg.length() - 1);
226 int pos = msg.indexOf(' ');
228 cmd = msg.toLowerCase(java.util.Locale.ENGLISH);
230 cmd = msg.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH);
231 param = msg.substring(pos + 1);
234 Source source = _server.getDefaultSource();
235 if (cmd.equals("ping")) {
236 long d = (new Long(param)).longValue();
237 long delta = (new Date()).getTime() - d;
239 source.report("\2\3" + "4"
240 + _ircConfiguration.getText(IRCTextProvider.CTCP_PING_REPLY, nick, (delta / 1000.0) + ""));
244 source.report("\2\3" + "4" + "[" + nick + " " + cmd.toUpperCase(java.util.Locale.ENGLISH) + " reply] : " + param);
252 public class IRCServer extends IRCObject implements Server, ServerProtocolListener {
253 private ServerProtocol _protocol;
254 private Hashtable _channels;
255 private Hashtable _queries;
256 private Hashtable _chanlist;
257 private Status _status;
259 private Hashtable _ignoreList;
261 private ListenerGroup _listeners;
262 private ListenerGroup _replylisteners;
263 private ListenerGroup _messagelisteners;
264 private String[] _askedNick;
265 private String _nick;
266 private String _userName;
267 private int _tryNickIndex;
268 private ModeHandler _mode;
269 private String[] _host;
271 private String _passWord[];
272 private int _tryServerIndex;
273 private boolean _connected;
274 private String _name;
275 private Source _defaultSource;
276 private boolean _serverLeaving;
277 private boolean _registered;
278 private FirstLineFilter _filter;
279 // private boolean _nickWaiting=false;
281 private char[] _nickModes = { 'o', 'h', 'v' };
282 private char[] _nickPrefixes = { '@', '%', '+' };
283 private char[] _channelPrefixes = { '#', '&', '!', '+' };
284 private char[][] _globalModes = { { 'b' }, { 'k' }, { 'l' }, { 'i', 'm', 'n', 'p', 's', 't', 'a', 'q', 'r' } };
287 * Create a new IRCServer.
290 * global IRCConfiguration.
292 * the server manager.
296 * claimed alternate nick.
302 public IRCServer(IRCConfiguration config, ServerManager mgr, String nick, String altNick, String userName, String name) {
304 _filter = new FirstLineFilter(this, mgr, config);
305 _serverLeaving = false;
307 _userName = userName;
308 _askedNick = new String[2];
309 _askedNick[0] = nick;
310 _askedNick[1] = altNick;
313 _ignoreList = new Hashtable();
315 _channels = new Hashtable();
316 _queries = new Hashtable();
317 _chanlist = new Hashtable();
319 _listeners = new ListenerGroup();
320 _replylisteners = new ListenerGroup();
321 _messagelisteners = new ListenerGroup();
323 _status = new Status(_ircConfiguration, this);
324 _defaultSource = _status;
326 _protocol = new ServerProtocol(_ircConfiguration);
327 _protocol.addServerProtocolListener(this);
330 _mode = new ModeHandler(_globalModes, _nickModes);
334 * Send a special request event to all listeners.
339 * request parameters.
342 public Object[] specialRequest(String request, Object[] params) {
343 return _listeners.sendEvent("specialServerRequest", request, this, params);
347 public void release() {
348 _protocol.removeServerProtocolListener(this);
354 public Enumeration getSources() {
355 Vector v = new Vector();
357 e = _channels.elements();
358 while (e.hasMoreElements())
359 v.insertElementAt(e.nextElement(), v.size());
360 e = _queries.elements();
361 while (e.hasMoreElements())
362 v.insertElementAt(e.nextElement(), v.size());
363 e = _chanlist.elements();
364 while (e.hasMoreElements())
365 v.insertElementAt(e.nextElement(), v.size());
367 v.insertElementAt(_status, v.size());
372 public void enumerateSourcesAsCreated(ServerListener lis) {
374 e = _channels.elements();
375 while (e.hasMoreElements())
376 lis.sourceCreated((Source) e.nextElement(), this, new Boolean(false));
377 e = _queries.elements();
378 while (e.hasMoreElements())
379 lis.sourceCreated((Source) e.nextElement(), this, new Boolean(false));
380 e = _chanlist.elements();
381 while (e.hasMoreElements())
382 lis.sourceCreated((Source) e.nextElement(), this, new Boolean(false));
384 lis.sourceCreated(_status, this, new Boolean(true));
388 public void enumerateSourcesAsRemoved(ServerListener lis) {
390 e = _channels.elements();
391 while (e.hasMoreElements())
392 lis.sourceRemoved((Source) e.nextElement(), this);
393 e = _queries.elements();
394 while (e.hasMoreElements())
395 lis.sourceRemoved((Source) e.nextElement(), this);
396 e = _chanlist.elements();
397 while (e.hasMoreElements())
398 lis.sourceRemoved((Source) e.nextElement(), this);
400 lis.sourceRemoved(_status, this);
404 public void setDefaultSource(Source s) {
409 * Get the default server source, or null if no default source is defined.
411 * @return default source.
413 public Source getDefaultSource() {
414 return _defaultSource;
418 * Set default configuration for the next connection.
427 public void setServers(String host[], int port[], String passWord[]) {
429 _host = new String[host.length];
430 for (int i = 0; i < host.length; i++)
432 _port = new int[port.length];
433 for (int i = 0; i < port.length; i++)
435 _passWord = new String[passWord.length];
436 for (int i = 0; i < passWord.length; i++)
437 _passWord[i] = passWord[i];
441 public void connect() {
444 connect(_host, _port, _passWord);
447 private void connect(String host[], int port[], String[] passWord) {
449 // if(_nickWaiting) return;
450 if (_tryServerIndex == _host.length)
453 _passWord = passWord;
454 if (_protocol.connecting()) {
455 sendStatusMessage(getText(IRCTextProvider.SERVER_UNABLE_TO_CONNECT_STILL, host[_tryServerIndex],
456 _host[_tryServerIndex]));
459 if (_protocol.connected()) {
460 // sendStatusMessage(getText(IRCTextProvider.SERVER_DISCONNECTED,_host[_tryServerIndex]));
462 _protocol.disconnect();
465 sendStatusMessage(getText(IRCTextProvider.SERVER_CONNECTING));
466 _protocol.connect(host[_tryServerIndex], port[_tryServerIndex]);
470 * Disconnect from the irc server.
473 public void disconnect() {
474 // if(_nickWaiting) return;
475 if (_protocol.connected()) {
476 if (_ircConfiguration.getS("quitmessage").length() == 0) {
479 execute("QUIT :" + _ircConfiguration.get("quitmessage"));
482 sendStatusMessage(getText(IRCTextProvider.SERVER_NOT_CONNECTED));
487 * Return true if connected to the server, false otherwise.
489 * @return connected state.
492 public boolean isConnected() {
497 public void connectionFailed(String message, String host) {
498 sendStatusMessage(getText(IRCTextProvider.SERVER_UNABLE_TO_CONNECT, message));
500 if (_tryServerIndex < _host.length)
501 connect(_host, _port, _passWord);
504 private void nickUsed() {
505 if (_tryNickIndex >= _askedNick.length) {
506 // _nickWaiting=true;
507 Object[] res = _listeners.sendEvent("cannotUseRequestedNicknames", new Object[] { this });
509 _askedNick = (String[]) res[0];
510 // _nickWaiting=false;
512 } else if (_askedNick[_tryNickIndex].indexOf("?") == -1)
516 private void register() {
517 String tryUseNick = _askedNick[_tryNickIndex];
518 if (tryUseNick.length() == 0)
519 tryUseNick = "Anon????";
521 for (int i = 0; i < tryUseNick.length(); i++) {
522 char c = tryUseNick.charAt(i);
524 c = (char) ('0' + Math.random() * 10);
527 if (_passWord[_tryServerIndex].length() > 0)
528 execute("pass " + _passWord[_tryServerIndex]);
529 execute("nick " + ans);
530 String name = _ircConfiguration.getS("userid");
531 if (name.length() == 0)
535 execute("user " + name + " 0 0 :" + _userName);
540 * Get the local port of the remote connection.
542 * @return the local, client-side port of the remote connection.
544 public int getLocalPort() {
545 return _protocol.getLocalPort();
549 public void connected(String host) {
550 sendStatusMessage(getText(IRCTextProvider.SERVER_LOGIN));
554 private void clear(Hashtable l) {
557 while (e.hasMoreElements())
558 _listeners.sendEvent("sourceRemoved", e.nextElement(), this);
560 while (e.hasMoreElements())
561 ((Source) e.nextElement()).release();
566 public void disconnected(String host) {
567 sendStatusMessage(getText(IRCTextProvider.SERVER_DISCONNECTED, host));
575 _status.modeChanged(getMode());
576 // _defaultSource=null;
579 _listeners.sendEvent("serverDisconnected", this);
581 if (_serverLeaving) {
582 _listeners.sendEvent("sourceRemoved", _status, this);
584 _listeners.sendEvent("serverLeft", this);
589 public void sendStatusMessage(String msg) {
595 * Get all the channels.
597 * @return an enumeration of channels.
599 public Enumeration getChannels() {
600 return _channels.elements();
604 * Get all the queries.
606 * @return an enumeration of queries.
608 public Enumeration getQueries() {
609 return _queries.elements();
613 * Get all the chanlists.
615 * @return an enumeration of chanlists.
617 public Enumeration getChanLists() {
618 return _chanlist.elements();
622 * Get the channel from its name. If this channel doesn't exist, it is created
623 * only if create boolean is set.
628 * true if channel must be created if not existing.
629 * @return channel, or null.
631 public Channel getChannel(String name, boolean create) {
632 Channel c = (Channel) _channels.get(name.toLowerCase(java.util.Locale.ENGLISH));
633 if ((c == null) && create) {
634 c = new Channel(_ircConfiguration, name, this);
635 _channels.put(name.toLowerCase(java.util.Locale.ENGLISH), c);
636 _listeners.sendEvent("sourceCreated", c, this, new Boolean(true));
642 * Get the query from its name. If this query doesn't exist, it is created.
643 * The query cannot be get if the server is not connected.
648 * true if this query has been created following a local request.
649 * @return query, or null if server was not connected.
651 public Query getQuery(String nick, boolean local) {
654 if (_ircConfiguration.getB("disablequeries"))
656 Query c = (Query) _queries.get(nick.toLowerCase(java.util.Locale.ENGLISH));
658 c = new Query(_ircConfiguration, nick, this);
659 _queries.put(nick.toLowerCase(java.util.Locale.ENGLISH), c);
660 _listeners.sendEvent("sourceCreated", c, this, new Boolean(local));
667 * Get the chanlist from its name. If this chanlist doesn't exist, it is
674 private ChanList getChanList(String name) {
675 ChanList c = (ChanList) _chanlist.get(name.toLowerCase(java.util.Locale.ENGLISH));
677 c = new ChanList(_ircConfiguration, this, name);
678 _chanlist.put(name.toLowerCase(java.util.Locale.ENGLISH), c);
679 _listeners.sendEvent("sourceCreated", c, this, new Boolean(true));
685 * Request to leave the given channel.
690 public void leaveChannel(String name) {
691 execute("part " + name);
695 * Request to leave the given query.
700 public void leaveQuery(String name) {
701 Query q = getQuery(name, false);
704 _listeners.sendEvent("sourceRemoved", q, this);
709 public void leave() {
714 * Request to leave the status. This will cause server leaving.
717 * Status name. Unused.
719 public void leaveStatus(String name) {
723 _serverLeaving = true;
726 _listeners.sendEvent("sourceRemoved", _status, this);
728 _listeners.sendEvent("serverLeft", this);
731 * long time=System.currentTimeMillis(); while(isConnected()) { try {
732 * Thread.sleep(100); if(System.currentTimeMillis()-time>10000) break; }
733 * catch(InterruptedException ex) { } }
736 * _listeners.sendEvent("sourceRemoved",_status,this); deleteStatus(name);
737 * _listeners.sendEvent("serverLeft",this);
742 * Request to leave the given channel list.
747 public void leaveChanList(String name) {
748 _listeners.sendEvent("sourceRemoved", getChanList(name), this);
749 deleteChanList(name);
752 private void deleteSource(Source src) {
753 if (src == _defaultSource)
754 _defaultSource = null;
758 private void deleteChannel(String name) {
759 deleteSource((Source) _channels.remove(name.toLowerCase(java.util.Locale.ENGLISH)));
762 private void deleteQuery(String name) {
763 deleteSource((Source) _queries.remove(name.toLowerCase(java.util.Locale.ENGLISH)));
766 private void deleteChanList(String name) {
767 deleteSource((Source) _chanlist.remove(name.toLowerCase(java.util.Locale.ENGLISH)));
770 private void deleteStatus(String name) {
771 deleteSource(_status);
776 public String getServerName() {
777 if (_name.length() == 0) {
778 if (_tryServerIndex < _host.length)
779 return _host[_tryServerIndex];
787 * Get this server's status, or null if this server has no status.
789 * @return the status, or null if the server hasno status.
791 public Status getStatus() {
796 * Add a server listener.
802 public void addServerListener(ServerListener l) {
803 _listeners.addListener(l);
810 * listener to remove.
813 public void removeServerListener(ServerListener l) {
814 _listeners.removeListener(l);
818 * Add a reply listener.
823 public void addReplyServerListener(ReplyServerListener l) {
824 _replylisteners.addListener(l);
828 * Add a message listener.
833 public void addMessageServerListener(MessageServerListener l) {
834 _messagelisteners.addListener(l);
838 * Remove a reply listener.
841 * listener to remove.
843 public void removeReplyServerListener(ReplyServerListener l) {
844 _replylisteners.removeListener(l);
848 * Remove a message listener.
851 * listener to remove.
853 public void removeMessageServerListener(MessageServerListener l) {
854 _messagelisteners.removeListener(l);
858 * Get an array of all known channel prefixes.
860 * @return an array of all channel prefixes.
862 public char[] getChannelPrefixes() {
863 return _channelPrefixes;
867 * Get an array of all known nickname prefixes.
869 * @return array of all nickname prefixes.
871 public char[] getNickPrefixes() {
872 return _nickPrefixes;
876 * Get an array of all known nickname modes.
878 * @return array of all nickname modes.
880 public char[] getNickModes() {
885 * Get an array of all known A,B,C,D channel modes.
887 * @return array of all channel modes. This is an array of four char arrays.
889 public char[][] getChannelModes() {
894 * Get the nick prefix associated with the given nick mode.
898 * @return nick prefix for this mode.
900 public String getNickPrefix(String mode) {
901 if (mode.length() == 0)
903 char cmode = mode.charAt(0);
904 for (int i = 0; i < _nickModes.length; i++)
905 if (_nickModes[i] == cmode)
906 return "" + _nickPrefixes[i];
911 * Get the nick mode associated with the given nick prefix.
915 * @return nick mode for this prefix.
917 public String getNickMode(String prefix) {
918 if (prefix.length() == 0)
920 char cprefix = prefix.charAt(0);
921 for (int i = 0; i < _nickPrefixes.length; i++)
922 if (_nickPrefixes[i] == cprefix)
923 return "" + _nickModes[i];
927 private void setNicks(Channel c, Vector nicks) {
928 String[] n = new String[nicks.size()];
929 String[] modes = new String[nicks.size()];
931 for (int i = 0; i < nicks.size(); i++) {
932 n[i] = (String) nicks.elementAt(i);
934 if (n[i].length() > 0) {
935 modes[i] = getNickMode("" + n[i].charAt(0));
936 if (modes[i].length() != 0)
937 n[i] = n[i].substring(1);
940 c.setNicks(n, modes);
943 private void decodeVariable(String key, String val) {
944 if (key.toLowerCase(java.util.Locale.ENGLISH).equals("prefix")) {
945 if (!val.startsWith("("))
947 int pos = val.indexOf(")");
950 String modes = val.substring(1, pos);
951 String prefixes = val.substring(pos + 1);
952 if (prefixes.length() != modes.length())
955 _nickModes = new char[modes.length()];
956 for (int i = 0; i < modes.length(); i++)
957 _nickModes[i] = modes.charAt(i);
958 _nickPrefixes = new char[modes.length()];
959 for (int i = 0; i < prefixes.length(); i++)
960 _nickPrefixes[i] = prefixes.charAt(i);
961 } else if (key.toLowerCase(java.util.Locale.ENGLISH).equals("chantypes")) {
962 _channelPrefixes = new char[val.length()];
963 for (int i = 0; i < _channelPrefixes.length; i++)
964 _channelPrefixes[i] = val.charAt(i);
965 } else if (key.toLowerCase(java.util.Locale.ENGLISH).equals("chanmodes")) {
966 int pos = val.indexOf(',');
969 String a = val.substring(0, pos);
970 val = val.substring(pos + 1);
971 pos = val.indexOf(',');
974 String b = val.substring(0, pos);
975 val = val.substring(pos + 1);
976 pos = val.indexOf(',');
979 String c = val.substring(0, pos);
980 String d = val.substring(pos + 1);
981 _globalModes = new char[4][];
982 _globalModes[0] = new char[a.length()];
983 for (int i = 0; i < a.length(); i++)
984 _globalModes[0][i] = a.charAt(i);
985 _globalModes[1] = new char[b.length()];
986 for (int i = 0; i < b.length(); i++)
987 _globalModes[1][i] = b.charAt(i);
988 _globalModes[2] = new char[c.length()];
989 for (int i = 0; i < c.length(); i++)
990 _globalModes[2][i] = c.charAt(i);
991 _globalModes[3] = new char[d.length()];
992 for (int i = 0; i < d.length(); i++)
993 _globalModes[3][i] = d.charAt(i);
997 private void learnServerVariables(String var[]) {
998 for (int i = 1; i < var.length; i++) {
1000 int pos = v.indexOf('=');
1007 key = v.substring(0, pos);
1008 val = v.substring(pos + 1);
1010 decodeVariable(key, val);
1012 _mode = new ModeHandler(_globalModes, _nickModes);
1016 public void replyReceived(String prefix, String id, String params[]) {
1017 Object[] b = _replylisteners.sendEvent("replyReceived", new Object[] { prefix, id, params, this });
1018 for (int i = 0; i < b.length; i++)
1019 if (((Boolean) b[i]).booleanValue())
1022 if (id.equals("324")) // mode : RPL_CHANNELMODEIS
1024 Channel c = getChannel(params[1], false);
1027 for (int i = 2; i < params.length; i++)
1028 mode += " " + params[i];
1029 mode = mode.substring(1);
1030 c.applyMode(mode, "");
1032 } else if (id.equals("332")) // topic : RPL_TOPIC
1034 Channel c = getChannel(params[1], false);
1036 c.setTopic(params[2], "");
1037 } else if (id.equals("353")) // names : RPL_NAMREPLY
1040 if (params[1].length() == 1)
1042 Channel c = getChannel(params[first], false);
1045 Vector nicks = new Vector();
1046 for (int i = 0; i < params[first + 1].length(); i++) {
1047 char u = params[first + 1].charAt(i);
1049 if (nick.length() > 0)
1050 nicks.insertElementAt(nick, nicks.size());
1056 if (nick.length() > 0)
1057 nicks.insertElementAt(nick, nicks.size());
1060 } else if (id.equals("001")) // RPL_WELCOME
1062 String nick = params[0];
1063 if (!(nick.equals(_nick))) {
1065 if (_status != null)
1066 _status.nickChanged(nick);
1069 _listeners.sendEvent("serverConnected", this);
1070 } else if (id.equals("005")) // RPL_ISUPPORT
1072 learnServerVariables(params);
1073 } else if (id.equals("321")) // /list begin : RPL_LISTSTART
1075 getChanList(_host[_tryServerIndex]).begin();
1076 } else if (id.equals("322")) // /list : RPL_LIST
1078 String name = params[1];
1079 int count = new Integer(params[2]).intValue();
1080 if ((count < 32767) && (isChannel(name))) {
1081 String topic = params[3];
1082 getChanList(_host[_tryServerIndex]).addChannel(new ChannelInfo(name, topic, count));
1084 } else if (id.equals("323")) // /list end : RPL_LISTEND
1086 getChanList(_host[_tryServerIndex]).end();
1087 } else if (id.equals("433")) // nick used : ERR_NICKNAMEINUSE
1094 // We failed to rejoin the channel
1095 // ERR_INVITEONLYCHAN || ERR_CHANNELISFULL || ERR_NOSUCHCHANNEL ||
1096 // ERR_BANNEDFROMCHAN || ERR_BADCHANNELKEY || ERR_BADCHANMASK ||
1097 // ERR_TOOMANYCHANNELS
1098 else if (id.equals("473") || id.equals("471") || id.equals("403") || id.equals("474") || id.equals("475")
1099 || id.equals("476") || id.equals("405")) {
1100 String cname = params[1];
1101 Channel channel = getChannel(cname, false);
1102 if (channel != null) {
1103 sendStatusMessage(getText(IRCTextProvider.SERVER_AUTOREJOIN_FAILED, cname));
1104 _listeners.sendEvent("sourceRemoved", channel, this);
1105 deleteChannel(cname);
1108 // We're performing an action on a channel we're not into
1109 else if (id.equals("442")) // ERR_NOTONCHANNEL
1111 Channel chan = getChannel(params[1], false);
1113 _listeners.sendEvent("sourceRemoved", chan, this);
1114 deleteChannel(chan.getName());
1118 * String toSend=""; for(int i=1;i<params.length;i++)
1119 * toSend+=" "+params[i]; toSend=toSend.substring(1);
1120 * sendStatusMessage(toSend);
1126 private String extractNick(String full) {
1127 int pos = full.indexOf('!');
1130 return full.substring(0, pos);
1133 private boolean isChannel(String name) {
1134 if (name.length() == 0)
1136 for (int i = 0; i < _channelPrefixes.length; i++)
1137 if (name.charAt(0) == _channelPrefixes[i])
1142 private void globalNickRemove(String nick, String reason) {
1143 Enumeration e = _channels.elements();
1144 while (e.hasMoreElements()) {
1145 Channel c = (Channel) e.nextElement();
1146 if (c.hasNick(nick))
1147 c.quitNick(nick, reason);
1151 private void globalNickChange(String oldNick, String newNick) {
1153 e = _channels.elements();
1154 while (e.hasMoreElements()) {
1155 Channel c = (Channel) e.nextElement();
1156 if (c.hasNick(oldNick))
1157 c.changeNick(oldNick, newNick);
1160 Query q = (Query) _queries.get(oldNick.toLowerCase(java.util.Locale.ENGLISH));
1162 _queries.remove(oldNick.toLowerCase(java.util.Locale.ENGLISH));
1163 q.changeNick(newNick);
1164 Query existing = (Query) _queries.get(newNick.toLowerCase(java.util.Locale.ENGLISH));
1165 if (existing != null)
1167 _queries.put(newNick.toLowerCase(java.util.Locale.ENGLISH), q);
1172 * Return true if this server is ignoring the given nick, false otherwise.
1176 * @return the ignore status of the given nick.
1178 public synchronized boolean ignore(String nick) {
1179 return _ignoreList.get(nick) != null;
1183 * Ignore the given nick.
1188 public synchronized void addIgnore(String nick) {
1189 _ignoreList.put(nick, nick);
1193 * Remove the given list from the ignore list.
1196 * nick to remove from ignore list.
1198 public synchronized void removeIgnore(String nick) {
1199 _ignoreList.remove(nick);
1203 public void messageReceived(String prefix, String command, String params[]) {
1204 Object[] b = _messagelisteners.sendEvent("messageReceived", new Object[] { prefix, command, params, this });
1205 for (int i = 0; i < b.length; i++)
1206 if (((Boolean) b[i]).booleanValue())
1210 for (int i = 0; i < params.length; i++)
1211 toSend += " " + params[i];
1213 command = command.toLowerCase(java.util.Locale.ENGLISH);
1215 String nick = extractNick(prefix);
1217 if (command.equals("notice")) {
1218 if (!ignore(nick)) {
1219 if (!_filter.performFromNotice(nick, params[1]))
1220 if (_defaultSource != null)
1221 _defaultSource.noticeReceived(nick, params[1]);
1223 } else if (command.equals("privmsg")) {
1224 if (!ignore(nick)) {
1225 if (isChannel(params[0])) {
1226 if (!_filter.performFromChannelMessage(params[0], nick, params[1])) {
1227 Channel c = getChannel(params[0], false);
1229 c.messageReceived(nick, params[1]);
1232 if (!_filter.performFromNickMessage(nick, params[1])) {
1233 Query q = getQuery(nick, false);
1235 q.messageReceived(nick, params[1]);
1239 } else if (command.equals("join")) {
1240 if (!nick.equals(getNick())) {
1241 Channel c = getChannel(params[0], false);
1243 c.joinNick(nick, "");
1245 Channel c = getChannel(params[0], true);
1248 execute("mode " + params[0]);
1251 } else if (command.equals("part")) {
1252 Channel c = getChannel(params[0], false);
1254 if (params.length > 1) {
1255 c.partNick(nick, params[1]);
1257 c.partNick(nick, "");
1259 if (nick.equals(getNick())) {
1260 _listeners.sendEvent("sourceRemoved", c, this);
1261 deleteChannel(c.getName());
1264 } else if (command.equals("kick")) {
1265 Channel c = getChannel(params[0], false);
1267 String target = params[1];
1269 if (params.length > 2)
1271 c.kickNick(target, nick, reason);
1272 if (target.equals(getNick())) {
1273 if (_ircConfiguration.getB("autorejoin")) {
1274 c.report(getText(IRCTextProvider.SERVER_AUTOREJOIN_ATTEMPT, c.getName()));
1275 execute("join " + params[0]);
1277 _listeners.sendEvent("sourceRemoved", c, this);
1278 deleteChannel(c.getName());
1282 } else if (command.equals("topic")) {
1283 Channel c = getChannel(params[0], false);
1285 c.setTopic(params[1], nick);
1286 } else if (command.equals("mode")) {
1288 for (int i = 1; i < params.length; i++)
1289 full += params[i] + " ";
1290 if (isChannel(params[0])) {
1291 Channel c = getChannel(params[0], false);
1293 MultiModeHandler h = new MultiModeHandler(full, _globalModes, _nickModes);
1294 while (!h.terminated()) {
1296 if (h.isPrefix() || h.isModeA()) {
1297 c.applyUserMode(h.getParameter(), h.getMode(), nick);
1299 if (h.hasParameter())
1300 c.applyMode(h.getMode() + " " + h.getParameter(), nick);
1302 c.applyMode(h.getMode(), nick);
1306 } else if (nick.equals(getNick())) {
1308 if (_status != null)
1309 _status.modeChanged(getMode());
1311 } else if (command.equals("nick")) {
1312 if (nick.equals(getNick())) {
1314 if (_status != null)
1315 _status.nickChanged(getNick());
1317 globalNickChange(nick, params[0]);
1318 } else if (command.equals("quit")) {
1319 if (params.length > 0)
1320 globalNickRemove(nick, params[0]);
1322 globalNickRemove(nick, "");
1323 } else if (command.equals("ping")) {
1324 execute("pong :" + params[0]);
1325 // sendStatusMessage("\3"+"3"+"PING? PONG!");
1326 } else if (command.equals("invite")) {
1327 String invited = params[0];
1328 String channel = params[1];
1329 if (invited.equals(getNick())) {
1330 if (_status != null)
1331 _status.invited(channel, nick);
1333 // if(_defaultSource!=null)
1334 // _defaultSource.report(getText(IRCTextProvider.SOURCE_YOU_INVITED,nick,channel));
1336 } else if (command.equals("error")) {
1337 sendStatusMessage(getText(IRCTextProvider.SERVER_ERROR, params[0]));
1339 // System.out.println("("+command+") "+prefix+" -> "+toSend);
1345 public String getNick() {
1350 public String getUserName() {
1355 * Get the current status mode.
1357 * @return status mode.
1359 public String getMode() {
1360 return _mode.getMode();
1364 public void say(String destination, String str) {
1365 execute("PRIVMSG " + destination + " :" + str);
1369 public void execute(String str) {
1370 int pos = str.indexOf(' ');
1372 String cmd = str.substring(0, pos).toLowerCase(java.util.Locale.ENGLISH);
1373 if (cmd.equals("join")) {
1374 String rem = str.substring(pos + 1);
1375 pos = rem.indexOf(' ');
1377 rem = rem.substring(0, pos);
1378 if (!_ircConfiguration.mayJoin(rem))
1380 } else if (cmd.equals("part")) {
1381 String rem = str.substring(pos + 1);
1382 pos = rem.indexOf(' ');
1384 rem = rem.substring(0, pos);
1385 if (!_ircConfiguration.mayLeave(rem))
1390 pos = str.indexOf(' ');
1392 String cmd = str.substring(0, pos).toUpperCase(java.util.Locale.ENGLISH);
1393 String param = str.substring(pos + 1);
1394 str = cmd + " " + param;
1396 str = str.toUpperCase(java.util.Locale.ENGLISH);
1401 private void sendString(String str) {
1403 _protocol.sendString(str);
1404 } catch (Exception e) {
1405 sendStatusMessage(getText(IRCTextProvider.SERVER_ERROR, e.getMessage()));