Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace MUD.Lib.Daemons
- {
- /// <summary>
- /// Handles the details of logging in and out. Yes, I'm playing enums-as-state-machines here. Leave me alone.
- /// </summary>
- internal class Login : VerbProcessor
- {
- private enum LoginState
- {
- Name,
- NameExistsPass,
- NameConfirm,
- NewPassword1,
- NewPassword2,
- Email,
- CharacterSequence
- }
- private delegate bool LoginStateHandler(User user, string input);
- private Dictionary<LoginState, LoginStateHandler> LoginStateMachine;
- private User.ReceiveHandler Listener;
- private LoginState _currentState = LoginState.Name;
- private int InvalidLoginTries = 0;
- public Login(User user)
- {
- LoginStateMachine = new Dictionary<LoginState, LoginStateHandler>();
- Listener = new User.ReceiveHandler(ReceiveInput);
- user.OnExclusiveReceive += Listener;
- InitializeSteps();
- }
- private void InitializeSteps()
- {
- LoginStateMachine.Add(LoginState.Name, new LoginStateHandler(ProcessName));
- LoginStateMachine.Add(LoginState.NameExistsPass, new LoginStateHandler(ValidatePassword));
- LoginStateMachine.Add(LoginState.NameConfirm, new LoginStateHandler(NameConfirm));
- LoginStateMachine.Add(LoginState.NewPassword1, new LoginStateHandler(NewPassword1));
- LoginStateMachine.Add(LoginState.NewPassword2, new LoginStateHandler(NewPassword2));
- LoginStateMachine.Add(LoginState.Email, new LoginStateHandler(EmailHandler));
- LoginStateMachine.Add(LoginState.CharacterSequence, new LoginStateHandler(ToCharacterSequence));
- }
- private bool ReceiveInput(User user, string command)
- {
- if (LoginStateMachine.Keys.Contains(_currentState))
- return LoginStateMachine[_currentState](user, command.TrimNewline());
- else
- return false;
- }
- // First thing we're going to see from the user.
- private bool ProcessName(User user, string input)
- {
- user.Username = input;
- // attempt to load the user;
- user.Load();
- if (!string.IsNullOrEmpty(user.Password))
- {
- // ok, there is a user by this name.
- _currentState = LoginState.NameExistsPass;
- user.Write("Welcome back, " + user.Username + "! Please enter your password:\r\n");
- }
- else
- {
- // this is a new user.
- _currentState = LoginState.NameConfirm;
- user.Write("Are you sure this is the account name you wish to use? (y/n)\r\n");
- }
- return true;
- }
- private bool ValidatePassword(User user, string input)
- {
- MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
- if (user.Password == BitConverter.ToString(md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(input))))
- {
- // password valid, continue to character selection
- // TODO: Move to character creation/selection
- _currentState = LoginState.CharacterSequence;
- ToCharacterSequence(user, "y");
- }
- else
- {
- // password invalid, ask them to try again.
- InvalidLoginTries++;
- if (InvalidLoginTries < 3)
- {
- user.Write("Password invalid, please try again:\r\n ");
- return false;
- }
- else
- {
- user.Write("Maximum login attempts reached, disconnecting.\r\n");
- user.OnExclusiveReceive -= Listener;
- user.Disconnect();
- }
- }
- return true;
- }
- private bool NameConfirm(User user, string input)
- {
- if (input.ToLower() == "y")
- {
- // they want this name, move on.
- user.Write("Great! Please enter a password.\r\n");
- _currentState = LoginState.NewPassword1;
- }
- else
- {
- user.Write("Ok, what name would you like to use?\r\n");
- _currentState = LoginState.Name;
- }
- return true;
- }
- private bool NewPassword1(User user, string input)
- {
- MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
- user.Password = BitConverter.ToString(md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(input)));
- _currentState = LoginState.NewPassword2;
- user.Write("Please reenter your password:\r\n");
- return true;
- }
- private bool NewPassword2(User user, string input)
- {
- MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
- if (BitConverter.ToString(md5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(input))) == user.Password)
- {
- // Password accepted, move on.
- _currentState = LoginState.Email;
- user.Write("Please enter a valid email address.\r\n");
- }
- else
- {
- // Passwords don't match, reenter.
- _currentState = LoginState.NewPassword1;
- user.Write("Passwords do not match, please choose a password:\r\n");
- }
- return true;
- }
- private bool EmailHandler(User user, string input)
- {
- if (IsEmailValid(input))
- {
- // store it and move on to character selection/creation!
- user.Email = input;
- user.Write("Ok, your new account with username " + user.Username + " and email address: " + user.Email + " is created. Please verify these details before continuing. (y/n)\r\n Warning: entering 'n' will cause the creation process to restart!\r\n");
- _currentState = LoginState.CharacterSequence;
- }
- else
- {
- // oops, need to reenter.
- user.Write("Email invalid, please enter a valid email address.");
- }
- return true;
- }
- private bool ToCharacterSequence(User user, string input)
- {
- if (input.ToLower() == "y")
- {
- // TODO: load character select/creation sequence
- user.OnExclusiveReceive -= Listener;
- user.Save();
- user.Write("Welcome to MUD.Net!!\r\n");
- }
- else
- {
- user.Write("Ok, starting over. Please enter desired username.\r\n");
- _currentState = LoginState.Name;
- }
- return true;
- }
- private bool IsEmailValid(string email)
- {
- if (string.IsNullOrEmpty(email))
- return false;
- // is there more than one "@"?
- int First = email.IndexOf('@');
- int Last = email.IndexOf('@');
- if (First != Last && First < email.Length - 1)
- return false;
- return true;
- }
- // TODO: Should I assign a single Login instance to every user for the duration of their login sequence or handle it via daemon?
- // TODO: Also, should I handle all character creation here as well?
- // enum++ and -- work just fine, btw.
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement