<NME> IMC2Driver.java
<BEF> package com.planet_ink.coffee_mud.core.intermud.imc2;

import com.planet_ink.coffee_mud.Commands.interfaces.Command;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.ChannelsLibrary.CMChannel;
import com.planet_ink.coffee_mud.Libraries.interfaces.ChannelsLibrary.ChannelFlag;
import com.planet_ink.coffee_mud.Libraries.interfaces.ChannelsLibrary;
import com.planet_ink.coffee_mud.Libraries.interfaces.ColorLibrary;
import com.planet_ink.coffee_mud.Locales.interfaces.Room;
import com.planet_ink.coffee_mud.MOBS.interfaces.MOB;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.CMSecurity.DbgFlag;
import com.planet_ink.coffee_mud.core.CMSecurity.DisFlag;
import com.planet_ink.coffee_mud.core.collections.*;

import java.io.*;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.*;

/**
 * IMC2 version 0.10 - an inter-mud communications protocol
 * Copyright (C) 1996 - 1997 Oliver Jowet: oliver@randomly.org
 *
 * IMC2 Gold versions 1.00 though 2.00 are developed by MudWorld.
 * Copyright (C) 1999 - 2002 Haslage Net Electronics (Anthony R. Haslage)
 *
 * IMC2 MUD-Net version 3.10 is developed by Alsherok and Crimson Oracles
 * Copyright (C) 2002 Roger Libiez ( Samson )
 * Additional code Copyright (C) 2002 Orion Elder
 * Registered with the United States Copyright Office
 * TX 5-555-584
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (see the file COPYING); if not, write to the
 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Ported to Java by Istvan David (u_davis@users.sourceforge.net)
 *
 */

public final class IMC2Driver extends Thread
{
	Socket sa;

	/* a player on IMC */
	final class imc_char_data {
		String name = ""; /* name of character */
		int invis; /* invisible to IMC? */
		int level; /* trust level */
		int wizi; /* wizi level */
	}
	static final int PERM_NONE = 0;
	static final int PERM_PLAYER = 1;
	static final int PERM_IMMORTAL = 2;
	static final int PERM_ADMIN = 3;
	boolean shutdown=false;
	boolean isShutdown=false;

	Date imc_boot = new Date();
	long imc_now,imc_sequencenumber,imc_prev_sequencenumber;
	public hubinfo this_imcmud = new hubinfo();
	public siteinfo imc_siteinfo = new siteinfo();
	imc_statistics imc_stats = new imc_statistics();
	public int imc_active; /* Connection state */
	long HeartBeat = 0; // elapsed heartbeats
	call_out c_thread=null;
	call_in c_thread2=null;

	Hashtable<String,REMOTEINFO> muds = new Hashtable<String,REMOTEINFO>();
	Hashtable<String,IMC_CHANNEL> channels = new Hashtable<String,IMC_CHANNEL>();
	public Hashtable<String,List<String>> chanhist = new Hashtable<String,List<String>>();
	Hashtable<String,String> replies = new Hashtable<String,String>();

	public Hashtable<String,String> chan_conf = new Hashtable<String,String>();
	public Hashtable<String,String> chan_mask = new Hashtable<String,String>();

	BufferedReader in;
	DataOutputStream out;

	public String imc_name = "";
	public short imc_log_on;

	private long reconnectBackoffTime = 20000;

	/* refresh timeout */
	final static int  IMC_TIMEOUT = 650;

	public final static int CHAN_OPEN     = 1;
	public final static int CHAN_CLOSED   = 2;
	public final static int CHAN_PRIVATE  = 3;
	public final static int CHAN_COPEN    = 4;
	public final static int CHAN_CPRIVATE = 5;

	/* max length of any mud name */
	final static int IMC_MNAME_LENGTH = 20;

	/* max length of any player name */
	final static int IMC_PNAME_LENGTH = 40;

	/* max length of any player@mud name */
	final static int IMC_NAME_LENGTH = (IMC_MNAME_LENGTH + IMC_PNAME_LENGTH + 1);

	/* activation states */
	public final static int IA_NONE = 0;
	public final static int IA_CONFIG1 = 1;
	public final static int IA_CONFIG2 = 2;
	public final static int IA_UP = 3;

	/* connection states */
	final static int IMC_CLOSED = 0; /* No active connection */
	final static int IMC_CONNECTING = 1; /* Contacting hub */
	final static int IMC_WAIT1 = 2; /* Waiting for hub verification */
	final static int IMC_CONNECTED = 3; /* Fully connected */

	final static int IMC_VERSION = 2;
	final static String IMC_VERSIONID  = "IMC2 4.00 for CoffeeMud";

	final void tracef(final int level, final String s)
	{
		if((level<1)||(CMSecurity.isDebugging(CMSecurity.DbgFlag.IMC2)))
			Log.debugOut("IMC2",level+"/"+s);
	}

	final void send_to_player(final String name, final String text)
	{
		if(name.equalsIgnoreCase("all"))
		{
			for(final Session S : CMLib.sessions().localOnlineIterable())
				S.println(text);
		}
		else
		{
			final MOB M=CMLib.players().getPlayerAllHosts(name);
			if(M!=null)
				M.tell(text);
		}
	}

	public void ev_request_keepalive(final Object param)
	{
		imc_request_keepalive();
		//imc_register_call_out(25, "ev_keepalive", null);
	}

	final public List<CMChannel> rebuildChannelMap()
	{
		final List<CMChannel> map=new Vector<CMChannel>(chan_conf.size());
		for(final Enumeration<String> e=chan_conf.keys();e.hasMoreElements();)
		{
			final String name=e.nextElement();
			final String mask=chan_mask.get(name);
			final String imc2Name=chan_conf.get(name);
			final CMChannel chan=CMLib.channels().createNewChannel(name, "", imc2Name, mask, new HashSet<ChannelFlag>(),"","");
			map.add(chan);
		}
		return map;
	}

	final public static String[] explodeNicely(final String s)
	{
		  return explodeNicely(s, " ");
	}

	public void shutdown()
	{
		shutdown=true;
		try
		{
		if(c_thread!=null)
			c_thread.shutdown();
		}
		catch(final Exception e)
		{
		}
		try
		{
		if(c_thread2!=null)
			c_thread2.shutdown();
		}
		catch(final Exception e)
		{
		}
		CMLib.killThread(this,500,1);

		int i=0;
		while (((++i)<60)&&((!c_thread.isShutdown)||(!c_thread2.isShutdown)||(!isShutdown)))
			try { sleep(1000);    }
			catch (final Exception ex)
			{
			}
	}

	final public static String[] explodeNicely(final String s, final String separator)
	{
		final StringTokenizer st = new StringTokenizer(s, separator);

		final int n = st.countTokens();
		if(n==0)
		{
			final String array[] = new String[1];
			array[0] = s;
			return array;
		}

		final String array[]  = new String[n];

		int i = 0;
		while(st.hasMoreTokens())
		{
			array[i] = st.nextToken();
				i++;
		}

		return array;
	}

	/* put a line onto descriptors output buffer */
	final void do_imcsend( final String line )
	{
		if(line.endsWith("\n\r"))
			this_imcmud.outbuf = line;
		else
			this_imcmud.outbuf = line+"\n\r";
	}

	/* connect to hub */
	final boolean imc_connect_to()
	{
		String buf;

		if (imc_active == IA_NONE)
		{
			tracef(0, "IMC is not active");
			return false;
		}

		tracef(8, "Connecting to " + this_imcmud.hubname);

		try
		{
			setName("IMC2Client:"+this_imcmud.host+"@"+this_imcmud.port);
			sa = new Socket(this_imcmud.host, this_imcmud.port);
		}
		catch (final Exception e)
		{
			tracef(0, "Error connecting to " + this_imcmud.host + ":" +
						  this_imcmud.port);
			return false;

		}
		if (sa == null)
		{
			tracef(0, "Error connecting to " + this_imcmud.host + ":" +
						  this_imcmud.port);
			return false;
		}

		try
		{
			sa.setSoTimeout(60000);
			in = new BufferedReader(new InputStreamReader(sa.getInputStream()));
			out = new DataOutputStream(sa.getOutputStream());
		}
		catch(final Exception e)
		{
		}

		this_imcmud.state = IMC_CONNECTING;
		this_imcmud.insize = 1024;
		this_imcmud.outsize = 1024;

		buf = "PW " + imc_name.trim() + " " + this_imcmud.clientpw + " version=" +
			IMC_VERSION+" autosetup "+this_imcmud.serverpw;
		do_imcsend(buf);

		imc_write_to_socket(out);
		imc_read_from_socket(in);
		reconnectBackoffTime=20000;
		return true;
	}

	/* start up IMC */
	final boolean imc_startup_network()
	{
		if (imc_active != IA_CONFIG2)
		{
			tracef(0, "imc_startup_network: called with imc_active == "+
						  imc_active);
			return false;
		}

		tracef(8, "IMC2 Network Initializing");

		imc_active = IA_UP;
		imc_stats.start = imc_now;
		imc_stats.rx_pkts = 0;
		imc_stats.tx_pkts = 0;
		imc_stats.rx_bytes = 0;
		imc_stats.tx_bytes = 0;
		imc_stats.sequence_drops = 0;

		/* Connect to Hub */
		if (!imc_connect_to())
			return false;

		imc_register_call_out(5, "ev_keepalive", null);

		imc_register_call_out(6, "ev_request_keepalive", null);

		return true;
	}

	final public void ev_imc_firstrefresh()
	{
		final PACKET out = new PACKET();
		if (this_imcmud == null || imc_active < IA_UP)
			return;

		out.from = "*";
		out.to = "IMC@*";
		out.type = "ice-refresh";
		imc_initdata(out);
		imc_addkey(out, "channel", "*");
		imc_send(out);
	}

	final public boolean imc_startup( final boolean force,
									  final String loginName,
									  final String host,
									  final String email,
									  final String web,
									  final String hub,
									  final int port,
									  final String passclient,
									  final String passsrvr,
									  final List<CMChannel> imc2Channels)
	{
	   if( imc_active != IA_NONE )
	   {
		  tracef(0,  "imc_startup: called with imc_active = "+imc_active );
		  return false;
	   }
	   imc_now = new Date().getTime()/1000; 				 /* start our clock */
	   imc_boot = new Date();

	   imc_sequencenumber = imc_now;

		for(final CMChannel chan : imc2Channels)
		{
			chan_mask.put(chan.name(),chan.mask());
			chan_conf.put(chan.name(),chan.imc2Name());
		}

		imc_name=loginName;
		imc_log_on=1; // logging?
		this_imcmud.autoconnect=true;
		imc_siteinfo.name=CMProps.getVar(CMProps.Str.MUDNAME);
		imc_siteinfo.host=host;
		imc_siteinfo.port=CMath.s_int(CMParms.parse(CMProps.getVar(CMProps.Str.MUDPORTS)).elementAt(0));
		imc_siteinfo.email=email;
		imc_siteinfo.base="CoffeeMud v"+CMProps.getVar(CMProps.Str.MUDVER);
		imc_siteinfo.details="Custom Java-based Mud";
		imc_siteinfo.www=web;
		this_imcmud.hubname=hub;
		this_imcmud.host=hub;
		this_imcmud.port=port;
		this_imcmud.clientpw=passclient;
		this_imcmud.serverpw=passsrvr;
		if( !this_imcmud.autoconnect && !force )
		{
			tracef(8,  "IMC2 data loaded. Autoconnect not set. "+
						 "IMC will need to be connected manually." );
			return false;
		}

		imc_active = !imc_name.equals("") ? IA_CONFIG2 : IA_CONFIG1;

		if( imc_active == IA_CONFIG2 && ( this_imcmud.autoconnect || force ) )
		{
			if( imc_startup_network() )
			{
				ev_imc_firstrefresh();
				return true;
			}
			imc_active = IA_NONE;
		}
		return false;
	}

	final String normal2(String data)
	{
		data = CMStrings.replaceAll(data, "\\\"", "\"");
		final StringBuffer str=new StringBuffer(data);
		for(int i=0;i<str.length()-1;i++)
		{
			if(str.charAt(i)=='~')
			switch(str.charAt(i+1))
			{
			case 'R':
			case 'r':
			case 'y':
			case 'Y':
			case 'g':
			case 'G':
			case 'b':
			case 'B':
			case 'w':
			case 'W':
			case 'c':
			case 'C':
				str.setCharAt(i, '^');
				break;
			case 'm':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'p');
				break;
			case 'M':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'P');
				break;
			case 'p':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'p');
				break;
			case 'P':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'P');
				break;
			case 'z':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'R');
				break;
			case 'x':
			case 'u':
			case 'v':
			case 'i':
			case '$':
			case 's':
			case 'Z':
			case 'X':
			case 'D':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'W');
				break;
			case 'd':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, 'w');
				break;
			case '!':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, '.');
				break;
			case 'L':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, '!');
				break;
			}
			else
			if(str.charAt(i)=='^')
			switch(str.charAt(i+1))
			{
			case 'O':
				str.setCharAt(i + 1, 'y');
				break;
			}
			else
			if(str.charAt(i)=='&')
			switch(str.charAt(i+1))
			{
			case 'D':
				str.setCharAt(i, '^');
				str.setCharAt(i + 1, '!');
				break;
			}
		}
		return str.toString();
	}

	/* printkeys: print key-value pairs, escaping values */
	final String printkeys(final PACKET data)
	{
		String buf;
		int i;

		buf = "";

		for (i = 0; i < PACKET.IMC_MAX_KEYS; i++)
		{
			if (!data.key[i].equals("") )
			{

				buf = buf + data.key[i] + "=";
				if (data.value[i].equals(""))
					buf = buf + "\"" + data.value[i] + "\"";
				else
					buf = buf + data.value[i];
				buf = buf + " ";
			}
		}
		return buf;
	}

	final public String do_imcstats()
	{
		return "IMC Statistics:\\n\\r\\n"+
			"Received packets:    "+imc_stats.rx_pkts+"\\n\\r"+
			"Received bytes:      "+imc_stats.rx_bytes+"\\n\\r"+
			"Transmitted packets: "+imc_stats.tx_pkts+"\\n\\r"+
			"Transmitted bytes:   "+imc_stats.tx_bytes+"\\n\\r"+
			"Packets dropped:     "+imc_stats.sequence_drops+"\\n\\n\\r"+
			"Last IMC Boot:       "+imc_boot.toString()+"\\n\\r";
	}
	final public String do_imcinfo()
	{
		final String host=CMProps.getVar(CMProps.Str.MUDDOMAIN).toLowerCase();
		return "IMC Statistics:\\n\\r\\n"+
			"Site Name           :"+imc_siteinfo.name+"\\n\\r"+
			"Site Host           :"+((host.length()>0)?host:sa.getLocalAddress().getHostName())+"\\n\\r"+
			"Site Port           :"+imc_siteinfo.port+"\\n\\r"+
			((imc_siteinfo.www.length()>0)?"Web Address         :"+imc_siteinfo.www+"\\n\\r":"")+
			((imc_siteinfo.www.length()>0)?"Email               :"+imc_siteinfo.email+"\\n\\r":"")+
			"Codebase            :"+imc_siteinfo.base+"\\n\\r"+
			"IMC Version         :"+IMC_VERSIONID+"\\n\\r";
	}

	final PACKET interpret2(final String argument )
	{
		String seq;
		final PACKET out = new PACKET();

		imc_initdata(out);

		final StringTokenizer st = new StringTokenizer(argument, " ");
		if(st.countTokens() < 5)
		{
			if(st.countTokens() == 4)
			{
				final String tmp = st.nextToken();
				if(tmp.equalsIgnoreCase("autosetup"))
				{
					// who cares what the server says.
					/*
					String serverName = st.nextToken();
					if(st.nextToken().equalsIgnoreCase("accept"))
					{
						String networkName = st.nextToken();
					}
					*/
				}
			}
			else
			{
				tracef(0, "interpret: bad packet received, discarding");
				tracef(0, "interpret: argument was '"+argument+"'");
				imc_stats.sequence_drops++;
			}
			return null;
		}

		if(imc_stats.max_pkt < argument.length())
			imc_stats.max_pkt = argument.length();

		imc_stats.rx_bytes += argument.length();
		imc_stats.rx_pkts++;

		int pos = 0;
		String tmp = st.nextToken();
		out.i.from = tmp; pos+=tmp.length();
		tmp = st.nextToken();
		seq = tmp; pos+=tmp.length();
		tmp = st.nextToken();
		out.i.path = tmp; pos+=tmp.length();
		tmp = st.nextToken();
		out.type = tmp; pos+=tmp.length();
		tmp = st.nextToken();
		out.i.to = tmp; pos+=tmp.length();

		String keys = argument.substring(pos+5, argument.length());

		try
		{

		while((keys.length() > 0) && !keys.equals(" "))
		{
			String key = "";
			String val = "";
			final int kpos = keys.indexOf('=');
			if(kpos > -1)
			{
				key = keys.substring(0, kpos);
				keys = keys.substring(kpos+1, keys.length());
				if(keys.startsWith("\""))
				{
					int p = 0;
					boolean found = false;
					while(!found)
					{
						p = keys.indexOf("\"", p+1);
						if(p > -1)
						{
							final String tmp2 = keys.substring(p-1, p+1);
							if(!tmp2.equals("\\\""))
								found = true;
						}
						else
						{
							p=keys.length();
							found = true;
						}
					}
					val = keys.substring(1, p);
					if(p>=keys.length())
						keys="";
					else
					if(p+2>=keys.length())
						keys = keys.substring(p+1, keys.length());
					else
						keys = keys.substring(p+2, keys.length());
				}
				else
				{
					if(!keys.equals(" "))
					{
						final int npos = keys.indexOf(' ');
						if (npos > -1)
						{
							val = keys.substring(0, npos);
							if(npos+2 > keys.length())
								keys = "";
							else
								keys = keys.substring(npos + 1, keys.length());
						}
						else
						{
							val = keys;
							keys = "";
						}
					}
					else
						keys = "";
				}
			}

			val = normal2(val);
			imc_addkey(out, key, val);
		}

		}
		catch (final StringIndexOutOfBoundsException x)
		{
			Log.errOut("IMC2Driver", "Stringerror: "+keys);
			Log.errOut("IMC2Driver", x);
		}
		catch (final Exception e)
		{
			Log.errOut("IMC2Driver", e);
		}

		out.i.sequence = Long.valueOf(seq).longValue();
		return out;
	}

	final String generate2( final PACKET p )
	{
	   String temp;
	   String newpath;

	   if(p.i.path.equals(""))
		  newpath = imc_name;
	   else
		  newpath = imc_name+"!"+p.i.path;

	   temp = p.i.from+" "+p.i.sequence+" "+newpath+" "+p.type+" "+p.i.to+" "+printkeys( p );

	   imc_stats.tx_bytes += temp.length();
	   imc_stats.tx_pkts++;

	   return temp;
	}

	final void do_send_packet( final PACKET p )
	{
		String output;

		output = generate2(p);
		do_imcsend(output);
	}

	final IMC_CHANNEL imc_findchannel( final String name )
	{
		if(channels.get(name)!=null)
			return channels.get(name);
		return null;
	}

	/* return 'mud' from 'player@mud' */
	final String imc_mudof(final String fullname )
	{
	   String buf;

	   final int pos = fullname.indexOf('@');
	   if(pos > -1)
		   buf = fullname.substring(pos+1);
		else
			buf = "*";

	   return buf;
	}

	/* return d from a!b!c!d */
	final String imc_lastinpath(final String path)
	{
		final int pos = path.lastIndexOf('!');
		if(pos < 0)
			return path;

		return path.substring(pos+1, path.length());
	}

	/* return 'player' from 'player@mud' */
	final String imc_playerof(final String fullname )
	{
	   String buf;

	   final int pos = fullname.indexOf('@');
	   if(pos > -1)
		   buf = fullname.substring(0, pos);
		else
			buf = "*";

	   return buf;
	}

	/* add "key=value" to "p" */
	final void imc_addkey(final PACKET p, final String key, String value)
	{

		for(int i = 0; i < value.length(); i++)
		{
			if(value.substring(i, i+1).equals("\""))
			{
				String tmp = value.substring(0, i);
				tmp = tmp.concat("\\\"").concat(value.substring(i+1, value.length()));
				value = tmp;
				i++;
			}
		}

		for (int i = 0; i < PACKET.IMC_MAX_KEYS; i++)
		{
			if (!p.key[i].equals("") && (key.equalsIgnoreCase(p.key[i])))
			{
				p.key[i] = "";
				p.value[i] = "";
				break;
			}
		}
		if (value=="")
			return;

		for (int i = 0; i < PACKET.IMC_MAX_KEYS; i++)
		{
			if (p.key[i] == "")
			{
				p.key[i] = key;
				if((value.indexOf(' ') > -1))
					value = "\""+value+"\"";
				p.value[i] = value;
				return;
			}
		}
	}

	/* add "key=value" for an integer value */
	final void imc_addkeyi(final PACKET p, final String key, final int value)
	{
		String temp;
		temp = String.valueOf(value);
		imc_addkey(p, key, temp);
	}

	/* clear all keys in "p" */
	final void imc_initdata(final PACKET p)
	{
		int i;

		for (i = 0; i < PACKET.IMC_MAX_KEYS; i++)
		{
			p.key[i] = "";
			p.value[i] = "";
		}
	}

	/* convert back from 'd' to 'p' */
	final void setdata(final PACKET p, final imc_char_data d)
	{
		imc_initdata(p);

		if (d == null)
		{
			p.from = "*";
			imc_addkeyi(p, "level", -1);
			return;
		}

		p.from = d.name;

		if (d.wizi > 0)
			imc_addkeyi(p, "wizi", d.wizi);
//  	  imc_addkeyi(p, "level", d.level);
	}

	/* send a who-request to a remote mud */
	final void imc_send_who(final imc_char_data from, final String to, final String type)
	{
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return;

		if (imc_mudof(to).equals("*"))
			return; /* don't let them do this */

		setdata(out, from);

		out.to = "*@" + imc_mudof(to);
		out.type = "who";

		imc_addkey(out, "type", type);

		imc_send(out);
	}

	/* send a who-request to a remote mud */
   public final void imc_send_whois(final String from, final String to, final int level)
   {
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return;

		//if (imc_mudof(to).equals("*"))
		//    return; /* don't let them do this */

		imc_initdata(out);

		out.from = from;

		out.to = to+"@*";
		out.type = "whois";

		imc_addkeyi(out, "level", level);

		imc_send(out);
	}

	final void imc_send( final PACKET p)
	{
		if (imc_active < IA_UP)
		{
			tracef(0, "imc_send when not active!");
			return;
		}

		/* initialize packet fields that the caller shouldn't/doesn't set */

		p.i.stamp = 0;
		p.i.path = "";

		p.i.sequence = imc_sequencenumber;
		if(p.i.sequence == imc_prev_sequencenumber)
		{
			p.i.sequence++;
			imc_sequencenumber++;
		}

		imc_prev_sequencenumber = imc_sequencenumber;

		p.i.to = p.to;
		p.i.from = p.from;
		p.i.from = p.i.from.concat("@");
		p.i.from = p.i.from.concat(imc_name);

//  	p.i.path = this_imcmud.hubname;

		do_send_packet(p);
	}

	final void imc_loop()
	{
		return;
	}

//
	// list of all active call_out's in the game
	//
	static LinkedList<Vector<Object>> call_outs = new LinkedList<Vector<Object>>();

	public void imc_register_call_out(final int hbeat, final String function_name, final Object param)
	{
		final Vector<Object> call_out = new Vector<Object>();
		call_out.add(function_name);
		call_out.add(Long.valueOf(HeartBeat + hbeat));
		call_out.add(param);

		call_outs.add(call_out);
	}

	public void imc_process_call_outs()
	{
		if (call_outs.size() < 1)
		{
			return;
		}

		for (int i = 0; i < call_outs.size(); i++)
		{
			final Vector<Object> call_out = call_outs.get(i);
			final String fun = (String) call_out.elementAt(0);
			final long hbeat = ( (Long) call_out.elementAt(1)).longValue();
			final Object param = call_out.elementAt(2);

			if (hbeat == HeartBeat)
			{
				final Object o = this;
				final Class<?> cl = o.getClass();
				final java.lang.reflect.Method funcs[] = cl.getMethods();
				if (funcs.length > 1)
				{
					for (final Method func : funcs)
					{
						final String m_name = func.getName();
						if (m_name.equals(fun))
						{
							try
							{
								func.invoke(o, new Object[] {param});
							}
							catch (final Exception e)
							{
								tracef(0,
									   "imc: call_out failed with error: "
									   + e.toString());
							 }
						}
					}
				}
				call_outs.remove(i);
				i--;
			}
		}
	}

	final public static String toIMCColours(String res)
	{
		// ANSI color macros
		res = CMStrings.replaceAll(res, "\"", "\\\"");
		final StringBuffer str=new StringBuffer(res);
		for(int i=0;i<str.length()-1;i++)
		{
			if(str.charAt(i)=='`')
				str.setCharAt(i,'\'');
			else
			if(str.charAt(i)=='^')
			switch(str.charAt(i+1))
			{
			case ColorLibrary.COLORCODE_BACKGROUND:
				if (i < str.length() - 2)
					str.delete(i, i + 3);
				break;
			case ColorLibrary.COLORCODE_FANSI256:
			case ColorLibrary.COLORCODE_BANSI256:
				if (i < str.length() - 4)
					str.delete(i, i + 5);
				break;
			case 'R':
			case 'r':
			case 'y':
			case 'Y':
			case 'g':
			case 'G':
			case 'b':
			case 'B':
			case 'w':
			case 'W':
			case 'c':
			case 'C':
				str.setCharAt(i, '~');
				break;
			case 'm':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'p');
				break;
			case 'M':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'P');
				break;
			case 'p':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'm');
				break;
			case 'P':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'M');
				break;
			case '?':
			case '.':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, '!');
				break;
			case '!':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'L');
				break;
			case '*':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, '$');
				break;
			case '/':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 's');
				break;
			case '_':
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'u');
				break;
			case '^':
				str.setCharAt(i, '^');
				str.deleteCharAt(i + 1);
				break;
			default:
				str.setCharAt(i, '~');
				str.setCharAt(i + 1, 'c');
				break;
			}
		}
		return str.toString();
	}

	final String update_wholist()
	{
		final StringBuffer str=new StringBuffer("Players on "+CMProps.getVar(CMProps.Str.MUDNAME)+":\\n\\r");
		final Command C=CMClass.getCommand("Who");
		if(C!=null)
		{
			String msg=null;
			try
			{
				msg=(String)C.executeInternal(null,0);
			}
			catch(final Exception e)
			{
			}
			if(msg!=null)
			{
				msg=CMStrings.replaceAll(msg,"\n\r","\\n\\r");
				return str.toString()+msg;
			}
		}
		return "Unavailable";
	}

	final String who_help()
	{
		return "\\n\\r"+
			"Available imcminfo types:\\n\\r"+
			"help   - this screen\\n\\r"+
			"who    - who is online\\n\\r"+
			"info   - mud information\\n\\r"+
			"who    - who is online\\n\\r";
	}

	final void imc_recv_who(final imc_char_data from, final String sender, final String type)
	{
		final PACKET out = new PACKET();

		imc_initdata(out);
		out.from = from.name;
		imc_addkeyi(out, "level", 3);

		out.to = sender;
		out.type = "who-reply";

		if(type.equals("who"))
			imc_addkey(out, "text", toIMCColours(update_wholist()));
		else
		if(type.equals("istats"))
			imc_addkey(out, "text", toIMCColours(do_imcstats()));
		else
		if(type.equals("info"))
			imc_addkey(out, "text", toIMCColours(do_imcinfo()));
		else
		if(type.equals("help"))
			imc_addkey(out, "text", toIMCColours(who_help()));

		imc_send(out);
	}

	final void imc_recv_whois(final imc_char_data from, final String sender, final int level)
	{
		final PACKET out = new PACKET();

		imc_initdata(out);
		out.from = from.name;
		imc_addkeyi(out, "level", 3);

		out.to = sender;
		out.type = "whois-reply";

		final MOB M=CMLib.players().getPlayerAllHosts(from.name);
		if(M==null)
			return;
		imc_addkey(out, "text", "imcpfind "+from.name+"@"+imc_name
						+" is "+(CMLib.flags().isInTheGame(M,false) ? "online":"offline")+ ".");

		imc_send(out);
	}

	final void imc_recv_ping(final imc_char_data from, final String path, final String sender)
	{
		final PACKET out = new PACKET();

		imc_initdata(out);
		out.from = from.name;

		out.to = sender;
		out.type = "ping-reply";

		imc_addkey(out, "path", path);

		imc_send(out);
	}

	final void imc_recv_tell(final imc_char_data d, final String from, final String text)
	{
		final MOB mob=CMClass.getFactoryMOB();
		mob.setName(from);
		mob.setLocation(CMClass.getLocale("StdRoom"));
		final MOB smob=CMLib.sessions().findCharacterOnline(d.name,true);
		if(smob!=null)
			CMLib.commands().postSay(mob,smob,text,true,true);
		final Room R=mob.location();
		mob.destroy();
		if(R!=null)
			R.destroy();
	}

	public REMOTEINFO getIMC2Mud(final String named)
	{
		final Hashtable<String,REMOTEINFO> l=query_muds();
		if(l.containsKey(named))
			return l.get(named);
		for(final Enumeration<REMOTEINFO> e=l.elements();e.hasMoreElements();)
		{
			final REMOTEINFO m=e.nextElement();
			if(m.name.equalsIgnoreCase(named))
				return m;
		}
		return null;
	}

	final void imc_recv_chat(final imc_char_data d, final String from, String channel, final String text, final int emote)
	{
		final StringTokenizer st = new StringTokenizer(channel, ":");
		if (st.countTokens() > 1)
		{
			channel = st.nextToken();
			channel = st.nextToken();
		}
		else
		if(st.countTokens()> 0)
			channel=st.nextToken();

		String channelName=channel;
		CMMsg msg=null;
		if(from.toUpperCase().endsWith(imc_name.toUpperCase()))
			return;
		if(channelName.length()==0)
			return;
		channelName=read_channel_name(channelName);
		if(channelName.length()==0)
			return;
		final ChannelsLibrary channels = CMLib.channels();
		final int channelInt=channels.getChannelIndex(channelName);
		if(channelInt<0)
			return;
		final String channelColor="^Q";
		final MOB mob=CMClass.getFactoryMOB();
		mob.setName(from);
		mob.setLocation(CMClass.getLocale("StdRoom"));
		String str=channelColor+"^<CHANNEL \""+channelName+"\"^>"+mob.name()+" "+channelName+"(S) '"+text+"'^</CHANNEL^>^N^.";
		if(emote>0)
		{
			if(emote==1)
				str=channelColor+"^<CHANNEL \""+channelName+"\"^>["+channelName+"] "+from+" "+text+"^</CHANNEL^>^N^.";
			else
				str=channelColor+"^<CHANNEL \""+channelName+"\"^>["+channelName+"] "+text+"^</CHANNEL^>^N^.";
		}

		msg=CMClass.getMsg(mob,null,null,CMMsg.NO_EFFECT,null,CMMsg.NO_EFFECT,null,CMMsg.MASK_CHANNEL|(CMMsg.TYP_CHANNEL+channelInt),str);

		channels.channelQueUp(channelInt,(CMMsg)msg.copyOf(), 0);
		for(final Session S : CMLib.sessions().localOnlineIterable())
		{
			final ChannelsLibrary myChanLib=CMLib.get(S)._channels();
			final int chanNum = (myChanLib == channels) ? channelInt : myChanLib.getChannelIndex(channel);
			if((chanNum >= 0)
			&&(myChanLib.mayReadThisChannel(mob,false,S,chanNum))
			&&(S.mob().location()!=null))
			{
				msg.setOthersCode(CMMsg.MASK_CHANNEL|(CMMsg.TYP_CHANNEL+chanNum));
				if(S.mob().location().okMessage(S.mob(),msg))
					S.mob().executeMsg(S.mob(),msg);
			}
		}

		List<String> l = chanhist.get(channel);
		if(l == null)
			l = new LinkedList<String>();

		l.add(str);
		chanhist.put(channel, l);
		final Room R=mob.location();
		mob.destroy();
		if(R!=null)
			R.destroy();
	}

	final void imc_recv_is_alive(final imc_char_data d, final String from, final String path,
						   final String version, final String netname)
	{
		final String mudname = imc_mudof(from);
		final REMOTEINFO rinfo = new REMOTEINFO();
		rinfo.name = mudname;
		rinfo.network = netname;
		rinfo.version = version;

		final int pos = path.indexOf('!');
		if(pos > -1)
		{
			final String hubs = path.substring(pos+1, path.length());
			final int pos2 = hubs.indexOf('!');
			if(pos2 > -1)
				rinfo.hub = hubs.substring(0, pos2);
			else
				rinfo.hub = hubs;
		}
		else
			rinfo.hub = "None";

		muds.put(mudname, rinfo);
	}

	final void imc_recv_who_reply(final imc_char_data d, String text)
	{
		text = CMStrings.replaceAll(text, "\\n\\r", "\n\r");
		send_to_player(d.name, "\n\r"+text+"^.^?");
	}

	final void imc_recv_whois_reply(final imc_char_data d, final String to, String text)
	{
		text = CMStrings.replaceAll(text, "\\n\\r", "\n\r");
		send_to_player(d.name, "\n\r"+to+": "+text+"^.^?");
	}

	final void imc_recv_ping_reply(final imc_char_data d, final String from, final String path)
	{
	   final String route[] = explodeNicely(path, "!");

	   final StringBuffer text = new StringBuffer("Traceroute information for "+from+"\n\r");

	   text.append("^cSend path:^?   ");
	   for(int i = 0; i < route.length; i++)
	   {
		   if (i > 0)
			   text.append("->");
		   text.append(route[i]);
	   }
	   text.append("\n\r");
	   text.append("^cReturn path:^? ");
	   for(int i= route.length-1; i >= 0; i--)
	   {
		   if (i < route.length-1)
			   text.append("->");
		   text.append(route[i]);
	   }

	   if(CMSecurity.isDebugging(DbgFlag.IMC2))
		   Log.debugOut("IMC2Driver",text.toString());
	   //send_to_player(d.name, text.toString());
   }

	final String read_channel_name(String channame)
	{
		if(channame==null)
			return "";
		channame=channame.toUpperCase();
		for(final Enumeration<String> e=chan_conf.keys();e.hasMoreElements();)
		{
			final String key=e.nextElement();
			final String val=chan_conf.get(key).toUpperCase();
			if(val.equals(channame))
				return key;
			if(val.endsWith(":"+channame))
				return key;
			if(channame.endsWith(":"+val))
				return key;
		}
		return "";
	}

	public IMC_CHANNEL getAnIMC2Channel(String name)
	{
		name=name.toUpperCase();
		for(final Enumeration<IMC_CHANNEL> e=channels.elements();e.hasMoreElements();)
		{
			final IMC_CHANNEL c=e.nextElement();
			if(read_channel_name(c.name).equalsIgnoreCase(name))
				return c;
		}
		return null;
	}

	final void imc_recv_update(final String from, final String chan, final String owner,
						 final String operators, final String policy, final String invited,
						 final String excluded )
	{
		IMC_CHANNEL c;
		String mud;

		mud = imc_mudof(from);

		/* forged? */
		if (chan.indexOf(':')<-1 || !mud.equalsIgnoreCase(imc_mudof(chan)))
			return;

		c = new IMC_CHANNEL();
		c.name = chan;
		c.owner = owner;
		c.operators = operators;
		c.invited = invited;
		c.excluded = excluded;
		c.local_name = this.read_channel_name(chan);
		c.perm_level = PERM_ADMIN;
		c.refreshed = true;

		if (policy.equalsIgnoreCase("open"))
			c.policy = CHAN_OPEN;
		else
		if (policy.equalsIgnoreCase("closed"))
			c.policy = CHAN_CLOSED;
		else
		if (policy.equalsIgnoreCase("copen"))
			c.policy = CHAN_COPEN;
		else
		if (policy.equalsIgnoreCase("cprivate"))
			c.policy = CHAN_CPRIVATE;
		else
			c.policy = CHAN_PRIVATE;

		channels.put(c.name, c);
   }

	/* get the value of "key" from "p"; if it isn't present, return "def" */
	final String imc_getkey( final PACKET p, final String key, final String def )
	{
	   int i;

	   for( i = 0; i < PACKET.IMC_MAX_KEYS; i++ )
	{
		  if( !p.key[i].equals("") && p.key[i].equalsIgnoreCase(key))
		  {
			  if(p.value[i].startsWith("\""))
				  return p.value[i].substring(1, p.value[i].length()-1);
			  return p.value[i];
		  }

	}
	   return def;
	}

	/* identical to imc_getkey, except get the integer value of the key */
	final int imc_getkeyi( final PACKET p, final String key, final int def )
	{
	   int i;

	   for( i = 0; i < PACKET.IMC_MAX_KEYS; i++ )
	{
		  if( !p.key[i].equals("") && p.key[i].equalsIgnoreCase(key) )
		  {
			  return CMath.s_int(p.value[i]);
		  }

	}
	   return def;
	}

	final public Hashtable<String,IMC_CHANNEL> query_channels()
	{
		return channels;
	}

	final public Hashtable<String,REMOTEINFO> query_muds()
	{
		return muds;
	}

	final public void exec_commands(final PACKET p)
	{
		if (p == null)
			return;
		final imc_char_data d = new imc_char_data();

		d.name = p.i.to;
		d.wizi = imc_getkeyi(p, "wizi", 0);
		d.level = imc_getkeyi(p, "level", 0);
		d.invis = 0;

		final String to_mud = imc_mudof(d.name);
		if (!to_mud.equalsIgnoreCase(imc_name) && !to_mud.equals("*"))
		{
			tracef(8, "Message was for "+to_mud+", not "+imc_name+" -- rejecting!");
			return;
		}

		d.name = imc_playerof(d.name);
		tracef(8, "Received message was sent to " + d.name+", "+p.type+", "+CMParms.toListString(p.value));

		if (p.type.equals("who"))
		{
			tracef(8, "Who request received from " + p.i.from);
			imc_recv_who(d, p.i.from, imc_getkey(p, "type", "who"));
		}

		if (p.type.equals("whois"))
		{
			tracef(8, "Whois request received from " + p.i.from);
			imc_recv_whois(d, p.i.from, imc_getkeyi(p, "level", 0));
		}

		if (p.type.equals("ping"))
		{
			tracef(8, "Ping reply received from " + p.i.from);
			imc_recv_ping(d, p.i.path, p.i.from);
		}

		if (p.type.equals("tell"))
		{
			tracef(8, "Tell received from " + p.i.from);
			imc_recv_tell(d, p.i.from, imc_getkey(p, "text", ""));
		}

		if (p.type.equals("keepalive-request"))
		{
			tracef(8, "Keepalive request received from " + p.i.from);
			imc_send_isalive(p.i.from);
		}

		if (p.type.equals("who-reply"))
		{
			tracef(8, "Who reply received from " + p.i.from);
			imc_recv_who_reply(d, imc_getkey(p, "text", ""));
		}

		if (p.type.equals("whois-reply"))
		{
			tracef(8, "Who-Is reply received from " + p.i.from);
			imc_recv_whois_reply(d, p.i.from, imc_getkey(p, "text", ""));
		}

		if (p.type.equals("ping-reply"))
		{
			tracef(8, "Ping-reply reply received from " + p.i.from);
			imc_recv_ping_reply(d, p.i.from, imc_getkey(p, "path", ""));
		}

		if (p.type.equals("is-alive"))
		{
			tracef(8, "is-alive received from " + p.i.from);
			imc_recv_is_alive(d, p.i.from, p.i.path,
							  imc_getkey(p, "versionid", "Unknown"),
							  imc_getkey(p, "networkname", "None"));
		}

		if (p.type.equals("ice-msg-b"))
		{
			tracef(8, "Chat received from " + p.i.from);
			imc_recv_chat(d, p.i.from, imc_getkey(p, "channel", "ICHAT"),
						  imc_getkey(p, "text", ""),CMath.s_int(imc_getkey(p,"emote","0")));
		}

		if (p.type.equals("ice-update"))
		{
			tracef(8, "Ice update reply from " + p.i.from);
			imc_recv_update(p.from, imc_getkey(p, "channel", ""),
							imc_getkey(p, "owner", ""),
							imc_getkey(p, "operators", ""),
							imc_getkey(p, "policy", ""),
							imc_getkey(p, "invited", ""),
							imc_getkey(p, "excluded", ""));

		}
	}

	final boolean check_password(final String s)
	{
		final StringTokenizer st = new StringTokenizer(s, " ");
		if (st.countTokens() < 3)
		{
			tracef(0, "Password not found in Hub reply.");
			return false;
		}

		st.nextToken();
		st.nextToken();
		final String pwd = st.nextToken();

		if (pwd.equals(this_imcmud.serverpw))
		{
			tracef(8, "Password OK.");
			return true;
		}
		tracef(0, "Password incorrect.");
		return false;
	}

	final public void imc_read_from_socket(final BufferedReader in)
	{
		try
		{
			if ((in!=null)&&(in.ready()))
			{
				final String s = in.readLine();
				if (s == null) return;

				if (s.length() > 0)
            long timeSinceLastPing=System.currentTimeMillis();
            while (!shutdown) 
            {
            	if((System.currentTimeMillis()-timeSinceLastPing) > ( 60 * 1000))
            	{
            		imc_client.imc_send_ping("Server01");
            		timeSinceLastPing=System.currentTimeMillis();
						if(p!=null)
							exec_commands(p);
					}
				}
			}
		}
		catch (final Exception e)
		{
			final String errMsg=e.getMessage()==null?e.toString():e.getMessage();
			if((errMsg==null)
			||(errMsg.toUpperCase().indexOf("TIMED OUT")<0))
				Log.errOut("IMC2Driver", "read: "+errMsg);
			if((errMsg!=null)
			&&(!shutdown)
			&&(errMsg.toUpperCase().indexOf("CONNECTION")>=0))
			{
				imc_active = IA_NONE;
				tracef(1, "Waiting "+(reconnectBackoffTime/1000)+" seconds and try to reconnect.");
				try
				{
					sleep(reconnectBackoffTime);
					reconnectBackoffTime=reconnectBackoffTime*2;
				}
				catch (final Exception ex)
				{
				}
				this.imc_startup(true,
								 imc_name,
								 imc_siteinfo.host,
								 imc_siteinfo.email,
								 imc_siteinfo.www,
								 this_imcmud.hubname,
								 this_imcmud.port,
								 this_imcmud.clientpw,
								 this_imcmud.serverpw,
								 rebuildChannelMap());
			}
		}
	}

	final public void imc_write_to_socket(final DataOutputStream out)
	{
		try
		{
			if (this_imcmud.outbuf.equals(""))
				return;

			tracef(8, "imc: sending '" + this_imcmud.outbuf + "'");
			out.write(this_imcmud.outbuf.getBytes());
			this_imcmud.outbuf = "";
		}
		catch (final Exception e)
		{
			tracef(1, "write socket error: " + e.toString());
			imc_active = IA_NONE;
			tracef(1, "Waiting "+(reconnectBackoffTime/1000)+" seconds and try to reconnect.");
			try
			{
				sleep(reconnectBackoffTime);
				reconnectBackoffTime=reconnectBackoffTime*2;
			}
			catch (final Exception ex)
			{
			}
			this.imc_startup(true,
							 imc_name,
							 imc_siteinfo.host,
							 imc_siteinfo.email,
							 imc_siteinfo.www,
							 this_imcmud.hubname,
							 this_imcmud.port,
							 this_imcmud.clientpw,
							 this_imcmud.serverpw,
							 rebuildChannelMap());
		}
	}

	/* send a keepalive to everyone */
	final public void imc_send_isalive(final String reqFrom)
	{
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return;

		imc_initdata(out);
		out.type = "is-alive";
		out.from = "*";
		if(reqFrom.endsWith("*"))
		{
			Log.errOut("IMC2 SPAM DETECTED: "+reqFrom+"!");
		}
		out.to = reqFrom;
		imc_addkey(out, "versionid", IMC_VERSIONID);
		imc_addkey(out, "networkname", this_imcmud.network);
		if (imc_siteinfo.flags != null && !"".equals(imc_siteinfo.flags))
			imc_addkey(out, "flags", imc_siteinfo.flags);
		imc_send(out);
	}

	/* send a keepalive to everyone */
	final public void imc_request_keepalive()
	{
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return;

		imc_initdata(out);
		out.type = "keepalive-request";
		out.from = "*";
		out.to = "*@*";
		imc_addkey(out, "versionid", IMC_VERSIONID);
		if (imc_siteinfo.flags != null && !"".equals(imc_siteinfo.flags))
			imc_addkey(out, "flags", imc_siteinfo.flags);
		imc_send(out);
	}

	final class call_out extends Thread
	{

		IMC2Driver imc_client;
		boolean shutdown=false;
		public boolean isShutdown=false;
		int seq = 0;
		long lastPingReceived=System.currentTimeMillis();

		public call_out(final IMC2Driver _imc_client)
		{
			super("IMC2-call_out");
			setName("IMC2-call_out");
			imc_client = _imc_client;
			setDaemon(true);
		}

		public void shutdown()
		{
			shutdown=true;
			interrupt();
		}

		@Override
		final public void run()
		{
			if (imc_client == null)
				return;
			long timeSinceLastPing=System.currentTimeMillis();
			while (!shutdown)
			{
				if(CMSecurity.isDisabled(DisFlag.IMC2))
				{
					CMLib.s_sleep(100);
					continue;
				}
				if((System.currentTimeMillis()-timeSinceLastPing) > (30 * 60 * 1000))
				{
					imc_client.imc_send_ping("Server01");
					timeSinceLastPing=System.currentTimeMillis();
					// everything is taken care of from here.  detect disconnect, reconnect -- everything.
				}
//  			tracef(1, "call_out: process call outs");
				imc_client.imc_process_call_outs();
				imc_client.imc_write_to_socket(out);
				try
				{
					sleep(100);
					seq++;
					if (seq % 10 == 0)
					{
						imc_client.imc_sequencenumber++;
						seq = 0;
					}
				}
				catch (final Exception e)
				{
				}

			}
			isShutdown=true;
		}
	}

	final class call_in extends Thread {

		IMC2Driver imc_client;
		boolean shutdown=false;
		public boolean isShutdown=false;

		public call_in(final IMC2Driver _imc_client)
		{
			super("IMC2-call_in");
			setName("IMC2-call_in");
			imc_client = _imc_client;
			setDaemon(true);
		}

		public void shutdown()
		{
			shutdown=true;
			interrupt();
		}

		@Override
		final public void run()
		{
			if (imc_client == null)
				return;
			while (!shutdown)
			{
				if(!CMSecurity.isDisabled(DisFlag.IMC2))
				{
//	  			tracef(1, "call_out: process call outs");
					imc_client.imc_read_from_socket(in);
				}
				try
				{
					sleep(100);
				}
				catch (final Exception e)
				{
				}
			}
			isShutdown=true;
		}

	}

	/* send a ping with a given timestamp */
	final public void imc_send_ping(final String to)
	{
		PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return;

		imc_initdata(out);
		out.type = "ping";
		out.from = "*";
		out.to = "*@" + to;
		imc_send(out);
		out = null;
	}

	final public void run_imcpinfo(final String name, final String mudname, final String who, final int level,
							 final int invis)
							 {
		final imc_char_data test = new imc_char_data();
		test.name = name;
		test.level = level;
		test.invis = invis;
		imc_send_who(test, "@" + mudname, "finger " + who);
	}

	final public void run_imcminfo(final String name, final String mudname, final String type,
							 final int level, final int invis)
							 {
		final imc_char_data test = new imc_char_data();
		test.name = name;
		test.level = level;
		test.invis = invis;
		imc_send_who(test, "@" + mudname, type);
	}

	final public void imc_send_who(final String name, final String mudname, final String type, final int level, final int invis)
	{
		final imc_char_data test = new imc_char_data();
		test.name = name;
		test.level = level;
		test.invis = invis;
		imc_send_who(test, "@" + mudname, type);
	}

	final public String imc_send_tell(final String from, final String to, final String text, final int level,
								final int invis)
								{
		final imc_char_data chr = new imc_char_data();
		chr.name = from;
		chr.level = level;
		chr.invis = invis;
		return imc_send_tell(chr, to, text, 1);
	}

	final public String imc_send_reply(final String from, final String text, final int level, final int invis)
	{
		final imc_char_data chr = new imc_char_data();
		chr.name = from;
		chr.level = level;
		chr.invis = invis;
		return imc_send_reply(chr, text);
	}

	final public String imc_send_chat(final String from, final String to, final String text, final int level,
								final int emote)
								{
		final imc_char_data chr = new imc_char_data();
		chr.name = from;
		chr.level = level;
		return imc_send_chat(chr, to, text, level, emote);
	}

	/* send a tell to a remote player */
	final String imc_send_tell(final imc_char_data from, final String to, final String argument,
						 final int isreply)
						 {
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return "IMC is not active.";

		if (imc_mudof(to).equals("*"))
		{
			return "You cannot send tell to everyone!";
				/* don't let them do this */
		}

		setdata(out, from);

		out.to = to;
		out.type = "tell";
		imc_addkeyi(out, "level", 3);
		imc_addkey(out, "text", toIMCColours(argument));

		imc_send(out);

		replies.put(from.name, to);

		final String chatText = "You tell " + to + " '^c" + argument +
			"'^?.";
		return chatText;
	}

	/* send a reply to a remote player */
	final String imc_send_reply(final imc_char_data from, final String argument)
	{
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return "IMC is not active.";

		setdata(out, from);
		final String to = replies.get(from.name);
		if (to == null)
			return "No one to reply to.";

		out.to = to;
		out.type = "tell";
		imc_addkeyi(out, "level", 3);
		imc_addkey(out, "text", toIMCColours(argument));

		imc_send(out);

		final String chatText = "You tell " + to + " ^c'" + argument +
			"'^?.";
		return chatText;
	}

	/* send a tell to a remote player */
	final String imc_send_chat(final imc_char_data from,
								final String to,
								final String argument,
								final int isreply,
								final int emote)
								{
		final PACKET out = new PACKET();

		if (imc_active < IA_UP)
			return "IMC is not running.";

		setdata(out, from);

//  	imc_addkey(p, "level", 3);

		out.to = "*@*";
		out.type = "ice-msg-b";
		imc_addkey(out, "channel", to);
		imc_addkey(out, "text", toIMCColours(argument));
		imc_addkeyi(out, "emote", emote);

		/*  	if (isreply > 0)
				  imc_addkeyi(out, "isreply", isreply);*/

		imc_send(out);

		String chan = to;
		final int pos = to.indexOf(':');
		if (pos > -1)
			chan = to.substring(pos + 1, to.length());

		String text = argument;
		if (argument.startsWith(", ") || emote == 1)
			text = from.name + "@" + this.imc_name;

		final String chatText = from.name + "@" + this.imc_name +
			" [" + chan +
			"] " +
			" " + text + "^?";

		List<String> l =  chanhist.get(chan);
		if (l == null)
			l = new LinkedList<String>();

		l.add(chatText);
		chanhist.put(chan, l);

		return chatText;

	}

	@Override
	final public void run()
	{
		imc_read_from_socket(in);
		HeartBeat = 0;

		if(c_thread2==null)
		{
			c_thread2 = new call_in(this);
			c_thread2.start();
		}
		if(c_thread==null)
		{
			c_thread = new call_out(this);
			c_thread.start();
		}
		Log.sysOut("IMC2","(c) 1996-2002/Java port by Istvan David");
		Log.sysOut("IMC2","Client connected to "+this_imcmud.host.trim());

		while (!shutdown)
		{
			HeartBeat++;
			try
			{
				sleep(2000);
			}
			catch (final Exception e)
			{
			}
			isShutdown=true;
		}
	}

}

<MSG> 

git-svn-id: svn://192.168.1.10/public/CoffeeMud@9005 0d6f1817-ed0e-0410-87c9-987e46238f29

<DFF> @@ -1548,7 +1548,7 @@ public final class IMC2Driver extends Thread {
             long timeSinceLastPing=System.currentTimeMillis();
             while (!shutdown) 
             {
-            	if((System.currentTimeMillis()-timeSinceLastPing) > ( 60 * 1000))
+            	if((System.currentTimeMillis()-timeSinceLastPing) > (30 * 60 * 1000))
             	{
             		imc_client.imc_send_ping("Server01");
             		timeSinceLastPing=System.currentTimeMillis();

{'commit': 'diff --git a/com/planet_ink/coffee_mud/core/intermud/i3/packets/Intermud.java b/com/planet_ink/coffee_mud/core/intermud/i3/packets/Intermud.java\nindex 2908f2f9b0..1af73a8472 100644\n--- a/com/planet_ink/coffee_mud/core/intermud/i3/packets/Intermud.java\n+++ b/com/planet_ink/coffee_mud/core/intermud/i3/packets/Intermud.java\n@@ -430,14 +430,14 @@ public class Intermud implements Runnable, Persistent, Serializable\n \t\t\t\t}\r\n \t\t\t}\r\n             \r\n-            if((System.currentTimeMillis()-lastPingTime)>( 60 * 1000))\r\n+            if((System.currentTimeMillis()-lastPingTime)>( 30 * 60 * 1000))\r\n             {\r\n             \tlastPingTime=System.currentTimeMillis();\r\n             \ttry { new MudAuthRequest(I3Server.getMudName()).send(); } catch(Exception e) { }\r\n             \tif(PingPacket.lastPingResponse==0)\r\n             \t\tPingPacket.lastPingResponse=1;\r\n             \telse\r\n-            \tif((System.currentTimeMillis()-PingPacket.lastPingResponse)>(2  * 60 * 1000)) // one hour\r\n+            \tif((System.currentTimeMillis()-PingPacket.lastPingResponse)>(60  * 60 * 1000)) // one hour\r\n             \t{\r\n             \t\tPingPacket.lastPingResponse=System.currentTimeMillis();\r\n             \t\tLog.errOut("Intermud","No I3 Ping received in "+CMLib.time().date2EllapsedTime(System.currentTimeMillis()-PingPacket.lastPingResponse, TimeUnit.SECONDS, false));\r\ndiff --git a/com/planet_ink/coffee_mud/core/intermud/imc2/IMC2Driver.java b/com/planet_ink/coffee_mud/core/intermud/imc2/IMC2Driver.java\nindex bdc0d38b99..1cce285373 100644\n--- a/com/planet_ink/coffee_mud/core/intermud/imc2/IMC2Driver.java\n+++ b/com/planet_ink/coffee_mud/core/intermud/imc2/IMC2Driver.java\n@@ -1548,7 +1548,7 @@ public final class IMC2Driver extends Thread {\n             long timeSinceLastPing=System.currentTimeMillis();\r\n             while (!shutdown) \r\n             {\r\n-            \tif((System.currentTimeMillis()-timeSinceLastPing) > ( 60 * 1000))\r\n+            \tif((System.currentTimeMillis()-timeSinceLastPing) > (30 * 60 * 1000))\r\n             \t{\r\n             \t\timc_client.imc_send_ping("Server01");\r\n             \t\ttimeSinceLastPing=System.currentTimeMillis();\r\n', 'commit_subject': '', 'repo_name': 'bozimmerman/CoffeeMud', 'committer': {'name': 'bozimmerman', 'email': 'dc45fe023482b3b890b5e574e53c1d051f45b1ef@zimmers.net', 'time_sec': '1301262717', 'tz_offset': '0', 'date': {'seconds': '1301262717'}}, 'commit_tree': 'd3b592d6805588f189b4f55c1af34b0d1dd810b7', 'commit_message': '\n\ngit-svn-id: svn://192.168.1.10/public/CoffeeMud@9005 0d6f1817-ed0e-0410-87c9-987e46238f29\n', 'language_name': 'HTML', 'license': 'apache-2.0', 'hunks': '@@ -1548,7 +1548,7 @@ public final class IMC2Driver extends Thread {\n             long timeSinceLastPing=System.currentTimeMillis();\r\n             while (!shutdown) \r\n             {\r\n-            \tif((System.currentTimeMillis()-timeSinceLastPing) > ( 60 * 1000))\r\n+            \tif((System.currentTimeMillis()-timeSinceLastPing) > (30 * 60 * 1000))\r\n             \t{\r\n             \t\timc_client.imc_send_ping("Server01");\r\n             \t\ttimeSinceLastPing=System.currentTimeMillis();\r\n', 'addition_count': 1, 'deletion_count': 1, 'src_file': 'a/com/planet_ink/coffee_mud/core/intermud/imc2/IMC2Driver.java', 'tgt_file': 'b/com/planet_ink/coffee_mud/core/intermud/imc2/IMC2Driver.java', 'file_extension': '.java', 'before_file': 'package com.planet_ink.coffee_mud.core.intermud.imc2;\n\nimport com.planet_ink.coffee_mud.Commands.interfaces.Command;\nimport com.planet_ink.coffee_mud.Common.interfaces.*;\nimport com.planet_ink.coffee_mud.Libraries.interfaces.ChannelsLibrary.CMChannel;\nimport com.planet_ink.coffee_mud.Libraries.interfaces.ChannelsLibrary.ChannelFlag;\nimport com.planet_ink.coffee_mud.Libraries.interfaces.ChannelsLibrary;\nimport com.planet_ink.coffee_mud.Libraries.interfaces.ColorLibrary;\nimport com.planet_ink.coffee_mud.Locales.interfaces.Room;\nimport com.planet_ink.coffee_mud.MOBS.interfaces.MOB;\nimport com.planet_ink.coffee_mud.core.*;\nimport com.planet_ink.coffee_mud.core.CMSecurity.DbgFlag;\nimport com.planet_ink.coffee_mud.core.CMSecurity.DisFlag;\nimport com.planet_ink.coffee_mud.core.collections.*;\n\nimport java.io.*;\nimport java.lang.reflect.Method;\nimport java.net.Socket;\nimport java.util.*;\n\n/**\n * IMC2 version 0.10 - an inter-mud communications protocol\n * Copyright (C) 1996 - 1997 Oliver Jowet: oliver@randomly.org\n *\n * IMC2 Gold versions 1.00 though 2.00 are developed by MudWorld.\n * Copyright (C) 1999 - 2002 Haslage Net Electronics (Anthony R. Haslage)\n *\n * IMC2 MUD-Net version 3.10 is developed by Alsherok and Crimson Oracles\n * Copyright (C) 2002 Roger Libiez ( Samson )\n * Additional code Copyright (C) 2002 Orion Elder\n * Registered with the United States Copyright Office\n * TX 5-555-584\n *\n * This program is free software; you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation; either version 2 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with this program (see the file COPYING); if not, write to the\n * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n *\n * Ported to Java by Istvan David (u_davis@users.sourceforge.net)\n *\n */\n\npublic final class IMC2Driver extends Thread\n{\n\tSocket sa;\n\n\t/* a player on IMC */\n\tfinal class imc_char_data {\n\t\tString name = ""; /* name of character */\n\t\tint invis; /* invisible to IMC? */\n\t\tint level; /* trust level */\n\t\tint wizi; /* wizi level */\n\t}\n\tstatic final int PERM_NONE = 0;\n\tstatic final int PERM_PLAYER = 1;\n\tstatic final int PERM_IMMORTAL = 2;\n\tstatic final int PERM_ADMIN = 3;\n\tboolean shutdown=false;\n\tboolean isShutdown=false;\n\n\tDate imc_boot = new Date();\n\tlong imc_now,imc_sequencenumber,imc_prev_sequencenumber;\n\tpublic hubinfo this_imcmud = new hubinfo();\n\tpublic siteinfo imc_siteinfo = new siteinfo();\n\timc_statistics imc_stats = new imc_statistics();\n\tpublic int imc_active; /* Connection state */\n\tlong HeartBeat = 0; // elapsed heartbeats\n\tcall_out c_thread=null;\n\tcall_in c_thread2=null;\n\n\tHashtable<String,REMOTEINFO> muds = new Hashtable<String,REMOTEINFO>();\n\tHashtable<String,IMC_CHANNEL> channels = new Hashtable<String,IMC_CHANNEL>();\n\tpublic Hashtable<String,List<String>> chanhist = new Hashtable<String,List<String>>();\n\tHashtable<String,String> replies = new Hashtable<String,String>();\n\n\tpublic Hashtable<String,String> chan_conf = new Hashtable<String,String>();\n\tpublic Hashtable<String,String> chan_mask = new Hashtable<String,String>();\n\n\tBufferedReader in;\n\tDataOutputStream out;\n\n\tpublic String imc_name = "";\n\tpublic short imc_log_on;\n\n\tprivate long reconnectBackoffTime = 20000;\n\n\t/* refresh timeout */\n\tfinal static int  IMC_TIMEOUT = 650;\n\n\tpublic final static int CHAN_OPEN     = 1;\n\tpublic final static int CHAN_CLOSED   = 2;\n\tpublic final static int CHAN_PRIVATE  = 3;\n\tpublic final static int CHAN_COPEN    = 4;\n\tpublic final static int CHAN_CPRIVATE = 5;\n\n\t/* max length of any mud name */\n\tfinal static int IMC_MNAME_LENGTH = 20;\n\n\t/* max length of any player name */\n\tfinal static int IMC_PNAME_LENGTH = 40;\n\n\t/* max length of any player@mud name */\n\tfinal static int IMC_NAME_LENGTH = (IMC_MNAME_LENGTH + IMC_PNAME_LENGTH + 1);\n\n\t/* activation states */\n\tpublic final static int IA_NONE = 0;\n\tpublic final static int IA_CONFIG1 = 1;\n\tpublic final static int IA_CONFIG2 = 2;\n\tpublic final static int IA_UP = 3;\n\n\t/* connection states */\n\tfinal static int IMC_CLOSED = 0; /* No active connection */\n\tfinal static int IMC_CONNECTING = 1; /* Contacting hub */\n\tfinal static int IMC_WAIT1 = 2; /* Waiting for hub verification */\n\tfinal static int IMC_CONNECTED = 3; /* Fully connected */\n\n\tfinal static int IMC_VERSION = 2;\n\tfinal static String IMC_VERSIONID  = "IMC2 4.00 for CoffeeMud";\n\n\tfinal void tracef(final int level, final String s)\n\t{\n\t\tif((level<1)||(CMSecurity.isDebugging(CMSecurity.DbgFlag.IMC2)))\n\t\t\tLog.debugOut("IMC2",level+"/"+s);\n\t}\n\n\tfinal void send_to_player(final String name, final String text)\n\t{\n\t\tif(name.equalsIgnoreCase("all"))\n\t\t{\n\t\t\tfor(final Session S : CMLib.sessions().localOnlineIterable())\n\t\t\t\tS.println(text);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfinal MOB M=CMLib.players().getPlayerAllHosts(name);\n\t\t\tif(M!=null)\n\t\t\t\tM.tell(text);\n\t\t}\n\t}\n\n\tpublic void ev_request_keepalive(final Object param)\n\t{\n\t\timc_request_keepalive();\n\t\t//imc_register_call_out(25, "ev_keepalive", null);\n\t}\n\n\tfinal public List<CMChannel> rebuildChannelMap()\n\t{\n\t\tfinal List<CMChannel> map=new Vector<CMChannel>(chan_conf.size());\n\t\tfor(final Enumeration<String> e=chan_conf.keys();e.hasMoreElements();)\n\t\t{\n\t\t\tfinal String name=e.nextElement();\n\t\t\tfinal String mask=chan_mask.get(name);\n\t\t\tfinal String imc2Name=chan_conf.get(name);\n\t\t\tfinal CMChannel chan=CMLib.channels().createNewChannel(name, "", imc2Name, mask, new HashSet<ChannelFlag>(),"","");\n\t\t\tmap.add(chan);\n\t\t}\n\t\treturn map;\n\t}\n\n\tfinal public static String[] explodeNicely(final String s)\n\t{\n\t\t  return explodeNicely(s, " ");\n\t}\n\n\tpublic void shutdown()\n\t{\n\t\tshutdown=true;\n\t\ttry\n\t\t{\n\t\tif(c_thread!=null)\n\t\t\tc_thread.shutdown();\n\t\t}\n\t\tcatch(final Exception e)\n\t\t{\n\t\t}\n\t\ttry\n\t\t{\n\t\tif(c_thread2!=null)\n\t\t\tc_thread2.shutdown();\n\t\t}\n\t\tcatch(final Exception e)\n\t\t{\n\t\t}\n\t\tCMLib.killThread(this,500,1);\n\n\t\tint i=0;\n\t\twhile (((++i)<60)&&((!c_thread.isShutdown)||(!c_thread2.isShutdown)||(!isShutdown)))\n\t\t\ttry { sleep(1000);    }\n\t\t\tcatch (final Exception ex)\n\t\t\t{\n\t\t\t}\n\t}\n\n\tfinal public static String[] explodeNicely(final String s, final String separator)\n\t{\n\t\tfinal StringTokenizer st = new StringTokenizer(s, separator);\n\n\t\tfinal int n = st.countTokens();\n\t\tif(n==0)\n\t\t{\n\t\t\tfinal String array[] = new String[1];\n\t\t\tarray[0] = s;\n\t\t\treturn array;\n\t\t}\n\n\t\tfinal String array[]  = new String[n];\n\n\t\tint i = 0;\n\t\twhile(st.hasMoreTokens())\n\t\t{\n\t\t\tarray[i] = st.nextToken();\n\t\t\t\ti++;\n\t\t}\n\n\t\treturn array;\n\t}\n\n\t/* put a line onto descriptors output buffer */\n\tfinal void do_imcsend( final String line )\n\t{\n\t\tif(line.endsWith("\\n\\r"))\n\t\t\tthis_imcmud.outbuf = line;\n\t\telse\n\t\t\tthis_imcmud.outbuf = line+"\\n\\r";\n\t}\n\n\t/* connect to hub */\n\tfinal boolean imc_connect_to()\n\t{\n\t\tString buf;\n\n\t\tif (imc_active == IA_NONE)\n\t\t{\n\t\t\ttracef(0, "IMC is not active");\n\t\t\treturn false;\n\t\t}\n\n\t\ttracef(8, "Connecting to " + this_imcmud.hubname);\n\n\t\ttry\n\t\t{\n\t\t\tsetName("IMC2Client:"+this_imcmud.host+"@"+this_imcmud.port);\n\t\t\tsa = new Socket(this_imcmud.host, this_imcmud.port);\n\t\t}\n\t\tcatch (final Exception e)\n\t\t{\n\t\t\ttracef(0, "Error connecting to " + this_imcmud.host + ":" +\n\t\t\t\t\t\t  this_imcmud.port);\n\t\t\treturn false;\n\n\t\t}\n\t\tif (sa == null)\n\t\t{\n\t\t\ttracef(0, "Error connecting to " + this_imcmud.host + ":" +\n\t\t\t\t\t\t  this_imcmud.port);\n\t\t\treturn false;\n\t\t}\n\n\t\ttry\n\t\t{\n\t\t\tsa.setSoTimeout(60000);\n\t\t\tin = new BufferedReader(new InputStreamReader(sa.getInputStream()));\n\t\t\tout = new DataOutputStream(sa.getOutputStream());\n\t\t}\n\t\tcatch(final Exception e)\n\t\t{\n\t\t}\n\n\t\tthis_imcmud.state = IMC_CONNECTING;\n\t\tthis_imcmud.insize = 1024;\n\t\tthis_imcmud.outsize = 1024;\n\n\t\tbuf = "PW " + imc_name.trim() + " " + this_imcmud.clientpw + " version=" +\n\t\t\tIMC_VERSION+" autosetup "+this_imcmud.serverpw;\n\t\tdo_imcsend(buf);\n\n\t\timc_write_to_socket(out);\n\t\timc_read_from_socket(in);\n\t\treconnectBackoffTime=20000;\n\t\treturn true;\n\t}\n\n\t/* start up IMC */\n\tfinal boolean imc_startup_network()\n\t{\n\t\tif (imc_active != IA_CONFIG2)\n\t\t{\n\t\t\ttracef(0, "imc_startup_network: called with imc_active == "+\n\t\t\t\t\t\t  imc_active);\n\t\t\treturn false;\n\t\t}\n\n\t\ttracef(8, "IMC2 Network Initializing");\n\n\t\timc_active = IA_UP;\n\t\timc_stats.start = imc_now;\n\t\timc_stats.rx_pkts = 0;\n\t\timc_stats.tx_pkts = 0;\n\t\timc_stats.rx_bytes = 0;\n\t\timc_stats.tx_bytes = 0;\n\t\timc_stats.sequence_drops = 0;\n\n\t\t/* Connect to Hub */\n\t\tif (!imc_connect_to())\n\t\t\treturn false;\n\n\t\timc_register_call_out(5, "ev_keepalive", null);\n\n\t\timc_register_call_out(6, "ev_request_keepalive", null);\n\n\t\treturn true;\n\t}\n\n\tfinal public void ev_imc_firstrefresh()\n\t{\n\t\tfinal PACKET out = new PACKET();\n\t\tif (this_imcmud == null || imc_active < IA_UP)\n\t\t\treturn;\n\n\t\tout.from = "*";\n\t\tout.to = "IMC@*";\n\t\tout.type = "ice-refresh";\n\t\timc_initdata(out);\n\t\timc_addkey(out, "channel", "*");\n\t\timc_send(out);\n\t}\n\n\tfinal public boolean imc_startup( final boolean force,\n\t\t\t\t\t\t\t\t\t  final String loginName,\n\t\t\t\t\t\t\t\t\t  final String host,\n\t\t\t\t\t\t\t\t\t  final String email,\n\t\t\t\t\t\t\t\t\t  final String web,\n\t\t\t\t\t\t\t\t\t  final String hub,\n\t\t\t\t\t\t\t\t\t  final int port,\n\t\t\t\t\t\t\t\t\t  final String passclient,\n\t\t\t\t\t\t\t\t\t  final String passsrvr,\n\t\t\t\t\t\t\t\t\t  final List<CMChannel> imc2Channels)\n\t{\n\t   if( imc_active != IA_NONE )\n\t   {\n\t\t  tracef(0,  "imc_startup: called with imc_active = "+imc_active );\n\t\t  return false;\n\t   }\n\t   imc_now = new Date().getTime()/1000; \t\t\t\t /* start our clock */\n\t   imc_boot = new Date();\n\n\t   imc_sequencenumber = imc_now;\n\n\t\tfor(final CMChannel chan : imc2Channels)\n\t\t{\n\t\t\tchan_mask.put(chan.name(),chan.mask());\n\t\t\tchan_conf.put(chan.name(),chan.imc2Name());\n\t\t}\n\n\t\timc_name=loginName;\n\t\timc_log_on=1; // logging?\n\t\tthis_imcmud.autoconnect=true;\n\t\timc_siteinfo.name=CMProps.getVar(CMProps.Str.MUDNAME);\n\t\timc_siteinfo.host=host;\n\t\timc_siteinfo.port=CMath.s_int(CMParms.parse(CMProps.getVar(CMProps.Str.MUDPORTS)).elementAt(0));\n\t\timc_siteinfo.email=email;\n\t\timc_siteinfo.base="CoffeeMud v"+CMProps.getVar(CMProps.Str.MUDVER);\n\t\timc_siteinfo.details="Custom Java-based Mud";\n\t\timc_siteinfo.www=web;\n\t\tthis_imcmud.hubname=hub;\n\t\tthis_imcmud.host=hub;\n\t\tthis_imcmud.port=port;\n\t\tthis_imcmud.clientpw=passclient;\n\t\tthis_imcmud.serverpw=passsrvr;\n\t\tif( !this_imcmud.autoconnect && !force )\n\t\t{\n\t\t\ttracef(8,  "IMC2 data loaded. Autoconnect not set. "+\n\t\t\t\t\t\t "IMC will need to be connected manually." );\n\t\t\treturn false;\n\t\t}\n\n\t\timc_active = !imc_name.equals("") ? IA_CONFIG2 : IA_CONFIG1;\n\n\t\tif( imc_active == IA_CONFIG2 && ( this_imcmud.autoconnect || force ) )\n\t\t{\n\t\t\tif( imc_startup_network() )\n\t\t\t{\n\t\t\t\tev_imc_firstrefresh();\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\timc_active = IA_NONE;\n\t\t}\n\t\treturn false;\n\t}\n\n\tfinal String normal2(String data)\n\t{\n\t\tdata = CMStrings.replaceAll(data, "\\\\\\"", "\\"");\n\t\tfinal StringBuffer str=new StringBuffer(data);\n\t\tfor(int i=0;i<str.length()-1;i++)\n\t\t{\n\t\t\tif(str.charAt(i)==\'~\')\n\t\t\tswitch(str.charAt(i+1))\n\t\t\t{\n\t\t\tcase \'R\':\n\t\t\tcase \'r\':\n\t\t\tcase \'y\':\n\t\t\tcase \'Y\':\n\t\t\tcase \'g\':\n\t\t\tcase \'G\':\n\t\t\tcase \'b\':\n\t\t\tcase \'B\':\n\t\t\tcase \'w\':\n\t\t\tcase \'W\':\n\t\t\tcase \'c\':\n\t\t\tcase \'C\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tbreak;\n\t\t\tcase \'m\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'p\');\n\t\t\t\tbreak;\n\t\t\tcase \'M\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'P\');\n\t\t\t\tbreak;\n\t\t\tcase \'p\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'p\');\n\t\t\t\tbreak;\n\t\t\tcase \'P\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'P\');\n\t\t\t\tbreak;\n\t\t\tcase \'z\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'R\');\n\t\t\t\tbreak;\n\t\t\tcase \'x\':\n\t\t\tcase \'u\':\n\t\t\tcase \'v\':\n\t\t\tcase \'i\':\n\t\t\tcase \'$\':\n\t\t\tcase \'s\':\n\t\t\tcase \'Z\':\n\t\t\tcase \'X\':\n\t\t\tcase \'D\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'W\');\n\t\t\t\tbreak;\n\t\t\tcase \'d\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'w\');\n\t\t\t\tbreak;\n\t\t\tcase \'!\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'.\');\n\t\t\t\tbreak;\n\t\t\tcase \'L\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'!\');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\tif(str.charAt(i)==\'^\')\n\t\t\tswitch(str.charAt(i+1))\n\t\t\t{\n\t\t\tcase \'O\':\n\t\t\t\tstr.setCharAt(i + 1, \'y\');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\telse\n\t\t\tif(str.charAt(i)==\'&\')\n\t\t\tswitch(str.charAt(i+1))\n\t\t\t{\n\t\t\tcase \'D\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.setCharAt(i + 1, \'!\');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn str.toString();\n\t}\n\n\t/* printkeys: print key-value pairs, escaping values */\n\tfinal String printkeys(final PACKET data)\n\t{\n\t\tString buf;\n\t\tint i;\n\n\t\tbuf = "";\n\n\t\tfor (i = 0; i < PACKET.IMC_MAX_KEYS; i++)\n\t\t{\n\t\t\tif (!data.key[i].equals("") )\n\t\t\t{\n\n\t\t\t\tbuf = buf + data.key[i] + "=";\n\t\t\t\tif (data.value[i].equals(""))\n\t\t\t\t\tbuf = buf + "\\"" + data.value[i] + "\\"";\n\t\t\t\telse\n\t\t\t\t\tbuf = buf + data.value[i];\n\t\t\t\tbuf = buf + " ";\n\t\t\t}\n\t\t}\n\t\treturn buf;\n\t}\n\n\tfinal public String do_imcstats()\n\t{\n\t\treturn "IMC Statistics:\\\\n\\\\r\\\\n"+\n\t\t\t"Received packets:    "+imc_stats.rx_pkts+"\\\\n\\\\r"+\n\t\t\t"Received bytes:      "+imc_stats.rx_bytes+"\\\\n\\\\r"+\n\t\t\t"Transmitted packets: "+imc_stats.tx_pkts+"\\\\n\\\\r"+\n\t\t\t"Transmitted bytes:   "+imc_stats.tx_bytes+"\\\\n\\\\r"+\n\t\t\t"Packets dropped:     "+imc_stats.sequence_drops+"\\\\n\\\\n\\\\r"+\n\t\t\t"Last IMC Boot:       "+imc_boot.toString()+"\\\\n\\\\r";\n\t}\n\tfinal public String do_imcinfo()\n\t{\n\t\tfinal String host=CMProps.getVar(CMProps.Str.MUDDOMAIN).toLowerCase();\n\t\treturn "IMC Statistics:\\\\n\\\\r\\\\n"+\n\t\t\t"Site Name           :"+imc_siteinfo.name+"\\\\n\\\\r"+\n\t\t\t"Site Host           :"+((host.length()>0)?host:sa.getLocalAddress().getHostName())+"\\\\n\\\\r"+\n\t\t\t"Site Port           :"+imc_siteinfo.port+"\\\\n\\\\r"+\n\t\t\t((imc_siteinfo.www.length()>0)?"Web Address         :"+imc_siteinfo.www+"\\\\n\\\\r":"")+\n\t\t\t((imc_siteinfo.www.length()>0)?"Email               :"+imc_siteinfo.email+"\\\\n\\\\r":"")+\n\t\t\t"Codebase            :"+imc_siteinfo.base+"\\\\n\\\\r"+\n\t\t\t"IMC Version         :"+IMC_VERSIONID+"\\\\n\\\\r";\n\t}\n\n\tfinal PACKET interpret2(final String argument )\n\t{\n\t\tString seq;\n\t\tfinal PACKET out = new PACKET();\n\n\t\timc_initdata(out);\n\n\t\tfinal StringTokenizer st = new StringTokenizer(argument, " ");\n\t\tif(st.countTokens() < 5)\n\t\t{\n\t\t\tif(st.countTokens() == 4)\n\t\t\t{\n\t\t\t\tfinal String tmp = st.nextToken();\n\t\t\t\tif(tmp.equalsIgnoreCase("autosetup"))\n\t\t\t\t{\n\t\t\t\t\t// who cares what the server says.\n\t\t\t\t\t/*\n\t\t\t\t\tString serverName = st.nextToken();\n\t\t\t\t\tif(st.nextToken().equalsIgnoreCase("accept"))\n\t\t\t\t\t{\n\t\t\t\t\t\tString networkName = st.nextToken();\n\t\t\t\t\t}\n\t\t\t\t\t*/\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttracef(0, "interpret: bad packet received, discarding");\n\t\t\t\ttracef(0, "interpret: argument was \'"+argument+"\'");\n\t\t\t\timc_stats.sequence_drops++;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\n\t\tif(imc_stats.max_pkt < argument.length())\n\t\t\timc_stats.max_pkt = argument.length();\n\n\t\timc_stats.rx_bytes += argument.length();\n\t\timc_stats.rx_pkts++;\n\n\t\tint pos = 0;\n\t\tString tmp = st.nextToken();\n\t\tout.i.from = tmp; pos+=tmp.length();\n\t\ttmp = st.nextToken();\n\t\tseq = tmp; pos+=tmp.length();\n\t\ttmp = st.nextToken();\n\t\tout.i.path = tmp; pos+=tmp.length();\n\t\ttmp = st.nextToken();\n\t\tout.type = tmp; pos+=tmp.length();\n\t\ttmp = st.nextToken();\n\t\tout.i.to = tmp; pos+=tmp.length();\n\n\t\tString keys = argument.substring(pos+5, argument.length());\n\n\t\ttry\n\t\t{\n\n\t\twhile((keys.length() > 0) && !keys.equals(" "))\n\t\t{\n\t\t\tString key = "";\n\t\t\tString val = "";\n\t\t\tfinal int kpos = keys.indexOf(\'=\');\n\t\t\tif(kpos > -1)\n\t\t\t{\n\t\t\t\tkey = keys.substring(0, kpos);\n\t\t\t\tkeys = keys.substring(kpos+1, keys.length());\n\t\t\t\tif(keys.startsWith("\\""))\n\t\t\t\t{\n\t\t\t\t\tint p = 0;\n\t\t\t\t\tboolean found = false;\n\t\t\t\t\twhile(!found)\n\t\t\t\t\t{\n\t\t\t\t\t\tp = keys.indexOf("\\"", p+1);\n\t\t\t\t\t\tif(p > -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfinal String tmp2 = keys.substring(p-1, p+1);\n\t\t\t\t\t\t\tif(!tmp2.equals("\\\\\\""))\n\t\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tp=keys.length();\n\t\t\t\t\t\t\tfound = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tval = keys.substring(1, p);\n\t\t\t\t\tif(p>=keys.length())\n\t\t\t\t\t\tkeys="";\n\t\t\t\t\telse\n\t\t\t\t\tif(p+2>=keys.length())\n\t\t\t\t\t\tkeys = keys.substring(p+1, keys.length());\n\t\t\t\t\telse\n\t\t\t\t\t\tkeys = keys.substring(p+2, keys.length());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tif(!keys.equals(" "))\n\t\t\t\t\t{\n\t\t\t\t\t\tfinal int npos = keys.indexOf(\' \');\n\t\t\t\t\t\tif (npos > -1)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tval = keys.substring(0, npos);\n\t\t\t\t\t\t\tif(npos+2 > keys.length())\n\t\t\t\t\t\t\t\tkeys = "";\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tkeys = keys.substring(npos + 1, keys.length());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tval = keys;\n\t\t\t\t\t\t\tkeys = "";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tkeys = "";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tval = normal2(val);\n\t\t\timc_addkey(out, key, val);\n\t\t}\n\n\t\t}\n\t\tcatch (final StringIndexOutOfBoundsException x)\n\t\t{\n\t\t\tLog.errOut("IMC2Driver", "Stringerror: "+keys);\n\t\t\tLog.errOut("IMC2Driver", x);\n\t\t}\n\t\tcatch (final Exception e)\n\t\t{\n\t\t\tLog.errOut("IMC2Driver", e);\n\t\t}\n\n\t\tout.i.sequence = Long.valueOf(seq).longValue();\n\t\treturn out;\n\t}\n\n\tfinal String generate2( final PACKET p )\n\t{\n\t   String temp;\n\t   String newpath;\n\n\t   if(p.i.path.equals(""))\n\t\t  newpath = imc_name;\n\t   else\n\t\t  newpath = imc_name+"!"+p.i.path;\n\n\t   temp = p.i.from+" "+p.i.sequence+" "+newpath+" "+p.type+" "+p.i.to+" "+printkeys( p );\n\n\t   imc_stats.tx_bytes += temp.length();\n\t   imc_stats.tx_pkts++;\n\n\t   return temp;\n\t}\n\n\tfinal void do_send_packet( final PACKET p )\n\t{\n\t\tString output;\n\n\t\toutput = generate2(p);\n\t\tdo_imcsend(output);\n\t}\n\n\tfinal IMC_CHANNEL imc_findchannel( final String name )\n\t{\n\t\tif(channels.get(name)!=null)\n\t\t\treturn channels.get(name);\n\t\treturn null;\n\t}\n\n\t/* return \'mud\' from \'player@mud\' */\n\tfinal String imc_mudof(final String fullname )\n\t{\n\t   String buf;\n\n\t   final int pos = fullname.indexOf(\'@\');\n\t   if(pos > -1)\n\t\t   buf = fullname.substring(pos+1);\n\t\telse\n\t\t\tbuf = "*";\n\n\t   return buf;\n\t}\n\n\t/* return d from a!b!c!d */\n\tfinal String imc_lastinpath(final String path)\n\t{\n\t\tfinal int pos = path.lastIndexOf(\'!\');\n\t\tif(pos < 0)\n\t\t\treturn path;\n\n\t\treturn path.substring(pos+1, path.length());\n\t}\n\n\t/* return \'player\' from \'player@mud\' */\n\tfinal String imc_playerof(final String fullname )\n\t{\n\t   String buf;\n\n\t   final int pos = fullname.indexOf(\'@\');\n\t   if(pos > -1)\n\t\t   buf = fullname.substring(0, pos);\n\t\telse\n\t\t\tbuf = "*";\n\n\t   return buf;\n\t}\n\n\t/* add "key=value" to "p" */\n\tfinal void imc_addkey(final PACKET p, final String key, String value)\n\t{\n\n\t\tfor(int i = 0; i < value.length(); i++)\n\t\t{\n\t\t\tif(value.substring(i, i+1).equals("\\""))\n\t\t\t{\n\t\t\t\tString tmp = value.substring(0, i);\n\t\t\t\ttmp = tmp.concat("\\\\\\"").concat(value.substring(i+1, value.length()));\n\t\t\t\tvalue = tmp;\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t\tfor (int i = 0; i < PACKET.IMC_MAX_KEYS; i++)\n\t\t{\n\t\t\tif (!p.key[i].equals("") && (key.equalsIgnoreCase(p.key[i])))\n\t\t\t{\n\t\t\t\tp.key[i] = "";\n\t\t\t\tp.value[i] = "";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (value=="")\n\t\t\treturn;\n\n\t\tfor (int i = 0; i < PACKET.IMC_MAX_KEYS; i++)\n\t\t{\n\t\t\tif (p.key[i] == "")\n\t\t\t{\n\t\t\t\tp.key[i] = key;\n\t\t\t\tif((value.indexOf(\' \') > -1))\n\t\t\t\t\tvalue = "\\""+value+"\\"";\n\t\t\t\tp.value[i] = value;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t/* add "key=value" for an integer value */\n\tfinal void imc_addkeyi(final PACKET p, final String key, final int value)\n\t{\n\t\tString temp;\n\t\ttemp = String.valueOf(value);\n\t\timc_addkey(p, key, temp);\n\t}\n\n\t/* clear all keys in "p" */\n\tfinal void imc_initdata(final PACKET p)\n\t{\n\t\tint i;\n\n\t\tfor (i = 0; i < PACKET.IMC_MAX_KEYS; i++)\n\t\t{\n\t\t\tp.key[i] = "";\n\t\t\tp.value[i] = "";\n\t\t}\n\t}\n\n\t/* convert back from \'d\' to \'p\' */\n\tfinal void setdata(final PACKET p, final imc_char_data d)\n\t{\n\t\timc_initdata(p);\n\n\t\tif (d == null)\n\t\t{\n\t\t\tp.from = "*";\n\t\t\timc_addkeyi(p, "level", -1);\n\t\t\treturn;\n\t\t}\n\n\t\tp.from = d.name;\n\n\t\tif (d.wizi > 0)\n\t\t\timc_addkeyi(p, "wizi", d.wizi);\n//  \t  imc_addkeyi(p, "level", d.level);\n\t}\n\n\t/* send a who-request to a remote mud */\n\tfinal void imc_send_who(final imc_char_data from, final String to, final String type)\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn;\n\n\t\tif (imc_mudof(to).equals("*"))\n\t\t\treturn; /* don\'t let them do this */\n\n\t\tsetdata(out, from);\n\n\t\tout.to = "*@" + imc_mudof(to);\n\t\tout.type = "who";\n\n\t\timc_addkey(out, "type", type);\n\n\t\timc_send(out);\n\t}\n\n\t/* send a who-request to a remote mud */\n   public final void imc_send_whois(final String from, final String to, final int level)\n   {\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn;\n\n\t\t//if (imc_mudof(to).equals("*"))\n\t\t//    return; /* don\'t let them do this */\n\n\t\timc_initdata(out);\n\n\t\tout.from = from;\n\n\t\tout.to = to+"@*";\n\t\tout.type = "whois";\n\n\t\timc_addkeyi(out, "level", level);\n\n\t\timc_send(out);\n\t}\n\n\tfinal void imc_send( final PACKET p)\n\t{\n\t\tif (imc_active < IA_UP)\n\t\t{\n\t\t\ttracef(0, "imc_send when not active!");\n\t\t\treturn;\n\t\t}\n\n\t\t/* initialize packet fields that the caller shouldn\'t/doesn\'t set */\n\n\t\tp.i.stamp = 0;\n\t\tp.i.path = "";\n\n\t\tp.i.sequence = imc_sequencenumber;\n\t\tif(p.i.sequence == imc_prev_sequencenumber)\n\t\t{\n\t\t\tp.i.sequence++;\n\t\t\timc_sequencenumber++;\n\t\t}\n\n\t\timc_prev_sequencenumber = imc_sequencenumber;\n\n\t\tp.i.to = p.to;\n\t\tp.i.from = p.from;\n\t\tp.i.from = p.i.from.concat("@");\n\t\tp.i.from = p.i.from.concat(imc_name);\n\n//  \tp.i.path = this_imcmud.hubname;\n\n\t\tdo_send_packet(p);\n\t}\n\n\tfinal void imc_loop()\n\t{\n\t\treturn;\n\t}\n\n//\n\t// list of all active call_out\'s in the game\n\t//\n\tstatic LinkedList<Vector<Object>> call_outs = new LinkedList<Vector<Object>>();\n\n\tpublic void imc_register_call_out(final int hbeat, final String function_name, final Object param)\n\t{\n\t\tfinal Vector<Object> call_out = new Vector<Object>();\n\t\tcall_out.add(function_name);\n\t\tcall_out.add(Long.valueOf(HeartBeat + hbeat));\n\t\tcall_out.add(param);\n\n\t\tcall_outs.add(call_out);\n\t}\n\n\tpublic void imc_process_call_outs()\n\t{\n\t\tif (call_outs.size() < 1)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tfor (int i = 0; i < call_outs.size(); i++)\n\t\t{\n\t\t\tfinal Vector<Object> call_out = call_outs.get(i);\n\t\t\tfinal String fun = (String) call_out.elementAt(0);\n\t\t\tfinal long hbeat = ( (Long) call_out.elementAt(1)).longValue();\n\t\t\tfinal Object param = call_out.elementAt(2);\n\n\t\t\tif (hbeat == HeartBeat)\n\t\t\t{\n\t\t\t\tfinal Object o = this;\n\t\t\t\tfinal Class<?> cl = o.getClass();\n\t\t\t\tfinal java.lang.reflect.Method funcs[] = cl.getMethods();\n\t\t\t\tif (funcs.length > 1)\n\t\t\t\t{\n\t\t\t\t\tfor (final Method func : funcs)\n\t\t\t\t\t{\n\t\t\t\t\t\tfinal String m_name = func.getName();\n\t\t\t\t\t\tif (m_name.equals(fun))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttry\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfunc.invoke(o, new Object[] {param});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcatch (final Exception e)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttracef(0,\n\t\t\t\t\t\t\t\t\t   "imc: call_out failed with error: "\n\t\t\t\t\t\t\t\t\t   + e.toString());\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcall_outs.remove(i);\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t}\n\n\tfinal public static String toIMCColours(String res)\n\t{\n\t\t// ANSI color macros\n\t\tres = CMStrings.replaceAll(res, "\\"", "\\\\\\"");\n\t\tfinal StringBuffer str=new StringBuffer(res);\n\t\tfor(int i=0;i<str.length()-1;i++)\n\t\t{\n\t\t\tif(str.charAt(i)==\'`\')\n\t\t\t\tstr.setCharAt(i,\'\\\'\');\n\t\t\telse\n\t\t\tif(str.charAt(i)==\'^\')\n\t\t\tswitch(str.charAt(i+1))\n\t\t\t{\n\t\t\tcase ColorLibrary.COLORCODE_BACKGROUND:\n\t\t\t\tif (i < str.length() - 2)\n\t\t\t\t\tstr.delete(i, i + 3);\n\t\t\t\tbreak;\n\t\t\tcase ColorLibrary.COLORCODE_FANSI256:\n\t\t\tcase ColorLibrary.COLORCODE_BANSI256:\n\t\t\t\tif (i < str.length() - 4)\n\t\t\t\t\tstr.delete(i, i + 5);\n\t\t\t\tbreak;\n\t\t\tcase \'R\':\n\t\t\tcase \'r\':\n\t\t\tcase \'y\':\n\t\t\tcase \'Y\':\n\t\t\tcase \'g\':\n\t\t\tcase \'G\':\n\t\t\tcase \'b\':\n\t\t\tcase \'B\':\n\t\t\tcase \'w\':\n\t\t\tcase \'W\':\n\t\t\tcase \'c\':\n\t\t\tcase \'C\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tbreak;\n\t\t\tcase \'m\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'p\');\n\t\t\t\tbreak;\n\t\t\tcase \'M\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'P\');\n\t\t\t\tbreak;\n\t\t\tcase \'p\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'m\');\n\t\t\t\tbreak;\n\t\t\tcase \'P\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'M\');\n\t\t\t\tbreak;\n\t\t\tcase \'?\':\n\t\t\tcase \'.\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'!\');\n\t\t\t\tbreak;\n\t\t\tcase \'!\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'L\');\n\t\t\t\tbreak;\n\t\t\tcase \'*\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'$\');\n\t\t\t\tbreak;\n\t\t\tcase \'/\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'s\');\n\t\t\t\tbreak;\n\t\t\tcase \'_\':\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'u\');\n\t\t\t\tbreak;\n\t\t\tcase \'^\':\n\t\t\t\tstr.setCharAt(i, \'^\');\n\t\t\t\tstr.deleteCharAt(i + 1);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstr.setCharAt(i, \'~\');\n\t\t\t\tstr.setCharAt(i + 1, \'c\');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn str.toString();\n\t}\n\n\tfinal String update_wholist()\n\t{\n\t\tfinal StringBuffer str=new StringBuffer("Players on "+CMProps.getVar(CMProps.Str.MUDNAME)+":\\\\n\\\\r");\n\t\tfinal Command C=CMClass.getCommand("Who");\n\t\tif(C!=null)\n\t\t{\n\t\t\tString msg=null;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tmsg=(String)C.executeInternal(null,0);\n\t\t\t}\n\t\t\tcatch(final Exception e)\n\t\t\t{\n\t\t\t}\n\t\t\tif(msg!=null)\n\t\t\t{\n\t\t\t\tmsg=CMStrings.replaceAll(msg,"\\n\\r","\\\\n\\\\r");\n\t\t\t\treturn str.toString()+msg;\n\t\t\t}\n\t\t}\n\t\treturn "Unavailable";\n\t}\n\n\tfinal String who_help()\n\t{\n\t\treturn "\\\\n\\\\r"+\n\t\t\t"Available imcminfo types:\\\\n\\\\r"+\n\t\t\t"help   - this screen\\\\n\\\\r"+\n\t\t\t"who    - who is online\\\\n\\\\r"+\n\t\t\t"info   - mud information\\\\n\\\\r"+\n\t\t\t"who    - who is online\\\\n\\\\r";\n\t}\n\n\tfinal void imc_recv_who(final imc_char_data from, final String sender, final String type)\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\timc_initdata(out);\n\t\tout.from = from.name;\n\t\timc_addkeyi(out, "level", 3);\n\n\t\tout.to = sender;\n\t\tout.type = "who-reply";\n\n\t\tif(type.equals("who"))\n\t\t\timc_addkey(out, "text", toIMCColours(update_wholist()));\n\t\telse\n\t\tif(type.equals("istats"))\n\t\t\timc_addkey(out, "text", toIMCColours(do_imcstats()));\n\t\telse\n\t\tif(type.equals("info"))\n\t\t\timc_addkey(out, "text", toIMCColours(do_imcinfo()));\n\t\telse\n\t\tif(type.equals("help"))\n\t\t\timc_addkey(out, "text", toIMCColours(who_help()));\n\n\t\timc_send(out);\n\t}\n\n\tfinal void imc_recv_whois(final imc_char_data from, final String sender, final int level)\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\timc_initdata(out);\n\t\tout.from = from.name;\n\t\timc_addkeyi(out, "level", 3);\n\n\t\tout.to = sender;\n\t\tout.type = "whois-reply";\n\n\t\tfinal MOB M=CMLib.players().getPlayerAllHosts(from.name);\n\t\tif(M==null)\n\t\t\treturn;\n\t\timc_addkey(out, "text", "imcpfind "+from.name+"@"+imc_name\n\t\t\t\t\t\t+" is "+(CMLib.flags().isInTheGame(M,false) ? "online":"offline")+ ".");\n\n\t\timc_send(out);\n\t}\n\n\tfinal void imc_recv_ping(final imc_char_data from, final String path, final String sender)\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\timc_initdata(out);\n\t\tout.from = from.name;\n\n\t\tout.to = sender;\n\t\tout.type = "ping-reply";\n\n\t\timc_addkey(out, "path", path);\n\n\t\timc_send(out);\n\t}\n\n\tfinal void imc_recv_tell(final imc_char_data d, final String from, final String text)\n\t{\n\t\tfinal MOB mob=CMClass.getFactoryMOB();\n\t\tmob.setName(from);\n\t\tmob.setLocation(CMClass.getLocale("StdRoom"));\n\t\tfinal MOB smob=CMLib.sessions().findCharacterOnline(d.name,true);\n\t\tif(smob!=null)\n\t\t\tCMLib.commands().postSay(mob,smob,text,true,true);\n\t\tfinal Room R=mob.location();\n\t\tmob.destroy();\n\t\tif(R!=null)\n\t\t\tR.destroy();\n\t}\n\n\tpublic REMOTEINFO getIMC2Mud(final String named)\n\t{\n\t\tfinal Hashtable<String,REMOTEINFO> l=query_muds();\n\t\tif(l.containsKey(named))\n\t\t\treturn l.get(named);\n\t\tfor(final Enumeration<REMOTEINFO> e=l.elements();e.hasMoreElements();)\n\t\t{\n\t\t\tfinal REMOTEINFO m=e.nextElement();\n\t\t\tif(m.name.equalsIgnoreCase(named))\n\t\t\t\treturn m;\n\t\t}\n\t\treturn null;\n\t}\n\n\tfinal void imc_recv_chat(final imc_char_data d, final String from, String channel, final String text, final int emote)\n\t{\n\t\tfinal StringTokenizer st = new StringTokenizer(channel, ":");\n\t\tif (st.countTokens() > 1)\n\t\t{\n\t\t\tchannel = st.nextToken();\n\t\t\tchannel = st.nextToken();\n\t\t}\n\t\telse\n\t\tif(st.countTokens()> 0)\n\t\t\tchannel=st.nextToken();\n\n\t\tString channelName=channel;\n\t\tCMMsg msg=null;\n\t\tif(from.toUpperCase().endsWith(imc_name.toUpperCase()))\n\t\t\treturn;\n\t\tif(channelName.length()==0)\n\t\t\treturn;\n\t\tchannelName=read_channel_name(channelName);\n\t\tif(channelName.length()==0)\n\t\t\treturn;\n\t\tfinal ChannelsLibrary channels = CMLib.channels();\n\t\tfinal int channelInt=channels.getChannelIndex(channelName);\n\t\tif(channelInt<0)\n\t\t\treturn;\n\t\tfinal String channelColor="^Q";\n\t\tfinal MOB mob=CMClass.getFactoryMOB();\n\t\tmob.setName(from);\n\t\tmob.setLocation(CMClass.getLocale("StdRoom"));\n\t\tString str=channelColor+"^<CHANNEL \\""+channelName+"\\"^>"+mob.name()+" "+channelName+"(S) \'"+text+"\'^</CHANNEL^>^N^.";\n\t\tif(emote>0)\n\t\t{\n\t\t\tif(emote==1)\n\t\t\t\tstr=channelColor+"^<CHANNEL \\""+channelName+"\\"^>["+channelName+"] "+from+" "+text+"^</CHANNEL^>^N^.";\n\t\t\telse\n\t\t\t\tstr=channelColor+"^<CHANNEL \\""+channelName+"\\"^>["+channelName+"] "+text+"^</CHANNEL^>^N^.";\n\t\t}\n\n\t\tmsg=CMClass.getMsg(mob,null,null,CMMsg.NO_EFFECT,null,CMMsg.NO_EFFECT,null,CMMsg.MASK_CHANNEL|(CMMsg.TYP_CHANNEL+channelInt),str);\n\n\t\tchannels.channelQueUp(channelInt,(CMMsg)msg.copyOf(), 0);\n\t\tfor(final Session S : CMLib.sessions().localOnlineIterable())\n\t\t{\n\t\t\tfinal ChannelsLibrary myChanLib=CMLib.get(S)._channels();\n\t\t\tfinal int chanNum = (myChanLib == channels) ? channelInt : myChanLib.getChannelIndex(channel);\n\t\t\tif((chanNum >= 0)\n\t\t\t&&(myChanLib.mayReadThisChannel(mob,false,S,chanNum))\n\t\t\t&&(S.mob().location()!=null))\n\t\t\t{\n\t\t\t\tmsg.setOthersCode(CMMsg.MASK_CHANNEL|(CMMsg.TYP_CHANNEL+chanNum));\n\t\t\t\tif(S.mob().location().okMessage(S.mob(),msg))\n\t\t\t\t\tS.mob().executeMsg(S.mob(),msg);\n\t\t\t}\n\t\t}\n\n\t\tList<String> l = chanhist.get(channel);\n\t\tif(l == null)\n\t\t\tl = new LinkedList<String>();\n\n\t\tl.add(str);\n\t\tchanhist.put(channel, l);\n\t\tfinal Room R=mob.location();\n\t\tmob.destroy();\n\t\tif(R!=null)\n\t\t\tR.destroy();\n\t}\n\n\tfinal void imc_recv_is_alive(final imc_char_data d, final String from, final String path,\n\t\t\t\t\t\t   final String version, final String netname)\n\t{\n\t\tfinal String mudname = imc_mudof(from);\n\t\tfinal REMOTEINFO rinfo = new REMOTEINFO();\n\t\trinfo.name = mudname;\n\t\trinfo.network = netname;\n\t\trinfo.version = version;\n\n\t\tfinal int pos = path.indexOf(\'!\');\n\t\tif(pos > -1)\n\t\t{\n\t\t\tfinal String hubs = path.substring(pos+1, path.length());\n\t\t\tfinal int pos2 = hubs.indexOf(\'!\');\n\t\t\tif(pos2 > -1)\n\t\t\t\trinfo.hub = hubs.substring(0, pos2);\n\t\t\telse\n\t\t\t\trinfo.hub = hubs;\n\t\t}\n\t\telse\n\t\t\trinfo.hub = "None";\n\n\t\tmuds.put(mudname, rinfo);\n\t}\n\n\tfinal void imc_recv_who_reply(final imc_char_data d, String text)\n\t{\n\t\ttext = CMStrings.replaceAll(text, "\\\\n\\\\r", "\\n\\r");\n\t\tsend_to_player(d.name, "\\n\\r"+text+"^.^?");\n\t}\n\n\tfinal void imc_recv_whois_reply(final imc_char_data d, final String to, String text)\n\t{\n\t\ttext = CMStrings.replaceAll(text, "\\\\n\\\\r", "\\n\\r");\n\t\tsend_to_player(d.name, "\\n\\r"+to+": "+text+"^.^?");\n\t}\n\n\tfinal void imc_recv_ping_reply(final imc_char_data d, final String from, final String path)\n\t{\n\t   final String route[] = explodeNicely(path, "!");\n\n\t   final StringBuffer text = new StringBuffer("Traceroute information for "+from+"\\n\\r");\n\n\t   text.append("^cSend path:^?   ");\n\t   for(int i = 0; i < route.length; i++)\n\t   {\n\t\t   if (i > 0)\n\t\t\t   text.append("->");\n\t\t   text.append(route[i]);\n\t   }\n\t   text.append("\\n\\r");\n\t   text.append("^cReturn path:^? ");\n\t   for(int i= route.length-1; i >= 0; i--)\n\t   {\n\t\t   if (i < route.length-1)\n\t\t\t   text.append("->");\n\t\t   text.append(route[i]);\n\t   }\n\n\t   if(CMSecurity.isDebugging(DbgFlag.IMC2))\n\t\t   Log.debugOut("IMC2Driver",text.toString());\n\t   //send_to_player(d.name, text.toString());\n   }\n\n\tfinal String read_channel_name(String channame)\n\t{\n\t\tif(channame==null)\n\t\t\treturn "";\n\t\tchanname=channame.toUpperCase();\n\t\tfor(final Enumeration<String> e=chan_conf.keys();e.hasMoreElements();)\n\t\t{\n\t\t\tfinal String key=e.nextElement();\n\t\t\tfinal String val=chan_conf.get(key).toUpperCase();\n\t\t\tif(val.equals(channame))\n\t\t\t\treturn key;\n\t\t\tif(val.endsWith(":"+channame))\n\t\t\t\treturn key;\n\t\t\tif(channame.endsWith(":"+val))\n\t\t\t\treturn key;\n\t\t}\n\t\treturn "";\n\t}\n\n\tpublic IMC_CHANNEL getAnIMC2Channel(String name)\n\t{\n\t\tname=name.toUpperCase();\n\t\tfor(final Enumeration<IMC_CHANNEL> e=channels.elements();e.hasMoreElements();)\n\t\t{\n\t\t\tfinal IMC_CHANNEL c=e.nextElement();\n\t\t\tif(read_channel_name(c.name).equalsIgnoreCase(name))\n\t\t\t\treturn c;\n\t\t}\n\t\treturn null;\n\t}\n\n\tfinal void imc_recv_update(final String from, final String chan, final String owner,\n\t\t\t\t\t\t final String operators, final String policy, final String invited,\n\t\t\t\t\t\t final String excluded )\n\t{\n\t\tIMC_CHANNEL c;\n\t\tString mud;\n\n\t\tmud = imc_mudof(from);\n\n\t\t/* forged? */\n\t\tif (chan.indexOf(\':\')<-1 || !mud.equalsIgnoreCase(imc_mudof(chan)))\n\t\t\treturn;\n\n\t\tc = new IMC_CHANNEL();\n\t\tc.name = chan;\n\t\tc.owner = owner;\n\t\tc.operators = operators;\n\t\tc.invited = invited;\n\t\tc.excluded = excluded;\n\t\tc.local_name = this.read_channel_name(chan);\n\t\tc.perm_level = PERM_ADMIN;\n\t\tc.refreshed = true;\n\n\t\tif (policy.equalsIgnoreCase("open"))\n\t\t\tc.policy = CHAN_OPEN;\n\t\telse\n\t\tif (policy.equalsIgnoreCase("closed"))\n\t\t\tc.policy = CHAN_CLOSED;\n\t\telse\n\t\tif (policy.equalsIgnoreCase("copen"))\n\t\t\tc.policy = CHAN_COPEN;\n\t\telse\n\t\tif (policy.equalsIgnoreCase("cprivate"))\n\t\t\tc.policy = CHAN_CPRIVATE;\n\t\telse\n\t\t\tc.policy = CHAN_PRIVATE;\n\n\t\tchannels.put(c.name, c);\n   }\n\n\t/* get the value of "key" from "p"; if it isn\'t present, return "def" */\n\tfinal String imc_getkey( final PACKET p, final String key, final String def )\n\t{\n\t   int i;\n\n\t   for( i = 0; i < PACKET.IMC_MAX_KEYS; i++ )\n\t{\n\t\t  if( !p.key[i].equals("") && p.key[i].equalsIgnoreCase(key))\n\t\t  {\n\t\t\t  if(p.value[i].startsWith("\\""))\n\t\t\t\t  return p.value[i].substring(1, p.value[i].length()-1);\n\t\t\t  return p.value[i];\n\t\t  }\n\n\t}\n\t   return def;\n\t}\n\n\t/* identical to imc_getkey, except get the integer value of the key */\n\tfinal int imc_getkeyi( final PACKET p, final String key, final int def )\n\t{\n\t   int i;\n\n\t   for( i = 0; i < PACKET.IMC_MAX_KEYS; i++ )\n\t{\n\t\t  if( !p.key[i].equals("") && p.key[i].equalsIgnoreCase(key) )\n\t\t  {\n\t\t\t  return CMath.s_int(p.value[i]);\n\t\t  }\n\n\t}\n\t   return def;\n\t}\n\n\tfinal public Hashtable<String,IMC_CHANNEL> query_channels()\n\t{\n\t\treturn channels;\n\t}\n\n\tfinal public Hashtable<String,REMOTEINFO> query_muds()\n\t{\n\t\treturn muds;\n\t}\n\n\tfinal public void exec_commands(final PACKET p)\n\t{\n\t\tif (p == null)\n\t\t\treturn;\n\t\tfinal imc_char_data d = new imc_char_data();\n\n\t\td.name = p.i.to;\n\t\td.wizi = imc_getkeyi(p, "wizi", 0);\n\t\td.level = imc_getkeyi(p, "level", 0);\n\t\td.invis = 0;\n\n\t\tfinal String to_mud = imc_mudof(d.name);\n\t\tif (!to_mud.equalsIgnoreCase(imc_name) && !to_mud.equals("*"))\n\t\t{\n\t\t\ttracef(8, "Message was for "+to_mud+", not "+imc_name+" -- rejecting!");\n\t\t\treturn;\n\t\t}\n\n\t\td.name = imc_playerof(d.name);\n\t\ttracef(8, "Received message was sent to " + d.name+", "+p.type+", "+CMParms.toListString(p.value));\n\n\t\tif (p.type.equals("who"))\n\t\t{\n\t\t\ttracef(8, "Who request received from " + p.i.from);\n\t\t\timc_recv_who(d, p.i.from, imc_getkey(p, "type", "who"));\n\t\t}\n\n\t\tif (p.type.equals("whois"))\n\t\t{\n\t\t\ttracef(8, "Whois request received from " + p.i.from);\n\t\t\timc_recv_whois(d, p.i.from, imc_getkeyi(p, "level", 0));\n\t\t}\n\n\t\tif (p.type.equals("ping"))\n\t\t{\n\t\t\ttracef(8, "Ping reply received from " + p.i.from);\n\t\t\timc_recv_ping(d, p.i.path, p.i.from);\n\t\t}\n\n\t\tif (p.type.equals("tell"))\n\t\t{\n\t\t\ttracef(8, "Tell received from " + p.i.from);\n\t\t\timc_recv_tell(d, p.i.from, imc_getkey(p, "text", ""));\n\t\t}\n\n\t\tif (p.type.equals("keepalive-request"))\n\t\t{\n\t\t\ttracef(8, "Keepalive request received from " + p.i.from);\n\t\t\timc_send_isalive(p.i.from);\n\t\t}\n\n\t\tif (p.type.equals("who-reply"))\n\t\t{\n\t\t\ttracef(8, "Who reply received from " + p.i.from);\n\t\t\timc_recv_who_reply(d, imc_getkey(p, "text", ""));\n\t\t}\n\n\t\tif (p.type.equals("whois-reply"))\n\t\t{\n\t\t\ttracef(8, "Who-Is reply received from " + p.i.from);\n\t\t\timc_recv_whois_reply(d, p.i.from, imc_getkey(p, "text", ""));\n\t\t}\n\n\t\tif (p.type.equals("ping-reply"))\n\t\t{\n\t\t\ttracef(8, "Ping-reply reply received from " + p.i.from);\n\t\t\timc_recv_ping_reply(d, p.i.from, imc_getkey(p, "path", ""));\n\t\t}\n\n\t\tif (p.type.equals("is-alive"))\n\t\t{\n\t\t\ttracef(8, "is-alive received from " + p.i.from);\n\t\t\timc_recv_is_alive(d, p.i.from, p.i.path,\n\t\t\t\t\t\t\t  imc_getkey(p, "versionid", "Unknown"),\n\t\t\t\t\t\t\t  imc_getkey(p, "networkname", "None"));\n\t\t}\n\n\t\tif (p.type.equals("ice-msg-b"))\n\t\t{\n\t\t\ttracef(8, "Chat received from " + p.i.from);\n\t\t\timc_recv_chat(d, p.i.from, imc_getkey(p, "channel", "ICHAT"),\n\t\t\t\t\t\t  imc_getkey(p, "text", ""),CMath.s_int(imc_getkey(p,"emote","0")));\n\t\t}\n\n\t\tif (p.type.equals("ice-update"))\n\t\t{\n\t\t\ttracef(8, "Ice update reply from " + p.i.from);\n\t\t\timc_recv_update(p.from, imc_getkey(p, "channel", ""),\n\t\t\t\t\t\t\timc_getkey(p, "owner", ""),\n\t\t\t\t\t\t\timc_getkey(p, "operators", ""),\n\t\t\t\t\t\t\timc_getkey(p, "policy", ""),\n\t\t\t\t\t\t\timc_getkey(p, "invited", ""),\n\t\t\t\t\t\t\timc_getkey(p, "excluded", ""));\n\n\t\t}\n\t}\n\n\tfinal boolean check_password(final String s)\n\t{\n\t\tfinal StringTokenizer st = new StringTokenizer(s, " ");\n\t\tif (st.countTokens() < 3)\n\t\t{\n\t\t\ttracef(0, "Password not found in Hub reply.");\n\t\t\treturn false;\n\t\t}\n\n\t\tst.nextToken();\n\t\tst.nextToken();\n\t\tfinal String pwd = st.nextToken();\n\n\t\tif (pwd.equals(this_imcmud.serverpw))\n\t\t{\n\t\t\ttracef(8, "Password OK.");\n\t\t\treturn true;\n\t\t}\n\t\ttracef(0, "Password incorrect.");\n\t\treturn false;\n\t}\n\n\tfinal public void imc_read_from_socket(final BufferedReader in)\n\t{\n\t\ttry\n\t\t{\n\t\t\tif ((in!=null)&&(in.ready()))\n\t\t\t{\n\t\t\t\tfinal String s = in.readLine();\n\t\t\t\tif (s == null) return;\n\n\t\t\t\tif (s.length() > 0)\n            long timeSinceLastPing=System.currentTimeMillis();\r\n            while (!shutdown) \r\n            {\r\n            \tif((System.currentTimeMillis()-timeSinceLastPing) > ( 60 * 1000))\r\n            \t{\r\n            \t\timc_client.imc_send_ping("Server01");\r\n            \t\ttimeSinceLastPing=System.currentTimeMillis();\r\n\t\t\t\t\t\tif(p!=null)\n\t\t\t\t\t\t\texec_commands(p);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcatch (final Exception e)\n\t\t{\n\t\t\tfinal String errMsg=e.getMessage()==null?e.toString():e.getMessage();\n\t\t\tif((errMsg==null)\n\t\t\t||(errMsg.toUpperCase().indexOf("TIMED OUT")<0))\n\t\t\t\tLog.errOut("IMC2Driver", "read: "+errMsg);\n\t\t\tif((errMsg!=null)\n\t\t\t&&(!shutdown)\n\t\t\t&&(errMsg.toUpperCase().indexOf("CONNECTION")>=0))\n\t\t\t{\n\t\t\t\timc_active = IA_NONE;\n\t\t\t\ttracef(1, "Waiting "+(reconnectBackoffTime/1000)+" seconds and try to reconnect.");\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsleep(reconnectBackoffTime);\n\t\t\t\t\treconnectBackoffTime=reconnectBackoffTime*2;\n\t\t\t\t}\n\t\t\t\tcatch (final Exception ex)\n\t\t\t\t{\n\t\t\t\t}\n\t\t\t\tthis.imc_startup(true,\n\t\t\t\t\t\t\t\t imc_name,\n\t\t\t\t\t\t\t\t imc_siteinfo.host,\n\t\t\t\t\t\t\t\t imc_siteinfo.email,\n\t\t\t\t\t\t\t\t imc_siteinfo.www,\n\t\t\t\t\t\t\t\t this_imcmud.hubname,\n\t\t\t\t\t\t\t\t this_imcmud.port,\n\t\t\t\t\t\t\t\t this_imcmud.clientpw,\n\t\t\t\t\t\t\t\t this_imcmud.serverpw,\n\t\t\t\t\t\t\t\t rebuildChannelMap());\n\t\t\t}\n\t\t}\n\t}\n\n\tfinal public void imc_write_to_socket(final DataOutputStream out)\n\t{\n\t\ttry\n\t\t{\n\t\t\tif (this_imcmud.outbuf.equals(""))\n\t\t\t\treturn;\n\n\t\t\ttracef(8, "imc: sending \'" + this_imcmud.outbuf + "\'");\n\t\t\tout.write(this_imcmud.outbuf.getBytes());\n\t\t\tthis_imcmud.outbuf = "";\n\t\t}\n\t\tcatch (final Exception e)\n\t\t{\n\t\t\ttracef(1, "write socket error: " + e.toString());\n\t\t\timc_active = IA_NONE;\n\t\t\ttracef(1, "Waiting "+(reconnectBackoffTime/1000)+" seconds and try to reconnect.");\n\t\t\ttry\n\t\t\t{\n\t\t\t\tsleep(reconnectBackoffTime);\n\t\t\t\treconnectBackoffTime=reconnectBackoffTime*2;\n\t\t\t}\n\t\t\tcatch (final Exception ex)\n\t\t\t{\n\t\t\t}\n\t\t\tthis.imc_startup(true,\n\t\t\t\t\t\t\t imc_name,\n\t\t\t\t\t\t\t imc_siteinfo.host,\n\t\t\t\t\t\t\t imc_siteinfo.email,\n\t\t\t\t\t\t\t imc_siteinfo.www,\n\t\t\t\t\t\t\t this_imcmud.hubname,\n\t\t\t\t\t\t\t this_imcmud.port,\n\t\t\t\t\t\t\t this_imcmud.clientpw,\n\t\t\t\t\t\t\t this_imcmud.serverpw,\n\t\t\t\t\t\t\t rebuildChannelMap());\n\t\t}\n\t}\n\n\t/* send a keepalive to everyone */\n\tfinal public void imc_send_isalive(final String reqFrom)\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn;\n\n\t\timc_initdata(out);\n\t\tout.type = "is-alive";\n\t\tout.from = "*";\n\t\tif(reqFrom.endsWith("*"))\n\t\t{\n\t\t\tLog.errOut("IMC2 SPAM DETECTED: "+reqFrom+"!");\n\t\t}\n\t\tout.to = reqFrom;\n\t\timc_addkey(out, "versionid", IMC_VERSIONID);\n\t\timc_addkey(out, "networkname", this_imcmud.network);\n\t\tif (imc_siteinfo.flags != null && !"".equals(imc_siteinfo.flags))\n\t\t\timc_addkey(out, "flags", imc_siteinfo.flags);\n\t\timc_send(out);\n\t}\n\n\t/* send a keepalive to everyone */\n\tfinal public void imc_request_keepalive()\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn;\n\n\t\timc_initdata(out);\n\t\tout.type = "keepalive-request";\n\t\tout.from = "*";\n\t\tout.to = "*@*";\n\t\timc_addkey(out, "versionid", IMC_VERSIONID);\n\t\tif (imc_siteinfo.flags != null && !"".equals(imc_siteinfo.flags))\n\t\t\timc_addkey(out, "flags", imc_siteinfo.flags);\n\t\timc_send(out);\n\t}\n\n\tfinal class call_out extends Thread\n\t{\n\n\t\tIMC2Driver imc_client;\n\t\tboolean shutdown=false;\n\t\tpublic boolean isShutdown=false;\n\t\tint seq = 0;\n\t\tlong lastPingReceived=System.currentTimeMillis();\n\n\t\tpublic call_out(final IMC2Driver _imc_client)\n\t\t{\n\t\t\tsuper("IMC2-call_out");\n\t\t\tsetName("IMC2-call_out");\n\t\t\timc_client = _imc_client;\n\t\t\tsetDaemon(true);\n\t\t}\n\n\t\tpublic void shutdown()\n\t\t{\n\t\t\tshutdown=true;\n\t\t\tinterrupt();\n\t\t}\n\n\t\t@Override\n\t\tfinal public void run()\n\t\t{\n\t\t\tif (imc_client == null)\n\t\t\t\treturn;\n\t\t\tlong timeSinceLastPing=System.currentTimeMillis();\n\t\t\twhile (!shutdown)\n\t\t\t{\n\t\t\t\tif(CMSecurity.isDisabled(DisFlag.IMC2))\n\t\t\t\t{\n\t\t\t\t\tCMLib.s_sleep(100);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif((System.currentTimeMillis()-timeSinceLastPing) > (30 * 60 * 1000))\n\t\t\t\t{\n\t\t\t\t\timc_client.imc_send_ping("Server01");\n\t\t\t\t\ttimeSinceLastPing=System.currentTimeMillis();\n\t\t\t\t\t// everything is taken care of from here.  detect disconnect, reconnect -- everything.\n\t\t\t\t}\n//  \t\t\ttracef(1, "call_out: process call outs");\n\t\t\t\timc_client.imc_process_call_outs();\n\t\t\t\timc_client.imc_write_to_socket(out);\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsleep(100);\n\t\t\t\t\tseq++;\n\t\t\t\t\tif (seq % 10 == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\timc_client.imc_sequencenumber++;\n\t\t\t\t\t\tseq = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (final Exception e)\n\t\t\t\t{\n\t\t\t\t}\n\n\t\t\t}\n\t\t\tisShutdown=true;\n\t\t}\n\t}\n\n\tfinal class call_in extends Thread {\n\n\t\tIMC2Driver imc_client;\n\t\tboolean shutdown=false;\n\t\tpublic boolean isShutdown=false;\n\n\t\tpublic call_in(final IMC2Driver _imc_client)\n\t\t{\n\t\t\tsuper("IMC2-call_in");\n\t\t\tsetName("IMC2-call_in");\n\t\t\timc_client = _imc_client;\n\t\t\tsetDaemon(true);\n\t\t}\n\n\t\tpublic void shutdown()\n\t\t{\n\t\t\tshutdown=true;\n\t\t\tinterrupt();\n\t\t}\n\n\t\t@Override\n\t\tfinal public void run()\n\t\t{\n\t\t\tif (imc_client == null)\n\t\t\t\treturn;\n\t\t\twhile (!shutdown)\n\t\t\t{\n\t\t\t\tif(!CMSecurity.isDisabled(DisFlag.IMC2))\n\t\t\t\t{\n//\t  \t\t\ttracef(1, "call_out: process call outs");\n\t\t\t\t\timc_client.imc_read_from_socket(in);\n\t\t\t\t}\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tsleep(100);\n\t\t\t\t}\n\t\t\t\tcatch (final Exception e)\n\t\t\t\t{\n\t\t\t\t}\n\t\t\t}\n\t\t\tisShutdown=true;\n\t\t}\n\n\t}\n\n\t/* send a ping with a given timestamp */\n\tfinal public void imc_send_ping(final String to)\n\t{\n\t\tPACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn;\n\n\t\timc_initdata(out);\n\t\tout.type = "ping";\n\t\tout.from = "*";\n\t\tout.to = "*@" + to;\n\t\timc_send(out);\n\t\tout = null;\n\t}\n\n\tfinal public void run_imcpinfo(final String name, final String mudname, final String who, final int level,\n\t\t\t\t\t\t\t final int invis)\n\t\t\t\t\t\t\t {\n\t\tfinal imc_char_data test = new imc_char_data();\n\t\ttest.name = name;\n\t\ttest.level = level;\n\t\ttest.invis = invis;\n\t\timc_send_who(test, "@" + mudname, "finger " + who);\n\t}\n\n\tfinal public void run_imcminfo(final String name, final String mudname, final String type,\n\t\t\t\t\t\t\t final int level, final int invis)\n\t\t\t\t\t\t\t {\n\t\tfinal imc_char_data test = new imc_char_data();\n\t\ttest.name = name;\n\t\ttest.level = level;\n\t\ttest.invis = invis;\n\t\timc_send_who(test, "@" + mudname, type);\n\t}\n\n\tfinal public void imc_send_who(final String name, final String mudname, final String type, final int level, final int invis)\n\t{\n\t\tfinal imc_char_data test = new imc_char_data();\n\t\ttest.name = name;\n\t\ttest.level = level;\n\t\ttest.invis = invis;\n\t\timc_send_who(test, "@" + mudname, type);\n\t}\n\n\tfinal public String imc_send_tell(final String from, final String to, final String text, final int level,\n\t\t\t\t\t\t\t\tfinal int invis)\n\t\t\t\t\t\t\t\t{\n\t\tfinal imc_char_data chr = new imc_char_data();\n\t\tchr.name = from;\n\t\tchr.level = level;\n\t\tchr.invis = invis;\n\t\treturn imc_send_tell(chr, to, text, 1);\n\t}\n\n\tfinal public String imc_send_reply(final String from, final String text, final int level, final int invis)\n\t{\n\t\tfinal imc_char_data chr = new imc_char_data();\n\t\tchr.name = from;\n\t\tchr.level = level;\n\t\tchr.invis = invis;\n\t\treturn imc_send_reply(chr, text);\n\t}\n\n\tfinal public String imc_send_chat(final String from, final String to, final String text, final int level,\n\t\t\t\t\t\t\t\tfinal int emote)\n\t\t\t\t\t\t\t\t{\n\t\tfinal imc_char_data chr = new imc_char_data();\n\t\tchr.name = from;\n\t\tchr.level = level;\n\t\treturn imc_send_chat(chr, to, text, level, emote);\n\t}\n\n\t/* send a tell to a remote player */\n\tfinal String imc_send_tell(final imc_char_data from, final String to, final String argument,\n\t\t\t\t\t\t final int isreply)\n\t\t\t\t\t\t {\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn "IMC is not active.";\n\n\t\tif (imc_mudof(to).equals("*"))\n\t\t{\n\t\t\treturn "You cannot send tell to everyone!";\n\t\t\t\t/* don\'t let them do this */\n\t\t}\n\n\t\tsetdata(out, from);\n\n\t\tout.to = to;\n\t\tout.type = "tell";\n\t\timc_addkeyi(out, "level", 3);\n\t\timc_addkey(out, "text", toIMCColours(argument));\n\n\t\timc_send(out);\n\n\t\treplies.put(from.name, to);\n\n\t\tfinal String chatText = "You tell " + to + " \'^c" + argument +\n\t\t\t"\'^?.";\n\t\treturn chatText;\n\t}\n\n\t/* send a reply to a remote player */\n\tfinal String imc_send_reply(final imc_char_data from, final String argument)\n\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn "IMC is not active.";\n\n\t\tsetdata(out, from);\n\t\tfinal String to = replies.get(from.name);\n\t\tif (to == null)\n\t\t\treturn "No one to reply to.";\n\n\t\tout.to = to;\n\t\tout.type = "tell";\n\t\timc_addkeyi(out, "level", 3);\n\t\timc_addkey(out, "text", toIMCColours(argument));\n\n\t\timc_send(out);\n\n\t\tfinal String chatText = "You tell " + to + " ^c\'" + argument +\n\t\t\t"\'^?.";\n\t\treturn chatText;\n\t}\n\n\t/* send a tell to a remote player */\n\tfinal String imc_send_chat(final imc_char_data from,\n\t\t\t\t\t\t\t\tfinal String to,\n\t\t\t\t\t\t\t\tfinal String argument,\n\t\t\t\t\t\t\t\tfinal int isreply,\n\t\t\t\t\t\t\t\tfinal int emote)\n\t\t\t\t\t\t\t\t{\n\t\tfinal PACKET out = new PACKET();\n\n\t\tif (imc_active < IA_UP)\n\t\t\treturn "IMC is not running.";\n\n\t\tsetdata(out, from);\n\n//  \timc_addkey(p, "level", 3);\n\n\t\tout.to = "*@*";\n\t\tout.type = "ice-msg-b";\n\t\timc_addkey(out, "channel", to);\n\t\timc_addkey(out, "text", toIMCColours(argument));\n\t\timc_addkeyi(out, "emote", emote);\n\n\t\t/*  \tif (isreply > 0)\n\t\t\t\t  imc_addkeyi(out, "isreply", isreply);*/\n\n\t\timc_send(out);\n\n\t\tString chan = to;\n\t\tfinal int pos = to.indexOf(\':\');\n\t\tif (pos > -1)\n\t\t\tchan = to.substring(pos + 1, to.length());\n\n\t\tString text = argument;\n\t\tif (argument.startsWith(", ") || emote == 1)\n\t\t\ttext = from.name + "@" + this.imc_name;\n\n\t\tfinal String chatText = from.name + "@" + this.imc_name +\n\t\t\t" [" + chan +\n\t\t\t"] " +\n\t\t\t" " + text + "^?";\n\n\t\tList<String> l =  chanhist.get(chan);\n\t\tif (l == null)\n\t\t\tl = new LinkedList<String>();\n\n\t\tl.add(chatText);\n\t\tchanhist.put(chan, l);\n\n\t\treturn chatText;\n\n\t}\n\n\t@Override\n\tfinal public void run()\n\t{\n\t\timc_read_from_socket(in);\n\t\tHeartBeat = 0;\n\n\t\tif(c_thread2==null)\n\t\t{\n\t\t\tc_thread2 = new call_in(this);\n\t\t\tc_thread2.start();\n\t\t}\n\t\tif(c_thread==null)\n\t\t{\n\t\t\tc_thread = new call_out(this);\n\t\t\tc_thread.start();\n\t\t}\n\t\tLog.sysOut("IMC2","(c) 1996-2002/Java port by Istvan David");\n\t\tLog.sysOut("IMC2","Client connected to "+this_imcmud.host.trim());\n\n\t\twhile (!shutdown)\n\t\t{\n\t\t\tHeartBeat++;\n\t\t\ttry\n\t\t\t{\n\t\t\t\tsleep(2000);\n\t\t\t}\n\t\t\tcatch (final Exception e)\n\t\t\t{\n\t\t\t}\n\t\t\tisShutdown=true;\n\t\t}\n\t}\n\n}\n', 'message': '\n\ngit-svn-id: svn://192.168.1.10/public/CoffeeMud@9005 0d6f1817-ed0e-0410-87c9-987e46238f29\n', 'author_name': 'bozimmerman', 'lang': 'java'}