Exemple #1
0
 /// <summary>
 /// Checks to see if this registered user can authenticate by the host.
 /// </summary>
 /// <param name="host">The host to check for.</param>
 /// <returns>Yes or no</returns>
 public bool HasHost(IRCHost host)
 {
     foreach ( IRCHost i in hostList )
         if ( host.CompareTo( i ) == 0 )
             return true;
     return false;
 }
Exemple #2
0
        /// <summary>
        /// Creates a server from a ServerConfig with a parameter
        /// to provide an interface for logging.
        /// </summary>
        /// <param name="config">The configuration to build the Server from.</param>
        /// <param name="logFunction">The function to call to log text for the application.</param>
        public Server(Configuration.ServerConfig config, Project2QService.WriteLogFunction logFunction)
        {
            //Instantiate and load databases
            uc = new UserCollection();
            cc = new ChannelCollection();
            uc.LoadRegisteredUsers( "userdb\\" + config.Name + ".udb" );

            //Rip up this little guy to help us out :D
            currentHost = new IRCHost();
            currentIP = null;

            this.authmode = !File.Exists( "userdb\\" + config.Name + ".udb" );

            this.writeLogFunction = logFunction;

            //Assign a Server ID
            this.serverId = Server.NextServerId;
            if ( this.serverId == -1 ) throw new OverflowException( "Too many servers created." );
            servers[serverId] = this;

            //Save the configuration.
            this.config = config;

            //Tie default static handlers together for this instance of IRCEvents.
            irce = new IRCEvents();

            //Initialize the socket pipe before the modules. Modules are scary.
            state = State.Disconnected;

            socketPipe = new SocketPipe(
                this.serverId, config.RetryTimeout, config.OperationTimeout, config.SendInhibit, config.SocketBufferSize ); //Default values for now, get them from config later plz.
            socketPipe.OnDisconnect += new SocketPipe.NoParams( this.OnDisconnect );
            socketPipe.OnReceive += new SocketPipe.ReceiveData( this.OnReceive );
        }
Exemple #3
0
 /// <summary>
 /// Adds a host to the registered user's host list.
 /// </summary>
 /// <param name="host">The host to add.</param>
 /// <returns>True or false.</returns>
 public bool AddHost(IRCHost host)
 {
     if ( host.Equals( new IRCHost( "*!*@*" ) ) )
         return false;
     hostList.Add( host );
     return true;
 }
Exemple #4
0
        /// <summary>
        /// Adds a host to a user.
        /// </summary>
        /// <param name="repnick">The user that initiated the command.</param>
        /// <param name="host">The host to add.</param>
        /// <param name="user">The user to add the host to.</param>
        public void AddHost(string repnick, string host, string user)
        {
            User u = null;
            UserCollection uc = (UserCollection)mp.RequestVariable( Request.UserCollection, channelMessageData.sid );

            try {
                u = uc[user];
            }
            catch ( KeyNotFoundException ) {
                BoldNickNotice( repnick, "Error(Invalid User):", " User not in active user database." );
                return;
            }

            if ( u.UserAttributes == null ) {
                BoldNickNotice( repnick, "Error(Invalid User):", " User not in user database." );
                return;
            }

            IRCHost irch = null;
            try {
                irch = new IRCHost( host );
            }
            catch ( FormatException ) {
                BoldNickNotice( repnick, "Error(Invalid Host):", " The host must be in the form [nick]![username]@[host] where all fields can contain wildcard characters '?' and '*'." );
                return;
            }

            if ( uc.HasHost( irch ) ) {
                BoldNickNotice( repnick, "Error(Host Exists):", " The host specified already exists. Please use a wider subset of the host you require." );
                return;
            }

            if ( !u.UserAttributes.AddHost( irch ) ) {
                BoldNickNotice( repnick, "Error(Invalid Host):", " The host specified was rejected. Try a more specific subset of the host you require." );
                return;
            }

            BoldNickNotice( repnick, "Host Added:", " " + irch.ToString() + " to " + ( ( repnick.Equals( u.Nickname ) ) ? "your account." : u.Nickname ) );
        }
Exemple #5
0
        /// <summary>
        /// Determines if a user is known by the internal databases. If not
        /// it will create and authenticate the user. If so, it will simply look up the user.
        /// </summary>
        /// <param name="s">The server to check for the user on.</param>
        /// <param name="irch">The irc host to check for.</param>
        /// <returns>The new or old user.</returns>
        private static User UpdateUserDB(Server s, IRCHost irch)
        {
            User u;
            try {
                u = s.UserDatabase[irch.Nick];

                if ( !u.CurrentHost.Equals( irch ) )
                    u.CurrentHost = irch;
            }
            catch ( KeyNotFoundException ) {
                u = new User( irch );
                s.UserDatabase.AddUser( u );
                s.UserDatabase.Authenticate( u );
            }

            return u;
        }
Exemple #6
0
        /// <summary>
        /// This method parses all raw data for each packet of data that
        /// a Server object might receive. It then uses the events defined
        /// in IRCEvents and fires them through the appropriate server object.
        /// </summary>
        /// <param name="s">The Server which the data was received on.</param>
        /// <param name="raw">The raw text from the socket.</param>
        public static void Parse(Server s, string raw)
        {
            //TODO: IMPLEMENT THE REST :D

            int spacestring = 0;
            int lastchar = 0;
            int firstchar = 0;

            //Remove excessive spaces from everything.
            StringBuilder sb = new StringBuilder();

            for ( int i = 0; i < raw.Length; i++ ) {
                if ( raw[i] == ' ' ) {
                    if ( spacestring++ == 0 )
                        lastchar = i;
                }
                else if ( spacestring > 1 ) {
                    sb.Append( raw, firstchar, lastchar - firstchar + 1 );
                    spacestring = 0;
                    firstchar = i;
                    lastchar = i;
                }
                else {
                    spacestring = 0;
                    lastchar = i;
                }
            }

            if ( sb.Length > 0 || ( lastchar != firstchar && firstchar != 0 && lastchar != raw.Length - 1 ) ) {
                sb.Append( raw, firstchar, lastchar - firstchar + 1 );
            }
            if ( sb.Length > 0 )
                raw = sb.ToString();

            //Make sure this excessive space is handled with care. (For all instances where text is preceeded by a space)
            raw = raw.Replace( ": ", ":" );

            //Replies to ping handler
            if ( raw.StartsWith( "PING :" ) ) {
                string[] parsed = raw.Split( ':' );
                s.QueueData( s.EventObject.OnPing( s.ServerID, parsed[1] ) );
            }

            if ( raw.StartsWith( "ERROR :" ) ) {
                Console.WriteLine( "[Error: whatsit]" );
            }

            //All that work above for this?
            string[] spaceSplit = raw.Split( ' ' );

            if ( spaceSplit.Length <= 1 ) return; //Nothing below here takes only one spaceSplit arg.
            switch ( spaceSplit[1] ) {
                case "001": {
                        string welcome = raw.Substring( spaceSplit[0].Length + spaceSplit[1].Length + 4 + spaceSplit[2].Length );
                        s.QueueData( s.EventObject.OnWelcome( s.ServerID, welcome ) );
                    }
                    break;
                case "352": {
                        //spaceSplit[5] = spaceSplit[5].Substring( 1 ); //Get rid of the : on the first name.
                        //
                        //                0                  1   2         3    4               5                        6          7  8  9   10
                        //":TechConnect.NL.EU.GameSurge.net 352 P2Q #phishcave ~2q d75-155-184-58.bchsia.telus.net *.GameSurge.net P2Q H :0 2Q Beta"
                        IRCHost ir = new IRCHost(spaceSplit[7], spaceSplit[4], spaceSplit[5]); //fix on debug.
                        Channel c = UpdateChanDB(s, spaceSplit[3]);
                        UpdateUserDB(s, ir);
                        //UpdateBothDB(s, spaceSplit[3], spaceSplit[7]);

                        //This should blank add all the users

                        if (spaceSplit[8].Contains("@"))
                            UpdateBothDB(s, spaceSplit[3], spaceSplit[7], '@');  //NO Simple. hah
                        else if (spaceSplit[8].Contains("+"))
                            UpdateBothDB(s, spaceSplit[3], spaceSplit[7], '+');
                        else
                            UpdateBothDB(s, spaceSplit[3], spaceSplit[7], null);

                        //Invoke the event.
                        s.QueueData(s.EventObject.OnNames(s.ServerID, c));
                    }
                    break;
                case "353": {
                        spaceSplit[5] = spaceSplit[5].Substring( 1 ); //Get rid of the : on the first name.

                        //if ( spaceSplit[2] == s.Config.NickName ) //Do we need to parse ourself? ~fish
                        //    break;

                        Channel c = UpdateChanDB( s, spaceSplit[4] );

                        //This should blank add all the users
                        for ( int i = 5; i < spaceSplit.Length; i++ ) {
                            if ( spaceSplit[i][0] == '@' || spaceSplit[i][0] == '+' )
                                UpdateBothDB( s, spaceSplit[4], spaceSplit[i].Substring( 1 ), spaceSplit[i][0] );
                            else
                                UpdateBothDB( s, spaceSplit[4], spaceSplit[i], null );
                        }

                        //Invoke the event.
                        s.QueueData( s.EventObject.OnNames( s.ServerID, c ) );
                    }
                    break;
                case "433": {
                        //:SERVER 433 * THENICK :Nickname is already in use.
                        s.QueueData( s.EventObject.OnErr_NickNameInUse( s.ServerID, spaceSplit[3] ) );
                    }
                    break;
                case "MODE": {

                        //SERVERMODE:
                        //:USERHOST MODE RECIPIENT :MODESTRING
                        if ( spaceSplit[3][0] == ':' ) {
                            IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) );
                            User u = new User( irch );
                            s.QueueData( s.EventObject.OnServerModeMessage( s.ServerID, u, spaceSplit[2], spaceSplit[3].TrimStart( ':' ) ) );
                        }
                        else {
                            //:USERMODE //TODO: HANDLE THIS
                            //:USERHOST MODE MODESTRING MODEAFFECTUSER MODEAFFECTUSER MODEAFFECTUSER
                        }

                    }
                    break;
                case "JOIN": {
                        IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) );
                        Channel c = UpdateChanDB( s, spaceSplit[2] );
                        if ( irch.Nick.Equals( s.CurrentNickName ) ) {
                            //We joined the channel.
                            s.QueueData( s.EventObject.OnBotJoin( s.ServerID, c ) );
                        }
                        else {
                            //Someone joined the channel.
                            //Update the user first.
                            UpdateUserDB( s, irch );
                            //Now update the channel.
                            ChannelUser cu = UpdateBothDB( s, spaceSplit[2], irch.Nick );
                            s.QueueData( s.EventObject.OnJoin( s.ServerID, c, cu ) );
                        }
                    }
                    break;
                case "PRIVMSG": {
                        string privmsgtxt = raw.Substring(
                        spaceSplit[0].Length + spaceSplit[1].Length + spaceSplit[2].Length + 4 );
                        //:USERHOST PRIVMSG RECIPIENT :TEXT
                        //  length    length  length + 4 (3 spaces & a :)

                        IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) );
                        User u = UpdateUserDB( s, irch );

                        //Replies to Channel/User CTCP Messages.
                        if ( spaceSplit.Length > 4 && spaceSplit[3].Length > 2 &&
                            spaceSplit[3][1] == (char)1 && raw.EndsWith( ( (char)1 ).ToString() ) ) {

                            if ( spaceSplit[2].Length >= 1 && ( spaceSplit[2][0] == '#' || spaceSplit[2][0] == '&' ) ) {
                                Channel c = UpdateChanDB( s, spaceSplit[2] );
                                ChannelUser cu = UpdateBothDB( s, spaceSplit[2], irch.Nick );
                                s.QueueData( s.EventObject.OnChannelCTCPMessage( s.ServerID, c, cu, privmsgtxt.Trim( (char)1 ) ) );
                            }
                            else
                                s.QueueData( s.EventObject.OnUserCTCPMessage( s.ServerID, spaceSplit[2], u, privmsgtxt.Trim( (char)1 ) ) );

                        }

                        //TODO: Evaluate if these can be moved up above the CTCP messages once it's converted.

                        else if ( spaceSplit[2][0] == '#' || spaceSplit[2][0] == '&' ) {
                            Channel c = UpdateChanDB( s, spaceSplit[2] );
                            ChannelUser cu = UpdateBothDB( s, spaceSplit[2], irch.Nick );
                            InvokeParsers( s, c, u, cu, privmsgtxt, IRCEvents.ParseTypes.ChannelMessage );
                            s.QueueData( s.EventObject.OnChannelMessage( s.ServerID, c, cu, privmsgtxt ) );
                        }
                        else {
                            InvokeParsers( s, null, u, null, privmsgtxt, IRCEvents.ParseTypes.PrivateMessage );
                            s.QueueData( s.EventObject.OnUserMessage( s.ServerID, spaceSplit[2], u, privmsgtxt ) );
                        }
                    }
                    break;
                case "NOTICE": {
                        // user notice
                        // :HOST NOTICE ME :MSG
                        // channel notice
                        // :HOST NOTICE CHANNEL :MSG
                        IRCHost irch;
                        string text = raw.Substring(
                        spaceSplit[0].Length + spaceSplit[1].Length + spaceSplit[2].Length + 4 );

                        try { irch = new IRCHost( spaceSplit[0].Substring( 1 ) ); }
                        catch ( FormatException ) { // looks like this is a server notice.
                            InvokeParsers( s, null, null, null, text, IRCEvents.ParseTypes.ServerNotice );
                            s.QueueData( s.EventObject.OnServerNotice( s.ServerID, text ) );
                            break;
                        }

                        User u = UpdateUserDB( s, irch );
                        if ( spaceSplit[2][0] == '#' || spaceSplit[2][0] == '&' ) {
                            Channel c = UpdateChanDB( s, spaceSplit[2] );
                            InvokeParsers( s, c, u, null, text, IRCEvents.ParseTypes.ChannelNotice );
                            s.QueueData( s.EventObject.OnChannelNotice( s.ServerID, c, u, text ) );
                        }
                        else {
                            InvokeParsers( s, null, u, null, text, IRCEvents.ParseTypes.PrivateNotice );
                            s.QueueData( s.EventObject.OnPrivateNotice( s.ServerID, u, text ) );
                        }
                    }
                    break;
                case "QUIT": {
                        //:USERHOST QUIT :MESSAGE
                        IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) );
                        User u = UpdateUserDB( s, irch );
                        //Premature call of event.
                        s.QueueData( s.EventObject.OnQuit( s.ServerID, u, raw.Substring(
                            spaceSplit[0].Length + spaceSplit[1].Length + 3 ) ) );
                        foreach ( Channel c in s.ChannelDatabase )
                            c.RemoveUser( u.Nickname );
                        s.UserDatabase.RemoveUser( u );
                    }
                    break;
                case "PART": {
                        //:USERHOST PART CHANNELNAME :MESSAGE
                        IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) );
                        if ( irch.Nick.Equals( s.CurrentNickName ) ) {
                            s.QueueData( s.EventObject.OnBotPart( s.ServerID, s.ChannelDatabase[spaceSplit[2]], spaceSplit.Length > 3 ? spaceSplit[3] : null ) );
                            s.ChannelDatabase.RemoveChannel( spaceSplit[2] );
                        }
                        else {
                            User u = UpdateUserDB( s, irch );
                            ChannelUser cu = UpdateBothDB( s, spaceSplit[2], u.Nickname );
                            //Premature call of event.
                            s.QueueData( s.EventObject.OnPart( s.ServerID, cu, s.ChannelDatabase[spaceSplit[2]], spaceSplit.Length > 3 ? spaceSplit[3] : null ) );
                            s.ChannelDatabase[spaceSplit[2]].RemoveUser( u );
                            bool stillOnAChannel = false;
                            foreach ( Channel c in s.ChannelDatabase )
                                if ( c.HasNick( u.Nickname ) )
                                    stillOnAChannel = true;
                            if ( stillOnAChannel == false )
                                s.UserDatabase.RemoveUser( u );
                        }
                    }
                    break;
                case "NICK": {
                        //:USERHOST NICK :NEWNICK
                        IRCHost irch = new IRCHost( spaceSplit[0].Substring( 1 ) );

                        string newNick = spaceSplit[2].Substring( 1 );
                        string oldNick = irch.Nick;

                        if ( oldNick == s.CurrentNickName ) { //We need to update.
                            s.CurrentNickName = newNick;
                            s.QueueData( s.EventObject.OnBotNickName( s.ServerID, newNick, oldNick ) );
                        }
                        else {
                            User oldUser = null;
                            try {
                                oldUser = s.UserDatabase[irch.Nick];//Get the old user. Remove him from the DB.
                            }
                            catch ( KeyNotFoundException ) {
                                //see below.
                            }

                            if ( oldUser == null ) {
                                //This means he wasn't in our user database.. WEIRD. Add him, add him to the db, but still
                                //broadcast it as a nick message.
                                oldUser = new User( irch );
                                s.UserDatabase.AddUser( oldUser );
                                s.UserDatabase.Authenticate( oldUser );
                            }
                            else {
                                s.UserDatabase.RemoveUser( oldUser ); //Removed him.
                                oldUser.CurrentHost.Nick = newNick; //Change his nick in the local User variable.
                                s.UserDatabase.AddUser( oldUser ); //Re-Add him to the database.
                                s.UserDatabase.Authenticate( oldUser );
                            }

                            ChannelUser cu = null;
                            foreach ( Channel c in s.ChannelDatabase ) { //Replace nick in all channels that had the old nick identifier.
                                try {
                                    cu = c[oldNick]; //Preserve his channel settings by retrieving this piece of info.
                                }
                                catch ( KeyNotFoundException ) { continue; }
                                cu.InternalUser = oldUser; //Set the new internal user. (nick matches might change authentication)
                                c.ReplaceUser( oldNick, cu ); //Replace the user in the database, remove oldNick, add the channeluser.
                            }

                            s.QueueData( s.EventObject.OnNickName( s.ServerID, oldUser, oldNick ) );
                        }
                    }
                    break;
            }
        }
Exemple #7
0
 /// <summary>
 /// Removes a host from the registered user's host list.
 /// </summary>
 /// <param name="host">The host to remove.</param>
 /// <returns>True or false.</returns>
 public bool RemoveHost(IRCHost host)
 {
     return hostList.Remove( host );
 }
Exemple #8
0
        /// <summary>
        /// Removes a host from a user.
        /// </summary>
        /// <param name="repnick">The user that initiated the command.</param>
        /// <param name="host">The host to remove.</param>
        /// <param name="user">The user to remove the host from.</param>
        public void RemoveHost(string repnick, string host, string user)
        {
            User u = null;
            UserCollection uc = (UserCollection)mp.RequestVariable( Request.UserCollection, channelMessageData.sid );

            try {
                u = uc[user];
            }
            catch ( KeyNotFoundException ) {
                BoldNickNotice( repnick, "Error(Invalid User):", " User not in active user database." );
                return;
            }

            if ( u.UserAttributes == null ) {
                BoldNickNotice( repnick, "Error(Invalid User):", " User not in user database." );
                return;
            }

            if ( u.UserAttributes.HostList.Count <= 1 ) {
                BoldNickNotice( repnick, "Error(Invalid Operation):", " User will have no hosts remaining if you remove this one. (Try " + Configuration.ModuleConfig.ModulePrefix + "rmusr." );
                return;
            }

            IRCHost irch = null;
            try {
                irch = new IRCHost( host );
            }
            catch ( FormatException ) {
                BoldNickNotice( repnick, "Error(Invalid Host):", " The host must be in the form [nick]![username]@[host] where all fields can contain wildcard characters '?' and '*'." );
                return;
            }

            if ( !u.UserAttributes.RemoveHost( irch ) ) {
                BoldNickNotice( repnick, "Error(Host not Found):", " The host specified was not found on this user." );
                return;
            }

            BoldNickNotice( repnick, "Host Removed:", " " + irch.ToString() + " from " + ( ( repnick.Equals( u.Nickname ) ) ? "your account." : u.Nickname ) );
        }
Exemple #9
0
 /// <summary>
 /// Fires the Who event.
 /// </summary>
 /// <param name="sid">The server on which the part happened.</param>
 /// <param name="c">The Channel that was who'd.</param>
 /// <param name="user">The user that was parsed out.</param>
 /// <returns>The raw data to be sent to the server.</returns>
 public string[][] OnWho(int sid, Channel c, IRCHost user)
 {
     if ( Who != null )
         return InvocationTunnel( this.Who.GetInvocationList(), sid, c, user );
     return null;
 }
Exemple #10
0
 /// <summary>
 /// Creates a User associated with a Registered User.
 /// </summary>
 /// <param name="current">The current hostname of this user.</param>
 /// <param name="ru">The associated registered user.</param>
 public User(IRCHost current, RegisteredUser ru)
 {
     this.ru = ru;
     currentHost = current;
 }
Exemple #11
0
 /// <summary>
 /// Creates a User.
 /// </summary>
 /// <param name="current">The current hostname of this user.</param>
 public User(IRCHost current)
 {
     ru = null;
     currentHost = current;
 }