def banip(self, ipaddress, reason="The Ban Hammer has spoken!", source="Wrapper", expires=False): """ Ban an IP address (IPV-4) :param ipaddress - ip address to ban :param reason - text reason for ban :param source - source (author/op) of ban. :param expires - expiration in seconds from epoch time. Field exists but not used by the vanilla server. - implement it for tempbans in future? - Gets converted to string representation in the ban file. This probably only works on 1.7.10 servers or later """ if not isipv4address(ipaddress): return "Invalid IPV4 address: %s" % ipaddress banlist = getjsonfile("banned-ips", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid banlist = dict() # ensure valid dict before operating on it if find_in_json(banlist, "ip", ipaddress): return "address already banned" # error text else: if expires: try: expiration = epoch_to_timestr(expires) except Exception as e: print('Exception: %s' % e) return "expiration date invalid" # error text else: expiration = "forever" banlist.append({ "ip": ipaddress, "created": epoch_to_timestr(time.time()), "source": source, "expires": expiration, "reason": reason }) if putjsonfile(banlist, "banned-ips", self.srv_data.serverpath): banned = "" for client in self.srv_data.clients: if client.ip == str(ipaddress): console_command = "kick %s Your IP is Banned!" % client.username self.eventhandler.callevent( "proxy.console", {"command": console_command}) """ eventdoc <description> internalfunction <description> """ banned += "\n%s" % client.username return "Banned ip address: %s\nPlayers kicked as " \ "a result:%s" % (ipaddress, banned) return "Could not write banlist to disk" else: return "Banlist not found on disk"
def _getbackups(self): if len(self.backups) == 0 and os.path.exists(self.config["Backups"]["backup-location"] + "/backups.json"): loadcode = getjsonfile("backups", self.config["Backups"]["backup-location"], encodedas=self.encoding) if not loadcode: self.log.error("NOTE - backups.json was unreadable. It might be corrupted. Backups will no " "longer be automatically pruned.") self.wrapper.events.callevent("wrapper.backupFailure", { "reasonCode": 4, "reasonText": "backups.json is corrupted. Please contact an administer instantly, as this " "may be critical." }) """ eventdoc <description> internalfunction <description> """ self.backups = [] else: self.backups = loadcode else: if len(os.listdir(self.config["Backups"]["backup-location"])) > 0: # import old backups from previous versions of Wrapper.py backuptimestamps = [] for backupNames in os.listdir(self.config["Backups"]["backup-location"]): # noinspection PyBroadException,PyUnusedLocal try: backuptimestamps.append(int(backupNames[backupNames.find('-') + 1:backupNames.find('.')])) except Exception as e: pass backuptimestamps.sort() for backupI in backuptimestamps: self.backups.append((int(backupI), "backup-%s.tar" % str(backupI)))
def _getbackups(self): if len(self.backups) == 0 and os.path.exists(self.config["Backups"]["backup-location"] + "/backups.json"): loadcode = getjsonfile("backups", self.config["Backups"]["backup-location"], encodedas=self.encoding) if not loadcode: self.log.error("NOTE - backups.json was unreadable. It might be corrupted. Backups will no " "longer be automatically pruned.") self.wrapper.events.callevent("wrapper.backupFailure", { "reasonCode": 4, "reasonText": "backups.json is corrupted. Please contact an administer instantly, as this " "may be critical." }) self.backups = [] else: self.backups = loadcode else: if len(os.listdir(self.config["Backups"]["backup-location"])) > 0: # import old backups from previous versions of Wrapper.py backuptimestamps = [] for backupNames in os.listdir(self.config["Backups"]["backup-location"]): # noinspection PyBroadException,PyUnusedLocal try: backuptimestamps.append(int(backupNames[backupNames.find('-') + 1:backupNames.find('.')])) except Exception as e: pass backuptimestamps.sort() for backupI in backuptimestamps: self.backups.append((int(backupI), "backup-%s.tar" % str(backupI)))
def read_ops_file(self, read_super_ops=True): """Keep a list of ops in the server instance to stop reading the disk for it. :rtype: Dictionary """ ops = False # (4 = PROTOCOL_1_7 ) - 1.7.6 or greater use ops.json if self.version_compute > 10700: ops = getjsonfile( "ops", self.serverpath, encodedas=self.encoding ) if not ops: # try for an old "ops.txt" file instead. ops = [] opstext = getfileaslines("ops.txt", self.serverpath) if not opstext: return False for op in opstext: # create a 'fake' ops list from the old pre-1.8 # text line name list notice that the level (an # option not the old list) is set to 1 This will # pass as true, but if the plugin is also # checking op-levels, it may not pass truth. indivop = {"uuid": op, "name": op, "level": 1} ops.append(indivop) # Grant "owner" an op level above 4. required for some wrapper commands if read_super_ops: for eachop in ops: if eachop["name"] in self.ownernames: eachop["level"] = self.ownernames[eachop["name"]] return ops
def read_ops_file(self, read_super_ops=True): """Keep a list of ops in the server instance to stop reading the disk for it. :rtype: Dictionary """ ops = False # (4 = PROTOCOL_1_7 ) - 1.7.6 or greater use ops.json if self.protocolVersion > 4: ops = getjsonfile("ops", self.serverpath, encodedas=self.encoding) if not ops: # try for an old "ops.txt" file instead. ops = [] opstext = getfileaslines("ops.txt", self.serverpath) if not opstext: return False for op in opstext: # create a 'fake' ops list from the old pre-1.8 # text line name list notice that the level (an # option not the old list) is set to 1 This will # pass as true, but if the plugin is also # checking op-levels, it may not pass truth. indivop = {"uuid": op, "name": op, "level": 1} ops.append(indivop) # Grant "owner" an op level above 4. required for some wrapper commands if read_super_ops: for eachop in ops: if eachop["name"] in self.ownernames: eachop["level"] = self.ownernames[eachop["name"]] return ops
def json_load(self): try_load = getjsonfile(self.name, self.root, encodedas=self.encoding) if try_load in (None, False): self.log.exception("bad/non-existent file or data '%s/%s.%s'" % (self.root, self.name, self.file_ext)) return {} else: return try_load
def banuuidraw(self, uuid, username, reason="The Ban Hammer has spoken!", source="Wrapper", expires=False): """ Ban a raw uuid/name combination with no mojang error checks :param uuid - uuid to ban (MCUUID) :param username - Name of player to ban :param reason - text reason for ban :param source - source (author/op) of ban. :param expires - expiration in seconds from epoch time. Field exists but not used by the vanilla server - implement it for tempbans in future? Gets converted to string representation in the ban file. This probably only works on 1.7.10 servers or later """ banlist = getjsonfile("banned-players", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid banlist = dict() # ensure valid dict before operating on it if find_in_json(banlist, "uuid", str(uuid)): return "player already banned" # error text else: if expires: try: expiration = epoch_to_timestr(expires) except Exception as e: print('Exception: %s' % e) return "expiration date invalid" # error text else: expiration = "forever" banlist.append({ "uuid": uuid.string, "name": username, "created": epoch_to_timestr(time.time()), "source": source, "expires": expiration, "reason": reason }) if putjsonfile(banlist, "banned-players", self.srv_data.serverpath): self.log.info("kicking %s... %s", username, reason) console_command = "kick %s Banned: %s" % (username, reason) self.eventhandler.callevent("proxy.console", {"command": console_command}, abortable=False) """ eventdoc <description> internalfunction <description> """ # noqa return "Banned %s: %s - %s" % (username, uuid, reason) return "Could not write banlist to disk" else: return "Banlist not found on disk"
def getuuidbanreason(self, uuid): """ :param uuid: uuid of player as string :return: string representing ban reason """ banlist = getjsonfile("banned-players", self.srv_data.serverpath) if banlist: banrecord = find_in_json(banlist, "uuid", uuid) return "%s by %s" % (banrecord["reason"], banrecord["source"]) return "Banned by server"
def getuuidbanreason(self, uuid): """ :param uuid: uuid of player as string :return: string representing ban reason """ banlist = getjsonfile("banned-players", self.serverpath) if banlist: banrecord = find_in_json(banlist, "uuid", uuid) return "%s by %s" % (banrecord["reason"], banrecord["source"]) return "Banned by server"
def banip(self, ipaddress, reason="The Ban Hammer has spoken!", source="Wrapper", expires=False): """ Ban an IP address (IPV-4) :param ipaddress - ip address to ban :param reason - text reason for ban :param source - source (author/op) of ban. :param expires - expiration in seconds from epoch time. Field exists but not used by the vanilla server. - implement it for tempbans in future? - Gets converted to string representation in the ban file. This probably only works on 1.7.10 servers or later """ if not isipv4address(ipaddress): return "Invalid IPV4 address: %s" % ipaddress banlist = getjsonfile("banned-ips", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid banlist = dict() # ensure valid dict before operating on it if find_in_json(banlist, "ip", ipaddress): return "address already banned" # error text else: if expires: try: expiration = epoch_to_timestr(expires) except Exception as e: print('Exception: %s' % e) return "expiration date invalid" # error text else: expiration = "forever" banlist.append({"ip": ipaddress, "created": epoch_to_timestr(time.time()), "source": source, "expires": expiration, "reason": reason}) if putjsonfile(banlist, "banned-ips", self.srv_data.serverpath): banned = "" for client in self.srv_data.clients: if client.ip == str(ipaddress): console_command = "kick %s Your IP is Banned!" % client.username self.eventhandler.callevent("proxy.console", {"command": console_command}) """ eventdoc <description> internalfunction <description> """ banned += "\n%s" % client.username return "Banned ip address: %s\nPlayers kicked as " \ "a result:%s" % (ipaddress, banned) return "Could not write banlist to disk" else: return "Banlist not found on disk"
def _json_load(self): try_load = getjsonfile(self.name, self.root, encodedas=self.encoding) if try_load is None: self.log.exception("bad file or data '%s/%s.json'" % (self.root, self.name)) return {} if try_load is False: # file just does not exist (yet); return without comments/errors. return {} else: return try_load
def _json_load(self): try_load = getjsonfile(self.name, self.root, encodedas=self.encoding) if try_load is None: self.log.exception("bad file or data '%s/%s.json'" % (self.root, self.name)) return {} if try_load is False: # file just does not exist (yet); return without comments/errors. return {} else: return try_load
def banuuid(self, uuid, reason="The Ban Hammer has spoken!", source="Wrapper", expires=False): """ Ban someone by UUID This is the 1.7.6 way to ban.. :param uuid - uuid to ban (MCUUID) :param reason - text reason for ban :param source - source (author/op) of ban. :param expires - expiration in seconds from epoch time. Field exists but not used by the vanilla server - implement it for tempbans in future? Gets converted to string representation in the ban file. This probably only works on 1.7.10 servers or later """ banlist = getjsonfile("banned-players", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid banlist = dict() # ensure valid dict before operating on it if find_in_json(banlist, "uuid", str(uuid)): return "player already banned" # error text else: if expires: try: expiration = epoch_to_timestr(expires) except Exception as e: print('Exception: %s' % e) return "expiration date invalid" # error text else: expiration = "forever" name = self.uuids.getusernamebyuuid(uuid.string) banlist.append({ "uuid": uuid.string, "name": name, "created": epoch_to_timestr(time.time()), "source": source, "expires": expiration, "reason": reason }) if putjsonfile(banlist, "banned-players", self.srv_data.serverpath): # this actually is not needed. Commands now handle the kick. console_command = "kick %s %s" % (name, reason) self.run_command(console_command) return "Banned %s: %s" % (name, reason) return "Could not write banlist to disk" else: return "Banlist not found on disk"
def banuuidraw(self, uuid, username, reason="The Ban Hammer has spoken!", source="Wrapper", expires=False): """ Ban a raw uuid/name combination with no mojang error checks :param uuid - uuid to ban (MCUUID) :param username - Name of player to ban :param reason - text reason for ban :param source - source (author/op) of ban. :param expires - expiration in seconds from epoch time. Field exists but not used by the vanilla server - implement it for tempbans in future? Gets converted to string representation in the ban file. This probably only works on 1.7.10 servers or later """ banlist = getjsonfile("banned-players", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid banlist = dict() # ensure valid dict before operating on it if find_in_json(banlist, "uuid", str(uuid)): return "player already banned" # error text else: if expires: try: expiration = epoch_to_timestr(expires) except Exception as e: print('Exception: %s' % e) return "expiration date invalid" # error text else: expiration = "forever" banlist.append({"uuid": uuid.string, "name": username, "created": epoch_to_timestr(time.time()), "source": source, "expires": expiration, "reason": reason}) if putjsonfile(banlist, "banned-players", self.srv_data.serverpath): self.log.info("kicking %s... %s", username, reason) console_command = "kick %s Banned: %s" % (username, reason) self.eventhandler.callevent("proxy.console", {"command": console_command}) """ eventdoc <description> internalfunction <description> """ return "Banned %s: %s - %s" % (username, uuid, reason) return "Could not write banlist to disk" else: return "Banlist not found on disk"
def banuuid(self, uuid, reason="The Ban Hammer has spoken!", source="Wrapper", expires=False): """ Ban someone by UUID This is the 1.7.6 way to ban.. :param uuid - uuid to ban (MCUUID) :param reason - text reason for ban :param source - source (author/op) of ban. :param expires - expiration in seconds from epoch time. Field exists but not used by the vanilla server - implement it for tempbans in future? Gets converted to string representation in the ban file. This probably only works on 1.7.10 servers or later """ banlist = getjsonfile( "banned-players", self.javaserver.serverpath ) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid banlist = dict() # ensure valid dict before operating on it if find_in_json(banlist, "uuid", str(uuid)): return "player already banned" # error text else: if expires: try: expiration = epoch_to_timestr(expires) except Exception as e: print('Exception: %s' % e) return "expiration date invalid" # error text else: expiration = "forever" name = self.uuids.getusernamebyuuid(uuid.string) banlist.append({"uuid": uuid.string, "name": name, "created": epoch_to_timestr(time.time()), "source": source, "expires": expiration, "reason": reason}) if putjsonfile(banlist, "banned-players", self.javaserver.serverpath): # this actually is not needed. Commands now handle the kick. console_command = "kick %s %s" % (name, reason) self.run_command(console_command) return "Banned %s: %s" % (name, reason) return "Could not write banlist to disk" else: return "Banlist not found on disk"
def pardonname(self, username): banlist = getjsonfile("banned-players", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid return "No bans have ever been recorded..?" banrecord = find_in_json(banlist, "name", str(username)) if banrecord: for x in banlist: if x == banrecord: banlist.remove(x) if putjsonfile(banlist, "banned-players", self.srv_data.serverpath): return "pardoned %s" % username return "Could not write banlist to disk" else: return "That person was never banned" # error text else: return "Banlist not found on disk" # error text
def pardonname(self, username): banlist = getjsonfile("banned-players", self.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid return "No bans have ever been recorded..?" banrecord = find_in_json(banlist, "name", str(username)) if banrecord: for x in banlist: if x == banrecord: banlist.remove(x) if putjsonfile(banlist, "banned-players", self.serverpath): return "pardoned %s" % username return "Could not write banlist to disk" else: return "That person was never banned" # error text else: return "Banlist not found on disk" # error text
def isuuidbanned(self, uuid): # Check if the UUID of the user is banned banlist = getjsonfile("banned-players", self.serverpath) if banlist: # make sure banlist exists banrecord = find_in_json(banlist, "uuid", str(uuid)) if banrecord: # if ban has expired if read_timestr(banrecord["expires"]) < int(time.time()): pardoning = self.pardonuuid(str(uuid)) if pardoning[:8] == "pardoned": self.log.info("UUID: %s was pardoned " "(expired ban)", str(uuid)) return False # player is "NOT" banned (anymore) else: self.log.warning( "isuuidbanned attempted a pardon of" " uuid: %s (expired ban), " "but it failed:\n %s", uuid, pardoning) return True # player is still banned return False # banlist empty or record not found
def isuuidbanned(self, uuid): # Check if the UUID of the user is banned banlist = getjsonfile("banned-players", self.srv_data.serverpath) if banlist: # make sure banlist exists banrecord = find_in_json(banlist, "uuid", str(uuid)) if banrecord: # if ban has expired if read_timestr(banrecord["expires"]) < int(time.time()): pardoning = self.pardonuuid(str(uuid)) if pardoning[:8] == "pardoned": self.log.info("UUID: %s was pardoned " "(expired ban)", str(uuid)) return False # player is "NOT" banned (anymore) else: self.log.warning("isuuidbanned attempted a pardon of" " uuid: %s (expired ban), " "but it failed:\n %s", uuid, pardoning) return True # player is still banned return False # banlist empty or record not found
def isipbanned(self, ipaddress): # Check if the IP address is banned banlist = getjsonfile("banned-ips", self.javaserver.serverpath) if banlist: # make sure banlist exists for record in banlist: _ip = record["ip"] if _ip in ipaddress: _expires = read_timestr(record["expires"]) if _expires < int(time.time()): # if ban has expired pardoning = self.pardonip(ipaddress) if pardoning[:8] == "pardoned": self.log.info("IP: %s was pardoned " "(expired ban)", ipaddress) return False # IP is "NOT" banned (anymore) else: self.log.warning("isipbanned attempted a pardon " "of IP: %s (expired ban), but" " it failed:\n %s", ipaddress, pardoning) return True # IP is still banned return False # banlist empty or record not found
def pardonip(self, ipaddress): if not isipv4address(ipaddress): return "Invalid IPV4 address: %s" % ipaddress banlist = getjsonfile("banned-ips", self.srv_data.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid return "No IP bans have ever been recorded." banrecord = find_in_json(banlist, "ip", ipaddress) if banrecord: for x in banlist: if x == banrecord: banlist.remove(x) if putjsonfile(banlist, "banned-ips", self.srv_data.serverpath): return "pardoned %s" % ipaddress return "Could not write banlist to disk" else: return "That address was never banned" # error text else: return "Banlist not found on disk" # error text
def isipbanned(self, ipaddress): # Check if the IP address is banned banlist = getjsonfile("banned-ips", self.srv_data.serverpath) if banlist: # make sure banlist exists for record in banlist: _ip = record["ip"] if _ip in ipaddress: _expires = read_timestr(record["expires"]) if _expires < int(time.time()): # if ban has expired pardoning = self.pardonip(ipaddress) if pardoning[:8] == "pardoned": self.log.info("IP: %s was pardoned " "(expired ban)", ipaddress) return False # IP is "NOT" banned (anymore) else: self.log.warning("isipbanned attempted a pardon " "of IP: %s (expired ban), but" " it failed:\n %s", ipaddress, pardoning) return True # IP is still banned return False # banlist empty or record not found
def pardonip(self, ipaddress): if not isipv4address(ipaddress): return "Invalid IPV4 address: %s" % ipaddress banlist = getjsonfile("banned-ips", self.serverpath) if banlist is not False: # file and directory exist. if banlist is None: # file was empty or not valid return "No IP bans have ever been recorded." banrecord = find_in_json(banlist, "ip", ipaddress) if banrecord: for x in banlist: if x == banrecord: banlist.remove(x) if putjsonfile(banlist, "banned-ips", self.serverpath): return "pardoned %s" % ipaddress return "Could not write banlist to disk" else: return "That address was never banned" # error text else: return "Banlist not found on disk" # error text
def loadconfig(self): # load older versions of wrapper.properties to preserve prior settings. if os.path.exists("wrapper.properties"): with open("wrapper.properties", "r") as f: oldconfig = f.read() oldconfig = "Deprecated File! Use the 'wrapper.properties.json' instead!\n\n%s" % oldconfig with open("_wrapper.properties", "w") as f: f.write(oldconfig) os.remove("wrapper.properties") # Create new config if none exists if not os.path.exists("wrapper.properties.json"): putjsonfile(CONFIG, "wrapper.properties", sort=True) self.exit = True # Read existing configuration self.config = getjsonfile( "wrapper.properties") # the only data file that must be UTF-8 if self.config is None: self.log.error("I think you messed up the Json formatting of your " "wrapper.properties.json file. " "Take your file and have it checked at: \n" "http://jsonlint.com/") self.exit = True # detection and addition must be separated to prevent changing dictionary while iterating over it. # detect changes changesmade = False deprecated_entries = [] new_sections = [] new_entries = [] for section in CONFIG: if section not in self.config: self.log.debug("Adding section [%s] to configuration", section) new_sections.append(section) changesmade = True for configitem in CONFIG[section]: if section in self.config: # mark deprecated items for deletion if configitem in self.config[section]: if CONFIG[section][configitem] == "deprecated": self.log.debug( "Deprecated item '%s' in section '%s'. - removing it from" " wrapper properties", configitem, section) deprecated_entries.append([section, configitem]) changesmade = True # mark new items for addition else: # handle new items in an existing section if CONFIG[section][ configitem] != "deprecated": # avoid re-adding deprecated items self.log.debug( "Item '%s' in section '%s' not in wrapper properties - adding it!", configitem, section) new_entries.append([section, configitem]) changesmade = True else: # handle new items in a (new) section self.log.debug( "Item '%s' in new section '%s' not in wrapper properties - adding it!", configitem, section) if CONFIG[section][configitem] != "deprecated": new_entries.append([section, configitem]) changesmade = True # Apply changes and save. if changesmade: # add new section if len(new_sections) > 0: for added_section in new_sections: self.config[added_section] = {} # Removed deprecated entries if len(deprecated_entries) > 0: for removed in deprecated_entries: del self.config[removed[0]][removed[1]] # Add new entries if len(new_entries) > 0: for added in new_entries: self.config[added[0]][added[1]] = CONFIG[added[0]][ added[1]] self.save() self.exit = True if self.exit: self.log.warning( "Updated wrapper.properties.json file - check and edit configuration if needed and start again." ) sys.exit()
def main(wrapper_start_args): # same as old 'use-readline = True' better_console = wrapper_start_args.betterconsole encoding = wrapper_start_args.encoding config = getjsonfile("wrapper.properties", ".", encodedas=encoding) if config and "Misc" in config: if "use-betterconsole" in config["Misc"]: # use readline = not using better_console better_console = (config["Misc"]["use-betterconsole"]) configure_logger(betterconsole=better_console) # develop master passphrase for wrapper secret_key = wrapper_start_args.passphrase if len(secret_key) < 8: secret_key = get_passphrase( 'please input a master passphrase for Wrapper. This passphrase ' 'will be used to encrypt sensitive information in Wrapper.\n>') # __init__ wrapper and set up logging wrapper = Wrapper(secret_key) log = wrapper.log # start first wrapper log entry log.info("Wrapper.py started - Version %s", wrapper.getbuildstring()) log.debug("Wrapper is using Python %s.%s.%s.", VERSION, SUBVER, MICRO) # flag python version problems if SUBVER < MINSUB: log.warning( "You are using Python %s.%s. There are Wrapper dependencies" " and methods that may require a minimum version of %s.%s." " Please press <y> and <Enter> to acknowledge and continue" " (anything else to exit)..." % (VERSION, SUBVER, VERSION, MINSUB)) userstdin = sys.stdin.readline().strip() if userstdin.lower() != "y": print("bye..") sys.exit(1) # start wrapper # noinspection PyBroadException try: wrapper.start() except SystemExit: if not wrapper.configManager.exit: os.system("reset") wrapper.plugins.disableplugins() wrapper.alerts.ui_process_alerts( "Wrapper called SystemExit exception", blocking=True ) # save-all is required to have a flush argument wrapper.javaserver.console("save-all flush") wrapper.javaserver.stop("Wrapper.py received shutdown signal - bye") wrapper.haltsig.halt = True except ImportWarning as ex: crash_mess = ("Wrapper.py Could not start due to missing requests " "module: \n%s" % ex) wrapper.alerts.ui_process_alerts(crash_mess, blocking=True) log.critical(crash_mess) except Exception as ex: crash_mess = ("Wrapper crashed - stopping server to be safe (%s)" % ex) wrapper.alerts.ui_process_alerts(crash_mess, blocking=True) log.critical("Wrapper.py crashed - stopping server to be safe (%s)", ex, exc_info=True) wrapper.haltsig.halt = True wrapper.plugins.disableplugins() try: wrapper.javaserver.stop("Wrapper.py crashed - please contact" " the server host as soon as possible") except AttributeError as exc: log.critical("Wrapper has no server instance. Server is likely " "killed but could still be running, or it " "might be corrupted! (%s)", exc, exc_info=True)
def main(wrapper_start_args): # same as old 'use-readline = True' better_console = wrapper_start_args.betterconsole encoding = wrapper_start_args.encoding config = getjsonfile("wrapper.properties", ".", encodedas=encoding) if config and "Misc" in config: if "use-betterconsole" in config["Misc"]: # use readline = not using better_console better_console = (config["Misc"]["use-betterconsole"]) configure_logger(betterconsole=better_console) # develop master passphrase for wrapper secret_key = wrapper_start_args.passphrase if len(secret_key) < 8 and secret_key != 'none': secret_key = get_passphrase( 'please input a master passphrase for Wrapper. This passphrase ' 'will be used to encrypt sensitive information in Wrapper.\n>') if secret_key == "none": secret_key = False # __init__ wrapper and set up logging wrapper = Wrapper(secret_key) log = wrapper.log # start first wrapper log entry log.info("Wrapper.py started - Version %s", wrapper.getbuildstring()) log.debug("Wrapper is using Python %s.%s.", sys.version_info[0], SUBVER) # flag python version problems if SUBVER < MINSUB: log.warning( "You are using Python %s.%s. There are Wrapper dependencies" " and methods that may require a minimum version of %s.%s." " Please press <y> and <Enter> to acknowledge and continue" " (anything else to exit)..." % (VERSION, SUBVER, VERSION, MINSUB)) userstdin = sys.stdin.readline().strip() if userstdin.lower() != "y": print("bye..") sys.exit(1) # start wrapper # noinspection PyBroadException try: wrapper.start() except SystemExit: if not wrapper.configManager.exit: os.system("reset") wrapper.plugins.disableplugins() # save-all is required to have a flush argument wrapper.javaserver.console("save-all flush") wrapper.javaserver.stop("Wrapper.py received shutdown signal - bye") wrapper.halt.halt = True except Exception as ex: log.critical("Wrapper.py crashed - stopping server to be safe (%s)", ex, exc_info=True) wrapper.halt.halt = True wrapper.plugins.disableplugins() try: wrapper.javaserver.stop("Wrapper.py crashed - please contact" " the server host as soon as possible") except AttributeError as exc: log.critical( "Wrapper has no server instance. Server is likely " "killed but could still be running, or it " "might be corrupted! (%s)", exc, exc_info=True)
def loadconfig(self): # load older versions of wrapper.properties to preserve prior settings. if os.path.exists("wrapper.properties"): with open("wrapper.properties", "r") as f: oldconfig = f.read() oldconfig = "Deprecated File! Use the 'wrapper.properties.json' instead!\n\n%s" % oldconfig with open("_wrapper.properties", "w") as f: f.write(oldconfig) os.remove("wrapper.properties") # Create new config if none exists if not os.path.exists("wrapper.properties.json"): putjsonfile(CONFIG, "wrapper.properties", sort=True) self.exit = True # Read existing configuration self.config = getjsonfile("wrapper.properties") # the only data file that must be UTF-8 if self.config is None: self.log.error("I think you messed up the Json formatting of your " "wrapper.properties.json file. " "Take your file and have it checked at: \n" "http://jsonlint.com/") self.exit = True # detection and addition must be separated to prevent changing dictionary while iterating over it. # detect changes changesmade = False deprecated_entries = [] new_sections = [] new_entries = [] for section in CONFIG: if section not in self.config: self.log.debug("Adding section [%s] to configuration", section) new_sections.append(section) changesmade = True for configitem in CONFIG[section]: if section in self.config: # mark deprecated items for deletion if configitem in self.config[section]: if CONFIG[section][configitem] == "deprecated": self.log.debug("Deprecated item '%s' in section '%s'. - removing it from" " wrapper properties", configitem, section) deprecated_entries.append([section, configitem]) changesmade = True # mark new items for addition else: # handle new items in an existing section if CONFIG[section][configitem] != "deprecated": # avoid re-adding deprecated items self.log.debug("Item '%s' in section '%s' not in wrapper properties - adding it!", configitem, section) new_entries.append([section, configitem]) changesmade = True else: # handle new items in a (new) section self.log.debug("Item '%s' in new section '%s' not in wrapper properties - adding it!", configitem, section) if CONFIG[section][configitem] != "deprecated": new_entries.append([section, configitem]) changesmade = True # Apply changes and save. if changesmade: # add new section if len(new_sections) > 0: for added_section in new_sections: self.config[added_section] = {} # Removed deprecated entries if len(deprecated_entries) > 0: for removed in deprecated_entries: del self.config[removed[0]][removed[1]] # Add new entries if len(new_entries) > 0: for added in new_entries: self.config[added[0]][added[1]] = CONFIG[added[0]][added[1]] self.save() self.exit = True if self.exit: self.log.warning( "Updated wrapper.properties.json file - check and edit configuration if needed and start again.") sys.exit()