diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c99bc2..00c91bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -362,3 +362,6 @@ ### 200112a (4.2.3-post3) * Aligned wording of music list loading outputs with the ones from area list loading outputs * Fixed players/server being able to load music lists with invalid syntax. An informative error message will be returned to assist in fixing the music list + +### 200112b (4.2.3-post4) +* Fixed players/server being able to load any YAML files with invalid YAML syntax. An informative error message will be returned to assist in fixing said file diff --git a/server/area_manager.py b/server/area_manager.py index 1bb29a96..f5a3b6e2 100644 --- a/server/area_manager.py +++ b/server/area_manager.py @@ -866,7 +866,7 @@ def load_areas(self, area_list_file='config/areas.yaml'): # Check if valid area list file with Constants.fopen(area_list_file, 'r') as chars: - areas = yaml.safe_load(chars) + areas = Constants.yaml_load(chars) def_param = { 'bglock': False, diff --git a/server/commands.py b/server/commands.py index 7b5e3dc6..4b9fa458 100644 --- a/server/commands.py +++ b/server/commands.py @@ -3169,7 +3169,7 @@ def ooc_cmd_music_list(client: ClientManager.Client, arg: str): try: new_music_file = 'config/music_lists/{}.yaml'.format(arg) client.reload_music_list(new_music_file=new_music_file) - except ServerError.MusicInvalid as exc: + except ServerError.MusicInvalidError as exc: raise ArgumentError('The music list {} returned the following error when loading: `{}`.' .format(new_music_file, exc)) except ServerError as exc: diff --git a/server/constants.py b/server/constants.py index 364d61ee..75015e8b 100644 --- a/server/constants.py +++ b/server/constants.py @@ -20,6 +20,7 @@ import re import time import warnings +import yaml from enum import Enum from server.exceptions import ClientError, ServerError, ArgumentError, AreaError @@ -164,6 +165,19 @@ def fopen(file, *args, **kwargs): except OSError as ex: raise ServerError(str(ex)) + @staticmethod + def yaml_load(file): + try: + return yaml.safe_load(file) + except yaml.YAMLError as exc: + # Extract the name of the yaml + separator = max(file.name.rfind('\\'), file.name.rfind('/')) + file_name = file.name[separator+1:] + # Then raise the exception + msg = ('File {} returned the following YAML error when loading: `{}`.' + .format(file_name, exc)) + raise ServerError.YAMLInvalidError(msg) + @staticmethod def get_time(): return time.asctime(time.localtime(time.time())) diff --git a/server/exceptions.py b/server/exceptions.py index e0411c0c..e268c0a2 100644 --- a/server/exceptions.py +++ b/server/exceptions.py @@ -40,10 +40,23 @@ class ArgumentError(TsuserverException): pass class ServerError(TsuserverException): + class ServerFileNotFoundError(TsuserverException): + pass + class MusicNotFoundError(TsuserverException): pass class MusicInvalid(TsuserverException): + # Remove, kept for backwards compatibility + pass + + class MusicInvalidError(TsuserverException): + pass + + class YAMLNotFoundError(TsuserverException): + pass + + class YAMLInvalidError(TsuserverException): pass class PartyError(TsuserverException): diff --git a/server/tsuserver.py b/server/tsuserver.py index 6b5b95c4..acc0c92e 100644 --- a/server/tsuserver.py +++ b/server/tsuserver.py @@ -45,8 +45,8 @@ def __init__(self, protocol=None, client_manager=None, in_test=False): self.release = 4 self.major_version = 2 self.minor_version = 3 - self.segment_version = 'post3' - self.internal_version = '200112a' + self.segment_version = 'post4' + self.internal_version = '200112b' version_string = self.get_version_string() self.software = 'TsuserverDR {}'.format(version_string) self.version = 'TsuserverDR {} ({})'.format(version_string, self.internal_version) @@ -205,13 +205,13 @@ def get_version_string(self): def reload(self): with Constants.fopen('config/characters.yaml', 'r') as chars: - self.char_list = yaml.safe_load(chars) + self.char_list = Constants.yaml_load(chars) with Constants.fopen('config/music.yaml', 'r') as music: - self.music_list = yaml.safe_load(music) + self.music_list = Constants.yaml_load(music) self.build_music_pages_ao1() self.build_music_list_ao2() with Constants.fopen('config/backgrounds.yaml', 'r') as bgs: - self.backgrounds = yaml.safe_load(bgs) + self.backgrounds = Constants.yaml_load(bgs) def reload_commands(self): try: @@ -239,11 +239,11 @@ def get_player_count(self): def load_backgrounds(self): with Constants.fopen('config/backgrounds.yaml', 'r', encoding='utf-8') as bgs: - self.backgrounds = yaml.safe_load(bgs) + self.backgrounds = Constants.yaml_load(bgs) def load_config(self): with Constants.fopen('config/config.yaml', 'r', encoding='utf-8') as cfg: - self.config = yaml.safe_load(cfg) + self.config = Constants.yaml_load(cfg) self.config['motd'] = self.config['motd'].replace('\\n', ' \n') for i in range(1, 8): @@ -302,7 +302,7 @@ def load_config(self): def load_characters(self): with Constants.fopen('config/characters.yaml', 'r', encoding='utf-8') as chars: - self.char_list = yaml.safe_load(chars) + self.char_list = Constants.yaml_load(chars) self.build_char_pages_ao1() def load_commandhelp(self): @@ -403,7 +403,7 @@ def load_ids(self): def load_iniswaps(self): try: with Constants.fopen('config/iniswaps.yaml', 'r', encoding='utf-8') as iniswaps: - self.allowed_iniswaps = yaml.safe_load(iniswaps) + self.allowed_iniswaps = Constants.yaml_load(iniswaps) except Exception as ex: message = 'WARNING: Error loading config/iniswaps.yaml. Will assume empty values.\n' message += '{}: {}'.format(type(ex).__name__, ex) @@ -412,7 +412,7 @@ def load_iniswaps(self): def load_music(self, music_list_file='config/music.yaml', server_music_list=True): with Constants.fopen(music_list_file, 'r', encoding='utf-8') as music: - music_list = yaml.safe_load(music) + music_list = Constants.yaml_load(music) if server_music_list: self.music_list = music_list