123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- '''
- account_handler.py
- The login and creation of accounts, and handles all account procedures, loading
- and deleting, of characters.
- '''
- import mud, mudsys, char, hooks, account, socket, event, telnetlib, utils
- # control sequences for squelching passwords
- squelch = telnetlib.IAC + telnetlib.WILL + telnetlib.ECHO
- unsquelch = telnetlib.IAC + telnetlib.WONT + telnetlib.ECHO
- def check_acct_name(name):
- '''Makes sure an account name is valid'''
- return (len(name) > 3 and len(name) < 13 and
- name[0].isalpha() and name.isalnum())
- def login_method_prompt(sock):
- sock.send_raw("Choose an option: ")
- def acct_new_password_prompt(sock):
- sock.send_raw("\r\nWhat is your new password? " + squelch)
- def acct_password_prompt(sock):
- sock.send_raw("What is your password? " + squelch)
- def acct_wait_dns_prompt(sock):
- sock.send_raw(" Resolving your internet address, please have patience... ")
- def try_create_account(sock, name, psswd):
- if mudsys.account_exists(name):
- return False
- elif mudsys.account_creating(name):
- return False
- elif not check_acct_name(name):
- return False
- else:
- # creating a new account
- mud.log_string("Account '" + name + "' is trying to create.")
- # create our new account
- acct = mudsys.create_account(name)
- if acct == None:
- return False
- else:
- mudsys.attach_account_socket(acct, sock)
- mudsys.set_password(acct, psswd)
- sock.pop_ih()
- sock.push_ih(acct_menu_handler, acct_main_menu)
- #sock.push_ih(acct_finish_handler, acct_finish_prompt)
- # log that the account created
- mud.log_string("New account '" + acct.name + "' has created.")
- # register and save the account to disk
- mudsys.do_register(acct)
- return True
- return False
- def try_load_account(sock, name, psswd):
- '''Attempt to load an account with the given name and password.'''
- if not mudsys.account_exists(name):
- return False
- else:
- acct = mudsys.load_account(name)
- if not mudsys.password_matches(acct, psswd):
- return False
- # successful load
- mudsys.attach_account_socket(acct, sock)
- sock.pop_ih()
- sock.push_ih(acct_menu_handler, acct_main_menu)
- return True
- return False
- def login_method_handler(sock, arg):
- args = arg.split()
- if len(args) == 0:
- return
- args[0] = args[0].lower()
- if "create".startswith(args[0]):
- if len(args) != 3:
- return
- elif mudsys.account_exists(args[1]):
- sock.send("{cAn account by that name already exists.{n\r\n")
- elif not check_acct_name(args[1]):
- txt = "{cThat is an invalid account name. Your account name must "\
- "only consist of characters and numbers, and it must be " \
- "4 and 12 characters in length. The first character MUST be "\
- "a letter. Please pick another.{n"
- sock.send(mud.format_string(txt, False))
- elif not try_create_account(sock, args[1], args[2]):
- sock.send("Your account was unable to be created.")
- elif "load".startswith(args[0]):
- if len(args) != 3:
- return
- elif not try_load_account(sock, args[1], args[2]):
- sock.send("{cInvalid account name or password.{n\r\n")
- elif "guest".startswith(args[0]):
- if (mudsys.sys_getval("lockdown") != '' and
- not utils.is_keyword(mudsys.sys_getval("lockdown"), "player")):
- sock.send("{cThe mud is currently locked out to new players.{n\r\n")
- else:
- sock.pop_ih()
- hooks.run("create_guest", hooks.build_info("sk", (sock,)))
- def acct_wait_dns_handler(sock, arg):
- # do nothing
- return
- def acct_new_password_handler(sock, arg):
- '''asks a new account for a password'''
- sock.send_raw(unsquelch)
- if len(arg) > 0:
- # put in mudsys to prevent scripts from messing with passwords
- mudsys.set_password(sock.account, arg)
- sock.pop_ih()
- def acct_password_handler(sock, arg):
- '''asks an account to verify its password'''
- # password functions put in mudsys to prevent scripts from
- # messing with passwords
- sock.send_raw(unsquelch)
- if not mudsys.password_matches(sock.account, arg):
- sock.send("Incorrect password.")
- sock.close()
- else:
- # password matches, pop our handler and go down a level
- sock.pop_ih()
- def find_reconnect(name):
- '''searches through the character list for a PC whose name matches the
- supplied name'''
- name = name.lower()
- for ch in char.char_list():
- if ch.is_pc and name == ch.name.lower():
- return ch
- return None
- def acct_load_char(sock, name):
- '''loads a character attached to the account. Argument supplied must be a
- name of the corresponding character'''
- chars = sock.account.characters()
-
- if not name.lower() in [n.lower() for n in sock.account.characters()]:
- sock.send("A character by that name does not exist on your account.")
- else:
- # first, try a reconnect
- ch = find_reconnect(name)
- # no reconnect? Try loading our character
- if not ch == None:
- # swap the sockets
- old_sock = ch.sock
- # attach and detach put in mudsys to prevent scripts from
- # messing around with the connections between chars and sockets
- mudsys.detach_char_socket(ch)
- mudsys.attach_char_socket(ch, sock)
-
- if old_sock != None:
- old_sock.close()
- mud.log_string(ch.name + " has reconnected.")
- # ch.act("clear")
- ch.send("You take over a body already in use.")
- ch.act("look")
- hooks.run("reconnect", hooks.build_info("ch", (ch,)))
- sock.push_ih(mudsys.handle_cmd_input, mudsys.show_prompt, "playing")
- else:
- # load our character. Put in mudsys to prevent scripts from using it
- ch = mudsys.load_char(name)
- if ch == None:
- sock.send("The player file for " + name + " is missing.")
- elif (mudsys.sys_getval("lockdown") != '' and
- not ch.isInGroup(mudsys.sys_getval("lockdown"))):
- sock.send("You are currently locked out of the mud.")
- mud.extract(ch)
- else:
- # attach put in mudsys to prevent scripts from messing with
- # character and socket links
- mudsys.attach_char_socket(ch, sock)
- if mudsys.try_enter_game(ch):
- mud.log_string(ch.name + " has entered the game.")
- sock.push_ih(mudsys.handle_cmd_input, mudsys.show_prompt,
- "playing")
- # ch.act("clear")
- ch.page(mud.get_motd())
- ch.act("look")
- hooks.run("enter", hooks.build_info("ch rm", (ch, ch.room)))
- else:
- sock.send("There was a problem entering the game. " + \
- "try again later.")
- # detach put in mudsys t prevent scripts from messing with
- # character and socket links
- mudsys.detach_char_socket(ch, sock)
- mud.extract(ch)
- def acct_menu_handler(sock, arg):
- '''parses account commands (new character, enter game, quit, etc)'''
- if len(arg) == 0:
- return
- args = arg.split()
- args[0] = args[0].upper()
-
- if args[0].isdigit():
- opts = sock.account.characters()
- arg = int(args[0])
- if arg < 0 or arg >= len(opts):
- sock.send("Invalid choice!")
- else:
- acct_load_char(sock, opts[arg])
- elif args[0] == 'L':
- if len(args) == 1:
- sock.send("Which character would you like to load?")
- else:
- acct_load_char(sock, args[1])
- elif args[0] == 'Q' or "QUIT".startswith(args[0]):
- sock.send("Come back soon!")
- mudsys.do_save(sock.account)
- sock.close()
- elif args[0] == 'P':
- # sock.push_ih(acct_confirm_password_handler,acct_confirm_password_prompt)
- sock.push_ih(acct_new_password_handler, acct_new_password_prompt)
- sock.push_ih(acct_password_handler, acct_password_prompt)
- elif args[0] == 'N':
- if "player" in [x.strip() for x in mudsys.sys_getval("lockdown").split(",")]:
- sock.send("New characters are not allowed to be created at this time.")
- else:
- hooks.run("create_character", hooks.build_info("sk", (sock,)))
- else:
- sock.send("Invalid choice!")
- def display_acct_chars(sock):
- '''shows the socket a prettied list of characters tied to the account it
- has attached. Prints three names per line.'''
- num_cols = 3
- print_room = (80 - 10*num_cols)/num_cols
- fmt = " {c%2d{n) %-" + str(print_room) + "s"
- sock.send("{w\r\nPlay a Character:")
- i = 0
- for ch in sock.account.characters():
- sock.send_raw(fmt % (i, ch))
- if i % num_cols == num_cols - 1:
- sock.send_raw("\r\n")
- i = i + 1
- if not i % num_cols == 0:
- sock.send_raw("\r\n")
- def acct_main_menu(sock):
- '''displays the main menu for the account and asks for a command'''
- line_buf = "%-38s" % " "
- # make the account menu look pretty
- img = ["+--------------------------------------+",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| I M A G E |",
- "| H E R E |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "| |",
- "+--------------------------------------+"]
- # the lines for displaying our account options
- opts = [ ]
- chars = sock.account.characters()
- chars.sort()
- if len(chars) > 0:
- opts.append(" {wPlay A Character: ")
- for i in range(len(chars)):
- opts.append(" {n[{c%1d{n] %-30s" % (i,chars[i]))
- opts.append(line_buf)
- # append our other displays
- opts.append(" {wAccount Management: ")
- opts.append(" {n[{cP{n]assword change ")
- opts.append(" {n[{cN{n]ew character ")
- opts.append(" {n[{cL{n]oad character <name> ")
- opts.append(line_buf)
- opts.append(line_buf)
- opts.append(line_buf)
- # fill up our height to be in line with the image
- while len(opts) < len(img) - 2:
- opts.insert(0, line_buf)
- # append our title
- opts.insert(1, " {nW E L C O M E T O ")
- opts.insert(2, " {nN A K E D M U D ")
-
- # display all of our info
- sock.send("")
- for i in range(max(len(opts), len(img))):
- if i < len(opts):
- sock.send_raw(opts[i])
- else:
- sock.send_raw(line_buf)
- if i < len(img):
- sock.send_raw("{n%s" % img[i])
- sock.send("")
-
- sock.send_raw("{nEnter choice, or Q to quit: ")
- ################################################################################
- # events for blocking action when dns lookup is in progress
- ################################################################################
- def dns_check_event(owner, void, info):
- '''After a socket connects, monitor their hostname until dns lookup is
- complete. Then, put the socket into the account handler.
- '''
- sock, = hooks.parse_info(info)
- if sock != None and sock.can_use:
- sock.send(" Lookup complete.")
- sock.send("================================================================================")
- sock.send(mud.get_greeting())
- sock.pop_ih()
- sock.bust_prompt()
- # mud.log_string("new connection from " + sock.hostname)
- else:
- event.start_event(None, 0.2, dns_check_event, None, info)
- ################################################################################
- # account handler hooks
- ################################################################################
- def account_handler_hook(info):
- '''When a socket connects, put them into the account handler menu.'''
- # put a nonfunctional prompt up while waiting for the DNS to resolve
- sock, = hooks.parse_info(info)
- sock.push_ih(login_method_handler, login_method_prompt)
- mud.log_string("new socket, %d, attempting to connect" % sock.uid)
- sock.send(mud.get_greeting())
- sock.send("== Options Are ================================================================")
- sock.send(" Load account : load <account> <password>")
- sock.send(" Create account : create <account> <password>")
- sock.send(" Play as guest : guest")
- sock.send("===============================================================================")
- sock.send("")
- '''
- sock.push_ih(acct_wait_dns_handler, acct_wait_dns_prompt)
- sock.send("================================================================================")
- event.start_event(None, 0.2, dns_check_event, None, info)
- '''
- def copyover_complete_hook(info):
- sock, = hooks.parse_info(info)
- sock.push_ih(acct_menu_handler, acct_main_menu)
- sock.push_ih(mudsys.handle_cmd_input, mudsys.show_prompt, "playing")
- ################################################################################
- # loading and unloading the module
- ################################################################################
- hooks.add("receive_connection", account_handler_hook)
- hooks.add("copyover_complete", copyover_complete_hook)
- def __unload__():
- '''removes the hooks for account handling'''
- hooks.remove("receive_connection", account_handler_hook)
- hooks.remove("copyover_complete", copyover_complete_hook)
|