Exemple #1
0
        public bool DispatchCommand(CommandContext ctx)
        {
            string channelName = ctx.Args.ElementAtOrDefault(1);

            // no error, apparently
            if (string.IsNullOrWhiteSpace(channelName))
            {
                return(false);
            }

            Channels.GetChannelByName(channelName, channel => {
                // the original server sends ForceChannel before sending the error message, but this order probably makes more sense.
                // NEW: REVERT THIS ^^^^ WHEN CONVERTING BACK TO NOT EXCEPTIONS
                // EXCEPTIONS ARE HEAVY, DON'T USE THEM FOR USER ERRORS YOU IDIOT

                if (channel == null)
                {
                    Sessions.SwitchChannel(ctx.Session);
                    throw new ChannelNotFoundCommandException(channelName);
                }

                ChannelUsers.HasUser(channel, ctx.User, hasUser => {
                    if (hasUser)
                    {
                        Sessions.SwitchChannel(ctx.Session);
                        throw new AlreadyInChannelCommandException(channel);
                    }

                    string password = string.Join(' ', ctx.Args.Skip(2));

                    if (!ctx.User.Can(UserPermissions.JoinAnyChannel) && channel.OwnerId != ctx.User.UserId)
                    {
                        if (channel.MinimumRank > ctx.User.Rank)
                        {
                            Sessions.SwitchChannel(ctx.Session);
                            throw new ChannelRankCommandException(channel);
                        }

                        // add capacity check

                        Channels.VerifyPassword(channel, password, success => {
                            if (!success)
                            {
                                Sessions.SwitchChannel(ctx.Session);
                                throw new ChannelPasswordCommandException(channel);
                            }

                            ChannelUsers.JoinChannel(channel, ctx.Session);
                        });
                    }
                    else
                    {
                        ChannelUsers.JoinChannel(channel, ctx.Session);
                    }
                });
            });

            return(true);
        }
Exemple #2
0
        public bool DispatchCommand(CommandContext ctx)
        {
            if (!ctx.User.Can(UserPermissions.CreateChannel))
            {
                throw new CommandNotAllowedException(NAME);
            }

            bool hasRank;

            if (ctx.Args.Count() < 2 || (hasRank = ctx.Args.ElementAtOrDefault(1)?.All(char.IsDigit) == true && ctx.Args.Count() < 3))
            {
                throw new CommandFormatException();
            }

            int rank = 0;

            if (hasRank && !int.TryParse(ctx.Args.ElementAtOrDefault(1), out rank) && rank < 0)
            {
                rank = 0;
            }

            if (rank > ctx.User.Rank)
            {
                throw new InsufficientRankForChangeCommandException();
            }

            string   createChanName = string.Join('_', ctx.Args.Skip(hasRank ? 2 : 1));
            IChannel createChan;

            try {
                createChan = Channels.Create(
                    ctx.User,
                    createChanName,
                    null,
                    !ctx.User.Can(UserPermissions.SetChannelPermanent),
                    rank
                    );
            } catch (ChannelExistException) {
                throw new ChannelExistsCommandException(createChanName);
            } catch (ChannelInvalidNameException) {
                throw new ChannelNameInvalidCommandException();
            }

            ChannelUsers.JoinChannel(createChan, ctx.Session);

            ctx.Connection.SendPacket(new ChannelCreateResponsePacket(Sender, createChan));
            return(true);
        }
Exemple #3
0
        public bool DispatchCommand(ICommandContext ctx)
        {
            string channelName = ctx.Args.ElementAtOrDefault(1);

            // no error, apparently
            if (string.IsNullOrWhiteSpace(channelName))
            {
                return(false);
            }

            IChannel channel = Channels.GetChannel(channelName);

            // the original server sends ForceChannel before sending the error message, but this order probably makes more sense.

            if (channel == null)
            {
                Sessions.SwitchChannel(ctx.Session);
                throw new ChannelNotFoundCommandException(channelName);
            }

            if (ChannelUsers.HasUser(channel, ctx.User))
            {
                Sessions.SwitchChannel(ctx.Session);
                throw new AlreadyInChannelCommandException(channel);
            }

            string password = string.Join(' ', ctx.Args.Skip(2));

            if (!ctx.User.Can(UserPermissions.JoinAnyChannel) && channel.Owner != ctx.User)
            {
                if (channel.MinimumRank > ctx.User.Rank)
                {
                    Sessions.SwitchChannel(ctx.Session);
                    throw new ChannelRankCommandException(channel);
                }

                if (channel.VerifyPassword(password))
                {
                    Sessions.SwitchChannel(ctx.Session);
                    throw new ChannelPasswordCommandException(channel);
                }
            }

            ChannelUsers.JoinChannel(channel, ctx.Session);
            return(true);
        }
Exemple #4
0
        public void HandlePacket(PacketHandlerContext ctx)
        {
            if (ctx.HasSession)
            {
                return;
            }

            if (!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || userId < 1)
            {
                return;
            }

            string token = ctx.Args.ElementAtOrDefault(2);

            if (string.IsNullOrEmpty(token))
            {
                return;
            }

            Action <Exception> exceptionHandler = new Action <Exception>(ex => {
                Logger.Debug($@"[{ctx.Connection}] Auth fail: {ex.Message}");
                ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.AuthInvalid));
                ctx.Connection.Close();
            });

            DataProvider.UserAuthClient.AttemptAuth(
                new UserAuthRequest(userId, token, ctx.Connection.RemoteAddress),
                res => {
                DataProvider.BanClient.CheckBan(res.UserId, ctx.Connection.RemoteAddress, ban => {
                    if (ban.IsPermanent || ban.Expires > DateTimeOffset.Now)
                    {
                        ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.Banned, ban));
                        ctx.Connection.Close();
                        return;
                    }

                    Users.Connect(res, user => {
                        Sessions.HasAvailableSessions(user, available => {
                            if (!available)
                            {
                                ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.MaxSessions));
                                ctx.Connection.Close();
                                return;
                            }

                            Sessions.Create(ctx.Connection, user, session => {
                                string welcome = Server.WelcomeMessage;
                                if (!string.IsNullOrWhiteSpace(welcome))
                                {
                                    ctx.Connection.SendPacket(new WelcomeMessagePacket(Sender, welcome.Replace(@"{username}", user.UserName)));
                                }

                                if (WelcomeMessage.HasRandom)
                                {
                                    string line = WelcomeMessage.GetRandomString();
                                    if (!string.IsNullOrWhiteSpace(line))
                                    {
                                        ctx.Connection.SendPacket(new WelcomeMessagePacket(Sender, line));
                                    }
                                }

                                Channels.GetDefaultChannels(channels => {
                                    if (!channels.Any())
                                    {
                                        return;     // what do, this is impossible
                                    }
                                    // other channels should be joined if MCHAN has been received
                                    IChannel firstChan = channels.FirstOrDefault();

                                    ctx.Connection.LastChannel = firstChan;
                                    ctx.Connection.SendPacket(new AuthSuccessPacket(user, firstChan, session, Messages.TextMaxLength));

                                    Channels.GetChannels(user.Rank, c => ctx.Connection.SendPacket(new ContextChannelsPacket(c)));
                                    ChannelUsers.JoinChannel(firstChan, ctx.Session);
                                });
                            });
                        });
                    });
                }, exceptionHandler);
            },
                exceptionHandler
                );
        }
Exemple #5
0
        public void HandlePacket(IPacketHandlerContext ctx)
        {
            if (ctx.HasSession)
            {
                return;
            }

            if (!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || userId < 1)
            {
                return;
            }

            string token = ctx.Args.ElementAtOrDefault(2);

            if (string.IsNullOrEmpty(token))
            {
                return;
            }

            Action <Exception> exceptionHandler = new Action <Exception>(ex => {
                Logger.Debug($@"<{ctx.Connection.RemoteAddress}> Auth fail: {ex.Message}");
                ctx.Connection.Send(new AuthFailPacket(AuthFailReason.AuthInvalid));
                ctx.Connection.Close();
            });

            DataProvider.UserAuthClient.AttemptAuth(
                new UserAuthRequest(userId, token, ctx.Connection.RemoteAddress),
                res => {
                DataProvider.BanClient.CheckBan(res.UserId, ctx.Connection.RemoteAddress, ban => {
                    if (ban.IsPermanent || ban.Expires > DateTimeOffset.Now)
                    {
                        ctx.Connection.Send(new AuthFailPacket(AuthFailReason.Banned, ban));
                        ctx.Connection.Close();
                        return;
                    }

                    IUser user = Users.Connect(res);

                    // Enforce a maximum amount of connections per user
                    if (Sessions.GetAvailableSessionCount(user) < 1)
                    {
                        ctx.Connection.Send(new AuthFailPacket(AuthFailReason.MaxSessions));
                        ctx.Connection.Close();
                        return;
                    }

                    ISession sess = Sessions.Create(ctx.Connection, user);

                    sess.SendPacket(new WelcomeMessagePacket(Sender, $@"Welcome to Flashii Chat, {user.UserName}!"));

                    if (File.Exists(WELCOME))
                    {
                        IEnumerable <string> lines = File.ReadAllLines(WELCOME).Where(x => !string.IsNullOrWhiteSpace(x));
                        string line = lines.ElementAtOrDefault(RNG.Next(lines.Count()));

                        if (!string.IsNullOrWhiteSpace(line))
                        {
                            sess.SendPacket(new WelcomeMessagePacket(Sender, line));
                        }
                    }

                    IChannel chan   = Channels.DefaultChannel;
                    bool shouldJoin = !ChannelUsers.HasUser(chan, user);

                    if (shouldJoin)
                    {
                        // ChannelUsers?
                        //chan.SendPacket(new UserConnectPacket(DateTimeOffset.Now, user));
                        //ctx.Chat.DispatchEvent(this, new UserConnectEvent(chan, user));
                    }

                    sess.SendPacket(new AuthSuccessPacket(user, chan, sess, Version, Messages.TextMaxLength));
                    ChannelUsers.GetUsers(chan, u => sess.SendPacket(new ContextUsersPacket(u.Except(new[] { user }).OrderByDescending(u => u.Rank))));

                    Messages.GetMessages(chan, m => {
                        foreach (IMessage msg in m)
                        {
                            sess.SendPacket(new ContextMessagePacket(msg));
                        }
                    });

                    Channels.GetChannels(user.Rank, c => sess.SendPacket(new ContextChannelsPacket(c)));

                    if (shouldJoin)
                    {
                        ChannelUsers.JoinChannel(chan, sess);
                    }
                }, exceptionHandler);
            },
                exceptionHandler
                );
        }
Exemple #6
0
        public void HandleCommand(ClientCommandContext ctx)
        {
            if (ctx.Connection.HasAuthenticated)
            {
                ctx.Connection.SendReply(new AlreadyRegisteredReply());
                return;
            }

            // just drop subsequent calls
            if (ctx.Connection.IsAuthenticating)
            {
                return;
            }
            ctx.Connection.IsAuthenticating = true;

            string userName = ctx.Arguments.ElementAtOrDefault(0);
            string modeStr  = ctx.Arguments.ElementAtOrDefault(1);

            //string param3 = ctx.Arguments.ElementAtOrDefault(2);
            //string realName = ctx.Arguments.ElementAtOrDefault(3);

            if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(modeStr))
            {
                ctx.Connection.SendReply(new NeedMoreParamsReply(NAME));
                return;
            }

            // TODO: should accept normal text username in the future!!!!
            if (!long.TryParse(userName, out long userId))
            {
                ctx.Connection.SendReply(new PasswordMismatchReply());
                ctx.Connection.Close();
                return;
            }

            if (!int.TryParse(modeStr, out int mode))
            {
                mode = 0;
            }

            bool isInvisible    = (mode & MODE_I) > 0;
            bool receiveWallOps = (mode & MODE_W) > 0;

            Action <Exception> exceptionHandler = new Action <Exception>(ex => {
                Logger.Debug($@"[{ctx.Connection}] Auth fail: {ex.Message}");
                ctx.Connection.SendReply(new PasswordMismatchReply());
                ctx.Connection.Close();
            });

            DataProvider.UserAuthClient.AttemptAuth(
                new UserAuthRequest(userId, ctx.Connection.Password, ctx.Connection.RemoteAddress),
                res => {
                ctx.Connection.Password         = null;
                ctx.Connection.HasAuthenticated = true;

                DataProvider.BanClient.CheckBan(res.UserId, ctx.Connection.RemoteAddress, ban => {
                    if (ban.IsPermanent || ban.Expires > DateTimeOffset.Now)
                    {
                        // should probably include the time

                        ctx.Connection.SendReply(new YouAreBannedReply(@"You have been banned."));
                        ctx.Connection.Close();
                        return;
                    }

                    Users.Connect(res, user => {
                        Sessions.HasAvailableSessions(user, available => {
                            // Enforce a maximum amount of connections per user
                            if (!available)
                            {
                                // map somethign to this
                                //ctx.Connection.SendPacket(new AuthFailPacket(AuthFailReason.MaxSessions));
                                ctx.Connection.Close();
                                return;
                            }

                            Sessions.Create(ctx.Connection, user, session => {
                                ctx.Connection.SendReply(new WelcomeReply(Server, user));
                                ctx.Connection.SendReply(new YourHostReply(Server));
                                ctx.Connection.SendReply(new CreatedReply(Context));
                                ctx.Connection.SendReply(new MyInfoReply(Server));
                                ctx.Connection.SendReply(new ISupportReply(Server));

                                if (WelcomeMessage.HasRandom)
                                {
                                    ctx.Connection.SendReply(new MotdStartReply());

                                    string line = WelcomeMessage.GetRandomString();
                                    if (!string.IsNullOrWhiteSpace(line))
                                    {
                                        ctx.Connection.SendReply(new MotdReply(line));
                                    }

                                    ctx.Connection.SendReply(new MotdEndReply());
                                }
                                else
                                {
                                    ctx.Connection.SendReply(new NoMotdReply());
                                }

                                // are these necessary?
                                ctx.Connection.SendReply(new ListUserClientReply());
                                ctx.Connection.SendReply(new ListUserOperatorsReply());
                                ctx.Connection.SendReply(new ListUserUnknownReply());
                                ctx.Connection.SendReply(new ListUserChannelsReply());
                                ctx.Connection.SendReply(new ListUserMeReply());

                                Channels.GetDefaultChannels(channels => {
                                    foreach (IChannel channel in channels)
                                    {
                                        ChannelUsers.JoinChannel(channel, session);
                                    }
                                });
                            });
                        });
                    });
                }, exceptionHandler);
            },
                exceptionHandler
                );
        }