private void onData(object sender, OnDataEventArgs e) { if (e.IsServerMessage) { #region Server Message Handling strHost = e.User; switch (e.Command) { #region 001 // Connected case "001": base.CurrentConnection.SendData("USERHOST " + strNickname); break; #endregion #region 005 // Server Info String case "005": serverInfo.Parse005(e.Parameters, e.descriptionBeginsAtIndex); break; #endregion #region 302 // USERHOST reply case "302": if (e.Parameters[0].IndexOf("@")>-1) { e.Parameters[0] = e.Parameters[0].Substring(e.Parameters[0].IndexOf("@") + 1, e.Parameters[0].Length - e.Parameters[0].IndexOf("@") - 1).ToLower(); myIP = System.Net.Dns.GetHostEntry(e.Parameters[0]).AddressList[0]; if (LocalIPUpdated != null) LocalIPUpdated(this, new EventArgs()); } break; #endregion #region 433 // Nickname in use case "433": string strNewNick; if (NickNameInUse != null) { strNewNick = NickNameInUse(this, new EventArgs()); if (strNewNick != null && strNewNick.Trim() != "") { this.Nickname = strNewNick; break; } } if (blConnecting == true) { ShutdownClient(); if (ConnectFailed!=null) ConnectFailed(this, new ConnectFailedEventArgs(ConnectFailedReason.NicknameInUse)); } break; #endregion #region 376 // End of MOTD case "422": // MOTD File is missing. case "376": if (blConnecting==true) { blConnecting = false; identd.Listen = false; if (Connected!=null) Connected(this, new EventArgs()); } serverInfo.MessageOfTheDay = strMOTD.ToString(); strMOTD = null; serverInfo.FireMessageOfTheDayUpdated(this); break; #endregion #region 375, 372 // Start and content of MOTD case "375": case "372": if (e.Command=="375") strMOTD = new StringBuilder(); strMOTD.Append(string.Join(" ", e.Parameters)); break; #endregion #region 332 // Channel topic case "332": channels[e.Parameters[0]].SetTopic(e.Parameters[1]); break; #endregion #region 333 // Channel topic set time case "333": Channel topicChannel = channels[e.Parameters[0]]; topicChannel.TopicBy = e.Parameters[1]; topicChannel.TopicSetTime = IRCDateTime(e.Parameters[2]); break; #endregion #region 353 // Names in channel case "353": string[] strNames = e.Parameters; for (int x = e.descriptionBeginsAtIndex; x < strNames.Length; x++) { if (strNames[x].Trim().Length > 0) { ChannelUserStatus status = ChannelUserStatus.NotAStatus; bool blVoiced = false; bool blHalfOpped = false; bool blOpped = false; while ((status = serverInfo.GetUserStatusFromPrefix(strNames[x][0])) != ChannelUserStatus.NotAStatus) { switch (status) { case ChannelUserStatus.Operator: blOpped = true; break; case ChannelUserStatus.HalfOperator: blHalfOpped = true; break; case ChannelUserStatus.Voiced: blVoiced = true; break; } strNames[x] = strNames[x].Substring(1); } ChannelUser newUser; if (strNames[x] != strNickname) { newUser = new ChannelUser(base.CurrentConnection, users.GetUser(strNames[x], false), e.Parameters[1]); channels[e.Parameters[1]].Users.AddUser(newUser); } else { newUser = channels[e.Parameters[1]].Users[strNames[x]]; } newUser.IsOperator = blOpped; newUser.IsVoiced = blVoiced; newUser.IsHalfOperator = blHalfOpped; } } break; #endregion #region 324 // Channel Mode case "324": string strMode = ""; for (int x=1;x<e.Parameters.Length;x++) strMode += e.Parameters[x] + " "; strMode = strMode.Trim(); channels[e.Parameters[0]].ParseMode(strMode); break; #endregion #region 329 // Channel created time case "329": channels[e.Parameters[0]].SetCreatedAt(IRCDateTime(e.Parameters[1])); break; #endregion #region 367 // Channel ban case "367": ChannelBan newBan = new ChannelBan(base.CurrentConnection, e.Parameters[0], e.Parameters[1], e.Parameters[2], IRCDateTime(e.Parameters[3])); channels[e.Parameters[0]].Bans.AddBan(newBan); break; #endregion #region 321 // Start of channel list case "321": channels.List.Clear(); break; #endregion #region 322 // Channel list item case "322": ChannelList newChannel = new ChannelList(base.CurrentConnection, e.Parameters[0], int.Parse(e.Parameters[1]), e.Parameters[2]); channels.List.AddChannel(newChannel); channels.List.FireProgressEvent(this, new ChannelListUpdateProgress(this.channels.List.Count, newChannel)); break; #endregion #region 323 // End of channel list case "323": this.channels.List.FireUpdatedEvent(this, new EventArgs()); break; #endregion #region 352 // WHO response case "352": UserInfo cUser = new UserInfo(e.Parameters[4], e.Parameters[1], e.Parameters[2]); if (cUser.Nick.Length > 0 && cUser.Nick[0] == '~') cUser.Nick = cUser.Nick.Substring(1); string cRealName = e.description; if (cRealName.IndexOf(" ") > -1) cRealName = cRealName.Substring(cRealName.IndexOf(" ") + 1); User cFullUser = users.GetUser(cUser); if (channels[e.Parameters[0]] != null) { foreach (char c in e.Parameters[5]) { if (c == serverInfo.OperatorPrefix) channels[e.Parameters[0]].Users[cFullUser].IsOperator = true; if (c == serverInfo.VoicePrefix) channels[e.Parameters[0]].Users[cFullUser].IsVoiced = true; } } cFullUser.SetAllInfo(cUser, cRealName, e.Parameters[2]); break; #endregion #region 315 // End of WHO response case "315": Channel cChan = channels.GetChannel(e.Parameters[0]); if (cChan != null) channels.FireJoinCompleted(channels.GetChannel(e.Parameters[0])); break; } serverInfo.FireServerMessage(int.Parse(e.Command), e.Parameters); #endregion #endregion } else { if (e.User==null) { #region Direct Command Handling (eg. PING or ERROR) switch (e.Command.ToLower()) { #region PING? PONG! case "ping": base.CurrentConnection.SendData("PONG :" + e.Parameters[0] , false); serverInfo.FirePingPong(); break; #endregion #region ERROR case "error": ShutdownClient(); if (Error!=null) Error(this, new ErrorEventArgs(e.Parameters[0])); break; #region NOTICE case "notice": if (e.Parameters.Length>1) { string[] tmp = new string[e.Parameters.Length - 1]; for (int x=1;x<e.Parameters.Length;x++) tmp[x-1] = e.Parameters[x]; serverInfo.FireServerNotice(e.Parameters[0], string.Join(" ", tmp)); } break; #endregion #endregion } #endregion } else { #region Normal Message Handling (eg. :nick!ident@host PRIVMSG #channel :Wow!) UserInfo user; if (e.User.IndexOf("@")>-1) { string strUser = e.User; string strNick = strUser.Substring(0, strUser.IndexOf("!")); strUser = strUser.Substring(strUser.IndexOf("!") + 1, strUser.Length - (strUser.IndexOf("!") + 1)); string strIdentity = strUser.Substring(0, strUser.IndexOf("@")); string strHost = strUser.Substring(strUser.IndexOf("@") + 1, strUser.Length - (strUser.IndexOf("@") + 1)); user = new UserInfo(strNick, strIdentity, strHost); } else user = new UserInfo(e.User, "", ""); switch (e.Command.ToLower()) { #region JOIN case "join": EnsureInformation(user); if (user.Nick.ToLower()==strNickname.ToLower()) { Channel newChannel = new Channel(base.CurrentConnection, e.Parameters[0]); channels.AddChannel(newChannel); base.CurrentConnection.SendData("MODE " + e.Parameters[0]); base.CurrentConnection.SendData("MODE " + e.Parameters[0] + " +b"); base.CurrentConnection.SendData("WHO {0}", e.Parameters[0]); } ChannelUser newUser = new ChannelUser(base.CurrentConnection, users.GetUser(user), e.Parameters[0]); channels[e.Parameters[0]].Users.AddUser(newUser); channels[e.Parameters[0]].FireJoin(users.GetUser(user)); break; #endregion #region MODE case "mode": EnsureInformation(user); string strMode = ""; for (int x=1;x<e.Parameters.Length;x++) strMode += e.Parameters[x] + " "; strMode = strMode.Trim(); // Checks that we are on the channel that has changed mode. // If not, this is properbly a user mode. if (channels.IsOnChannel(e.Parameters[0])) { channels[e.Parameters[0]].ParseMode(strMode); CheckUserChannelStatus(user, e.Parameters[0], strMode); channels[e.Parameters[0]].FireModeChange(users.GetUser(user), strMode); } else { // Parse user mode bool blWay = false; for (int x = 0 ; x < strMode.Length ; x++) { switch (strMode.Substring(x, 1)) { case "+": blWay = true; break; case "-": blWay = false; break; case "i": blInvisible = blWay; break; } } } break; #endregion #region PART case "part": EnsureInformation(user); User partedUser = users.GetUser(user); Channel partedChannel = channels.GetChannel(e.Parameters[0]); if (user.Nick.ToLower()==strNickname.ToLower()) { foreach (ChannelUser u in partedChannel.Users) if (!channels.IsUserOnAnyChannel(u.User.Nick, e.Parameters[0])) users.Remove(u.User.Nick); channels.RemoveChannel(e.Parameters[0]); } else { partedChannel.Users.RemoveUser(user.Nick); if (!channels.IsUserOnAnyChannel(user.Nick)) users.Remove(user.Nick); } partedChannel.FirePart(partedUser, e.Parameters.Length>1?e.Parameters[1]:""); if (user.Nick.ToLower() == strNickname.ToLower()) channels.FirePartCompleted(partedChannel); break; #endregion #region KICK case "kick": EnsureInformation(user); User kicker = users.GetUser(user); User kicked = users.GetUser(e.Parameters[1]); Channel kickedChannel = channels.GetChannel(e.Parameters[0]); if (e.Parameters[1].ToLower()==strNickname.ToLower()) { foreach (ChannelUser u in kickedChannel.Users) if (!channels.IsUserOnAnyChannel(u.User.Nick, e.Parameters[0])) users.Remove(u.User.Nick); channels.RemoveChannel(e.Parameters[0]); } else { kickedChannel.Users.RemoveUser(e.Parameters[1]); if (!channels.IsUserOnAnyChannel(e.Parameters[1])) users.Remove(e.Parameters[1]); } kickedChannel.FireKick(kicker, kicked, e.Parameters[2]); break; #endregion #region QUIT case "quit": EnsureInformation(user); User quittedUser = users.GetUser(user); for (int x=0;x<channels.Count;x++) for (int y=0;y<channels[x].Users.Count;y++) if (channels[x].Users[y].User.Nick.ToLower()==user.Nick.ToLower()) channels[x].Users.RemoveUser(y); if (user.Nick.ToLower()!=strNickname.ToLower() && !channels.IsUserOnAnyChannel(user.Nick)) users.Remove(user.Nick); quittedUser.FireQuitted(e.Parameters[0]); if (user.Nick.ToLower()==strNickname.ToLower()) { ShutdownClient(); if (Disconnected!=null) Disconnected(this, new EventArgs()); } break; #endregion #region NICK case "nick": EnsureInformation(user); User nickChanger = users.GetUser(user); if (user.Nick.ToLower() == strNickname.ToLower()) { strNickname = e.Parameters[0]; users.OwnNick = strNickname; } string oldNick = nickChanger.Nick; nickChanger.Nick = e.Parameters[0]; nickChanger.FireNickChange(oldNick); break; #endregion #region INVITE case "invite": EnsureInformation(user); channels.FireInvitation(users.GetUser(user), e.Parameters[1]); break; #endregion #region PRIVMSG case "privmsg": EnsureInformation(user); CheckVoice(e.Parameters[0], user); if (e.Parameters[1].Length>2&&e.Parameters[1][0]==1&&e.Parameters[1][e.Parameters[1].Length - 1]==1) // Is CTCP ParseCTCP(user, GetMessageReciever(e.Parameters[0]), e.Parameters[1].Substring(1, e.Parameters[1].Length - 2), false); else GetMessageReciever(e.Parameters[0]).FireRecievedMessage(users.GetUser(user), e.Parameters[1], false); break; #endregion #region NOTICE case "notice": EnsureInformation(user); if (e.Parameters.Length > 1) { CheckVoice(e.Parameters[0], user); if (e.Parameters[1].Length > 2 && e.Parameters[1][0] == 1 && e.Parameters[1][e.Parameters[1].Length - 1] == 1) // Is CTPCP ParseCTCP(user, GetMessageReciever(e.Parameters[0]), e.Parameters[1].Substring(1, e.Parameters[1].Length - 2), true); else { User uInfo = users.GetUser(user); MessageReciever mRec = GetMessageReciever(e.Parameters[0]); if (mRec == null) serverInfo.FireServerNotice(e.Parameters[0], e.Parameters[1]); else mRec.FireRecievedNotice(uInfo, e.Parameters[1]); } } break; #endregion #region TOPIC case "topic": EnsureInformation(user); CheckVoice(e.Parameters[0], user); Channel topicChannel = channels.GetChannel(e.Parameters[0]); topicChannel.SetTopic(e.Parameters[1]); topicChannel.TopicBy = user.Nick; topicChannel.TopicSetTime = DateTime.Now; topicChannel.FireTopicChanged(users.GetUser(user), e.Parameters[1]); break; #endregion } #endregion } } if (e.Raw != null) serverInfo.FireRawRecieve(e.Raw); }
private void ParseCTCP(UserInfo user, MessageReciever Target, string CTCPData, bool blNotice) { CTCPData = CTCPData.Trim(); string strCommand = ""; string strParams = ""; if (CTCPData.IndexOf(" ")>-1) { strCommand = CTCPData.Substring(0, CTCPData.IndexOf(" ")); strParams = CTCPData.Substring(CTCPData.IndexOf(" ") + 1, CTCPData.Length - (CTCPData.IndexOf(" ") + 1)); } else strCommand = CTCPData; if (!blNotice) { #region CtCp Requests switch (strCommand.ToLower()) { case "ping": base.CurrentConnection.SendData("NOTICE " + user.Nick + " :\x01PING " + strParams + "\x01", false); break; case "version": string clientInfo = "TNets IRC Library v.0.7"; if (this.CtCpVersionNeedsClientInfo != null) clientInfo = this.CtCpVersionNeedsClientInfo(this, new EventArgs()); base.CurrentConnection.SendData("NOTICE " + user.Nick + " :\x01VERSION " + clientInfo + "\x01", false); break; case "finger": TimeSpan time = (TimeSpan) DateTime.Now.Subtract(base.CurrentConnection.LastActive); string strReadable = ""; #region Calculate readable idle time if (time.TotalSeconds>60) { string strHours = ""; string strMinutes = ""; string strSeconds = ""; if (time.Hours>0) { if (time.Hours>1) strHours = time.Hours.ToString() + " hours "; else strHours = time.Hours.ToString() + " hour "; } if (time.Minutes>0) { if (time.Minutes>1) strMinutes = time.Minutes.ToString() + " minutes "; else strMinutes = time.Minutes.ToString() + " minute "; } if (time.Seconds>0) { if (time.Seconds>1) strSeconds = time.Seconds.ToString() + " seconds "; else strSeconds = time.Seconds.ToString() + " second "; } strReadable = strHours + strMinutes + strSeconds; strReadable = " (" + strReadable.Trim() + ")"; } #endregion base.CurrentConnection.SendData("NOTICE " + user.Nick + " :\x01" + "FINGER Idle " + Math.Floor(time.TotalSeconds).ToString() + " seconds" + strReadable + "\x01", false); break; case "time": base.CurrentConnection.SendData("NOTICE " + user.Nick + " :\x01TIME " + mIRCDateTime(DateTime.Now) + "\x01", false); break; case "action": Target.FireRecievedMessage(users.GetUser(user), strParams, true); break; case "dcc": if (Target.GetType() == typeof(User)) { User userTarget = (User) Target; string[] strDccParams = strParams.Split(new char[] {' '}); if (strDccParams.Length>=4) { switch (strDccParams[0].ToLower()) { case "chat": DCCChat newChat = new DCCChat(base.CurrentConnection, long.Parse(strDccParams[2]), int.Parse(strDccParams[3]), user.Nick, dcc.Chats); dcc.Chats.AddDcc(newChat); userTarget.FireDCCChatRequest(newChat); break; case "send": DCCTransfer newTransfer = new DCCTransfer(base.CurrentConnection, long.Parse(strDccParams[2]), int.Parse(strDccParams[3]), user.Nick, strDccParams[1], long.Parse(strDccParams[4]), dcc.Transfer); dcc.Transfer.AddDcc(newTransfer); userTarget.FireDCCTransferRequest(newTransfer); break; case "accept": for (int x=0;x<dcc.Transfer.Count;x++) { if (dcc.Transfer[x].Identifier==int.Parse(strDccParams[2])) { dcc.Transfer[x].ResumeAccepted(long.Parse(strDccParams[3])); break; } } break; case "resume": for (int x=0;x<dcc.Transfer.Count;x++) { if (dcc.Transfer[x].Identifier==int.Parse(strDccParams[2])) { dcc.Transfer[x].ResumeRequested(long.Parse(strDccParams[3])); break; } } break; } } } break; default: Target.FireRecievedCtCpMessage(users.GetUser(user), strCommand, strParams); break; } #endregion } else { #region CtCp Responses switch (strCommand.ToLower()) { case "ping": users.GetUser(user).FireCtCpPingReplied(new TimeSpan(TimeSpan.TicksPerMillisecond * long.Parse(strParams))); break; case "time": users.GetUser(user).FireCtCpTimeReplied(strParams); break; case "finger": users.GetUser(user).FireCtCpFingerReplied(strParams); break; case "version": users.GetUser(user).FireCtCpVersionReplied(strParams); break; default: users.GetUser(user).FireCtCpReplied(strCommand, strParams); break; } #endregion } }
private void EnsureInformation(UserInfo user) { foreach (Channel channel in channels) { foreach (ChannelUser channelUser in channel.Users) { if (channelUser.User.Nick.ToLower()==user.Nick.ToLower()) { channelUser.User.HoldBackInfoUpdatedEvent = true; channelUser.User.Host = user.Host; channelUser.User.Identity = user.Identity; channelUser.User.HoldBackInfoUpdatedEvent = false; } } } }
private void CheckVoice(string ChannelName, UserInfo user) { if (channels.IsOnChannel(ChannelName)&&channels[ChannelName].Moderated&&!channels[ChannelName].Users[user.Nick].IsVoiced) onData(base.CurrentConnection, new OnDataEventArgs(strHost, "MODE", new string[] {ChannelName, "+v", user.Nick}, false, null)); }
private void CheckUserChannelStatus(UserInfo user, string ChannelName, string Mode) { string[] strParts = Mode.Split(new char[] {' '}); int cParam = 1; bool blWay = false; for (int x=0;x<strParts[0].Length;x++) { switch (strParts[0][x]) { case '+': blWay = true; break; case '-': blWay = false; break; case 'o': channels.GetChannel(ChannelName).FireUserOpStatusChanged(users.GetUser(user), users.GetUser(strParts[cParam++]), blWay); break; case 'v': channels.GetChannel(ChannelName).FireUserVoiceStatusChanged(users.GetUser(user), users.GetUser(strParts[cParam++]), blWay); break; case 'l': case 'k': cParam++; break; } } }
internal void SetAllInfo(UserInfo userInfo, string RealName, string UsingServer) { strNick = userInfo.Nick; strIdentity = userInfo.Identity; strHost = userInfo.Host; strRealName = RealName; strUsingServer = UsingServer; if (InfoUpdated != null) InfoUpdated(this, new EventArgs()); }
internal User GetUser(UserInfo user) { foreach (User u in users) if (u.Nick.ToLower() == user.Nick.ToLower()) return u; User ret = new User(base.CurrentConnection, user.Nick, user.Identity, user.Host, true); users.Add(ret); return ret; }