ask.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package server
  2. /* This file contains dialog helpers for the client. */
  3. // import "github.com/beoran/woe/monolog"
  4. import t "github.com/beoran/woe/telnet"
  5. import "github.com/beoran/woe/telnet"
  6. import "github.com/beoran/woe/world"
  7. import "github.com/beoran/woe/monolog"
  8. import "bytes"
  9. import "regexp"
  10. // import "fmt"
  11. // import "strconv"
  12. // Switches to "password" mode.
  13. func (me * Client) PasswordMode() telnet.Event {
  14. // The server sends "IAC WILL ECHO", meaning "I, the server, will do any
  15. // echoing from now on." The client should acknowledge this with an IAC DO
  16. // ECHO, and then stop putting echoed text in the input buffer.
  17. // It should also do whatever is appropriate for password entry to the input
  18. // box thing - for example, it might * it out. Text entered in server-echoes
  19. // mode should also not be placed any command history.
  20. // don't use the Q state machne for echos
  21. me.telnet.TelnetSendBytes(t.TELNET_IAC, t.TELNET_WILL, t.TELNET_TELOPT_ECHO)
  22. tev, _, _:= me.TryReadEvent(100)
  23. if tev != nil && !telnet.IsEventType(tev, t.TELNET_DO_EVENT) {
  24. return tev
  25. }
  26. return nil
  27. }
  28. // Switches to "normal, or non-password mode.
  29. func (me * Client) NormalMode() telnet.Event {
  30. // When the server wants the client to start local echoing again, it s}s
  31. // "IAC WONT ECHO" - the client must respond to this with "IAC DONT ECHO".
  32. // Again don't use Q state machine.
  33. me.telnet.TelnetSendBytes(t.TELNET_IAC, t.TELNET_WONT, t.TELNET_TELOPT_ECHO)
  34. tev, _, _ := me.TryReadEvent(100)
  35. if tev != nil && !telnet.IsEventType(tev, t.TELNET_DONT_EVENT) {
  36. return tev
  37. }
  38. return nil
  39. }
  40. func (me * Client) Printf(format string, args ...interface{}) {
  41. me.telnet.TelnetPrintf(format, args...)
  42. }
  43. func (me * Client) ColorTest() {
  44. me.Printf("\033[1mBold\033[0m\r\n")
  45. me.Printf("\033[3mItalic\033[0m\r\n")
  46. me.Printf("\033[4mUnderline\033[0m\r\n")
  47. for fg := 30; fg < 38; fg++ {
  48. me.Printf("\033[%dmForeground Color %d\033[0m\r\n", fg, fg)
  49. me.Printf("\033[1;%dmBold Foreground Color %d\033[0m\r\n", fg, fg)
  50. }
  51. for bg := 40; bg < 48; bg++ {
  52. me.Printf("\033[%dmBackground Color %d\033[0m\r\n", bg, bg)
  53. me.Printf("\033[1;%dmBold Background Color %d\033[0m\r\n", bg, bg)
  54. }
  55. }
  56. // Blockingly reads a single command from the client
  57. func (me * Client) ReadCommand() (something []byte) {
  58. something = nil
  59. for something == nil {
  60. something, _, _ = me.TryRead(-1)
  61. if something != nil {
  62. something = bytes.TrimRight(something, "\r\n")
  63. return something
  64. }
  65. }
  66. return nil
  67. }
  68. func (me * Client) AskSomething(prompt string, re string, nomatch_prompt string, noecho bool) (something []byte) {
  69. something = nil
  70. if noecho {
  71. me.PasswordMode()
  72. }
  73. for something == nil || len(something) == 0 {
  74. me.Printf("%s:", prompt)
  75. something, _, _ = me.TryRead(-1)
  76. if something != nil {
  77. something = bytes.TrimRight(something, "\r\n")
  78. if len(re) > 0 {
  79. ok, _ := regexp.Match(re, something)
  80. if !ok {
  81. me.Printf("\n%s\n", nomatch_prompt)
  82. something = nil
  83. }
  84. }
  85. }
  86. }
  87. if noecho {
  88. me.NormalMode()
  89. me.Printf("\n")
  90. }
  91. return something
  92. }
  93. const LOGIN_RE = "^[A-Za-z][A-Za-z0-9]+$"
  94. func (me * Client) AskLogin() []byte {
  95. return me.AskSomething("Login", LOGIN_RE, "Login must consist of a letter followed by letters or numbers.", false)
  96. }
  97. const EMAIL_RE = "@"
  98. func (me * Client) AskEmail() []byte {
  99. return me.AskSomething("E-mail", EMAIL_RE, "Email must have at least an @ in there somewhere.", false)
  100. }
  101. func (me * Client) AskPassword() []byte {
  102. return me.AskSomething("Password", "", "", true)
  103. }
  104. func (me * Client) AskRepeatPassword() []byte {
  105. return me.AskSomething("Repeat Password", "", "", true)
  106. }
  107. func (me * Client) HandleCommand() {
  108. command := me.ReadCommand()
  109. me.ProcessCommand(command)
  110. /*
  111. if bytes.HasPrefix(command, []byte("/quit")) {
  112. me.Printf("Byebye!\n")
  113. me.alive = false
  114. } else if bytes.HasPrefix(command, []byte("/shutdown")) {
  115. me.server.Broadcast("Shutting down server NOW!\n")
  116. me.server.Shutdown();
  117. } else if bytes.HasPrefix(command, []byte("/restart")) {
  118. me.server.Broadcast("Restarting down server NOW!\n")
  119. me.server.Restart();
  120. } else {
  121. me.server.Broadcast("Client %d said %s\r\n", me.id, command)
  122. }
  123. */
  124. }
  125. func (me * Client) ExistingAccountDialog() bool {
  126. pass := me.AskPassword()
  127. for pass == nil {
  128. me.Printf("Password may not be empty!\n")
  129. pass = me.AskPassword()
  130. }
  131. if !me.account.Challenge(string(pass)) {
  132. me.Printf("Password not correct!\n")
  133. me.Printf("Disconnecting!\n")
  134. return false
  135. }
  136. return true
  137. }
  138. func (me * Client) NewAccountDialog(login string) bool {
  139. for me.account == nil {
  140. me.Printf("\nWelcome, %s! Creating new account...\n", login)
  141. pass1 := me.AskPassword()
  142. if pass1 == nil {
  143. return false
  144. }
  145. pass2 := me.AskRepeatPassword()
  146. if pass1 == nil {
  147. return false
  148. }
  149. if string(pass1) != string(pass2) {
  150. me.Printf("\nPasswords do not match! Please try again!\n")
  151. continue
  152. }
  153. email := me.AskEmail()
  154. if email == nil { return false }
  155. me.account = world.NewAccount(login, string(pass1), string(email), 7)
  156. err := me.account.Save(me.server.DataPath())
  157. if err != nil {
  158. monolog.Error("Could not save account %s: %v", login, err)
  159. me.Printf("\nFailed to save your account!\nPlease contact a WOE administrator!\n")
  160. return false
  161. }
  162. monolog.Info("Created new account %s", login)
  163. me.Printf("\nSaved your account.\n")
  164. return true
  165. }
  166. return false
  167. }
  168. func (me * Client) AccountDialog() bool {
  169. login := me.AskLogin()
  170. if login == nil { return false }
  171. var err error
  172. if me.server.World.GetAccount(string(login)) != nil {
  173. me.Printf("Account already logged in!\n")
  174. me.Printf("Disconnecting!\n")
  175. return false
  176. }
  177. me.account, err = me.server.World.LoadAccount(me.server.DataPath(), string(login))
  178. if err != nil {
  179. monolog.Warning("Could not load account %s: %v", login, err)
  180. }
  181. if me.account != nil {
  182. return me.ExistingAccountDialog()
  183. } else {
  184. return me.NewAccountDialog(string(login))
  185. }
  186. }
  187. func (me * Client) CharacterDialog() bool {
  188. login := me.AskLogin()
  189. if login == nil { return false }
  190. var err error
  191. me.account, err = world.LoadAccount(me.server.DataPath(), string(login))
  192. if err != nil {
  193. monolog.Warning("Could not load account %s: %v", login, err)
  194. }
  195. if me.account != nil {
  196. return me.ExistingAccountDialog()
  197. } else {
  198. return me.NewAccountDialog(string(login))
  199. }
  200. }