def __init__(self):
"""Default values for the in-memory user variables."""
-
- # the account name
- self.name = ""
-
- # the password hash
- self.passhash = ""
-
- # the current client ip address
self.address = ""
-
- # the previous client ip address
self.last_address = ""
-
- # the current socket connection object
self.connection = None
-
- # a flag to denote whether the user is authenticated
self.authenticated = False
-
- # number of times password entry has failed during this session
self.password_tries = 1
-
- # the current state of the user
self.state = "entering_account_name"
-
- # flag to indicate whether a menu has been displayed
self.menu_seen = False
-
- # current error condition, if any
self.error = ""
-
- # fifo-style queue for lines of user input
self.input_queue = []
-
- # fifo-style queue for blocks of user output
self.output_queue = []
-
- # holding pen for unterminated user input
self.partial_input = ""
-
- # flag to indicate the current echo status of the client
self.echoing = True
-
- # the active avatar
self.avatar = None
-
- # an object containing persistent account data
- self.record = ConfigParser.SafeConfigParser()
+ self.account = None
def quit(self):
"""Log, save, close the connection and remove."""
- if self.name: message = "User " + self.name
+ name = self.account.get("name")
+ if name: message = "User " + name
else: message = "An unnamed user"
message += " logged out."
muffmisc.log(message)
- self.save()
self.connection.close()
self.remove()
new_user = muffuser.User()
# give it the same name
- new_user.name = self.name
-
- # load from file
- new_user.load()
+ new_user.account.set("name", self.account.get("name"))
# set everything else equivalent
new_user.address = self.address
for old_user in muffvars.userlist:
# the name is the same but it's not us
- if old_user.name == self.name and old_user is not self:
+ if old_user.account.get("name") == self.account.get("name") and old_user is not self:
# make a note of it
- muffmisc.log("User " + self.name + " reconnected--closing old connection to " + old_user.address + ".")
+ muffmisc.log("User " + self.account.get("name") + " reconnected--closing old connection to " + old_user.address + ".")
old_user.send("$(eol)$(red)New connection from " + self.address + ". Terminating old connection...$(nrm)$(eol)")
self.send("$(eol)$(red)Taking over old connection from " + old_user.address + ".$(nrm)")
def authenticate(self):
"""Flag the user as authenticated and disconnect duplicates."""
if not self.state is "authenticated":
- muffmisc.log("User " + self.name + " logged in.")
+ muffmisc.log("User " + self.account.get("name") + " logged in.")
self.authenticated = True
- def load(self):
- """Retrieve account data from cold storage."""
-
- # what the filename for the user account should be
- filename = muffconf.get("files", "accounts") + "/" + self.name
-
- # try to load the password hash and last connection ipa
- try:
- self.record.read(filename)
- self.passhash = self.record.get("account", "passhash")
- self.last_address = self.record.get("account", "last_address", self.address)
-
- # if we can't, that's okay too
- except:
- pass
-
- def get_passhash(self):
- """Retrieve the user's account password hash from storage."""
-
- # what the filename for the user account could be
- filename = muffconf.get("files", "accounts") + "/" + self.proposed_name
-
- # create a temporary account record object
- temporary_record = ConfigParser.SafeConfigParser()
-
- # try to load the indicated account and get a password hash
- try:
- temporary_record.read(filename)
- self.passhash = temporary_record.get("account", "passhash")
- return True
-
- # otherwise, the password hash is empty
- except:
- self.passhash = ""
- return False
-
- def save(self):
- """Record account data to cold storage."""
-
- # the user account must be authenticated to save
- if self.authenticated:
-
- # create an account section if it doesn't exist
- if not self.record.has_section("account"):
- self.record.add_section("account")
-
- # write some in-memory data to the record
- self.record.set("account", "name", self.name)
- self.record.set("account", "passhash", self.passhash)
- self.record.set("account", "last_address", self.address)
-
- # the account files live here
- account_path = muffconf.get("files", "accounts")
- # the filename to which we'll write
- filename = account_path + "/" + self.name.lower()
-
- # open the user account file for writing
- try:
- record_file = file(filename, "w")
-
- # if the directory doesn't exist, create it first
- except IOError:
- os.makedirs(account_path)
- record_file = file(filename, "w")
-
- # dump the account data to it
- self.record.write(record_file)
-
- # close the user account file
- record_file.flush()
- record_file.close()
-
- # set the permissions to 0600
- os.chmod(filename, 0600)
-
def show_menu(self):
"""Send the user their current menu."""
if not self.menu_seen:
def new_avatar(self):
"""Instantiate a new, unconfigured avatar for this user."""
- try:
- counter = muffuniv.universe.internals["counters"].getint("next_actor")
- except:
- muffmisc.log("get next_actor failed")
- counter = 1
- while muffuniv.element_exists("actor:" + repr(counter)): counter += 1
- muffuniv.universe.internals["counters"].set("next_actor", counter + 1)
- self.avatar = muffuniv.Element("actor:" + repr(counter), muffconf.get("files", "avatars"), muffuniv.universe)
- try:
- avatars = self.record.get("account", "avatars").split()
- except:
- avatars = []
+ counter = muffuniv.universe.categories["internal"]["counters"].getint("next_avatar")
+ while "avatar:" + repr(counter + 1) in muffuniv.universe.categories["actor"].keys(): counter += 1
+ muffuniv.universe.categories["internal"]["counters"].set("next_avatar", counter + 1)
+ self.avatar = muffuniv.Element("actor:avatar:" + repr(counter), muffuniv.universe)
+ avatars = self.account.get("avatars").split()
avatars.append(self.avatar.key)
- self.record.set("account", "avatars", " ".join(avatars))
+ self.account.set("avatars", " ".join(avatars))
def list_avatar_names(self):
"""A test function to list names of assigned avatars."""
try:
- avatars = self.record.get("account", "avatars").split()
+ avatars = self.account.get("avatars").split()
except:
avatars = []
avatar_names = []