UBrowser
Class UBrowserIRCLink

source: e:\games\UnrealTournament\UBrowser\Classes\UBrowserIRCLink.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Info
         |
         +--Engine.InternetInfo
            |
            +--IpDrv.InternetLink
               |
               +--IpDrv.TcpLink
                  |
                  +--UBrowser.UBrowserBufferedTcpLink
                     |
                     +--UBrowser.UBrowserIRCLink
Direct Known Subclasses:None

class UBrowserIRCLink
extends UBrowser.UBrowserBufferedTcpLink


Variables
 string ConnectedText
 string ConnectingToText
 string DefaultChannel
 string DisconnectReason
 string ErrorBindingText
 string FullName
 string InvalidAddressText
 string InviteString
 string NickName
 string ResolveFailedText
 string ServerAddress
 IpAddr ServerIpAddr
 int ServerPort
 UBrowserIRCSystemPage SystemPage
 string TimeOutError
 string UserIdent
 string VersionString

States
LoggedIn, LoggingIn

Function Summary
 string Chop(string Text)
 string ChopLeft(string Text)
 void Connect(UBrowserIRCSystemPage InSystemPage, string InServer, string InNickName, string InUserIdent, string InFullName, string InDefaultChannel)
 void PostBeginPlay()
 void ProcessInput(string Line)
 string RemoveNickPrefix(string Nick)
 void ResolveFailed()
     
// Host resolution failue.
 void Resolved(IpAddr Addr)
 void SendChannelAction(string Channel, string Text)
 void SendChannelText(string Channel, string Text)
 void SendCommandText(string Text)
 void Tick(float DeltaTime)


State LoggedIn Function Summary
 void DestroyLink()
 void SetAway(string AwayText)
 void SetNick(string NewNick)
 void PartChannel(string Channel)
 void JoinChannel(string Channel)
 void ProcessInput(string Line)


State LoggingIn Function Summary
 void SendCommandText(string Text)
 void ProcessInput(string Line)



Source Code


00001	class UBrowserIRCLink expands UBrowserBufferedTCPLink;
00002	
00003	var IpAddr			ServerIpAddr;
00004	
00005	var string			ServerAddress;
00006	var int				ServerPort;
00007	
00008	var string			NickName;
00009	var string			UserIdent;
00010	var string			FullName;
00011	var string			DefaultChannel;
00012	
00013	var localized string InvalidAddressText;
00014	var localized string ErrorBindingText;
00015	var localized string ResolveFailedText;
00016	var localized string ConnectedText;
00017	var localized string ConnectingToText;
00018	var localized string TimeOutError;
00019	var localized string InviteString;
00020	
00021	var UBrowserIRCSystemPage SystemPage; 
00022	
00023	var string DisconnectReason;
00024	var string VersionString;
00025	
00026	function PostBeginPlay()
00027	{
00028		Super.PostBeginPlay();
00029		Disable('Tick');
00030	}
00031	
00032	function Connect(UBrowserIRCSystemPage InSystemPage, string InServer, string InNickName, string InUserIdent, string InFullName, string InDefaultChannel)
00033	{
00034		local int i;
00035	
00036		SystemPage = InSystemPage;
00037		NickName = InNickName;
00038		FullName = InFullName;
00039		UserIdent = InUserIdent;
00040		DefaultChannel = InDefaultChannel;
00041	
00042		i = InStr(InServer, ":");
00043		if(i == -1)
00044		{
00045			ServerAddress = InServer;
00046			ServerPort = 6667;
00047		}
00048		else
00049		{
00050			ServerAddress = Left(InServer, i);
00051			ServerPort = Int(Mid(InServer, i+1));
00052		}
00053	
00054		ResetBuffer();
00055		ServerIpAddr.Port = ServerPort;
00056		SetTimer(20, False);
00057		SystemPage.SystemText( ConnectingToText@ServerAddress );
00058		Resolve( ServerAddress );
00059	}
00060	
00061	function string ChopLeft(string Text)
00062	{
00063		while(Text != "" && InStr(": !", Left(Text, 1)) != -1)
00064			Text = Mid(Text, 1);
00065		return Text;
00066	}
00067	
00068	function string RemoveNickPrefix(string Nick)
00069	{
00070		while(Nick != "" && InStr(":@+", Left(Nick, 1)) != -1)
00071			Nick = Mid(Nick, 1);
00072		return Nick;
00073	}
00074	
00075	function string Chop(string Text)
00076	{
00077		while(Text != "" && InStr(": !", Left(Text, 1)) != -1)
00078			Text = Mid(Text, 1);
00079		while(Text != "" && InStr(": !", Right(Text, 1)) != -1)
00080			Text = Left(Text, Len(Text)-1);
00081	
00082		return Text;
00083	}
00084	
00085	function Resolved( IpAddr Addr )
00086	{
00087		// Set the address
00088		ServerIpAddr.Addr = Addr.Addr;
00089	
00090		// Handle failure.
00091		if( ServerIpAddr.Addr == 0 )
00092		{
00093			if(SystemPage != None)
00094			{
00095				SystemPage.SystemText( InvalidAddressText );
00096				SystemPage.Disconnect();
00097			}
00098			return;
00099		}
00100	
00101		// Display success message.
00102		Log( "UBrowserIRCLink: Server is "$ServerAddress$":"$ServerIpAddr.Port );
00103	
00104		// Bind the local port.
00105		if( BindPort() == 0 )
00106		{
00107			if(SystemPage != None)
00108			{
00109				SystemPage.SystemText( ErrorBindingText );
00110				SystemPage.Disconnect();
00111			}
00112			return;
00113		}
00114	
00115		Open( ServerIpAddr );
00116	}
00117	
00118	event Closed()
00119	{
00120		if(SystemPage != None)
00121			SystemPage.Disconnect();
00122	}
00123	
00124	// Host resolution failue.
00125	function ResolveFailed()
00126	{
00127		if(SystemPage != None)
00128		{
00129			SystemPage.SystemText(ResolveFailedText);
00130			SystemPage.Disconnect();
00131		}
00132	}
00133	
00134	event Timer()
00135	{
00136		if(SystemPage != None)
00137		{
00138			SystemPage.SystemText( TimeOutError );
00139			SystemPage.Disconnect();
00140		}
00141		return;
00142	}
00143	
00144	event Opened()
00145	{
00146		SetTimer(0, False);
00147		if(SystemPage != None)
00148			SystemPage.SystemText(ConnectedText);
00149		Enable('Tick');
00150		GotoState('LoggingIn');
00151	}
00152	
00153	function Tick(float DeltaTime)
00154	{
00155		local string Line;
00156	
00157		DoBufferQueueIO();
00158		if(ReadBufferedLine(Line))
00159			ProcessInput(Line);
00160	}
00161	
00162	function SendCommandText(string Text)
00163	{
00164		local int i, j;
00165		local string Cmd, Temp, Temp2;
00166	
00167		// Process fake commands like /MSG
00168		if(Left(Text, 4) ~= "MSG ")
00169			Text = "PRIVMSG "$Mid(Text, 4);
00170		if(Left(Text, 6) ~= "LEAVE ")
00171			Text = "PART "$Mid(Text, 6);
00172	
00173		// Add colons for commands: PRIVMSG, QUIT, KILL, KICK, NOTICE
00174		i = InStr(Text, " ");
00175		if(i != -1)
00176		{
00177			Cmd = Caps(Left(Text, i));
00178			Text = Cmd$Mid(Text, i);
00179	
00180			switch(Cmd)
00181			{
00182			// CMD nick :message
00183			case "PRIVMSG":
00184			case "NOTICE":
00185			case "KILL":
00186				Temp = ChopLeft(Mid(Text, i+1));
00187				i = InStr(Temp, " ");
00188				if(i != -1)
00189					Text = Cmd@Left(Temp, i)$" :"$ChopLeft(Mid(Temp, i+1));
00190				break;
00191			// hack for CTCP
00192			case "CTCP":
00193				Temp = ChopLeft(Mid(Text, i+1));
00194				i = InStr(Temp, " ");
00195				if(i != -1)
00196					Text = "PRIVMSG "$Left(Temp, i)$" :"$Chr(1)$ChopLeft(Mid(Temp, i+1))$Chr(1);
00197				break;
00198			// CMD #channel nick :message
00199			case "KICK":
00200				Temp = ChopLeft(Mid(Text, i+1));
00201				i = InStr(Temp, " ");
00202				if(i != -1)
00203				{
00204					Temp2 = ChopLeft(Mid(Temp, i+1));
00205					j = InStr(Temp2, " ");
00206					if(j != -1)
00207						Text = Cmd@Left(Temp, i)@Left(Temp2, j)$" :"$ChopLeft(Mid(Temp2, j+1));
00208				}
00209				break;
00210			// CMD :message
00211			case "QUIT":
00212				Text = Cmd$" :"$ChopLeft(Mid(Text, i+1));
00213				break;
00214			}
00215		}
00216		else
00217			Text = Caps(Text);	
00218	
00219		SendBufferedData(Text$CRLF);
00220	}
00221	
00222	function SendChannelText(string Channel, string Text)
00223	{
00224		SendBufferedData("PRIVMSG "$Channel$" :"$Text$CRLF);
00225	}
00226	
00227	function SendChannelAction(string Channel, string Text)
00228	{
00229		SendBufferedData("PRIVMSG "$Channel$" :"$Chr(1)$"ACTION "$Text$Chr(1)$CRLF);
00230	}
00231	
00232	function ProcessInput(string Line)
00233	{
00234		// Respond to PING
00235		if(Left(Line, 5) == "PING ")
00236			SendBufferedData("PONG "$Mid(Line, 5)$CRLF);
00237	}
00238	
00239	state LoggingIn
00240	{
00241		function ProcessInput(string Line)
00242		{
00243			local string Temp;
00244			
00245			Temp = ParseDelimited(Line, " ", 2);
00246	
00247			if(ParseDelimited(Line, " ", 1)== "ERROR")
00248				SystemPage.SystemText(ChopLeft(ParseDelimited(Line, ":", 2, True)));
00249	
00250			// Handle nick already in use on connect...
00251			if(Temp == "433")
00252			{
00253				SystemPage.SystemText(ChopLeft(ParseDelimited(Line, " ", 3, True)));
00254			}
00255			else
00256			if(Int(Temp) != 0)
00257			{
00258				SystemPage.SystemText(ChopLeft(ParseDelimited(Line, " ", 3, True)));
00259				GotoState('LoggedIn');
00260			}
00261	
00262			Global.ProcessInput(Line);
00263		}
00264	
00265		function SendCommandText(string Text)
00266		{
00267			Global.SendCommandText(Text);
00268			if(ParseDelimited(Text, " ", 1) ~= "NICK")
00269			{
00270				SystemPage.ChangedNick(NickName, Chop(ParseDelimited(Text, " ", 2)));
00271			}
00272		}
00273	
00274	Begin:
00275		SendBufferedData("USER "$UserIdent$" localhost "$ServerAddress$" :"$FullName$CRLF);
00276		SendBufferedData("NICK "$NickName$CRLF);
00277	}
00278	
00279	state LoggedIn
00280	{
00281		function ProcessInput(string Line)
00282		{
00283			local string Temp, Temp2, Temp3;
00284			local bool bAddModifier;
00285			local int i;
00286			local string Command;
00287	
00288			Global.ProcessInput(Line);
00289			
00290			Command = ParseDelimited(Line, " ", 2);
00291	
00292			if(ParseDelimited(Line, " ", 1) == "ERROR")
00293			{
00294				SystemPage.SystemText(ChopLeft(ParseDelimited(Line, ":", 2, True)));
00295			}
00296			else if(Command == "JOIN")
00297			{
00298				Temp = ParseDelimited(Line, ":!", 2);
00299				if(Temp ~= NickName)
00300					Temp = "";
00301				SystemPage.JoinedChannel(Chop(ParseDelimited(Line, " ", 3)), Temp);
00302			}
00303			else if(Command == "PART")
00304			{
00305				Temp = ParseDelimited(Line, ":!", 2);
00306				if(Temp ~= NickName)
00307					Temp = "";
00308				SystemPage.PartedChannel(Chop(ParseDelimited(Line, " ", 3)), Temp);
00309			}
00310			else if(Command == "NICK")
00311			{
00312				SystemPage.ChangedNick(ParseDelimited(Line, ":!", 2), Chop(ParseDelimited(Line, " ", 3)));
00313			}
00314			else if(Command == "QUIT")
00315			{
00316				SystemPage.UserQuit(ParseDelimited(Line, ":!", 2), ChopLeft(ParseDelimited(Line, " ", 3, True)));
00317			}
00318			else if(Command == "353")	// NAMES
00319			{
00320				Temp2 = ParseDelimited(Line, "#", 2);
00321				Temp2 = ParseDelimited(Temp2, " :", 1);
00322	
00323				Temp = ParseDelimited(Line, ":", 3, True);
00324				while(Temp != "")
00325				{
00326					// Nickname
00327					Temp3 = ParseDelimited(Temp, " ", 1);
00328	
00329					SystemPage.UserInChannel("#"$Temp2, RemoveNickPrefix(Temp3));
00330	
00331					if(Left(Temp3, 1) == "@")
00332						SystemPage.ChangeOp("#"$Temp2, RemoveNickPrefix(Temp3), True);
00333					else
00334					if(Left(Temp3, 1) == "+")
00335						SystemPage.ChangeVoice("#"$Temp2, RemoveNickPrefix(Temp3), True);
00336	
00337					Temp = ParseDelimited(Temp, " ", 2, True);
00338				}	
00339			}
00340			else if(Command == "333")	// Channel formed info
00341			{
00342			}
00343			else if(Command == "366")	// End of NAMES
00344			{
00345			}
00346			else if(Command == "331")	// RPL_NOTOPIC
00347			{
00348			}
00349			else if(Command == "332")	// RPL_TOPIC
00350			{
00351			}
00352			else if(Command == "341")   // RPL_INVITING
00353			{
00354			}
00355			else if(Command == "301")	// RPL_AWAY
00356			{
00357				SystemPage.IsAway(Chop(ParseDelimited(Line, " ", 4)), ChopLeft(ParseDelimited(Line, ":", 3, True)));
00358			}
00359			else if(Command == "NOTICE")
00360			{
00361				Temp = ParseDelimited(Line, ": ", 2);
00362				Temp2 = ParseDelimited(Line, ":! ", 2);
00363	
00364				if(InStr(Temp, "!") != -1 && InStr(Temp2, ".") == -1)
00365				{
00366					// it's a Nick.
00367					Temp = ChopLeft(ParseDelimited(Line, " ", 4, True));
00368					if(Asc(Left(Temp, 1)) == 1 && Asc(Right(Temp, 1)) == 1)
00369						SystemPage.CTCP("", Temp2, Mid(Temp, 1, Len(Temp) - 2));
00370					else
00371						SystemPage.UserNotice(Temp2, Temp);
00372				}
00373				else
00374					SystemPage.SystemText(ChopLeft(ParseDelimited(Line, " ", 4, True)));
00375			}
00376			else if(Int(Command)!= 0)
00377			{
00378				SystemPage.SystemText(ChopLeft(ParseDelimited(Line, " ", 4, True)));
00379			}
00380			else if(Command == "MODE")
00381			{
00382				// channel mode
00383				Temp = Chop(ParseDelimited(Line, " ", 4));
00384				// channel
00385				Temp3 = Chop(ParseDelimited(Line, " ", 3));
00386				i = 5;
00387				bAddModifier = True;
00388				while(Temp != "")
00389				{
00390					Temp2 = Left(Temp, 1);
00391					if(Temp2 == "+")
00392						bAddModifier = True;
00393					if(Temp2 == "-")
00394						bAddModifier = False;
00395	
00396					if(Temp2 == "o")
00397					{
00398						SystemPage.ChangeOp(Temp3, Chop(ParseDelimited(Line, " ", i)), bAddModifier);
00399						i++;
00400					}
00401						
00402					if(Temp2 == "v")
00403					{
00404						SystemPage.ChangeVoice(Temp3, Chop(ParseDelimited(Line, " ", i)), bAddModifier);
00405						i++;
00406					}
00407	
00408					Temp = Mid(Temp, 1);
00409				}
00410				 
00411				SystemPage.ChangeMode(Temp3, ParseDelimited(Line, ":!", 2), ChopLeft(ParseDelimited(Line, " ", 4, True)));
00412	
00413			}
00414			else if(Command == "KICK")
00415			{
00416				// FIXME: handle multiple kicks in a single message
00417				SystemPage.KickUser(Chop(ParseDelimited(Line, " ", 3)), Chop(ParseDelimited(Line, " ", 4)), ParseDelimited(Line, ":!", 2), ChopLeft(ParseDelimited(Line, ":", 3, True)));
00418			}
00419			else if(Command == "INVITE")
00420			{
00421				SystemPage.SystemText(ParseDelimited(Line, ":!", 2)@InviteString@ParseDelimited(Line, ":", 3));	
00422			}
00423			else if(Command == "PRIVMSG")
00424			{
00425				Temp = Chop(ParseDelimited(Line, " ", 3));
00426				Temp2 = ChopLeft(ParseDelimited(Line, " ", 4, True));
00427	
00428				if(Mid(Temp2, 1, 7) == "ACTION " && Asc(Left(Temp2, 1))==1 && Asc(Right(Temp2, 1))==1)
00429				{
00430					Temp2 = Mid(Temp2, 8);
00431					Temp2 = Left(Temp2, Len(Temp2) - 1);
00432	
00433					if(Temp != "" && InStr("&#@", Left(Temp, 1)) != -1)
00434						SystemPage.ChannelAction(Temp, ParseDelimited(Line, ":!", 2), Temp2);
00435					else
00436						SystemPage.PrivateAction(ParseDelimited(Line, ":!", 2), Temp2);
00437				}
00438				else
00439				if(Asc(Left(Temp2, 1))==1 && Asc(Right(Temp2, 1))==1)
00440				{
00441					Temp2 = Mid(Temp2, 1, Len(Temp2) - 2);
00442					
00443					switch(Temp2)
00444					{
00445					case "VERSION":
00446						SendBufferedData("NOTICE "$ParseDelimited(Line, ":!", 2)$" :"$Chr(1)$"VERSION "$VersionString$Level.EngineVersion$Chr(1)$CRLF);
00447						SystemPage.CTCP(Temp, ParseDelimited(Line, ":!", 2), Temp2);
00448						break;
00449					default:
00450						SystemPage.CTCP(Temp, ParseDelimited(Line, ":!", 2), Temp2);
00451						break;
00452					}
00453				}
00454				else
00455				{
00456					if(Temp != "" && InStr("&#@", Left(Temp, 1)) != -1)
00457						SystemPage.ChannelText(Temp, ParseDelimited(Line, ":!", 2), Temp2);
00458					else
00459						SystemPage.PrivateText(ParseDelimited(Line, ":!", 2), Temp2);
00460				}
00461			}
00462		}
00463	Begin:
00464		JoinChannel(DefaultChannel);
00465	}
00466	
00467	function JoinChannel(string Channel)
00468	{
00469		if(Left(Channel, 1) == "#")
00470			SendBufferedData("JOIN "$Channel$CRLF);
00471	}
00472	
00473	function PartChannel(string Channel)
00474	{
00475		if(Left(Channel, 1) == "#")
00476			SendBufferedData("PART "$Channel$CRLF);
00477	}
00478	
00479	function SetNick(string NewNick)
00480	{
00481		SendBufferedData("NICK "$NewNick$CRLF);
00482	}
00483	
00484	function SetAway(string AwayText)
00485	{
00486		SendBufferedData("AWAY :"$AwayText$CRLF);
00487	}
00488	
00489	function DestroyLink()
00490	{
00491		SystemPage = None;
00492		if(IsConnected())
00493		{
00494			SendText("QUIT :"$DisconnectReason$CRLF);
00495			Close();
00496		}
00497		else
00498			Destroy();
00499	}
00500	
00501	defaultproperties
00502	{
00503	     InvalidAddressText="Invalid server address, aborting."
00504	     ErrorBindingText="Error binding local port, aborting."
00505	     ResolveFailedText="Failed to resolve server address, aborting."
00506	     ConnectedText="Connected."
00507	     ConnectingToText="Connecting to"
00508	     TimeOutError="Timeout connecting to server."
00509	     InviteString="invites you to join"
00510	     DisconnectReason="Disconnected"
00511	     VersionString="UBrowser IRC Client version "
00512	}

End Source Code