123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- package server
- /* This file contains dialog helpers for the client. */
- // import "github.com/beoran/woe/monolog"
- import t "github.com/beoran/woe/telnet"
- import "github.com/beoran/woe/telnet"
- import "github.com/beoran/woe/world"
- import "github.com/beoran/woe/monolog"
- import "bytes"
- import "regexp"
- // import "fmt"
- // import "strconv"
-
- // Switches to "password" mode.
- func (me * Client) PasswordMode() telnet.Event {
- // The server sends "IAC WILL ECHO", meaning "I, the server, will do any
- // echoing from now on." The client should acknowledge this with an IAC DO
- // ECHO, and then stop putting echoed text in the input buffer.
- // It should also do whatever is appropriate for password entry to the input
- // box thing - for example, it might * it out. Text entered in server-echoes
- // mode should also not be placed any command history.
- // don't use the Q state machne for echos
- me.telnet.TelnetSendBytes(t.TELNET_IAC, t.TELNET_WILL, t.TELNET_TELOPT_ECHO)
- tev, _, _:= me.TryReadEvent(100)
- if tev != nil && !telnet.IsEventType(tev, t.TELNET_DO_EVENT) {
- return tev
- }
- return nil
- }
- // Switches to "normal, or non-password mode.
- func (me * Client) NormalMode() telnet.Event {
- // When the server wants the client to start local echoing again, it s}s
- // "IAC WONT ECHO" - the client must respond to this with "IAC DONT ECHO".
- // Again don't use Q state machine.
- me.telnet.TelnetSendBytes(t.TELNET_IAC, t.TELNET_WONT, t.TELNET_TELOPT_ECHO)
- tev, _, _ := me.TryReadEvent(100)
- if tev != nil && !telnet.IsEventType(tev, t.TELNET_DONT_EVENT) {
- return tev
- }
- return nil
- }
- func (me * Client) Printf(format string, args ...interface{}) {
- me.telnet.TelnetPrintf(format, args...)
- }
- func (me * Client) ColorTest() {
- me.Printf("\033[1mBold\033[0m\r\n")
- me.Printf("\033[3mItalic\033[0m\r\n")
- me.Printf("\033[4mUnderline\033[0m\r\n")
- for fg := 30; fg < 38; fg++ {
- me.Printf("\033[%dmForeground Color %d\033[0m\r\n", fg, fg)
- me.Printf("\033[1;%dmBold Foreground Color %d\033[0m\r\n", fg, fg)
- }
-
- for bg := 40; bg < 48; bg++ {
- me.Printf("\033[%dmBackground Color %d\033[0m\r\n", bg, bg)
- me.Printf("\033[1;%dmBold Background Color %d\033[0m\r\n", bg, bg)
- }
- }
- // Blockingly reads a single command from the client
- func (me * Client) ReadCommand() (something []byte) {
- something = nil
- for something == nil {
- something, _, _ = me.TryRead(-1)
- if something != nil {
- something = bytes.TrimRight(something, "\r\n")
- return something
- }
- }
- return nil
- }
- func (me * Client) AskSomething(prompt string, re string, nomatch_prompt string, noecho bool) (something []byte) {
- something = nil
-
- if noecho {
- me.PasswordMode()
- }
- for something == nil || len(something) == 0 {
- me.Printf("%s:", prompt)
- something, _, _ = me.TryRead(-1)
- if something != nil {
- something = bytes.TrimRight(something, "\r\n")
- if len(re) > 0 {
- ok, _ := regexp.Match(re, something)
- if !ok {
- me.Printf("\n%s\n", nomatch_prompt)
- something = nil
- }
- }
- }
- }
-
- if noecho {
- me.NormalMode()
- me.Printf("\n")
- }
-
- return something
- }
-
- const LOGIN_RE = "^[A-Za-z][A-Za-z0-9]+$"
- func (me * Client) AskLogin() []byte {
- return me.AskSomething("Login", LOGIN_RE, "Login must consist of a letter followed by letters or numbers.", false)
- }
- const EMAIL_RE = "@"
- func (me * Client) AskEmail() []byte {
- return me.AskSomething("E-mail", EMAIL_RE, "Email must have at least an @ in there somewhere.", false)
- }
- func (me * Client) AskPassword() []byte {
- return me.AskSomething("Password", "", "", true)
- }
- func (me * Client) AskRepeatPassword() []byte {
- return me.AskSomething("Repeat Password", "", "", true)
- }
- func (me * Client) HandleCommand() {
- command := me.ReadCommand()
- if bytes.HasPrefix(command, []byte("/quit")) {
- me.Printf("Byebye!\n")
- me.alive = false
- } else if bytes.HasPrefix(command, []byte("/shutdown")) {
- me.server.Broadcast("Shutting down server NOW!\n")
- me.server.Shutdown();
- } else if bytes.HasPrefix(command, []byte("/restart")) {
- me.server.Broadcast("Restarting down server NOW!\n")
- me.server.Restart();
- } else {
- me.server.Broadcast("Client %d said %s\r\n", me.id, command)
- }
- }
-
- func (me * Client) ExistingAccountDialog() bool {
- pass := me.AskPassword()
- for pass == nil {
- me.Printf("Password may not be empty!\n")
- pass = me.AskPassword()
- }
-
- if !me.account.Challenge(string(pass)) {
- me.Printf("Password not correct!\n")
- me.Printf("Disconnecting!\n")
- return false
- }
- return true
- }
- func (me * Client) NewAccountDialog(login string) bool {
- for me.account == nil {
- me.Printf("\nWelcome, %s! Creating new account...\n", login)
- pass1 := me.AskPassword()
-
- if pass1 == nil {
- return false
- }
-
- pass2 := me.AskRepeatPassword()
-
- if pass1 == nil {
- return false
- }
-
- if string(pass1) != string(pass2) {
- me.Printf("\nPasswords do not match! Please try again!\n")
- continue
- }
-
- email := me.AskEmail()
- if email == nil { return false }
-
- me.account = world.NewAccount(login, string(pass1), string(email), 7)
- err := me.account.Save(me.server.DataPath())
-
- if err != nil {
- monolog.Error("Could not save account %s: %v", login, err)
- me.Printf("\nFailed to save your account!\nPlease contact a WOE administrator!\n")
- return false
- }
-
- monolog.Info("Created new account %s", login)
- me.Printf("\nSaved your account.\n")
- return true
- }
- return false
- }
-
- func (me * Client) AccountDialog() bool {
- login := me.AskLogin()
- if login == nil { return false }
- var err error
-
- if me.server.World.GetAccount(string(login)) != nil {
- me.Printf("Account already logged in!\n")
- me.Printf("Disconnecting!\n")
- return false
- }
-
- me.account, err = me.server.World.LoadAccount(me.server.DataPath(), string(login))
- if err != nil {
- monolog.Warning("Could not load account %s: %v", login, err)
- }
- if me.account != nil {
- return me.ExistingAccountDialog()
- } else {
- return me.NewAccountDialog(string(login))
- }
- }
-
- func (me * Client) CharacterDialog() bool {
- login := me.AskLogin()
- if login == nil { return false }
- var err error
- me.account, err = world.LoadAccount(me.server.DataPath(), string(login))
- if err != nil {
- monolog.Warning("Could not load account %s: %v", login, err)
- }
- if me.account != nil {
- return me.ExistingAccountDialog()
- } else {
- return me.NewAccountDialog(string(login))
- }
- }
|