Listener.cs :  » Chat-Servers » Thresher » Sharkbite » Irc » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Chat Servers » Thresher 
Thresher » Sharkbite » Irc » Listener.cs
/*
 * Thresher IRC client library
 * Copyright (C) 2002 Aaron Hunter <thresher@sharkbite.org>
 *
 * 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; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 * 
 * See the gpl.txt file located in the top-level-directory of
 * the archive of this library for complete text of license.
*/

using System;
using System.Globalization;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;
using System.Threading;


namespace Sharkbite.Irc{
  /// <summary>
  /// This class parses messages received from the IRC server and
  /// raises the appropriate event. 
  /// </summary>
  public sealed class Listener
  {
    /// <summary>
    /// Messages that are not handled by other events and are not errors.
    /// </summary>
    public event ReplyEventHandler OnReply;
    /// <summary>
    /// Error messages from the IRC server.
    /// </summary>
    public event ErrorMessageEventHandler OnError;
    /// <summary>
    ///A <see cref="Sender.PrivateNotice"/> or <see cref="Sender.PrivateMessage"/> message was sent to someone who is away.
    /// </summary>
    public event AwayEventHandler OnAway;
    /// <summary>
    /// An <see cref="Sender.Invite"/> message was successfully sent to another user. 
    /// </summary>
    public event InviteSentEventHandler OnInviteSent;
    /// <summary>
    /// The user tried to change his nick but it failed.
    /// </summary>
    public event NickErrorEventHandler OnNickError;
    /// <summary>
    /// A server keep-alive message.
    /// </summary>
    public event PingEventHandler OnPing;
    /// <summary>
    /// Connection with the IRC server is open and registered.
    /// </summary>
    public event RegisteredEventHandler OnRegistered;
    /// <summary>
    /// This connection is about to be closed. 
    /// </summary>
    public event DisconnectingEventHandler OnDisconnecting;
    /// <summary>
    /// This connection has been closed. 
    /// </summary>
    public event DisconnectedEventHandler OnDisconnected;
    /// <summary>
    /// A Notice type message was sent to a channel.
    /// </summary>
    public event PublicNoticeEventHandler OnPublicNotice;
    /// <summary>
    /// A private Notice type message was sent to the user.
    /// </summary>
    public event PrivateNoticeEventHandler OnPrivateNotice;
    /// <summary>
    /// Someone has joined a channel.
    /// </summary>
    public event JoinEventHandler OnJoin;
    /// <summary>
    /// A public message was sent to a channel.
    /// </summary>
    public event PublicMessageEventHandler OnPublic;
    /// <summary>
    /// An action message was sent to a channel.
    /// </summary>
    public event ActionEventHandler OnAction;
    /// <summary>
    /// A private action message was sent to the user.
    /// </summary>
    public event PrivateActionEventHandler OnPrivateAction;
    /// <summary>
    /// A user changed his nickname.
    /// </summary>
    public event NickEventHandler OnNick; 
    /// <summary>
    /// A private message was sent to the user.
    /// </summary>
    public event PrivateMessageEventHandler OnPrivate;
    /// <summary>
    /// A channel's topic has changed.
    /// </summary>
    public event TopicEventHandler OnTopicChanged;
    /// <summary>
    /// The response to a <see cref="Sender.RequestTopic"/> command.
    /// </summary>
    public event TopicRequestEventHandler OnTopicRequest;
    /// <summary>
    /// Someone has left a channel. 
    /// </summary>
    public event PartEventHandler OnPart;
    /// <summary>
    /// Someone has quit IRC.
    /// </summary>
    public event QuitEventHandler OnQuit;
    /// <summary>
    /// The user has been invited to a channel.
    /// </summary>
    public event InviteEventHandler OnInvite;
    /// <summary>
    /// Someone has been kicked from a channel. 
    /// </summary>
    public event KickEventHandler OnKick;
    /// <summary>
    /// The response to a <see cref="Sender.Names"/> request.
    /// </summary>
    public event NamesEventHandler OnNames;
    /// <summary>
    /// The response to a <see cref="Sender.List"/> request.
    /// </summary>
    public event ListEventHandler OnList;
    /// <summary>
    /// The response to a <see cref="Sender.Ison"/> request.
    /// </summary>
    public event IsonEventHandler OnIson;
    /// <summary>
    /// The response to a <see cref="Sender.Who"/> request.
    /// </summary>
    public event WhoEventHandler OnWho;
    /// <summary>
    /// The response to a <see cref="Sender.Whois"/> request.
    /// </summary>
    public event WhoisEventHandler OnWhois;
    /// <summary>
    /// The response to a <see cref="Sender.Whowas"/> request.
    /// </summary>
    public event WhowasEventHandler OnWhowas;
    /// <summary>
    /// Someone's user mode has changed.
    /// </summary>
    public event UserModeChangeEventHandler OnUserModeChange;
    /// <summary>
    /// The response to a <see cref="Sender.RequestUserModes"/> command for this user.
    /// </summary>
    public event UserModeRequestEventHandler OnUserModeRequest;
    /// <summary>
    /// The response to a <see cref="Sender.RequestChannelModes"/> command.
    /// </summary>
    public event ChannelModeRequestEventHandler OnChannelModeRequest;
    /// <summary>
    /// A channel's mode has changed.
    /// </summary>
    public event ChannelModeChangeEventHandler OnChannelModeChange;
    /// <summary>
    /// Response to a <see cref="Sender.RequestChannelList"/> command.
    /// </summary>
    public event ChannelListEventHandler OnChannelList;
    /// <summary>
    /// The response to a <see cref="Sender.Version"/> request.
    /// </summary>
    public event VersionEventHandler OnVersion;
    /// <summary>
    /// A server's 'Message of the Day'
    /// </summary>
    public event MotdEventHandler OnMotd;
    /// <summary>
    /// The response to a <see cref="Sender.Time"/> request.
    /// </summary>
    public event TimeEventHandler OnTime;
    /// <summary>
    /// The response to an <see cref="Sender.Info"/> request.
    /// </summary>
    public event InfoEventHandler OnInfo;
    /// <summary>
    /// The response to an <see cref="Sender.Admin"/> request.
    /// </summary>
    public event AdminEventHandler OnAdmin;
    /// <summary>
    /// The response to a <see cref="Sender.Lusers"/> request.
    /// </summary>
    public event LusersEventHandler OnLusers;
    /// <summary>
    /// The response to a <see cref="Sender.Links"/> request.
    /// </summary>
    public event LinksEventHandler OnLinks;
    /// <summary>
    /// The response to a <see cref="Sender.Stats"/> request.
    /// </summary>
    public event StatsEventHandler OnStats;
    /// <summary>
    /// A User has been disconnected via a Kill message.
    /// </summary>
    public event KillEventHandler OnKill;

    private const string PING = "PING";
    private const string ERROR = "ERROR";
    private const string NOTICE = "NOTICE";
    private const string JOIN = "JOIN";
    private const string PRIVMSG = "PRIVMSG";
    private const string NICK = "NICK";
    private const string TOPIC = "TOPIC";
    private const string PART = "PART";
    private const string QUIT = "QUIT";
    private const string INVITE = "INVITE";
    private const string KICK = "KICK";
    private const string MODE = "MODE";
    private const string KILL = "KILL";
    private const string ACTION = "\u0001ACTION";
    private readonly char[] Separator = { ' ' };
    private readonly Regex userPattern; 
    private readonly Regex channelPattern;
    private readonly Regex replyRegex;
    /// <summary>
    /// Table to hold WhoIsInfos while they are being created. The key is the
    /// nick and the value if the WhoisInfo struct.
    /// </summary>
    private Hashtable whoisInfos;

    /// <summary>
    /// Create an instance ready to parse
    /// incoming messages.
    /// </summary>
    public Listener() 
    {
      userPattern = new Regex( "([\\w\\-" + Rfc2812Util.Special + "]+![\\~\\w]+@[\\w\\.\\-]+)", RegexOptions.Compiled | RegexOptions.Singleline);
      channelPattern = new Regex( "([#!+&]\\w+)", RegexOptions.Compiled | RegexOptions.Singleline);
      replyRegex = new Regex("^:([^\\s]*) ([\\d]{3}) ([^\\s]*) (.*)", RegexOptions.Compiled | RegexOptions.Singleline);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="message"></param>
    internal void Parse(string message ) 
    {
      string[] tokens = message.Split( Separator );
      if( tokens[0] == PING ) 
      {
        if( OnPing != null ) 
        {
          tokens[1] = RemoveLeadingColon( tokens[1] );
          OnPing( CondenseStrings(tokens, 1) );
        }
      }
      else if( tokens[0] == NOTICE ) 
      {
        if( OnPrivateNotice != null )
        {
          OnPrivateNotice(
            UserInfo.Empty,
            CondenseStrings( tokens, 2) );
        }
      }
      else if ( tokens[0] == ERROR ) 
      {
        tokens[1] = RemoveLeadingColon( tokens[1] );
        Error( ReplyCode.IrcServerError, CondenseStrings(tokens, 1) );
      }
      else if( replyRegex.IsMatch( message ) )
      {
        ParseReply( tokens );
      }
      else 
      {
        ParseCommand( tokens );
      }
    }
    /// <summary>
    /// Warn listeners that we are about to close this connection
    /// </summary>
    internal void Disconnecting() 
    {
      if( OnDisconnecting != null ) 
      {
        OnDisconnecting();
      }
    }
    /// <summary>
    /// Tell listeners that this connection is closed
    /// </summary>
    internal void Disconnected() 
    {
      if( OnDisconnected != null )
      {
        OnDisconnected();
      }
    }
    /// <summary>
    /// Tell listeners that an error has been encountered
    /// </summary>
    internal void Error( ReplyCode code, string message ) 
    {
      if( OnError != null )
      {
        OnError( code, message );
      }
    }

    /// <summary>
    /// Parse the message and call the callback methods
    /// on the listeners.
    /// 
    /// </summary>
    /// <param name="tokens">The text received from the IRC server</param>
    private void ParseCommand(string[] tokens ) 
    {  
      //Remove colon user info string
      tokens[0] = RemoveLeadingColon( tokens[0] );
      switch( tokens[1] ) 
      {
        case NOTICE:    
          tokens[3] = RemoveLeadingColon( tokens[3] );
          if( Rfc2812Util.IsValidChannelName( tokens[2] ) )
          {      
            if( OnPublicNotice != null )
            {
              OnPublicNotice(
                Rfc2812Util.UserInfoFromString( tokens[0] ),
                tokens[2],
                CondenseStrings( tokens, 3) );
            }
          }
          else 
          {
            if( OnPrivateNotice != null )
            {
              OnPrivateNotice(
                Rfc2812Util.UserInfoFromString( tokens[0] ),
                CondenseStrings( tokens, 3) );
            }
          }
          break;
        case JOIN:
          if( OnJoin != null )
          {
            OnJoin( Rfc2812Util.UserInfoFromString( tokens[0] ), RemoveLeadingColon( tokens[2] ) );
          }
          break;
        case PRIVMSG:
          tokens[3] = RemoveLeadingColon( tokens[3] );
          if( tokens[3] == ACTION ) 
          {
            if( Rfc2812Util.IsValidChannelName( tokens[2] ) )
            {
              if( OnAction != null ) 
              {
                int last = tokens.Length - 1;
                tokens[ last ] = RemoveTrailingQuote( tokens[last] );
                OnAction( Rfc2812Util.UserInfoFromString( tokens[0] ),tokens[2],CondenseStrings( tokens, 4) );
              }
            }
            else 
            {
              if( OnPrivateAction != null ) 
              {
                int last = tokens.Length - 1;
                tokens[ last ] = RemoveTrailingQuote( tokens[last] );
                OnPrivateAction( Rfc2812Util.UserInfoFromString( tokens[0] ),CondenseStrings( tokens, 4) );
              }
            }
          }
          else if( channelPattern.IsMatch( tokens[2] ) )
          {
            if( OnPublic != null )
            {
              OnPublic(Rfc2812Util.UserInfoFromString( tokens[0] ),tokens[2],CondenseStrings( tokens, 3) );
            }
          }
          else 
          {
            if( OnPrivate != null )
            {
              OnPrivate(Rfc2812Util.UserInfoFromString( tokens[0] ), CondenseStrings( tokens, 3) );
            }
          }
          break;
        case NICK:
          if( OnNick != null )
          {
            OnNick(  Rfc2812Util.UserInfoFromString( tokens[0] ), RemoveLeadingColon( tokens[2] ) );
          }
          break;
        case TOPIC:
          if( OnTopicChanged != null ) 
          {
            tokens[3] = RemoveLeadingColon( tokens[3] );
            OnTopicChanged(
              Rfc2812Util.UserInfoFromString( tokens[0] ), tokens[2], CondenseStrings( tokens, 3) );
          }
          break;
        case PART:
          if( OnPart != null )          
          {
            OnPart(
              Rfc2812Util.UserInfoFromString( tokens[0] ), 
              tokens[2],
              tokens.Length >= 4 ? RemoveLeadingColon(CondenseStrings( tokens, 3)) : "" );
          }
          break;
        case QUIT:
          if( OnQuit != null ) 
          {
            tokens[2] = RemoveLeadingColon( tokens[2] );
            OnQuit( Rfc2812Util.UserInfoFromString( tokens[0] ), CondenseStrings( tokens, 2) );
          }
          break;
        case INVITE:
          if( OnInvite != null ) 
          {
            OnInvite(
              Rfc2812Util.UserInfoFromString( tokens[0] ), RemoveLeadingColon( tokens[3] ) );
          }
          break;
        case KICK:
          if( OnKick != null )
          {  
            tokens[4] = RemoveLeadingColon( tokens[4] );
            OnKick(Rfc2812Util.UserInfoFromString( tokens[0] ),tokens[2],tokens[3], CondenseStrings( tokens, 4) );
          }
          break;
        case MODE:        
          if( channelPattern.IsMatch( tokens[2] ) )
          {
            if( OnChannelModeChange != null ) 
            {
              UserInfo who = Rfc2812Util.UserInfoFromString( tokens[0] );              
              try 
              {
                ChannelModeInfo[] modes = ChannelModeInfo.ParseModes( tokens, 3);
                OnChannelModeChange( who, tokens[2], modes );
              }
              catch( Exception e ) 
              {
                if( OnError != null ) 
                {
                  OnError( ReplyCode.UnparseableMessage, CondenseStrings( tokens, 0 ) );
                }
                Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceWarning,"[" + Thread.CurrentThread.Name +"] Listener::ParseCommand() Bad IRC MODE string=" + tokens[0] );
              }
            }
          }
          else 
          {
            if( OnUserModeChange != null )
            {  
              tokens[3] = RemoveLeadingColon( tokens[3] );
              OnUserModeChange( Rfc2812Util.CharToModeAction( tokens[3][0] ), 
                Rfc2812Util.CharToUserMode( tokens[3][1] ) );
            }
          }
          break;
        case KILL:
          if( OnKill != null )
          {
            string reason = "";
            if( tokens.Length >= 4 ) 
            {
              tokens[3] = RemoveLeadingColon( tokens[3] );
              reason = CondenseStrings( tokens, 3 );
            }
            OnKill( Rfc2812Util.UserInfoFromString( tokens[0] ), tokens[2], reason );
          }
          break;
        default: 
          if( OnError != null ) 
          {
            OnError( ReplyCode.UnparseableMessage, CondenseStrings( tokens, 0 ) );
          }
          Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceWarning,"[" + Thread.CurrentThread.Name +"] Listener::ParseCommand() Unknown IRC command=" + tokens[1] );
          break;
      }
    }
    private void ParseReply( string[] tokens ) 
    {
      ReplyCode code = (ReplyCode) int.Parse( tokens[1], CultureInfo.InvariantCulture );
      tokens[3] = RemoveLeadingColon( tokens[3] );
      switch( code )
      {
        //Messages sent upon successful registration 
        case ReplyCode.RPL_WELCOME:
        case ReplyCode.RPL_YOURESERVICE:
          if( OnRegistered != null ) 
          {
            OnRegistered();
          }
          break;  
        case ReplyCode.RPL_MOTDSTART:
        case ReplyCode.RPL_MOTD: 
          if( OnMotd != null ) 
          {
            OnMotd( CondenseStrings( tokens, 3), false );
          }
          break;
        case ReplyCode.RPL_ENDOFMOTD:
          if( OnMotd != null ) 
          {
            OnMotd( CondenseStrings( tokens, 3), true );
          }
          break;
        case ReplyCode.RPL_ISON:
          if ( OnIson != null ) 
          {
            OnIson( tokens[3] );
          }
          break;
        case ReplyCode.RPL_NAMREPLY:
          if ( OnNames != null ) 
          {
            tokens[5] = RemoveLeadingColon( tokens[5] );
            int numberOfUsers = tokens.Length - 5;
            string[] users = new string[ numberOfUsers ];
            Array.Copy( tokens, 5 , users, 0 , numberOfUsers);
            OnNames( tokens[4], 
              users,
              false );
          }
          break;
        case ReplyCode.RPL_ENDOFNAMES:
          if( OnNames != null ) 
          {
            OnNames( tokens[3], new string[0], true );
          }
          break;
        case ReplyCode.RPL_LIST:
          if ( OnList != null ) 
          {
            tokens[5] = RemoveLeadingColon( tokens[5] );
            OnList(
              tokens[3],
              int.Parse( tokens[4] , CultureInfo.InvariantCulture),
              CondenseStrings( tokens, 5),
              false);
          }
          break;
        case ReplyCode.RPL_LISTEND:
          if( OnList != null ) 
          {
            OnList( "",0,"", true );
          }
          break;
        case ReplyCode.ERR_NICKNAMEINUSE:
        case ReplyCode.ERR_NICKCOLLISION:
          if ( OnNickError != null ) 
          {
            tokens[4] = RemoveLeadingColon( tokens[4] );
            OnNickError( tokens[3], CondenseStrings( tokens, 4) );
          }
          break;
        case ReplyCode.RPL_NOTOPIC:
          if( OnError != null ) 
          {
            OnError(code, CondenseStrings( tokens, 3) );
          }
          break;
        case ReplyCode.RPL_TOPIC:
          if( OnTopicRequest != null )
          {
            tokens[4] = RemoveLeadingColon( tokens[4] );
            OnTopicRequest(  tokens[3], CondenseStrings(tokens, 4 ) );
          }
          break;
        case ReplyCode.RPL_INVITING:
          if( OnInviteSent != null )
          {
            OnInviteSent(tokens[3], tokens[4] );
          }
          break;
        case ReplyCode.RPL_AWAY:
          if( OnAway != null )
          {
            OnAway(tokens[3], RemoveLeadingColon( CondenseStrings( tokens, 4) ) );
          }
          break;
        case ReplyCode.RPL_WHOREPLY:
          if( OnWho != null ) 
          {
            UserInfo user = new UserInfo( tokens[7],tokens[4],tokens[5]);
            OnWho(
              user,
              tokens[3],
              tokens[6],
              tokens[8],
              int.Parse( RemoveLeadingColon( tokens[9] ), CultureInfo.InvariantCulture),
              tokens[10],
              false );
          }
          break;
        case ReplyCode.RPL_ENDOFWHO:
          if( OnWho != null )
          {
            OnWho( UserInfo.Empty , "","","",0,"",true);
          }
          break;
        case ReplyCode.RPL_WHOISUSER:
          UserInfo whoUser = new UserInfo( tokens[3], tokens[4], tokens[5]);
          WhoisInfo whoisInfo = LookupInfo( whoUser.Nick );
          whoisInfo.userInfo = whoUser;
          tokens[7] = RemoveLeadingColon( tokens[7] );
          whoisInfo.realName = CondenseStrings( tokens, 7) ;
          break;
        case ReplyCode.RPL_WHOISCHANNELS:
          WhoisInfo whoisChannelInfo = LookupInfo( tokens[3] );
          tokens[4] = RemoveLeadingColon( tokens[4] );
          int numberOfChannels = tokens.Length - 4;
          string[] channels = new String[ numberOfChannels ];
          Array.Copy( tokens, 4, channels, 0 , numberOfChannels);
          whoisChannelInfo.SetChannels( channels );
          break;
        case ReplyCode.RPL_WHOISSERVER:
          WhoisInfo whoisServerInfo = LookupInfo( tokens[3] );
          whoisServerInfo.ircServer = tokens[4];
          tokens[5] = RemoveLeadingColon( tokens[5] );
          whoisServerInfo.serverDescription = CondenseStrings( tokens, 5) ;
          break;
        case ReplyCode.RPL_WHOISOPERATOR:
          WhoisInfo whoisOpInfo = LookupInfo( tokens[3] );
          whoisOpInfo.isOperator = true;
          break;
        case ReplyCode.RPL_WHOISIDLE:
          WhoisInfo whoisIdleInfo = LookupInfo( tokens[3] );
          whoisIdleInfo.idleTime = long.Parse( tokens[5], CultureInfo.InvariantCulture );      
          break;
        case ReplyCode.RPL_ENDOFWHOIS:
          string nick = tokens[3];
          WhoisInfo whoisEndInfo = LookupInfo( nick );
          if( OnWhois != null )
          {
            OnWhois( whoisEndInfo );
          }
          whoisInfos.Remove( nick );
          break;
        case ReplyCode.RPL_WHOWASUSER:
          if( OnWhowas != null )
          {
            UserInfo whoWasUser = new UserInfo( tokens[3], tokens[4], tokens[5]);
            tokens[7] = RemoveLeadingColon( tokens[7] );
            OnWhowas( whoWasUser, CondenseStrings( tokens, 7) , false);
          }
          break;
        case ReplyCode.RPL_ENDOFWHOWAS:
          if( OnWhowas != null )
          {
            OnWhowas( UserInfo.Empty, "", true);
          }
          break;
        case ReplyCode.RPL_UMODEIS:
          if( OnUserModeRequest != null ) 
          {
            //First drop the '+'
            string chars = tokens[3].Substring(1);
            UserMode[] modes = Rfc2812Util.UserModesToArray( chars );
            OnUserModeRequest( modes );
          }
          break;
        case ReplyCode.RPL_CHANNELMODEIS:
          if( OnChannelModeRequest != null )
          {
            try
            {
              ChannelModeInfo[] modes = ChannelModeInfo.ParseModes( tokens, 4);
              OnChannelModeRequest( tokens[3], modes);
            }
            catch( Exception e ) 
            {
              if( OnError != null ) 
              {
                OnError( ReplyCode.UnparseableMessage, CondenseStrings( tokens, 0 ) );
              }
              Debug.WriteLineIf( Rfc2812Util.IrcTrace.TraceWarning,"[" + Thread.CurrentThread.Name +"] Listener::ParseReply() Bad IRC MODE string=" + tokens[0] );
            }
          }
          break;
        case ReplyCode.RPL_BANLIST:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.Ban, tokens[4], Rfc2812Util.UserInfoFromString(tokens[5]), Convert.ToInt64(tokens[6], CultureInfo.InvariantCulture), false );
          }
          break;
        case ReplyCode.RPL_ENDOFBANLIST:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.Ban, "", UserInfo.Empty, 0, true );
          }
          break;
        case ReplyCode.RPL_INVITELIST:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.Invitation, tokens[4], Rfc2812Util.UserInfoFromString(tokens[5]), Convert.ToInt64(tokens[6]),false );
          }
          break;
        case ReplyCode.RPL_ENDOFINVITELIST:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.Invitation, "",UserInfo.Empty,0, true );
          }
          break;
        case ReplyCode.RPL_EXCEPTLIST:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.Exception, tokens[4], Rfc2812Util.UserInfoFromString(tokens[5]), Convert.ToInt64(tokens[6]),false );
          }
          break;
        case ReplyCode.RPL_ENDOFEXCEPTLIST:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.Exception, "", UserInfo.Empty,0,true );
          }
          break;
        case ReplyCode.RPL_UNIQOPIS:
          if( OnChannelList != null ) 
          {
            OnChannelList( tokens[3], ChannelMode.ChannelCreator, tokens[4], UserInfo.Empty,0, true );
          }
          break;
        case ReplyCode.RPL_VERSION:
          if ( OnVersion != null ) 
          {
            OnVersion( CondenseStrings(tokens,3) );
          }
          break;
        case ReplyCode.RPL_TIME:
          if ( OnTime != null ) 
          {
            OnTime( CondenseStrings(tokens,3) );
          }
          break;
        case ReplyCode.RPL_INFO:
          if ( OnInfo != null ) 
          {
            OnInfo( CondenseStrings(tokens,3), false );
          }
          break;
        case ReplyCode.RPL_ENDOFINFO:
          if ( OnInfo != null ) 
          {
            OnInfo( CondenseStrings(tokens,3), true);
          }
          break;
        case ReplyCode.RPL_ADMINME:
        case ReplyCode.RPL_ADMINLOC1:
        case ReplyCode.RPL_ADMINLOC2:
        case ReplyCode.RPL_ADMINEMAIL:
          if ( OnAdmin != null ) 
          {
            OnAdmin( RemoveLeadingColon( CondenseStrings(tokens,3) ) );
          }
          break;
        case ReplyCode.RPL_LUSERCLIENT:
        case ReplyCode.RPL_LUSEROP:
        case ReplyCode.RPL_LUSERUNKNOWN:
        case ReplyCode.RPL_LUSERCHANNELS:
        case ReplyCode.RPL_LUSERME:
          if ( OnLusers != null ) 
          {
            OnLusers( RemoveLeadingColon( CondenseStrings(tokens,3) ) );
          }
          break;
        case ReplyCode.RPL_LINKS:
          if ( OnLinks != null ) 
          {  
            OnLinks( tokens[3], //mask
                  tokens[4], //hostname
                  int.Parse( RemoveLeadingColon( tokens[5] ), CultureInfo.InvariantCulture), //hopcount
                      CondenseStrings(tokens,6), false );
          }
          break;
        case ReplyCode.RPL_ENDOFLINKS:
          if ( OnLinks != null ) 
          {
            OnLinks( String.Empty, String.Empty,-1, String.Empty, true);
          }
          break;
        case ReplyCode.RPL_STATSLINKINFO:
        case ReplyCode.RPL_STATSCOMMANDS:
        case ReplyCode.RPL_STATSUPTIME:
        case ReplyCode.RPL_STATSOLINE:
          if ( OnStats != null ) 
          {
            OnStats( GetQueryType(code), RemoveLeadingColon( CondenseStrings(tokens,3) ), false);
          }
          break;
        case ReplyCode.RPL_ENDOFSTATS:
          if ( OnStats != null ) 
          {
            OnStats( Rfc2812Util.CharToStatsQuery( tokens[3][0] ), RemoveLeadingColon( CondenseStrings(tokens,4) ), true);
          }
          break;
        default:
          HandleDefaultReply( code, tokens );
          break;
      }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="code"></param>
    /// <param name="tokens"></param>
    private void HandleDefaultReply( ReplyCode code, string[] tokens ) 
    {
      if (code >= ReplyCode.ERR_NOSUCHNICK && code <= ReplyCode.ERR_USERSDONTMATCH) 
      {
        if( OnError != null )
        {
          OnError(code, CondenseStrings( tokens, 3) );
        }
      }
      else if( OnReply != null )
      {
        OnReply(code, CondenseStrings( tokens, 3) );
      }
    }
    /// <summary>
    /// Find the correct WhoIs object based on the nick name.
    /// </summary>
    /// <param name="nick"></param>
    /// <returns></returns>
    private WhoisInfo LookupInfo( string nick )
    {
      if( whoisInfos == null ) 
      {
        whoisInfos = new Hashtable();
      }
      WhoisInfo info = (WhoisInfo) whoisInfos[nick] ;
      if( info == null ) 
      {
        info = new WhoisInfo();
        whoisInfos[ nick ] = info;
      }
      return info;
    }
    /// <summary>
    /// Turn an array of strings back into a single string.
    /// </summary>
    /// <param name="strings"></param>
    /// <param name="start"></param>
    /// <returns></returns>
    private string CondenseStrings( string[] strings, int start ) 
    {
      if( strings.Length == start + 1 ) 
      {
        return strings[start];
      }
      else 
      {
        return String.Join(" ", strings, start, (strings.Length - start) );
      }
    }
    private string RemoveLeadingColon( string text ) 
    {
      if( text[0] == ':' )
      {
        return text.Substring(1);
      }
      return text;
    }
    /// <summary>
    /// Strip off the trailing CTCP quote.
    /// </summary>
    /// <param name="text"></param>
    /// <returns></returns>
    private string RemoveTrailingQuote( string text ) 
    {
      return text.Substring(0, text.Length -1 );    
    }

    private StatsQuery GetQueryType( ReplyCode code ) 
    {
      switch( code ) 
      {
        case ReplyCode.RPL_STATSLINKINFO:
          return StatsQuery.Connections;
        case ReplyCode.RPL_STATSCOMMANDS:
          return StatsQuery.CommandUsage;
        case ReplyCode.RPL_STATSUPTIME:
          return StatsQuery.Uptime;
        case ReplyCode.RPL_STATSOLINE:
          return StatsQuery.Operators;
        //Should never get here
        default:
          return StatsQuery.CommandUsage;
      }
    }
  
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.