Guard against KeyError on universe.contents index
authorJeremy Stanley <fungi@yuggoth.org>
Sun, 14 May 2017 16:42:55 +0000 (16:42 +0000)
committerJeremy Stanley <fungi@yuggoth.org>
Sun, 14 May 2017 16:42:55 +0000 (16:42 +0000)
When accessing base level configuration elements from the main
engine, check that they're actually in universe.contents before
trying to retrieve their facets. Also use sane default fallbacks if
they're undefined.

mudpy/data.py
mudpy/misc.py

index d7de13a..2e22c7e 100644 (file)
@@ -134,9 +134,11 @@ class DataFile:
             if "__control__" in self.data and "backup_count" in self.data[
                     "__control__"]:
                 max_count = self.data["__control__"]["backup_count"]
-            else:
+            elif "mudpy.limit" in self.universe.contents:
                 max_count = self.universe.contents["mudpy.limit"].get(
-                    "backups")
+                    "backups", 0)
+            else:
+                max_count = 0
             if os.path.exists(self.filename) and max_count:
                 backups = []
                 for candidate in os.listdir(os.path.dirname(self.filename)):
index 3cb201c..2923feb 100644 (file)
@@ -651,8 +651,8 @@ class User:
         if self.state is not "authenticated":
             log("User " + self.account.get("name") + " logged in.", 2)
             self.authenticated = True
-            if self.account.subkey in universe.contents["mudpy.limit"].get(
-                    "admins"):
+            if ("mudpy.limit" in universe.contents and self.account.subkey in
+                    universe.contents["mudpy.limit"].get("admins")):
                 self.account.set("administrator", "True")
 
     def show_menu(self):
@@ -974,9 +974,14 @@ def log(message, level=0):
     """Log a message."""
 
     # a couple references we need
-    file_name = universe.contents["mudpy.log"].get("file")
-    max_log_lines = universe.contents["mudpy.log"].get("lines")
-    syslog_name = universe.contents["mudpy.log"].get("syslog")
+    if "mudpy.log" in universe.contents:
+        file_name = universe.contents["mudpy.log"].get("file", "")
+        max_log_lines = universe.contents["mudpy.log"].get("lines", 0)
+        syslog_name = universe.contents["mudpy.log"].get("syslog", "")
+    else:
+        file_name = ""
+        max_log_lines = 0
+        syslog_name = ""
     timestamp = time.asctime()[4:19]
 
     # turn the message into a list of nonempty lines
@@ -993,7 +998,8 @@ def log(message, level=0):
         file_descriptor.close()
 
     # send the timestamp and line to standard output
-    if universe.contents["mudpy.log"].get("stdout"):
+    if ("mudpy.log" in universe.contents and
+            universe.contents["mudpy.log"].get("stdout")):
         for line in lines:
             print(timestamp + " " + line)
 
@@ -1710,6 +1716,12 @@ def handler_checking_password(user):
     # get the next waiting line of input
     input_data = user.input_queue.pop(0)
 
+    if "mudpy.limit" in universe.contents:
+        max_password_tries = universe.contents["mudpy.limit"].get(
+            "password_tries", 3)
+    else:
+        max_password_tries = 3
+
     # does the hashed input equal the stored hash?
     if mudpy.password.verify(input_data, user.account.get("passhash")):
 
@@ -1719,8 +1731,7 @@ def handler_checking_password(user):
             user.state = "main_utility"
 
     # if at first your hashes don't match, try, try again
-    elif user.password_tries < universe.contents["mudpy.limit"].get(
-            "password_tries") - 1:
+    elif user.password_tries < max_password_tries - 1:
         user.password_tries += 1
         user.error = "incorrect"
 
@@ -1738,6 +1749,12 @@ def handler_entering_new_password(user):
     # get the next waiting line of input
     input_data = user.input_queue.pop(0)
 
+    if "mudpy.limit" in universe.contents:
+        max_password_tries = universe.contents["mudpy.limit"].get(
+            "password_tries", 3)
+    else:
+        max_password_tries = 3
+
     # make sure the password is strong--at least one upper, one lower and
     # one digit, seven or more characters in length
     if len(input_data) > 6 and len(
@@ -1753,8 +1770,7 @@ def handler_entering_new_password(user):
         user.state = "verifying_new_password"
 
     # the password was weak, try again if you haven't tried too many times
-    elif user.password_tries < universe.contents["mudpy.limit"].get(
-            "password_tries") - 1:
+    elif user.password_tries < max_password_tries - 1:
         user.password_tries += 1
         user.error = "weak"
 
@@ -1773,6 +1789,12 @@ def handler_verifying_new_password(user):
     # get the next waiting line of input
     input_data = user.input_queue.pop(0)
 
+    if "mudpy.limit" in universe.contents:
+        max_password_tries = universe.contents["mudpy.limit"].get(
+            "password_tries", 3)
+    else:
+        max_password_tries = 3
+
     # hash the input and match it to storage
     if mudpy.password.verify(input_data, user.account.get("passhash")):
         user.authenticate()
@@ -1783,8 +1805,7 @@ def handler_verifying_new_password(user):
 
     # go back to entering the new password as long as you haven't tried
     # too many times
-    elif user.password_tries < universe.contents["mudpy.limit"].get(
-            "password_tries") - 1:
+    elif user.password_tries < max_password_tries - 1:
         user.password_tries += 1
         user.error = "differs"
         user.state = "entering_new_password"
@@ -1998,12 +2019,13 @@ def command_say(actor, parameters):
     if message:
 
         # match the punctuation used, if any, to an action
-        actions = universe.contents["mudpy.linguistic"].get(
-            "actions"
-        )
-        default_punctuation = (
-            universe.contents["mudpy.linguistic"].get(
-                "default_punctuation"))
+        if "mudpy.linguistic" in universe.contents:
+            actions = universe.contents["mudpy.linguistic"].get("actions", {})
+            default_punctuation = (universe.contents["mudpy.linguistic"].get(
+                "default_punctuation", "."))
+        else:
+            actions = {}
+            default_punctuation = "."
         action = ""
 
         # reverse sort punctuation options so the longest match wins
@@ -2027,9 +2049,10 @@ def command_say(actor, parameters):
             message = message[0].lower() + message[1:]
 
             # iterate over all words in message, replacing typos
-            typos = universe.contents["mudpy.linguistic"].get(
-                "typos"
-            )
+            if "mudpy.linguistic" in universe.contents:
+                typos = universe.contents["mudpy.linguistic"].get("typos", {})
+            else:
+                typos = {}
             words = message.split()
             for index in range(len(words)):
                 word = words[index]
@@ -2313,7 +2336,8 @@ def daemonize(universe):
     """Fork and disassociate from everything."""
 
     # only if this is what we're configured to do
-    if universe.contents["mudpy.process"].get("daemon"):
+    if "mudpy.process" in universe.contents and universe.contents[
+            "mudpy.process"].get("daemon"):
 
         # log before we start forking around, so the terminal gets the message
         log("Disassociating from the controlling terminal.")
@@ -2350,7 +2374,10 @@ def create_pidfile(universe):
     """Write a file containing the current process ID."""
     pid = str(os.getpid())
     log("Process ID: " + pid)
-    file_name = universe.contents["mudpy.process"].get("pidfile")
+    if "mudpy.process" in universe.contents:
+        file_name = universe.contents["mudpy.process"].get("pidfile", "")
+    else:
+        file_name = ""
     if file_name:
         if not os.path.isabs(file_name):
             file_name = os.path.join(universe.startdir, file_name)
@@ -2362,7 +2389,10 @@ def create_pidfile(universe):
 
 def remove_pidfile(universe):
     """Remove the file containing the current process ID."""
-    file_name = universe.contents["mudpy.process"].get("pidfile")
+    if "mudpy.process" in universe.contents:
+        file_name = universe.contents["mudpy.process"].get("pidfile", "")
+    else:
+        file_name = ""
     if file_name:
         if not os.path.isabs(file_name):
             file_name = os.path.join(universe.startdir, file_name)