/*
* IP Messenger Main Class
* 1997/10/3 (C)Copyright T.Kazawa
*/
package ipmsg;
import JP.digitune.util.ResourceProperties;
import JP.digitune.util.StringReplacer;
import java.awt.*;
//import jp.kyasu.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
public class IPMsg implements IPMComListener {
/*========== Constant Value ==========*/
public static final long IPMSG_COMMASK = 0x000000ffL;
public static final long IPMSG_OPTMASK = 0xffffff00L;
public static final long IPMSG_NOOPERATION = 0x00000000L;
public static final long IPMSG_BR_ENTRY = 0x00000001L;
public static final long IPMSG_BR_EXIT = 0x00000002L;
public static final long IPMSG_ANSENTRY = 0x00000003L;
public static final long IPMSG_BR_ABSENCE = 0x00000004L;
public static final long IPMSG_BR_ISGETLIST = 0x00000018L;
public static final long IPMSG_OKGETLIST = 0x00000015L;
public static final long IPMSG_GETLIST = 0x00000016L;
public static final long IPMSG_ANSLIST = 0x00000017L;
public static final long IPMSG_SENDMSG = 0x00000020L;
public static final long IPMSG_RECVMSG = 0x00000021L;
public static final long IPMSG_READMSG = 0x00000030L;
public static final long IPMSG_DELMSG = 0x00000031L;
public static final long IPMSG_GETINFO = 0x00000040L;
public static final long IPMSG_SENDINFO = 0x00000041L;
public static final long IPMSG_GETPUBKEY = 0x00000072L;
public static final long IPMSG_ANSPUBKEY = 0x00000073L;
// other opt
public static final long IPMSG_ABSENCEOPT = 0x00000100L;
public static final long IPMSG_SERVEROPT = 0x00000200L;
public static final long IPMSG_DIALUPOPT = 0x00010000L;
public static final long IPMSG_ENCRYPTOPT = 0x00400000L;
public static final long IPMSG_ENCRYPTOPTOLD = 0x00800000L;
// send opt
public static final long IPMSG_SENDCHECKOPT = 0x00000100L;
public static final long IPMSG_SECRETOPT = 0x00000200L;
public static final long IPMSG_BROADCASTOPT = 0x00000400L;
public static final long IPMSG_MULTICASTOPT = 0x00000800L;
public static final long IPMSG_NOPOPUPOPT = 0x00001000L;
public static final long IPMSG_AUTORETOPT = 0x00002000L;
public static final long IPMSG_RETRYOPT = 0x00004000L;
public static final long IPMSG_PASSWORDOPT = 0x00008000L;
public static final long IPMSG_NOLOGOPT = 0x00020000L;
public static final long IPMSG_NEWMUTIOPT = 0x00040000L;
// encrypt opt
public static final long IPMSG_RSA_512 = 0x00000001L;
public static final long IPMSG_RSA_1024 = 0x00000002L;
public static final long IPMSG_RSA_2048 = 0x00000004L;
public static final long IPMSG_RC2_40 = 0x00001000L;
public static final long IPMSG_RC2_128 = 0x00004000L;
public static final long IPMSG_RC2_256 = 0x00008000L;
public static final long IPMSG_BLOWFISH_128 = 0x00020000L;
public static final long IPMSG_BLOWFISH_256 = 0x00040000L;
public static final int MAXBUF = 8192;
/*========== end ==========*/
private static final String P_FILE = "runtime.properties";
private ResourceProperties pref = new ResourceProperties("ipmsg.resources");
private boolean state = false;
private InetAddress localaddr;
private long serial = 0;
private String user, host;
private Hashtable userlist = new Hashtable();
private Hashtable dialupmember = new Hashtable();
private Hashtable ipmlistener = new Hashtable();
private Hashtable recentsend = new Hashtable();
private int port;
private int[] ports;
private DatagramSocket dsock;
private IPMProxy proxy;
private int receivecount = 0;
private class CryptoInfo {
private long cap = 0L;
private PublicKey publickey = null;
public CryptoInfo(long cap, PublicKey publickey) {
this.cap = cap;
this.publickey = publickey;
}
public long getCap() {
return cap;
}
public PublicKey getPublicKey() {
return publickey;
}
}
private boolean hasJCE = true;
private Hashtable publickeys = new Hashtable();
private PublicKey publickey = null;
private PrivateKey privatekey = null;
private long getCryptoCaps() {
return IPMSG_RSA_512 | IPMSG_RSA_1024
| IPMSG_RC2_40 | IPMSG_RC2_128
| IPMSG_BLOWFISH_128;
}
String makeKey(IPMComEvent ipme) {
IPMPack tmppack = ipme.getPack();
String key = ipme.getIPMAddress() + ":"
+ tmppack.getUser() + ":" + tmppack.getHost();
return key;
}
public void receive(IPMComEvent ipme) {
if (!state)
return;
IPMPack tmppack = ipme.getPack();
long opt = tmppack.getCommand() & IPMSG_OPTMASK;
switch ((int) (tmppack.getCommand() & IPMSG_COMMASK)) {
case (int) IPMSG_BR_ENTRY:
String nickname = pref.getProperty("nickName");
IPMSend.send(dsock, makePack(IPMSG_ANSENTRY | getEntryOpt()
, nickname, true), ipme.getIPMAddress());
case (int) IPMSG_ANSENTRY:
if (publickey != null)
IPMSend.send(dsock, makePack(IPMSG_GETPUBKEY
, Long.toString(getCryptoCaps(), 16).toUpperCase(), false)
, ipme.getIPMAddress());
case (int) IPMSG_BR_ABSENCE:
userlist.put(makeKey(ipme), ipme);
if ((opt & IPMSG_DIALUPOPT) != 0
&& dialupmember.get(ipme.getIPMAddress().toString()) == null)
dialupmember.put(ipme.getIPMAddress().toString()
, ipme.getIPMAddress());
IPMEvent ie = new IPMEvent(this, IPMEvent.UPDATELIST_EVENT
, new Date(System.currentTimeMillis()), ipme);
invokeListener(ie);
break;
case (int) IPMSG_BR_EXIT:
userlist.remove(makeKey(ipme));
dialupmember.remove(ipme.getIPMAddress().toString());
publickeys.remove(ipme.getIPMAddress().toString());
ie = new IPMEvent(this, IPMEvent.UPDATELIST_EVENT
, new Date(System.currentTimeMillis()), ipme);
invokeListener(ie);
break;
case (int) IPMSG_SENDMSG:
if ((opt & IPMSG_SENDCHECKOPT) != 0)
IPMSend.send(dsock
, makePack(IPMSG_RECVMSG | IPMSG_AUTORETOPT
, new Long(tmppack.getNo()).toString(), false)
, ipme.getIPMAddress());
if (new Boolean(pref.getProperty("absenceState")).booleanValue()
&& (opt & IPMSG_AUTORETOPT) == 0)
try {
String tmpmsg = pref.getProperty("absenceMsg");
if (!tmpmsg.equals(""))
IPMSend.send(dsock
, makePack(IPMSG_SENDMSG | IPMSG_AUTORETOPT
, tmpmsg, false), ipme.getIPMAddress());
} catch (MissingResourceException ex) {}
if (!userlist.containsKey(makeKey(ipme))) {
nickname = pref.getProperty("nickName");
IPMSend.send(dsock
, makePack(IPMSG_BR_ENTRY | IPMSG_AUTORETOPT
| getEntryOpt(), nickname, true)
, ipme.getIPMAddress());
}
if ((opt & IPMSG_ENCRYPTOPT) != 0)
tmppack.setExtra(decryptMessage(tmppack.getExtra()));
ie = new IPMEvent(this, IPMEvent.RECEIVEMSG_EVENT
, new Date(System.currentTimeMillis()), ipme);
invokeListener(ie);
break;
case (int) IPMSG_RECVMSG:
try {
Long tmpLong = new Long(tmppack.getExtra());
NormalSend ns = (NormalSend) recentsend.get(tmpLong);
if (ns != null) {
ns.receiveReply();
recentsend.remove(tmpLong);
}
} catch (NumberFormatException ex) {}
break;
case (int) IPMSG_READMSG:
ie = new IPMEvent(this, IPMEvent.READMSG_EVENT
, new Date(System.currentTimeMillis()), ipme);
invokeListener(ie);
break;
case (int) IPMSG_DELMSG:
ie = new IPMEvent(this, IPMEvent.DELETEMSG_EVENT
, new Date(System.currentTimeMillis()), ipme);
invokeListener(ie);
break;
case (int) IPMSG_GETPUBKEY:
IPMSend.send(dsock, makePack(IPMSG_ANSPUBKEY
, answerPublicKey(ipme.getPack()), false)
, ipme.getIPMAddress());
break;
case (int) IPMSG_ANSPUBKEY:
receivePublicKey(ipme);
break;
case (int) IPMSG_GETINFO:
IPMSend.send(dsock, makePack(IPMSG_SENDINFO
, pref.getProperty("version") + " ("
+ System.getProperty("java.vendor") + " ver."
+ System.getProperty("java.version") + "/"
+ System.getProperty("os.name") + " "
+ System.getProperty("os.version") + ")", fals