Example #1
0
 void ChangeModes( string modetext )
 {
     if ( CurrentView == null ) return;
     var modes = new Irc.ModeChangeSet(modetext);
     CurrentView.ID.Connection.ChangeModes( CurrentView.ID.Channel, modes );
 }
Example #2
0
        void OnRecv( IAsyncResult result )
        {
            lock (Lock) try {
                var state = (RecvState) result.AsyncState;
                var buffer = state.Buffer;
                if (Client == null || Client.Client == null || !Client.Connected) return; // XXX -- do we really want to silent-fail here?
                var buffer_end = Client.Client.EndReceive(result) + state.Offset;
                Handle(state.Error);
                var eol = Encoding.GetBytes("\n")[0]; // XXX

                var begin = 0;
                for (;;) {
                    var end = Array.FindIndex( buffer, begin, buffer_end-begin, (byte b) => b == eol );

                    if ( end == -1 ) {
                        for ( int i = begin ; i < buffer_end ; ++i ) buffer[i-begin] = buffer[i];
                        BeginRecv(buffer,buffer_end-begin);
                        return;
                    }

                    var s = Encoding.GetString(buffer, begin, end-begin).TrimEnd( new[]{'\r','\n'} );

                    //if (OnRecieve != null) OnRecieve(s);
                    Match match;
                    try {
                        if ( ( match = new Regex(@"^PING(.*)$").Match(s)).Success ) {
                            var code = match.Groups[1].Value;
                            Send( "PONG" + code );
                        } else if ( (match = new Regex(@"^\:([^ ]+) (\d\d\d) [^: ]+ \:?(.*)$").Match(s)).Success ) {
                            var sender     = match.Groups[1].Value;
                            var code       = match.Groups[2].Value;
                            var parameters = match.Groups[3].Value;
                            if (serverIdent == null) serverIdent = sender;

                            switch (code) {
                            case "001": // Welcome
                                Registered = true;
                                foreach ( string channel in TargetChannels ) Send("JOIN "+(channel.StartsWith("#")?channel:"#"+channel));
                                break;
                            case "311": // RPL_WHOISUSER "<nick> <user> <host> * :<real name>"
                            case "314": // RPL_WHOWASUSER "<nick> <user> <host> * :<real name>"
                                if ( (match = new Regex(@"^([^ ]+) ([^ ]+) ([^ ]+) \* \:(.+)$").Match(parameters)).Success ) {
                                    var nick = match.Groups[1].Value;
                                    var user = match.Groups[2].Value;
                                    var host = match.Groups[3].Value;
                                    var real = match.Groups[4].Value;

                                    if ( Users.ContainsKey(nick) ) Users[nick].Hostname = host;
                                }
                                break;
                            case "331": // RPL_NOTOPIC
                            case "332": // RPL_TOPIC
                                if ( (match = new Regex(@"^(?'channel'[^ ]+) \:?(?'topic'.+)$").Match(parameters)).Success ) {
                                    var channel = match.Groups["channel"].Value;
                                    var topic   = match.Groups["topic"].Value;
                                    foreach ( var l in Listeners ) l.OnTopic( this, null, channel, topic );
                                }
                                break;
                            case "353": // RPL_NAMREPLY (Names list)
                                if ( (match = new Regex(@"^(?:. )?(?'channel'[^: ]+) \:(?'nicks'.+)$").Match(parameters)).Success )
                                {
                                    var channelname = match.Groups["channel"].Value;
                                    if (!Channels.ContainsKey(channelname)) break;
                                    var channel     = Channels[channelname];
                                    var nicks       = match.Groups["nicks"].Value.Split(new[]{' '},StringSplitOptions.RemoveEmptyEntries);

                                    foreach ( string nick_ in nicks ) {
                                        string nick;
                                        switch ( nick_[0] ) {
                                        case '@':
                                        case '%':
                                        case '+':
                                            nick = nick_.Substring(1);
                                            break;
                                        default:
                                            nick = nick_;
                                            break;
                                        }

                                        channel.Users.Add( nick );
                                        if (!Users.ContainsKey(nick)) Users.Add(nick,new User());
                                    }
                                }
                                break;
                            case "366": // RPL_ENDOFNAMES (End of names list)
                                break;
                            case "401": // RPL_NOSUCHNICK "<nickname> :No such nick/channel"
                                Send( "WHOWAS "+ReadParam(ref parameters) );
                                break;
                            case "406": { // RPL_WASNOSUCHNICK "<nickname> :There was no such nickname"
                                var nick = ReadParam(ref parameters);
                                if ( Users.ContainsKey(nick) ) Users.Remove(nick);
                                break;
                            } case "433": // Nick already in use
                                ActualNickname = ActualNickname + "_";
                                Send( "NICK "+ActualNickname); // try a different one
                                break;
                            }
                        } else if ( (match = new Regex(@"^\:?(?'nick'[^ !]+)!(?'user'[^ @]+)@(?'host'[^ ]+) (?'action'[^ ]+)(?: (?'params'.+))?$").Match(s)).Success ) {
                            var nick   = match.Groups["nick"].Value;
                            var user   = match.Groups["user"].Value;
                            var host   = match.Groups["host"].Value;
                            var actor  = new Irc.Actor() { Nickname = nick, Username = user, Hostname = host };
                            var action = match.Groups["action"].Value;
                            var param  = match.Groups["params"].Value;

                            switch ( action ) {
                                case "NICK": {
                                    var newnick = ReadParam(ref param);
                                    if ( nick == ActualNickname ) ActualNickname = newnick; // we got renamed!

                                    if ( Users.ContainsKey(nick) ) {
                                        var info = Users[nick];
                                        if ( !Users.ContainsKey(newnick) ) Users.Add(newnick,info);
                                        Users.Remove(nick);
                                    }

                                    foreach ( var channel in Channels )
                                    if ( channel.Value.Users.Contains(nick) )
                                    {
                                        channel.Value.Users.Remove(nick);
                                        channel.Value.Users.Add(newnick);
                                        foreach ( var l in Listeners ) l.OnNick( this, actor, channel.Key, newnick );
                                    }
                                    break;
                                } case "JOIN": {
                                    var channel = ReadParam(ref param);
                                    if ( nick == ActualNickname ) AddChannel(channel); // we joined a channel!
                                    if ( Channels.ContainsKey(channel) ) Channels[channel].Users.Add(nick);
                                    foreach ( var l in Listeners ) l.OnJoin( this, actor, channel );
                                    break;
                                } case "PART": {
                                    var channel = ReadParam(ref param);
                                    if ( nick == ActualNickname ) RemoveChannel(channel); // we left a channel!
                                    if ( Channels.ContainsKey(channel) ) Channels[channel].Users.Remove(nick);
                                    foreach ( var l in Listeners ) l.OnPart( this, actor, channel );
                                    break;
                                } case "QUIT": {
                                    var message = TrimColon(param);

                                    foreach ( var l in Listeners )
                                    foreach ( var channel in Channels )
                                    if ( channel.Value.Users.Contains(nick) )
                                    {
                                        channel.Value.Users.Remove(nick);
                                        l.OnQuit( this, actor, channel.Key, message );
                                    }
                                    break;
                                } case "KICK": {
                                    var channel = ReadParam(ref param);
                                    var target  = ReadParam(ref param);
                                    var message = TrimColon(param);
                                    if ( Channels.ContainsKey(channel) ) Channels[channel].Users.Remove(target);
                                    if ( target == ActualNickname ) { // we were kicked from a channel!
                                        RemoveChannel( channel );
                                        if ( AutoRejoin ) Join( channel );
                                    }
                                    foreach ( var l in Listeners ) l.OnKick( this, actor, channel, target, message );
                                    break;
                                } case "PRIVMSG": {
                                    var target = ReadParam(ref param);
                                    var message = TrimColon(param);
                                    switch ( message ) {
                                    case "\u0001VERSION\u0001": // http://www.irchelp.org/irchelp/rfc/ctcpspec.html
                                        if ( target != ActualNickname ) break;
                                        Send( "NOTICE "+nick+" :\u0001VERSION UberIRC "+Assembly.GetExecutingAssembly().ImageRuntimeVersion+" Unknown Unavailable\u0001" );
                                        break;
                                    default:
                                        foreach ( var l in Listeners ) l.OnPrivMsg( this, actor, target, message );
                                        break;
                                    }
                                    break;
                                } case "NOTICE": {
                                    var target = ReadParam(ref param);
                                    var message = TrimColon(param);
                                    foreach ( var l in Listeners ) l.OnNotice( this, actor, target, message );
                                    break;
                                } case "MODE": {
                                    var channel = ReadParam(ref param);
                                    var modes = new Irc.ModeChangeSet(param);

                                    foreach ( var l in Listeners ) {
                                        foreach ( var mode in modes.UserModes    ) l.OnModeChange( this, actor, channel, mode.Key, mode.Value );
                                        foreach ( var mode in modes.ChannelModes ) l.OnChannelModeChange( this, actor, channel, mode.Key, mode.Value );
                                    }
                                    break;
                                } case "TOPIC": {
                                    var channel = ReadParam(ref param);
                                    var newtopic = TrimColon(param);
                                    foreach ( var l in Listeners ) l.OnTopic( this, actor, channel, newtopic );
                                    break;
                                }
                            }
                        }
                    } catch ( Exception e ) {
                        foreach ( var l in Listeners ) l.OnRecvParseError( this, s, e );
                    }

                    begin = end+1;
                }
            }
            catch ( SocketException e ) { Handle(e); }
            catch ( ObjectDisposedException e ) { Handle(e); }
            catch ( Exception e ) { foreach ( var l in Listeners ) l.OnConnectionError(this,e); }
        }