0001: /*- LlamaChat.java ------------------------------------------------+
0002: | |
0003: | Copyright (C) 2002-2003 Joseph Monti, LlamaChat |
0004: | countjoe@users.sourceforge.net |
0005: | http://www.42llamas.com/LlamaChat/ |
0006: | |
0007: | This program is free software; you can redistribute it and/or |
0008: | modify it under the terms of the GNU General Public License |
0009: | as published by the Free Software Foundation; either version 2 |
0010: | of the License, or (at your option) any later version |
0011: | |
0012: | This program is distributed in the hope that it will be useful, |
0013: | but WITHOUT ANY WARRANTY; without even the implied warranty of |
0014: | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
0015: | GNU General Public License for more details. |
0016: | |
0017: | A copy of the GNU General Public License may be found in the |
0018: | installation directory named "GNUGPL.txt" |
0019: | |
0020: +-----------------------------------------------------------------+
0021: */
0022:
0023: package client;
0024:
0025: import java.awt.*;
0026: import java.awt.event.*;
0027: import javax.swing.*;
0028: import javax.swing.text.*;
0029: import javax.swing.text.html.*;
0030: import javax.swing.event.*;
0031: import javax.swing.border.*;
0032: import java.util.*;
0033: import java.lang.*;
0034: import java.net.URL;
0035: import java.net.MalformedURLException;
0036: import java.nio.CharBuffer;
0037: import java.util.regex.Pattern;
0038: import java.util.Properties;
0039:
0040: import common.*;
0041: import common.sd.*;
0042:
0043: /* -------------------- JavaDoc Information ----------------------*/
0044: /**
0045: * For use in a webpage:<br><pre>
0046: <OBJECT
0047: classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
0048: width="615" height="360"
0049: codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4-windows-i586.cab#Version=1,4,0,mn">
0050: <PARAM name="code" value="LlamaChat.class">
0051: <PARAM name="archive" value="LlamaChat.jar">
0052: <PARAM name="type" value="application/x-java-applet;version=1.4">
0053: <PARAM name="scriptable" value="true">
0054: <param name="username" value="[replace with username]">
0055: <param name="port" value="[replace with port]">
0056: <COMMENT>
0057: <EMBED type="application/x-java-applet;version=1.4"
0058: width="615" height="331"
0059: code="LlamaChat.class" archive="LlamaChat.jar"
0060: pluginspage="http://java.sun.com/j2se/1.4.1/download.html"
0061: username="[replace with username]"
0062: port="[replace with port]">
0063: <NOEMBED>
0064: No Java 1.4 plugin
0065: </NOEMBED></EMBED>
0066: </COMMENT>
0067: </OBJECT>
0068: </pre>
0069: This is the LlamaChat client applet; The above html needs values for
0070: username, port, site, and location; Username is the name of the connecting
0071: user, port is the port on which the server is running, site is the
0072: IP address or hostname of the server, location is the location of the
0073: client applet on the web
0074: * @author Joseph Monti <a href="mailto:countjoe@users.sourceforge.net">countjoe@users.sourceforge.net</a>
0075: * @version 0.8
0076: */
0077: /*
0078: For use in a webpage:
0079: <OBJECT
0080: classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
0081: width="615" height="360"
0082: codebase="http://java.sun.com/products/plugin/autodl/jinstall-1_4-windows-i586.cab#Version=1,4,0,mn">
0083: <PARAM name="code" value="client/LlamaChat.class">
0084: <PARAM name="archive" value="LlamaChat.jar">
0085: <PARAM name="type" value="application/x-java-applet;version=1.4">
0086: <PARAM name="scriptable" value="true">
0087: <param name="username" value="[replace with username]">
0088: <param name="port" value="[replace with port]">
0089: <COMMENT>
0090: <EMBED type="application/x-java-applet;version=1.4"
0091: width="615" height="331"
0092: code="client/LlamaChat.class" archive="LlamaChat.jar"
0093: pluginspage="http://java.sun.com/j2se/1.4.1/download.html"
0094: username="[replace with username]"
0095: port="[replace with port]">
0096: <NOEMBED>
0097: No Java 1.4 plugin
0098: </NOEMBED></EMBED>
0099: </COMMENT>
0100: </OBJECT>
0101: */
0102: public class LlamaChat extends JApplet {
0103:
0104: public String username;
0105: private ServerConnection server;
0106: public int PORT;
0107: public String site;
0108: public ArrayList users;
0109: private CommandHistory history;
0110: public ArrayList ignores;
0111: public ArrayList afks;
0112: public ArrayList admins;
0113: public boolean admin;
0114: public String locationURL;
0115: private final String linkURL = "http://joe.tgpr.org/LlamaChat";
0116: public Hashtable channels;
0117: private static final String VERSION = "v0.8";
0118: public PrivateMsg privates;
0119: public boolean showUserStatus;
0120: public boolean chanAdmin;
0121:
0122: Container c;
0123:
0124: ChatPane mainChat;
0125: JList userList;
0126: JTextField messageText;
0127: JScrollPane textScroller;
0128: JPopupMenu popup;
0129: JComboBox cboChannels;
0130: JButton butChannel;
0131: JButton butCreate;
0132:
0133: ImageIcon conNo;
0134: ImageIcon conYes;
0135: ImageIcon secNo;
0136: ImageIcon secYes;
0137: JLabel conIcon;
0138: JLabel secIcon;
0139: JLabel bottomText;
0140:
0141: MyAction myAction;
0142: MyKeyListener myKeyListener;
0143: MyMouseListener myMouseListener;
0144: MyHyperlinkListener myHyperlinkListener;
0145: Color myColors[] = new Color[3];
0146:
0147: Rectangle rect;
0148:
0149: /**
0150: * Initializes the graphical components
0151: */
0152: public void init() {
0153: username = getParameter("username");
0154: if (username == null) {
0155: username = JOptionPane.showInputDialog(this ,
0156: "Please enter a username", "Login",
0157: JOptionPane.QUESTION_MESSAGE);
0158: }
0159: try {
0160: PORT = Integer.valueOf(getParameter("port")).intValue();
0161: } catch (NumberFormatException e) {
0162: PORT = 42412;
0163: }
0164:
0165: URL url = getDocumentBase();
0166: site = url.getHost();
0167: locationURL = "http://" + site + ":" + url.getPort() + "/"
0168: + url.getPath();
0169:
0170: setSize(615, 362);
0171: c = getContentPane();
0172:
0173: c.setBackground(new Color(224, 224, 224));
0174:
0175: if (site == null || locationURL == null) {
0176: c.add(new JLabel(
0177: "ERROR: did not recieve needed data from page"));
0178: }
0179:
0180: myAction = new MyAction();
0181: myKeyListener = new MyKeyListener();
0182: myMouseListener = new MyMouseListener();
0183: myHyperlinkListener = new MyHyperlinkListener();
0184:
0185: c.setLayout(null);
0186:
0187: cboChannels = new JComboBox();
0188: cboChannels.setBounds(5, 5, 150, 24);
0189:
0190: butChannel = new JButton("Join");
0191: butChannel.setToolTipText("Join channel");
0192: butChannel.addActionListener(myAction);
0193: butChannel.setBounds(160, 5, 60, 24);
0194:
0195: butCreate = new JButton("Create");
0196: butCreate.setToolTipText("Create new channel");
0197: butCreate.addActionListener(myAction);
0198: butCreate.setBounds(230, 5, 80, 24);
0199: butCreate.setEnabled(false);
0200:
0201: mainChat = new ChatPane(this );
0202: textScroller = new JScrollPane(mainChat,
0203: JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
0204: JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
0205: textScroller.setBounds(5, 34, 500, 270);
0206:
0207: userList = new JList();
0208: userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
0209: userList.setCellRenderer(new MyCellRenderer());
0210: userList.setBackground(new Color(249, 249, 250));
0211: JScrollPane userScroller = new JScrollPane(userList);
0212: userScroller.setBounds(510, 34, 100, 297);
0213:
0214: messageText = new JTextField();
0215: messageText.setBounds(5, 309, 500, 22);
0216: messageText.setColumns(10);
0217: messageText.setBackground(new Color(249, 249, 250));
0218:
0219: JMenuItem item;
0220: popup = new JPopupMenu("test");
0221: popup.add("whisper").addActionListener(myAction);
0222: popup.add("private message").addActionListener(myAction);
0223: popup.add("ignore").addActionListener(myAction);
0224: popup.add("clear ignore list").addActionListener(myAction);
0225:
0226: conNo = new ImageIcon(getURL("images/connect_no.gif"));
0227: conYes = new ImageIcon(getURL("images/connect_established.gif"));
0228: secNo = new ImageIcon(getURL("images/decrypted.gif"));
0229: secYes = new ImageIcon(getURL("images/encrypted.gif"));
0230:
0231: conIcon = new JLabel(conNo);
0232: conIcon.setBorder(new EtchedBorder());
0233: secIcon = new JLabel(secNo);
0234: secIcon.setBorder(new EtchedBorder());
0235:
0236: conIcon.setBounds(563, 334, 22, 22);
0237: secIcon.setBounds(588, 334, 22, 22);
0238:
0239: bottomText = new JLabel("<html><body><font color=#445577><b>"
0240: + "LlamaChat " + VERSION + "</b></font> © "
0241: + "<a href=\"" + linkURL
0242: + "\">Joseph Monti</a> 2002-2003" + "</body></html>");
0243: bottomText.setBounds(5, 336, 500, 20);
0244:
0245: c.add(cboChannels);
0246: c.add(butChannel);
0247: c.add(butCreate);
0248: c.add(textScroller);
0249: c.add(userScroller);
0250: c.add(messageText);
0251: c.add(conIcon);
0252: c.add(secIcon);
0253: c.add(bottomText);
0254:
0255: userList.addMouseListener(myMouseListener);
0256: messageText.addKeyListener(myKeyListener);
0257: bottomText.addMouseListener(myMouseListener);
0258:
0259: users = new ArrayList();
0260: ignores = new ArrayList(5);
0261: afks = new ArrayList(5);
0262: admins = new ArrayList(5);
0263: history = new CommandHistory(10);
0264: admin = false;
0265: channels = new Hashtable();
0266: privates = new PrivateMsg(this );
0267: showUserStatus = false;
0268:
0269: myColors[0] = new Color(200, 0, 0);
0270: myColors[1] = new Color(0, 150, 0);
0271: myColors[2] = new Color(0, 0, 200);
0272:
0273: rect = new Rectangle(0, 0, 1, 1);
0274:
0275: String opening = "<font color=#333333>"
0276: + "==================================<br>"
0277: + "Welcome to LlamaChat " + VERSION + "<br>"
0278: + "If you need assistance, type \\help<br>"
0279: + "Enjoy your stay!<br>"
0280: + "==================================<br></font>";
0281: HTMLDocument doc = (HTMLDocument) mainChat.getDocument();
0282: HTMLEditorKit kit = (HTMLEditorKit) mainChat.getEditorKit();
0283: try {
0284: kit.insertHTML(doc, doc.getLength(), opening, 0, 0,
0285: HTML.Tag.FONT);
0286: } catch (Throwable t) {
0287: t.printStackTrace(System.out);
0288: }
0289:
0290: // validate the name
0291: if (!username.matches("[\\w_-]+?")) {
0292: error("username contains invalid characters, changing to "
0293: + "'invalid' for now. "
0294: + "Type \\rename to chose a new name");
0295: username = "invalid";
0296: }
0297: if (username.length() > 10) {
0298: username = username.substring(0, 10);
0299: error("username too long, changed to " + username);
0300: }
0301:
0302: connect();
0303: }
0304:
0305: public void start() {
0306: }
0307:
0308: public void stop() {
0309: if (server != null)
0310: server._writeObject(new SD_UserDel(null)); // to bypass the queue
0311: }
0312:
0313: /**
0314: * Subclass to act as the action listener for graphical components
0315: */
0316: protected final class MyAction implements ActionListener {
0317: public void actionPerformed(ActionEvent ae) {
0318: String cmd = ae.getActionCommand().intern();
0319: if (ae.getSource() == butChannel) {
0320: String pass = null;
0321: String channel = (String) cboChannels.getSelectedItem();
0322: if (channels.containsKey(channel)
0323: && ((Boolean) channels.get(channel))
0324: .booleanValue()) {
0325: String message = "Password for " + channel
0326: + "? (blank for no password)";
0327: pass = JOptionPane.showInputDialog((Component) ae
0328: .getSource(), message, "Join Channel",
0329: JOptionPane.QUESTION_MESSAGE);
0330: }
0331: server.writeObject(new SD_Channel(false, channel, (""
0332: .equals(pass) ? null : pass)));
0333: showUserStatus = false;
0334: } else if (ae.getSource() == butCreate) {
0335: String channel = JOptionPane.showInputDialog(
0336: (Component) ae.getSource(),
0337: "Enter the name of the channel",
0338: "Create Channel",
0339: JOptionPane.INFORMATION_MESSAGE);
0340: if (channel == null)
0341: return;
0342: String message = "Password for " + channel
0343: + "? (blank for no password)";
0344: String pass = JOptionPane.showInputDialog(
0345: (Component) ae.getSource(), message,
0346: "Join Channel", JOptionPane.QUESTION_MESSAGE);
0347: server.writeObject(new SD_Channel(true, channel, (""
0348: .equals(pass) ? null : pass)));
0349: showUserStatus = false;
0350: } else if (cmd == "whisper") {
0351: String user = (String) userList.getSelectedValue();
0352: if (user != null && !messageText.getText().equals("")
0353: && !user.equals(username)) {
0354: messageText.setText("\\whisper " + user + " "
0355: + messageText.getText());
0356: sendMessage();
0357: } else {
0358: error("invalid user or no message, type a message below,"
0359: + " select a user, and then whisper");
0360: }
0361: } else if (cmd == "private message") {
0362: String user = (String) userList.getSelectedValue();
0363: if (user != null && !user.equals(username)) {
0364: privates.newPrivate(user);
0365: } else {
0366: error("invalid user");
0367: }
0368: } else if (ae.getActionCommand().equals("ignore")) {
0369: String user = (String) userList.getSelectedValue();
0370: if (user != null) {
0371: ignore(user, false);
0372: } else {
0373: error("no user selected");
0374: }
0375: } else if (cmd == "clear ignore list") {
0376: ignores.clear();
0377: updateList();
0378: serverMessage("ignore list cleared");
0379: } else if (cmd == "kick user") {
0380: String user = (String) userList.getSelectedValue();
0381: if (user != null) {
0382: if (user.equals(username)) {
0383: error("cannot kick yourself");
0384: } else {
0385: server.writeObject(new SD_Kick(user));
0386: }
0387: } else {
0388: error("no user selected");
0389: }
0390: }
0391: }
0392: }
0393:
0394: /**
0395: * Subclass to act as the key listener for the graphical componets
0396: */
0397: protected final class MyKeyListener implements KeyListener {
0398: public void keyTyped(KeyEvent ke) {
0399: if (ke.getKeyChar() == KeyEvent.VK_ENTER) {
0400: sendMessage();
0401: }
0402: }
0403:
0404: public void keyPressed(KeyEvent ke) {
0405: //
0406: }
0407:
0408: public void keyReleased(KeyEvent ke) {
0409: if (ke.getKeyCode() == KeyEvent.VK_UP) {
0410: String up = history.getUp();
0411: if (up != null)
0412: messageText.setText(up);
0413: } else if (ke.getKeyCode() == KeyEvent.VK_DOWN) {
0414: String down = history.getDown();
0415: if (down != null)
0416: messageText.setText(down);
0417: }
0418: }
0419: }
0420:
0421: /**
0422: * Subclass to act as the mouse listener for the graphical components
0423: */
0424: protected final class MyMouseListener implements MouseListener {
0425: public void mousePressed(MouseEvent e) {
0426: }
0427:
0428: public void mouseReleased(MouseEvent e) {
0429: maybeShowPopup(e);
0430: }
0431:
0432: public void mouseEntered(MouseEvent e) {
0433: if (e.getSource() == bottomText) {
0434: bottomText.setCursor(Cursor
0435: .getPredefinedCursor(Cursor.HAND_CURSOR));
0436: }
0437: }
0438:
0439: public void mouseExited(MouseEvent e) {
0440: if (e.getSource() == bottomText) {
0441: bottomText.setCursor(Cursor.getDefaultCursor());
0442: }
0443: }
0444:
0445: public void mouseClicked(MouseEvent e) {
0446: if (e.getSource() == bottomText) {
0447: try {
0448: getAppletContext().showDocument(new URL(linkURL),
0449: "_blank");
0450: } catch (java.net.MalformedURLException ex) {
0451: }
0452: } else {
0453: maybeShowPopup(e);
0454: }
0455: }
0456:
0457: /**
0458: * Checks to see if the event was to show the popup menu
0459: */
0460: private void maybeShowPopup(MouseEvent e) {
0461: if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {
0462: popup.show(userList, e.getX(), e.getY());
0463: }
0464: }
0465: }
0466:
0467: protected final class MyHyperlinkListener implements
0468: HyperlinkListener {
0469: public void hyperlinkUpdate(HyperlinkEvent e) {
0470: if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
0471: getAppletContext().showDocument(e.getURL(), "_blank");
0472: }
0473: }
0474: }
0475:
0476: /**
0477: * a Subclass to handle cell items in the user list
0478: * lets us modify add an icon to the username
0479: */
0480: protected final class MyCellRenderer extends
0481: DefaultListCellRenderer {
0482: final ImageIcon normal = new ImageIcon(
0483: getURL("images/face.gif"));
0484: final ImageIcon ignored = new ImageIcon(
0485: getURL("images/face_ignore.gif"));
0486: final ImageIcon afk = new ImageIcon(getURL("images/afk.gif"));
0487: final ImageIcon admin = new ImageIcon(
0488: getURL("images/admin.gif"));
0489:
0490: /* This is the only method defined by ListCellRenderer. We just
0491: * reconfigure the Jlabel each time we're called.
0492: */
0493: public Component getListCellRendererComponent(JList list,
0494: Object value, // value to display
0495: int index, // cell index
0496: boolean iss, // is the cell selected
0497: boolean chf) // the list and the cell have the focus
0498: {
0499: /* The DefaultListCellRenderer class will take care of
0500: * the JLabels text property, it's foreground and background
0501: * colors, and so on.
0502: */
0503: super .getListCellRendererComponent(list, value, index, iss,
0504: chf);
0505: if (afks.contains(value.toString())) {
0506: setIcon(afk);
0507: } else if (admins.contains(value.toString())) {
0508: setIcon(admin);
0509: } else if (ignores.contains(value.toString())) {
0510: setIcon(ignored);
0511: } else {
0512: setIcon(normal);
0513: }
0514: if (username.equals(getText())) {
0515: setForeground(myColors[1]);
0516: } else {
0517: setForeground(myColors[2]);
0518: }
0519:
0520: return this ;
0521: }
0522: }
0523:
0524: /**
0525: * Method to take a filename and return a URL object
0526: * @param filename the name of the file to be turned into URL
0527: * @return the url representing filename
0528: */
0529: protected final URL getURL(String filename) {
0530: URL url = null;
0531:
0532: try {
0533: url = new URL(locationURL + filename);
0534: } catch (java.net.MalformedURLException e) {
0535: System.err.println("Couldn't create image: "
0536: + "badly specified URL");
0537: return null;
0538: }
0539:
0540: return url;
0541: }
0542:
0543: /**
0544: * Method called when a user message has been sent.
0545: * checks to see if it is a command or regular message
0546: */
0547: private void sendMessage() {
0548: String txt = new String(messageText.getText());
0549: if (!txt.equals("")) {
0550: if (txt.charAt(0) == '\\' || txt.charAt(0) == '/') {
0551: parseCommand(txt.substring(1));
0552: messageText.setText("");
0553: history.add(txt);
0554: } else if (server != null && server.connected
0555: && username != null) {
0556: sendText(username, txt, false);
0557: messageText.setText("");
0558: sendChat(txt);
0559: history.add(txt);
0560: } else {
0561: error("Not connected, type \\reconnect to try and reconnect");
0562: }
0563: }
0564: }
0565:
0566: /**
0567: * Method to parse a command and perform the specified action
0568: * @param cmd the command that the user typed
0569: * @return a status indicator to tell if the command was valid
0570: */
0571: public boolean parseCommand(String cmd) {
0572: cmd = cmd.intern();
0573: if (cmd == "help" || cmd == "?") {
0574: String commands = "Listing available commands:\n"
0575: + "<pre>\\help or \\? \t\t- display this message<br>"
0576: + "\\admin <passphrase> \t- become an admin<br>"
0577: + "\\create <channel> [password]\t- create a new channel with optional password<br>"
0578: + "\\join <channel> [password]\t- join channel with optional password<br>"
0579: + "\\disconnect \t\t- disconnect from server<br>"
0580: + "\\whisper <user> <message> \t- whisper to a user<br>"
0581: + "\\private <user> \t- start a private message session<br>"
0582: + "\\ignore <user> \t\t- ignores a user<br>"
0583: + "\\clearignore \t\t- clear list of ignores<br>"
0584: + "\\reconnect \t\t- attempt to reconnect to server<br>"
0585: + "\\rename <new name> \t\t- change your username<br>";
0586: if (admin) {
0587: commands += "\\kick <user> \t\t- kick user from room<br>"
0588: + "\\logstart \t\t- start logging sessoin<br>"
0589: + "\\logstop \t\t- stop logging session<br>";
0590: }
0591: commands += "up or down \t\t- cycle your chat history</pre>";
0592: sendText("server", commands, false);
0593: return true;
0594: } else if (cmd == "disconnect") {
0595: if (server != null) {
0596: stop();
0597: }
0598: return true;
0599: } else if (cmd == "reconnect") {
0600: if (username == null) {
0601: error("username still invalid. use \\rename <new name> to chose a new name and reconnect");
0602: } else {
0603: if (server != null) {
0604: stop();
0605: }
0606: server = new ServerConnection(this );
0607: }
0608: return true;
0609: } else if (cmd == "clearignore") {
0610: ignores.clear();
0611: updateList();
0612: serverMessage("ignore list cleared");
0613: return true;
0614: } else if (cmd.startsWith("whisper")) {
0615: int start = cmd.indexOf(' ');
0616: if (start < 0) {
0617: error("usage: \\whisper <user> <message>");
0618: return false;
0619: }
0620: cmd = cmd.substring(start + 1);
0621: start = cmd.indexOf(' ');
0622: if (start < 0) {
0623: error("usage: \\whisper <user> <message>");
0624: return false;
0625: }
0626: String un = cmd.substring(0, start);
0627: if (username.equals(un) || !users.contains(un)) {
0628: error("invalid user");
0629: return false;
0630: }
0631: String message = cmd.substring(start + 1);
0632: if (message.length() < 1) {
0633: error("usage: \\whisper <user> <message>");
0634: }
0635: sendWhisper(un, message);
0636: sendText(username, message, true);
0637: return true;
0638: } else if (cmd.startsWith("private")) {
0639: int start = cmd.indexOf(' ');
0640: if (start < 0) {
0641: error("usage: \\private <user>");
0642: return false;
0643: }
0644: String un = cmd.substring(start + 1);
0645: if (username.equals(un)) {
0646: error("cannot private message yourself");
0647: return false;
0648: }
0649: privates.newPrivate(un);
0650: return true;
0651: } else if (cmd.startsWith("rename")) {
0652: int start = cmd.indexOf(' ');
0653: if (start < 0) {
0654: error("usage: \\rename <newname>");
0655: return false;
0656: }
0657: String newName = cmd.substring(start + 1);
0658: if ((newName.length() < 1) || (newName.length()) > 10
0659: || (newName.equals("server"))
0660: || (!newName.matches("[\\w_-]+?"))) {
0661: error("invalid name");
0662: return false;
0663: }
0664: if (!server.connected) {
0665: server = new ServerConnection(this );
0666: }
0667: if (username == null) {
0668: username = newName;
0669: server.writeObject(new SD_UserAdd(newName));
0670: } else {
0671: rename(username, newName);
0672: username = newName;
0673: server.writeObject(new SD_Rename(null, username));
0674: }
0675: return true;
0676: } else if (cmd.startsWith("ignore")) {
0677: int start = cmd.indexOf(' ');
0678: if (start < 0) {
0679: error("usage: \\ignre <user>");
0680: return false;
0681: }
0682: ignore(cmd.substring(start + 1), false);
0683: return true;
0684: } else if (cmd.startsWith("join")) {
0685: int start = cmd.indexOf(' ');
0686: if (start < 0) {
0687: error("usage: \\join <channel> [password]");
0688: return false;
0689: }
0690: String name = cmd.substring(start + 1);
0691: String pass = null;
0692: start = name.indexOf(' ');
0693: if (start > 0) {
0694: pass = name.substring(start + 1);
0695: name = name.substring(0, start);
0696: }
0697: server.writeObject(new SD_Channel(false, name, pass));
0698: return true;
0699: } else if (cmd.startsWith("create")) {
0700: int start = cmd.indexOf(' ');
0701: if (start < 0) {
0702: error("usage: \\create <channel> [password]");
0703: return false;
0704: }
0705: String name = cmd.substring(start + 1);
0706: String pass = null;
0707: start = name.indexOf(' ');
0708: if (start > 0) {
0709: pass = name.substring(start + 1);
0710: name = name.substring(0, start);
0711: }
0712: server.writeObject(new SD_Channel(true, name, pass));
0713: return true;
0714: /* } else if (cmd.startsWith("proxy")) {
0715: int start = cmd.indexOf(' ');
0716: if (start < 0) {
0717: error("usage: \\proxy <host> <port>");
0718: return false;
0719: }
0720: String phost = cmd.substring(start+1);
0721: start = phost.indexOf(' ');
0722: if (start < 0) {
0723: error("usage: \\proxy <host> <port>");
0724: return false;
0725: }
0726: String pport = phost.substring(start+1);
0727: phost = phost.substring(0, start);
0728: Properties systemSettings = System.getProperties();
0729: systemSettings.put("proxySet", "true");
0730: systemSettings.put("proxyHost", phost);
0731: systemSettings.put("proxyPort", pport);
0732: System.setProperties(systemSettings);
0733: serverMessage("Using " + phost + ":" + pport + " as proxy server<br>you can type \\reconnect to reconnect with this proxy");
0734: return true; */
0735: } else if (cmd.startsWith("admin")) {
0736: int start = cmd.indexOf(' ');
0737: if (start < 0) {
0738: error("usage: \\admin <password>");
0739: return false;
0740: }
0741: String pass = cmd.substring(start + 1);
0742: server.writeObject(new SD_AdminAdd(pass));
0743: return true;
0744: } else if (admin && cmd.startsWith("kick")) {
0745: int start = cmd.indexOf(' ');
0746: if (start < 0) {
0747: error("usage: \\kick <user>");
0748: return false;
0749: }
0750: String un = cmd.substring(start + 1);
0751: if (un.equals(username)) {
0752: error("cannot kick yourself");
0753: return false;
0754: }
0755: server.writeObject(new SD_Kick(un));
0756: return true;
0757: } else if (admin && cmd == "logstart") {
0758: server.writeObject(new SD_Log(true));
0759: return true;
0760: } else if (admin && cmd == "logstop") {
0761: server.writeObject(new SD_Log());
0762: return true;
0763: }
0764: error("unrecognized command, type \\help for help");
0765: return false;
0766: }
0767:
0768: /**
0769: * Method to ignore all incoming messages from a user
0770: * @param i the user to ignore
0771: * @param quite if true will not show confirmation
0772: * @return true on succes, false on failure
0773: */
0774: private boolean ignore(String i, boolean quiet) {
0775: if (username.equals(i) || i.equals("server")
0776: || admins.contains(i)) {
0777: if (!quiet) {
0778: error("can't ignore that person");
0779: }
0780: return false;
0781: }
0782: if (!users.contains(i)) {
0783: if (!quiet) {
0784: error("user does not exists");
0785: }
0786: return false;
0787: }
0788: if (ignores.contains(i)) {
0789: if (!quiet) {
0790: error("already ignoring user");
0791: }
0792: return false;
0793: }
0794: ignores.add(i);
0795: updateList();
0796: if (!quiet) {
0797: serverMessage("ignoring " + i);
0798: }
0799: return true;
0800: }
0801:
0802: /**
0803: * Sends a text to the chat window. Parses the message to pick
0804: * out emoticons.
0805: * @param un the name of the user sending the message
0806: * @param message the message to be sent
0807: * @param whisper indicates the message was a wisper and makes the
0808: * message italic
0809: */
0810: public void sendText(String un, String message, boolean whisper) {
0811: mainChat.sendText(un, message, whisper);
0812: }
0813:
0814: /**
0815: * Create a new connection to a server
0816: */
0817: private void connect() {
0818: server = new ServerConnection(this );
0819: }
0820:
0821: /**
0822: * sends a new message to the server
0823: * @param message the message to be sent
0824: */
0825: private void sendChat(String message) {
0826: if (server != null) {
0827: server.writeObject(new SD_Chat(null, message));
0828: }
0829: }
0830:
0831: /**
0832: * sends a whisper to the server
0833: * @param message the message to be sent
0834: */
0835: private void sendWhisper(String to, String message) {
0836: if (server != null) {
0837: server.writeObject(new SD_Whisper(to, message));
0838: }
0839: }
0840:
0841: /**
0842: * sorts the user list and rebuilds the user list from
0843: * the sorted user vector,
0844: */
0845: public void updateList() {
0846: Object[] tmp = users.toArray();
0847: Arrays.sort(tmp);
0848: userList.setListData(tmp);
0849: }
0850:
0851: /**
0852: * adds a new user to the interal list of users
0853: * @param un the name of the user to be added
0854: */
0855: public void userAdd(String un) {
0856: if (!users.contains(un)) {
0857: users.add(un);
0858: updateList();
0859: if (!un.equals(username) && showUserStatus)
0860: serverMessage(un + " has joined " + server.channel);
0861: }
0862: }
0863:
0864: /**
0865: * removes a user from the user list
0866: * @param un the name of the user to be removed
0867: */
0868: public void userDel(String un) {
0869: users.remove(users.indexOf(un));
0870: if (ignores.contains(un)) {
0871: ignores.remove(ignores.indexOf(un));
0872: }
0873: if (afks.contains(un)) {
0874: afks.remove(afks.indexOf(un));
0875: }
0876: if (admins.contains(un)) {
0877: admins.remove(admins.indexOf(un));
0878: }
0879: updateList();
0880: serverMessage(un + " has left " + server.channel);
0881: privates.serverMessage(un, un + " has left");
0882: }
0883:
0884: /**
0885: * changes the name of a user, updating list of admins,
0886: * afks, ignoes, and master user list
0887: * @param on old username
0888: * @param nn new username
0889: */
0890: public void rename(String on, String nn) {
0891: if (admins.contains(on)) {
0892: admins.remove(admins.indexOf(on));
0893: admins.add(nn);
0894: }
0895: if (afks.contains(on)) {
0896: afks.remove(afks.indexOf(on));
0897: afks.add(nn);
0898: }
0899: if (ignores.contains(on)) {
0900: ignores.remove(ignores.indexOf(on));
0901: ignores.add(nn);
0902: }
0903: users.remove(on);
0904: users.add(nn);
0905: updateList();
0906: serverMessage(on + " renamed to " + nn);
0907: }
0908:
0909: /**
0910: * Recieving method for a chat message
0911: * @param un the name of the user sending the chat
0912: * @param message the message that was sent
0913: */
0914: public void recieveChat(String un, String message) {
0915: if (!ignores.contains(un)) {
0916: sendText(un, message, false);
0917: }
0918: }
0919:
0920: /**
0921: * Reciving method for a whisper
0922: * @param un the name of the user sending the whisper
0923: * @param message the message that was sent
0924: */
0925: public void recieveWhisper(String un, String message) {
0926: if (!ignores.contains(un)) {
0927: sendText(un, message, true);
0928: }
0929: }
0930:
0931: /**
0932: * Recieving method for private
0933: * @param un the name of the user sending the message
0934: * @param message the message that was sent
0935: */
0936: public void recievePrivate(String un, String message) {
0937: if (!ignores.contains(un)) {
0938: privates.recievePrivate(un, message);
0939: }
0940: }
0941:
0942: /**
0943: * signifies an error and reports it to the user
0944: * @param s the error message
0945: */
0946: public void error(String s) {
0947: mainChat.error(s);
0948: }
0949:
0950: /**
0951: * A shortcut to be used when a message from the server (or any automated
0952: * message) must ben sent to the client
0953: * @param s the message
0954: */
0955: public void serverMessage(String s) {
0956: sendText("server", s, false);
0957: }
0958:
0959: /**
0960: * cleans up a connection by removing all user from all maintained lists
0961: */
0962: public void close() {
0963: error("Connection to server was lost");
0964: admin = false;
0965: users.clear();
0966: afks.clear();
0967: ignores.clear();
0968: admins.clear();
0969: channels.clear();
0970: cboChannels.removeAllItems();
0971: updateList();
0972: }
0973:
0974: /**
0975: * used to manage the connection icons to signify connection and
0976: * secure status
0977: * @param b true if connected
0978: */
0979: public void setConnected(boolean b) {
0980: if (b) {
0981: conIcon.setIcon(conYes);
0982: conIcon.setToolTipText("Connected");
0983: secIcon.setIcon(secYes);
0984: secIcon.setToolTipText("Secure Connection");
0985: butChannel.setEnabled(true);
0986: } else {
0987: conIcon.setIcon(conNo);
0988: conIcon.setToolTipText("Not Connected");
0989: secIcon.setIcon(secNo);
0990: secIcon.setToolTipText("Connection not Secured");
0991: butChannel.setEnabled(false);
0992: butCreate.setEnabled(false);
0993: }
0994: }
0995:
0996: /**
0997: * sets this user to be an admin
0998: */
0999: public void setAdmin() {
1000: admin = true;
1001: popup.add("kick user").addActionListener(myAction);
1002: if (chanAdmin) {
1003: butCreate.setEnabled(true);
1004: }
1005: }
1006:
1007: /**
1008: * creates a new channel, if the channel exists it is removed
1009: * (this method doubles as a removeChannel)
1010: * @param name the name of the channel
1011: */
1012: public void newChannel(String name, boolean pass) {
1013: if (channels.containsKey(name)) {
1014: channels.remove(name);
1015: cboChannels.removeItem(name);
1016: } else {
1017: channels.put(name, new Boolean(pass));
1018: cboChannels.addItem(name);
1019: }
1020: }
1021:
1022: public void sendPrivate(String name, String message) {
1023: server.writeObject(new SD_Private(name, message));
1024: }
1025: }
|