mirror of
				https://github.com/Py-KMS-Organization/py-kms.git
				synced 2025-10-31 03:43:31 +00:00 
			
		
		
		
	py-kms Gui: matched all terminal options so far done; added modes onlyserver / only client
Introduced option for asynchronous messages Slimmed down parsing process with improved errors catching
This commit is contained in:
		| @@ -592,8 +592,8 @@ def main(): | |||||||
|         parser = Etrigan_parser() |         parser = Etrigan_parser() | ||||||
|         args = vars(parser.parse_args()) |         args = vars(parser.parse_args()) | ||||||
|         # Check arguments. |         # Check arguments. | ||||||
|         Etrigan_check().checkfile(args['etriganpid'], 'pidfile', '.pid') |         Etrigan_check().checkfile(args['etriganpid'], '--etrigan-pid', '.pid') | ||||||
|         Etrigan_check().checkfile(args['etriganlog'], 'pidfile', '.log') |         Etrigan_check().checkfile(args['etriganlog'], '--etrigan-log', '.log') | ||||||
|  |  | ||||||
|         # Setup daemon. |         # Setup daemon. | ||||||
|         jasonblood_1 = Etrigan(pidfile = args['etriganpid'], logfile = args['etriganlog'], loglevel = args['etriganlev'], |         jasonblood_1 = Etrigan(pidfile = args['etriganpid'], logfile = args['etriganlog'], loglevel = args['etriganlev'], | ||||||
|   | |||||||
| @@ -140,21 +140,21 @@ class kmsBase: | |||||||
|                 # https://docs.microsoft.com/en-us/windows/deployment/volume-activation/activate-windows-10-clients-vamt                 |                 # https://docs.microsoft.com/en-us/windows/deployment/volume-activation/activate-windows-10-clients-vamt                 | ||||||
|                 MinClients = kmsRequest['requiredClientCount']  |                 MinClients = kmsRequest['requiredClientCount']  | ||||||
|                 RequiredClients = MinClients * 2 |                 RequiredClients = MinClients * 2 | ||||||
|                 if self.srv_config["CurrentClientCount"] != None: |                 if self.srv_config["clientcount"] != None: | ||||||
|                         if 0 < self.srv_config["CurrentClientCount"] < MinClients: |                         if 0 < self.srv_config["clientcount"] < MinClients: | ||||||
|                                 # fixed to 6 (product server) or 26 (product desktop) |                                 # fixed to 6 (product server) or 26 (product desktop) | ||||||
|                                 currentClientCount = MinClients + 1 |                                 currentClientCount = MinClients + 1 | ||||||
|                                 pretty_printer(log_obj = loggersrv.warning, |                                 pretty_printer(log_obj = loggersrv.warning, | ||||||
|                                                put_text = "{reverse}{yellow}{bold}Not enough clients ! Fixed with %s, but activated client \ |                                                put_text = "{reverse}{yellow}{bold}Not enough clients ! Fixed with %s, but activated client \ | ||||||
| could be detected as not genuine !{end}" %currentClientCount) | could be detected as not genuine !{end}" %currentClientCount) | ||||||
|                         elif MinClients <= self.srv_config["CurrentClientCount"] < RequiredClients: |                         elif MinClients <= self.srv_config["clientcount"] < RequiredClients: | ||||||
|                                 currentClientCount = self.srv_config["CurrentClientCount"] |                                 currentClientCount = self.srv_config["clientcount"] | ||||||
|                                 pretty_printer(log_obj = loggersrv.warning, |                                 pretty_printer(log_obj = loggersrv.warning, | ||||||
|                                                put_text = "{reverse}{yellow}{bold}With count = %s, activated client could be detected as not genuine !{end}" %currentClientCount) |                                                put_text = "{reverse}{yellow}{bold}With count = %s, activated client could be detected as not genuine !{end}" %currentClientCount) | ||||||
|                         elif self.srv_config["CurrentClientCount"] >= RequiredClients: |                         elif self.srv_config["clientcount"] >= RequiredClients: | ||||||
|                                 # fixed to 10 (product server) or 50 (product desktop) |                                 # fixed to 10 (product server) or 50 (product desktop) | ||||||
|                                 currentClientCount = RequiredClients |                                 currentClientCount = RequiredClients | ||||||
|                                 if self.srv_config["CurrentClientCount"] > RequiredClients: |                                 if self.srv_config["clientcount"] > RequiredClients: | ||||||
|                                         pretty_printer(log_obj = loggersrv.warning, |                                         pretty_printer(log_obj = loggersrv.warning, | ||||||
|                                                        put_text = "{reverse}{yellow}{bold}Too many clients ! Fixed with %s{end}" %currentClientCount) |                                                        put_text = "{reverse}{yellow}{bold}Too many clients ! Fixed with %s{end}" %currentClientCount) | ||||||
|                 else: |                 else: | ||||||
| @@ -230,8 +230,8 @@ could be detected as not genuine !{end}" %currentClientCount) | |||||||
|                 # rule: timeserver - 4h <= timeclient <= timeserver + 4h, check if is satisfied. |                 # rule: timeserver - 4h <= timeclient <= timeserver + 4h, check if is satisfied. | ||||||
|                 response['responseTime'] = kmsRequest['requestTime']  |                 response['responseTime'] = kmsRequest['requestTime']  | ||||||
|                 response['currentClientCount'] = currentClientCount |                 response['currentClientCount'] = currentClientCount | ||||||
|                 response['vLActivationInterval'] = self.srv_config["VLActivationInterval"] |                 response['vLActivationInterval'] = self.srv_config["activation"] | ||||||
|                 response['vLRenewalInterval'] = self.srv_config["VLRenewalInterval"] |                 response['vLRenewalInterval'] = self.srv_config["renewal"] | ||||||
|  |  | ||||||
|                 if self.srv_config['sqlite'] and self.srv_config['dbSupport']: |                 if self.srv_config['sqlite'] and self.srv_config['dbSupport']: | ||||||
|                         response = sql_update_epid(self.dbName, kmsRequest, response) |                         response = sql_update_epid(self.dbName, kmsRequest, response) | ||||||
|   | |||||||
| @@ -24,6 +24,7 @@ from pykms_RpcBase import rpcBase | |||||||
| from pykms_DB2Dict import kmsDB2Dict | from pykms_DB2Dict import kmsDB2Dict | ||||||
| from pykms_Misc import check_setup | from pykms_Misc import check_setup | ||||||
| from pykms_Misc import KmsParser, KmsParserException, KmsParserHelp | from pykms_Misc import KmsParser, KmsParserException, KmsParserHelp | ||||||
|  | from pykms_Misc import kms_parser_get, kms_parser_check_optionals, kms_parser_check_positionals | ||||||
| from pykms_Format import justify, byterize, enco, deco, pretty_printer | from pykms_Format import justify, byterize, enco, deco, pretty_printer | ||||||
|  |  | ||||||
| clt_version             = "py-kms_2020-02-02" | clt_version             = "py-kms_2020-02-02" | ||||||
| @@ -56,8 +57,10 @@ clt_options = { | |||||||
|                   'choi' : ["WindowsVista","Windows7","Windows8","Windows8.1","Windows10","Office2010","Office2013","Office2016","Office2019"]}, |                   'choi' : ["WindowsVista","Windows7","Windows8","Windows8.1","Windows10","Office2010","Office2013","Office2016","Office2019"]}, | ||||||
|         'cmid' : {'help' : 'Use this flag to manually specify a CMID to use. If no CMID is specified, a random CMID will be generated.', |         'cmid' : {'help' : 'Use this flag to manually specify a CMID to use. If no CMID is specified, a random CMID will be generated.', | ||||||
|                   'def' : None, 'des' : "cmid"}, |                   'def' : None, 'des' : "cmid"}, | ||||||
|         'name' : {'help' : 'Use this flag to manually specify an ASCII machineName to use. If no machineName is specified a random machineName \ |         'name' : {'help' : 'Use this flag to manually specify an ASCII machine name to use. If no machine name is specified a random one \ | ||||||
| will be generated.', 'def' : None, 'des' : "machineName"}, | will be generated.', 'def' : None, 'des' : "machine"}, | ||||||
|  |         'asyncmsg' : {'help' : 'Prints pretty / logging messages asynchronously. Desactivated by default.', | ||||||
|  |                       'def' : False, 'des' : "asyncmsg"}, | ||||||
|         'llevel' : {'help' : 'Use this option to set a log level. The default is \"ERROR\".', 'def' : "ERROR", 'des' : "loglevel", |         'llevel' : {'help' : 'Use this option to set a log level. The default is \"ERROR\".', 'def' : "ERROR", 'des' : "loglevel", | ||||||
|                     'choi' : ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "MINI"]}, |                     'choi' : ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "MINI"]}, | ||||||
|         'lfile' : {'help' : 'Use this option to set an output log file. The default is \"pykms_logclient.log\". Type \"STDOUT\" to view \ |         'lfile' : {'help' : 'Use this option to set an output log file. The default is \"pykms_logclient.log\". Type \"STDOUT\" to view \ | ||||||
| @@ -67,9 +70,6 @@ log info on stdout. Type \"FILESTDOUT\" to combine previous actions.', | |||||||
|         } |         } | ||||||
|  |  | ||||||
| def client_options(): | def client_options(): | ||||||
|         try: |  | ||||||
|                 client_parser = KmsParser(description = clt_description, epilog = 'version: ' + clt_version, add_help = False, allow_abbrew = False) |  | ||||||
|         except TypeError: |  | ||||||
|         client_parser = KmsParser(description = clt_description, epilog = 'version: ' + clt_version, add_help = False) |         client_parser = KmsParser(description = clt_description, epilog = 'version: ' + clt_version, add_help = False) | ||||||
|         client_parser.add_argument("ip", nargs = "?", action = "store", default = clt_options['ip']['def'], |         client_parser.add_argument("ip", nargs = "?", action = "store", default = clt_options['ip']['def'], | ||||||
|                                    help = clt_options['ip']['help'], type = str) |                                    help = clt_options['ip']['help'], type = str) | ||||||
| @@ -81,6 +81,8 @@ def client_options(): | |||||||
|                                    help = clt_options['cmid']['help'], type = str) |                                    help = clt_options['cmid']['help'], type = str) | ||||||
|         client_parser.add_argument("-n", "--name", dest = clt_options['name']['des'] , default = clt_options['name']['def'], |         client_parser.add_argument("-n", "--name", dest = clt_options['name']['des'] , default = clt_options['name']['def'], | ||||||
|                                    help = clt_options['name']['help'], type = str) |                                    help = clt_options['name']['help'], type = str) | ||||||
|  |         client_parser.add_argument("-y", "--async-msg", action = "store_true", dest = clt_options['asyncmsg']['des'], | ||||||
|  |                                    default = clt_options['asyncmsg']['def'], help = clt_options['asyncmsg']['help']) | ||||||
|         client_parser.add_argument("-V", "--loglevel", dest = clt_options['llevel']['des'], action = "store", |         client_parser.add_argument("-V", "--loglevel", dest = clt_options['llevel']['des'], action = "store", | ||||||
|                                    choices = clt_options['llevel']['choi'], default = clt_options['llevel']['def'], |                                    choices = clt_options['llevel']['choi'], default = clt_options['llevel']['def'], | ||||||
|                                    help = clt_options['llevel']['help'], type = str) |                                    help = clt_options['llevel']['help'], type = str) | ||||||
| @@ -88,14 +90,25 @@ def client_options(): | |||||||
|                                    default = clt_options['lfile']['def'], help = clt_options['lfile']['help'], type = str) |                                    default = clt_options['lfile']['def'], help = clt_options['lfile']['help'], type = str) | ||||||
|         client_parser.add_argument("-S", "--logsize", dest = clt_options['lsize']['des'], action = "store", |         client_parser.add_argument("-S", "--logsize", dest = clt_options['lsize']['des'], action = "store", | ||||||
|                                    default = clt_options['lsize']['def'], help = clt_options['lsize']['help'], type = float) |                                    default = clt_options['lsize']['def'], help = clt_options['lsize']['help'], type = float) | ||||||
|  |  | ||||||
|         client_parser.add_argument("-h", "--help", action = "help", help = "show this help message and exit") |         client_parser.add_argument("-h", "--help", action = "help", help = "show this help message and exit") | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|                 if "-h" in sys.argv[1:]: |                 userarg = sys.argv[1:] | ||||||
|  |  | ||||||
|  |                 # Run help. | ||||||
|  |                 if any(arg in ["-h", "--help"] for arg in userarg): | ||||||
|                         KmsParserHelp().printer(parsers = [client_parser]) |                         KmsParserHelp().printer(parsers = [client_parser]) | ||||||
|                 clt_config.update(vars(client_parser.parse_args())) |  | ||||||
|  |                 # Get stored arguments. | ||||||
|  |                 pykmsclt_zeroarg, pykmsclt_onearg = kms_parser_get(client_parser) | ||||||
|  |                 # Update pykms options for dict client config. | ||||||
|  |                 kms_parser_check_optionals(userarg, pykmsclt_zeroarg, pykmsclt_onearg, msg = 'optional py-kms client', | ||||||
|  |                                            exclude_opt_len = ['-F', '--logfile']) | ||||||
|  |                 kms_parser_check_positionals(clt_config, client_parser.parse_args, msg = 'positional py-kms client') | ||||||
|  |  | ||||||
|         except KmsParserException as e: |         except KmsParserException as e: | ||||||
|                 pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) |                 pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True, where = "clt") | ||||||
|  |  | ||||||
| def client_check(): | def client_check(): | ||||||
|         # Setup and some checks. |         # Setup and some checks. | ||||||
| @@ -107,18 +120,22 @@ def client_check(): | |||||||
|                         uuid.UUID(clt_config['cmid']) |                         uuid.UUID(clt_config['cmid']) | ||||||
|                 except ValueError: |                 except ValueError: | ||||||
|                         pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", |                         pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", | ||||||
|                                        put_text = "{reverse}{red}{bold}Bad CMID. Exiting...{end}") |                                        put_text = "{reverse}{red}{bold}argument `-c/--cmid`: invalid with: '%s'. Exiting...{end}" %clt_config['cmid']) | ||||||
|         # Check machineName. |  | ||||||
|         if clt_config['machineName'] is not None: |         # Check machine name. | ||||||
|  |         if clt_config['machine'] is not None: | ||||||
|                 try: |                 try: | ||||||
|                         clt_config['machineName'].encode('utf-16le') |                         clt_config['machine'].encode('utf-16le') | ||||||
|  |  | ||||||
|  |                         if len(clt_config['machine']) < 2: | ||||||
|  |                                 pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", | ||||||
|  |                                                put_text = "{reverse}{red}{bold}argument `-n/--name`: too short (required 2 - 63 chars). Exiting...{end}") | ||||||
|  |                         elif len(clt_config['machine']) > 63: | ||||||
|  |                                 pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", | ||||||
|  |                                                put_text = "{reverse}{red}{bold}argument `-n/--name`: too long (required 2 - 63 chars). Exiting...{end}") | ||||||
|                 except UnicodeEncodeError: |                 except UnicodeEncodeError: | ||||||
|                         pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", |                         pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", | ||||||
|                                        put_text = "{reverse}{red}{bold}Bad machineName. Exiting...{end}") |                                        put_text = "{reverse}{red}{bold}argument `-n/--name`: invalid with: '%s'. Exiting...{end}" %clt_config['machine']) | ||||||
|  |  | ||||||
|                 if len(clt_config['machineName']) < 2 or len(clt_config['machineName']) > 63: |  | ||||||
|                         pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", |  | ||||||
|                                        put_text = "{reverse}{red}{bold}machineName must be between 2 and 63 characters in length. Exiting...{end}") |  | ||||||
|                          |                          | ||||||
|         clt_config['call_id'] = 1 |         clt_config['call_id'] = 1 | ||||||
|  |  | ||||||
| @@ -149,8 +166,14 @@ def client_update(): | |||||||
|          |          | ||||||
| def client_create(): | def client_create(): | ||||||
|         loggerclt.info("Connecting to %s on port %d..." % (clt_config['ip'], clt_config['port'])) |         loggerclt.info("Connecting to %s on port %d..." % (clt_config['ip'], clt_config['port'])) | ||||||
|  |         try: | ||||||
|                 s = socket.create_connection((clt_config['ip'], clt_config['port'])) |                 s = socket.create_connection((clt_config['ip'], clt_config['port'])) | ||||||
|                 loggerclt.info("Connection successful !") |                 loggerclt.info("Connection successful !") | ||||||
|  |         except (socket.gaierror, socket.error) as e: | ||||||
|  |                 pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", | ||||||
|  |                                put_text = "{reverse}{red}{bold}Connection failed '%s:%d': %s. Exiting...{end}" %(clt_config['ip'], | ||||||
|  |                                                                                                                  clt_config['port'], | ||||||
|  |                                                                                                                  str(e))) | ||||||
|         binder = pykms_RpcBind.handler(None, clt_config) |         binder = pykms_RpcBind.handler(None, clt_config) | ||||||
|         RPC_Bind = enco(str(binder.generateRequest()), 'latin-1') |         RPC_Bind = enco(str(binder.generateRequest()), 'latin-1') | ||||||
|  |  | ||||||
| @@ -248,7 +271,7 @@ def createKmsRequestBase(): | |||||||
|         requestDict['previousClientMachineId'] = '\0' * 16 # I'm pretty sure this is supposed to be a null UUID. |         requestDict['previousClientMachineId'] = '\0' * 16 # I'm pretty sure this is supposed to be a null UUID. | ||||||
|         requestDict['requiredClientCount'] = clt_config['RequiredClientCount'] |         requestDict['requiredClientCount'] = clt_config['RequiredClientCount'] | ||||||
|         requestDict['requestTime'] = dt_to_filetime(datetime.datetime.utcnow()) |         requestDict['requestTime'] = dt_to_filetime(datetime.datetime.utcnow()) | ||||||
|         requestDict['machineName'] = (clt_config['machineName'] if (clt_config['machineName'] is not None) else |         requestDict['machineName'] = (clt_config['machine'] if (clt_config['machine'] is not None) else | ||||||
|                                       ''.join(random.choice(string.ascii_letters + string.digits) for i in range(random.randint(2,63)))).encode('utf-16le') |                                       ''.join(random.choice(string.ascii_letters + string.digits) for i in range(random.randint(2,63)))).encode('utf-16le') | ||||||
|         requestDict['mnPad'] = '\0'.encode('utf-16le') * (63 - len(requestDict['machineName'].decode('utf-16le'))) |         requestDict['mnPad'] = '\0'.encode('utf-16le') * (63 - len(requestDict['machineName'].decode('utf-16le'))) | ||||||
|          |          | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import re | |||||||
| import sys | import sys | ||||||
| import os | import os | ||||||
| from collections import OrderedDict | from collections import OrderedDict | ||||||
|  | import logging | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     # Python 2.x imports |     # Python 2.x imports | ||||||
| @@ -16,6 +17,7 @@ except ImportError: | |||||||
|     import queue as Queue |     import queue as Queue | ||||||
|  |  | ||||||
| pyver = sys.version_info[:2] | pyver = sys.version_info[:2] | ||||||
|  |  | ||||||
| #---------------------------------------------------------------------------------------------------------------------------------------------------------- | #---------------------------------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| def enco(strg, typ = 'latin-1'): | def enco(strg, typ = 'latin-1'): | ||||||
| @@ -195,13 +197,15 @@ if pyver < (3, 3): | |||||||
|             file = kwargs.get('file', sys.stdout) |             file = kwargs.get('file', sys.stdout) | ||||||
|             file.flush() if file is not None else sys.stdout.flush() |             file.flush() if file is not None else sys.stdout.flush() | ||||||
|  |  | ||||||
| # based on: https://ryanjoneil.github.io/posts/2014-02-14-capturing-stdout-in-a-python-child-process.html, | # based on: https://ryanjoneil.github.io/posts/2014-02-14-capturing-stdout-in-a-python-child-process.html | ||||||
| # but not using threading/multiprocessing so: | queue_print = Queue.Queue() | ||||||
| # 1) message visualization order preserved. |  | ||||||
| # 2) newlines_count function output not wrong. |  | ||||||
| class ShellMessage(object): | class ShellMessage(object): | ||||||
|     view = True |     viewsrv, viewclt = (True for _ in range(2)) | ||||||
|     count, remain, numlist = (0, 0, []) |     asyncmsgsrv, asyncmsgclt = (False for _ in range(2)) | ||||||
|  |     indx, count, remain, numlist = (0, 0, 0, []) | ||||||
|  |     loggersrv_pty = logging.getLogger('logsrvpty') | ||||||
|  |     loggerclt_pty = logging.getLogger('logcltpty') | ||||||
|  |  | ||||||
|     class Collect(StringIO): |     class Collect(StringIO): | ||||||
|         # Capture string sent to stdout. |         # Capture string sent to stdout. | ||||||
| @@ -215,8 +219,9 @@ class ShellMessage(object): | |||||||
|             self.put_text = put_text |             self.put_text = put_text | ||||||
|             self.where = where |             self.where = where | ||||||
|             self.plaintext = [] |             self.plaintext = [] | ||||||
|             self.path = os.path.dirname(os.path.abspath( __file__ )) + '/pykms_newlines.txt' |             self.path_nl = os.path.dirname(os.path.abspath( __file__ )) + '/pykms_newlines.txt' | ||||||
|             self.print_queue = Queue.Queue() |             self.path_clean_nl = os.path.dirname(os.path.abspath( __file__ )) + '/pykms_clean_newlines.txt' | ||||||
|  |             self.queue_get = Queue.Queue() | ||||||
|  |  | ||||||
|         def formatter(self, msgtofrmt): |         def formatter(self, msgtofrmt): | ||||||
|             if self.newlines: |             if self.newlines: | ||||||
| @@ -236,14 +241,14 @@ class ShellMessage(object): | |||||||
|  |  | ||||||
|         def newlines_file(self, mode, *args): |         def newlines_file(self, mode, *args): | ||||||
|             try: |             try: | ||||||
|                 with open(self.path, mode) as file: |                 with open(self.path_nl, mode) as file: | ||||||
|                     if mode in ['w', 'a']: |                     if mode in ['w', 'a']: | ||||||
|                         file.write(args[0]) |                         file.write(args[0]) | ||||||
|                     elif mode == 'r': |                     elif mode == 'r': | ||||||
|                         data = [int(i) for i in [line.rstrip('\n') for line in file.readlines()]] |                         data = [int(i) for i in [line.rstrip('\n') for line in file.readlines()]] | ||||||
|                         self.newlines, ShellMessage.remain = data[0], sum(data[1:]) |                         self.newlines, ShellMessage.remain = data[0], sum(data[1:]) | ||||||
|             except: |             except: | ||||||
|                 with open(self.path, 'w') as file: |                 with open(self.path_nl, 'w') as file: | ||||||
|                         pass |                         pass | ||||||
|  |  | ||||||
|         def newlines_count(self, num): |         def newlines_count(self, num): | ||||||
| @@ -265,13 +270,67 @@ class ShellMessage(object): | |||||||
|                     self.continuecount = True |                     self.continuecount = True | ||||||
|                 elif num in [-2 ,-4]: |                 elif num in [-2 ,-4]: | ||||||
|                     self.newlines_file('r') |                     self.newlines_file('r') | ||||||
|  |  | ||||||
|  |             self.newlines_clean(num) | ||||||
|  |  | ||||||
|  |         def newlines_clean(self, num): | ||||||
|  |             if num == 0: | ||||||
|  |                 with open(self.path_clean_nl, 'w') as file: | ||||||
|  |                     file.write('clean newlines') | ||||||
|  |             try: | ||||||
|  |                 with open(self.path_clean_nl, 'r') as file: | ||||||
|  |                     some = file.read() | ||||||
|                 if num == 21: |                 if num == 21: | ||||||
|                     ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, []) |                     ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, []) | ||||||
|                 os.remove(self.path) |                     os.remove(self.path_nl) | ||||||
|  |                     os.remove(self.path_clean_nl) | ||||||
|  |             except: | ||||||
|  |                 if num == 19: | ||||||
|  |                     ShellMessage.count, ShellMessage.remain, ShellMessage.numlist = (0, 0, []) | ||||||
|  |                     os.remove(self.path_nl) | ||||||
|  |  | ||||||
|         def run(self): |         def putter(self, aqueue, toput): | ||||||
|             # view = False part. |             try: | ||||||
|             if not ShellMessage.view: |                 aqueue.put_nowait(toput) | ||||||
|  |             except Queue.Full: | ||||||
|  |                 pass | ||||||
|  |  | ||||||
|  |         def execute(self): | ||||||
|  |             self.manage() | ||||||
|  |             ShellMessage.indx += 1 | ||||||
|  |  | ||||||
|  |         def print_logging_setup(self, logger, async_flag, formatter = logging.Formatter('%(name)s %(message)s')): | ||||||
|  |             from pykms_GuiBase import gui_redirector | ||||||
|  |             stream = gui_redirector(StringIO()) | ||||||
|  |             handler = logging.StreamHandler(stream) | ||||||
|  |             handler.name = 'LogStream' | ||||||
|  |             handler.setLevel(logging.INFO) | ||||||
|  |             handler.setFormatter(formatter) | ||||||
|  |  | ||||||
|  |             if logger.handlers: | ||||||
|  |                 logger.handlers = [] | ||||||
|  |  | ||||||
|  |             if async_flag: | ||||||
|  |                 from pykms_Misc import MultiProcessingLogHandler | ||||||
|  |                 logger.addHandler(MultiProcessingLogHandler('Thread-AsyncMsg{0}'.format(handler.name), handler = handler)) | ||||||
|  |             else: | ||||||
|  |                 logger.addHandler(handler) | ||||||
|  |             logger.setLevel(logging.INFO) | ||||||
|  |  | ||||||
|  |         def print_logging(self, toprint): | ||||||
|  |             if (self.nshell and ((0 in self.nshell) or (2 in self.nshell and not ShellMessage.viewclt))) or ShellMessage.indx == 0: | ||||||
|  |                 from pykms_GuiBase import gui_redirector_setup, gui_redirector_clear | ||||||
|  |                 gui_redirector_setup() | ||||||
|  |                 gui_redirector_clear() | ||||||
|  |                 self.print_logging_setup(ShellMessage.loggersrv_pty, ShellMessage.asyncmsgsrv) | ||||||
|  |                 self.print_logging_setup(ShellMessage.loggerclt_pty, ShellMessage.asyncmsgclt) | ||||||
|  |  | ||||||
|  |             if self.where == 'srv': | ||||||
|  |                 ShellMessage.loggersrv_pty.info(toprint) | ||||||
|  |             elif self.where == 'clt': | ||||||
|  |                 ShellMessage.loggerclt_pty.info(toprint) | ||||||
|  |  | ||||||
|  |         def notview(self): | ||||||
|             if self.get_text: |             if self.get_text: | ||||||
|                 self.newlines = 0 |                 self.newlines = 0 | ||||||
|                 if self.put_text is not None: |                 if self.put_text is not None: | ||||||
| @@ -280,25 +339,45 @@ class ShellMessage(object): | |||||||
|                 else: |                 else: | ||||||
|                     for num in self.nshell: |                     for num in self.nshell: | ||||||
|                         self.formatter(MsgMap[num]) |                         self.formatter(MsgMap[num]) | ||||||
|                     return self.plaintext |                 self.putter(self.queue_get, self.plaintext) | ||||||
|                 else: |  | ||||||
|  |         def manage(self): | ||||||
|  |             if not ShellMessage.viewsrv: | ||||||
|  |                 # viewsrv = False, viewclt = True. | ||||||
|  |                 if ShellMessage.viewclt: | ||||||
|  |                     if self.where == 'srv': | ||||||
|  |                         self.notview() | ||||||
|                         return |                         return | ||||||
|  |                 else: | ||||||
|  |                     # viewsrv = False, viewclt = False. | ||||||
|  |                     self.notview() | ||||||
|  |                     return | ||||||
|  |             else: | ||||||
|  |                 # viewsrv = True, viewclt = False. | ||||||
|  |                 if not ShellMessage.viewclt: | ||||||
|  |                     if self.where == 'clt': | ||||||
|  |                         self.notview() | ||||||
|  |                         return | ||||||
|  |                 else: | ||||||
|  |                     # viewsrv = True, viewclt = True. | ||||||
|  |                     pass | ||||||
|  |  | ||||||
|             # Do job. |             # Do job. | ||||||
|             self.produce() |             self.produce() | ||||||
|             toprint = self.consume(timeout = 0.1) |             toprint = self.consume(queue_print, timeout = 0.1) | ||||||
|             # Redirect output. |  | ||||||
|             if sys.stdout.isatty(): |             if sys.stdout.isatty(): | ||||||
|                 print(toprint) |                 print(toprint, flush = True) | ||||||
|             else: |             else: | ||||||
|                 try: |                 try: | ||||||
|                     # Import after variables creation. |                     self.print_logging(toprint) | ||||||
|                     from pykms_GuiBase import gui_redirect |  | ||||||
|                     gui_redirect(toprint, self.where) |  | ||||||
|                 except: |                 except: | ||||||
|                     print(toprint) |                     print(toprint, flush = True) | ||||||
|  |  | ||||||
|             # Get string/s printed. |             # Get string/s printed. | ||||||
|             if self.get_text: |             if self.get_text: | ||||||
|                 return self.plaintext |                 self.putter(self.queue_get, self.plaintext) | ||||||
|  |                 return | ||||||
|  |  | ||||||
|         def produce(self): |         def produce(self): | ||||||
|             # Save everything that would otherwise go to stdout. |             # Save everything that would otherwise go to stdout. | ||||||
| @@ -327,15 +406,12 @@ class ShellMessage(object): | |||||||
|             finally: |             finally: | ||||||
|                 # Restore stdout and send content. |                 # Restore stdout and send content. | ||||||
|                 sys.stdout = sys.__stdout__ |                 sys.stdout = sys.__stdout__ | ||||||
|                 try: |                 self.putter(queue_print, outstream.getvalue()) | ||||||
|                     self.print_queue.put(outstream.getvalue()) |  | ||||||
|                 except Queue.Full: |  | ||||||
|                     pass |  | ||||||
|  |  | ||||||
|         def consume(self, timeout = None): |         def consume(self, aqueue, timeout = None): | ||||||
|             try: |             try: | ||||||
|                 toprint = self.print_queue.get(block = timeout is not None, timeout = timeout) |                 toprint = aqueue.get(block = timeout is not None, timeout = timeout) | ||||||
|                 self.print_queue.task_done() |                 aqueue.task_done() | ||||||
|                 return toprint |                 return toprint | ||||||
|             except Queue.Empty: |             except Queue.Empty: | ||||||
|                 return None |                 return None | ||||||
| @@ -381,11 +457,13 @@ def pretty_printer(**kwargs): | |||||||
|                 options['get_text'] = False |                 options['get_text'] = False | ||||||
|  |  | ||||||
|         # Process messages. |         # Process messages. | ||||||
|         plain_messages = ShellMessage.Process(options['num_text'], |         shmsg = ShellMessage.Process(options['num_text'], | ||||||
|                                      get_text = options['get_text'], |                                      get_text = options['get_text'], | ||||||
|                                      put_text = options['put_text'], |                                      put_text = options['put_text'], | ||||||
|                                               where = options['where']).run() |                                      where = options['where']) | ||||||
|  |  | ||||||
|  |         shmsg.execute() | ||||||
|  |         plain_messages = shmsg.consume(shmsg.queue_get, timeout = None) | ||||||
|         if options['log_obj']: |         if options['log_obj']: | ||||||
|                 for plain_message in plain_messages: |                 for plain_message in plain_messages: | ||||||
|                         options['log_obj'](plain_message) |                         options['log_obj'](plain_message) | ||||||
|   | |||||||
| @@ -49,24 +49,35 @@ def get_ip_address(): | |||||||
|                 ip = 'Unknown' |                 ip = 'Unknown' | ||||||
|         return ip |         return ip | ||||||
|  |  | ||||||
| def gui_redirect(str_to_print, where): | def gui_redirector(stream, redirect_to = TextRedirect.Pretty, redirect_conditio = True, stderr_side = "srv"): | ||||||
|         global txsrv, txclt, txcol |         global txsrv, txclt, txcol | ||||||
|  |         if redirect_conditio: | ||||||
|  |                 if stream == 'stdout': | ||||||
|  |                         sys.stdout = redirect_to(txsrv, txclt, txcol) | ||||||
|  |                 elif stream == 'stderr': | ||||||
|  |                         sys.stderr = redirect_to(txsrv, txclt, txcol, stderr_side) | ||||||
|  |                 else: | ||||||
|  |                         stream = redirect_to(txsrv, txclt, txcol) | ||||||
|  |                         return stream | ||||||
|  |  | ||||||
|  | def gui_redirector_setup(): | ||||||
|  |         TextRedirect.Pretty.tag_num = 0 | ||||||
|  |         TextRedirect.Pretty.newlinecut = [-1, -2, -4, -5] | ||||||
|  |  | ||||||
|  | def gui_redirector_clear(): | ||||||
|  |         global txsrv, oysrv | ||||||
|         try: |         try: | ||||||
|                 TextRedirect.StdoutRedirect(txsrv, txclt, txcol, str_to_print, where) |                 if oysrv: | ||||||
|  |                         txsrv.configure(state = 'normal') | ||||||
|  |                         txsrv.delete('1.0', 'end') | ||||||
|  |                         txsrv.configure(state = 'disabled') | ||||||
|         except: |         except: | ||||||
|                 print(str_to_print) |                 # self.onlysrv not defined (menu not used) | ||||||
|  |                 pass | ||||||
|  |  | ||||||
| ##----------------------------------------------------------------------------------------------------------------------------------------------------------- | ##----------------------------------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| class KmsGui(tk.Tk): | class KmsGui(tk.Tk): | ||||||
|         def browse(self, entrywidget, options): |  | ||||||
|                 path = filedialog.askdirectory() |  | ||||||
|                 if os.path.isdir(path): |  | ||||||
|                         entrywidget.delete('0', 'end') |  | ||||||
|                         entrywidget.insert('end', path + os.sep + os.path.basename(options['lfile']['def'])) |  | ||||||
|                          |  | ||||||
|                          |  | ||||||
|         def __init__(self, *args, **kwargs): |         def __init__(self, *args, **kwargs): | ||||||
|                 tk.Tk.__init__(self, *args, **kwargs) |                 tk.Tk.__init__(self, *args, **kwargs) | ||||||
|                 self.wraplength = 200 |                 self.wraplength = 200 | ||||||
| @@ -97,18 +108,75 @@ class KmsGui(tk.Tk): | |||||||
|  |  | ||||||
|                 self.gui_create() |                 self.gui_create() | ||||||
|  |  | ||||||
|  |         def browse(self, entrywidget, options): | ||||||
|  |                 path = filedialog.askdirectory() | ||||||
|  |                 if os.path.isdir(path): | ||||||
|  |                         entrywidget.delete('0', 'end') | ||||||
|  |                         entrywidget.insert('end', path + os.sep + os.path.basename(options['lfile']['def'])) | ||||||
|  |  | ||||||
|  |         def invert(self, widgets = []): | ||||||
|  |                 for widget in widgets: | ||||||
|  |                         if widget['state'] == 'normal': | ||||||
|  |                                 widget.configure(state = 'disabled') | ||||||
|  |                         elif widget['state'] == 'disabled': | ||||||
|  |                                 widget.configure(state = 'normal') | ||||||
|  |  | ||||||
|  |         def gui_menu(self): | ||||||
|  |                 self.onlysrv, self.onlyclt = (False for _ in range(2)) | ||||||
|  |                 menubar = tk.Menu(self) | ||||||
|  |                 prefmenu = tk.Menu(menubar, tearoff = 0, font = ("Noto Sans Regular", 10), borderwidth = 3, relief = 'ridge') | ||||||
|  |                 menubar.add_cascade(label = 'Preferences', menu = prefmenu) | ||||||
|  |                 prefmenu.add_command(label = 'Enable server-side mode', command = lambda: self.pref_onlysrv(prefmenu)) | ||||||
|  |                 prefmenu.add_command(label = 'Enable client-side mode', command = lambda: self.pref_onlyclt(prefmenu)) | ||||||
|  |                 self.config(menu = menubar) | ||||||
|  |                  | ||||||
|  |         def pref_onlysrv(self, menu): | ||||||
|  |                 global oysrv | ||||||
|  |  | ||||||
|  |                 if self.onlyclt or serverthread.is_running_server: | ||||||
|  |                         return | ||||||
|  |                 self.onlysrv = not self.onlysrv | ||||||
|  |                 if self.onlysrv: | ||||||
|  |                         menu.entryconfigure(0, label = 'Disable server-side mode') | ||||||
|  |                         self.clt_on_show(force_remove = True) | ||||||
|  |                 else: | ||||||
|  |                         menu.entryconfigure(0, label = 'Enable server-side mode') | ||||||
|  |                 self.invert(widgets = [self.shbtnclt]) | ||||||
|  |                 oysrv = self.onlysrv | ||||||
|  |  | ||||||
|  |         def pref_onlyclt(self, menu): | ||||||
|  |                 if self.onlysrv or serverthread.is_running_server: | ||||||
|  |                         return | ||||||
|  |                 self.onlyclt = not self.onlyclt | ||||||
|  |                 if self.onlyclt: | ||||||
|  |                         menu.entryconfigure(1, label = 'Disable client-side mode') | ||||||
|  |                         if self.shbtnclt['text'] == 'SHOW\nCLIENT': | ||||||
|  |                                 self.clt_on_show(force_view = True) | ||||||
|  |                         self.optsrvwin.grid_remove() | ||||||
|  |                         self.msgsrvwin.grid_remove() | ||||||
|  |                         gui_redirector('stderr', redirect_to = TextRedirect.Stderr, stderr_side = "clt") | ||||||
|  |                 else: | ||||||
|  |                         menu.entryconfigure(1, label = 'Enable client-side mode') | ||||||
|  |                         self.optsrvwin.grid() | ||||||
|  |                         self.msgsrvwin.grid() | ||||||
|  |                         gui_redirector('stderr', redirect_to = TextRedirect.Stderr) | ||||||
|  |  | ||||||
|  |                 self.invert(widgets = [self.runbtnsrv, self.shbtnclt, self.runbtnclt]) | ||||||
|  |  | ||||||
|         def gui_create(self): |         def gui_create(self): | ||||||
|                 ## Create server gui |                 ## Create server gui | ||||||
|                 self.gui_srv() |                 self.gui_srv() | ||||||
|                 ## Create client gui + other operations. |                 ## Create client gui + other operations. | ||||||
|                 self.gui_complete() |                 self.gui_complete() | ||||||
|  |                 ## Create menu. | ||||||
|  |                 self.gui_menu() | ||||||
|                 ## Create globals for printing process (redirect stdout). |                 ## Create globals for printing process (redirect stdout). | ||||||
|                 global txsrv, txclt, txcol |                 global txsrv, txclt, txcol | ||||||
|                 txsrv = self.textboxsrv.get() |                 txsrv = self.textboxsrv.get() | ||||||
|                 txclt = self.textboxclt.get() |                 txclt = self.textboxclt.get() | ||||||
|                 txcol = self.customcolors |                 txcol = self.customcolors | ||||||
|                 ## Redirect stderr. |                 ## Redirect stderr. | ||||||
|                 sys.stderr = TextRedirect.StderrRedirect(txsrv, txclt, txcol) |                 gui_redirector('stderr', redirect_to = TextRedirect.Stderr) | ||||||
|  |  | ||||||
|         def gui_pages_show(self, pagename, side): |         def gui_pages_show(self, pagename, side): | ||||||
|                 # https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter |                 # https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter | ||||||
| @@ -162,7 +230,7 @@ class KmsGui(tk.Tk): | |||||||
|                         btnani = tk.Button(aniwin) |                         btnani = tk.Button(aniwin) | ||||||
|                         btnani.grid(row = 0, column = col[2], padx = 2, pady = 2, sticky = stick) |                         btnani.grid(row = 0, column = col[2], padx = 2, pady = 2, sticky = stick) | ||||||
|                         self.pagewidgets[side]["BtnAni"][position] = btnani |                         self.pagewidgets[side]["BtnAni"][position] = btnani | ||||||
|                 # customize buttons. |                 ## Customize buttons. | ||||||
|                 custom_pages(self, side) |                 custom_pages(self, side) | ||||||
|  |  | ||||||
|         def gui_pages_create(self, parent, side, create = {}): |         def gui_pages_create(self, parent, side, create = {}): | ||||||
| @@ -209,11 +277,11 @@ class KmsGui(tk.Tk): | |||||||
|  |  | ||||||
|                 self.pagewidgets = {} |                 self.pagewidgets = {} | ||||||
|  |  | ||||||
|                 ## subpages of optsrvwin. |                 ## Subpages of "optsrvwin". | ||||||
|                 self.gui_pages_create(parent = self.optsrvwin, side = "Srv", create = {"PageStart": None, |                 self.gui_pages_create(parent = self.optsrvwin, side = "Srv", create = {"PageStart": None, | ||||||
|                                                                                        "PageEnd": None}) |                                                                                        "PageEnd": None}) | ||||||
|  |  | ||||||
|                 ## continue to grid. |                 ## Continue to grid. | ||||||
|                 self.msgsrvwin.grid(row = 1, column = 2, padx = 1, pady = 1, sticky = 'nsew') |                 self.msgsrvwin.grid(row = 1, column = 2, padx = 1, pady = 1, sticky = 'nsew') | ||||||
|                 self.msgsrvwin.grid_propagate(False) |                 self.msgsrvwin.grid_propagate(False) | ||||||
|                 self.msgsrvwin.grid_columnconfigure(0, weight = 1) |                 self.msgsrvwin.grid_columnconfigure(0, weight = 1) | ||||||
| @@ -285,7 +353,7 @@ class KmsGui(tk.Tk): | |||||||
|                 self.activ.insert('end', str(srv_options['activation']['def'])) |                 self.activ.insert('end', str(srv_options['activation']['def'])) | ||||||
|                 ToolTip(self.activ, text = srv_options['activation']['help'], wraplength = self.wraplength) |                 ToolTip(self.activ, text = srv_options['activation']['help'], wraplength = self.wraplength) | ||||||
|                 # Renewal Interval. |                 # Renewal Interval. | ||||||
|                 renewlbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Activation Interval: ', font = self.optfont) |                 renewlbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Renewal Interval: ', font = self.optfont) | ||||||
|                 self.renew = tk.Entry(self.pagewidgets["Srv"]["PageWin"]["PageStart"], width = 10, font = self.optfont, validate = "key", |                 self.renew = tk.Entry(self.pagewidgets["Srv"]["PageWin"]["PageStart"], width = 10, font = self.optfont, validate = "key", | ||||||
|                                       validatecommand = self.validation_int) |                                       validatecommand = self.validation_int) | ||||||
|                 self.renew.insert('end', str(srv_options['renewal']['def'])) |                 self.renew.insert('end', str(srv_options['renewal']['def'])) | ||||||
| @@ -298,28 +366,34 @@ class KmsGui(tk.Tk): | |||||||
|                 ToolTip(self.srvfile, text = srv_options['lfile']['help'], wraplength = self.wraplength) |                 ToolTip(self.srvfile, text = srv_options['lfile']['help'], wraplength = self.wraplength) | ||||||
|                 srvfilebtnwin = tk.Button(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Browse', |                 srvfilebtnwin = tk.Button(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Browse', | ||||||
|                                        command = lambda: self.browse(self.srvfile, srv_options)) |                                        command = lambda: self.browse(self.srvfile, srv_options)) | ||||||
|  |  | ||||||
|                 # Loglevel. |                 # Loglevel. | ||||||
|                 srvlevellbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Loglevel: ', font = self.optfont) |                 srvlevellbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Loglevel: ', font = self.optfont) | ||||||
|                 self.srvlevel = ttk.Combobox(self.pagewidgets["Srv"]["PageWin"]["PageStart"], values = tuple(srv_options['llevel']['choi']), |                 self.srvlevel = ttk.Combobox(self.pagewidgets["Srv"]["PageWin"]["PageStart"], values = tuple(srv_options['llevel']['choi']), | ||||||
|                                              width = 10, height = 10, font = self.optfontredux, state = "readonly") |                                              width = 10, height = 10, font = self.optfontredux, state = "readonly") | ||||||
|                 self.srvlevel.set(srv_options['llevel']['def']) |                 self.srvlevel.set(srv_options['llevel']['def']) | ||||||
|                 ToolTip(self.srvlevel, text = srv_options['llevel']['help'], wraplength = self.wraplength) |                 ToolTip(self.srvlevel, text = srv_options['llevel']['help'], wraplength = self.wraplength) | ||||||
|  |  | ||||||
|                 self.chksrvfile = ListboxOfRadiobuttons(self.pagewidgets["Srv"]["PageWin"]["PageStart"], |  | ||||||
|                                                         ['FILE', 'FILEOFF', 'STDOUT', 'STDOUTOFF', 'FILESTDOUT'], |  | ||||||
|                                                         self.optfontredux, |  | ||||||
|                                                         changed = [(self.srvfile, srv_options['lfile']['def']), |  | ||||||
|                                                                    (srvfilebtnwin, ''), |  | ||||||
|                                                                    (self.srvlevel, srv_options['llevel']['def'])], |  | ||||||
|                                                         width = 10, height = 1, borderwidth = 2, relief = 'ridge') |  | ||||||
|  |  | ||||||
|                 # Logsize. |                 # Logsize. | ||||||
|                 srvsizelbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Logsize: ', font = self.optfont) |                 srvsizelbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Logsize: ', font = self.optfont) | ||||||
|                 self.srvsize = tk.Entry(self.pagewidgets["Srv"]["PageWin"]["PageStart"], width = 10, font = self.optfont, validate = "key", |                 self.srvsize = tk.Entry(self.pagewidgets["Srv"]["PageWin"]["PageStart"], width = 10, font = self.optfont, validate = "key", | ||||||
|                                         validatecommand = self.validation_float) |                                         validatecommand = self.validation_float) | ||||||
|                 self.srvsize.insert('end', srv_options['lsize']['def']) |                 self.srvsize.insert('end', srv_options['lsize']['def']) | ||||||
|                 ToolTip(self.srvsize, text = srv_options['lsize']['help'], wraplength = self.wraplength) |                 ToolTip(self.srvsize, text = srv_options['lsize']['help'], wraplength = self.wraplength) | ||||||
|  |                 # Asynchronous messages. | ||||||
|  |                 self.chkvalsrvasy = tk.BooleanVar() | ||||||
|  |                 self.chkvalsrvasy.set(srv_options['asyncmsg']['def']) | ||||||
|  |                 chksrvasy = tk.Checkbutton(self.pagewidgets["Srv"]["PageWin"]["PageStart"], text = 'Async\nMsg', | ||||||
|  |                                            font = self.optfontredux, var = self.chkvalsrvasy, relief = 'groove') | ||||||
|  |                 ToolTip(chksrvasy, text = srv_options['asyncmsg']['help'], wraplength = self.wraplength) | ||||||
|  |  | ||||||
|  |                 # Listbox radiobuttons server. | ||||||
|  |                 self.chksrvfile = ListboxOfRadiobuttons(self.pagewidgets["Srv"]["PageWin"]["PageStart"], | ||||||
|  |                                                         ['FILE', 'FILEOFF', 'STDOUT', 'STDOUTOFF', 'FILESTDOUT'], | ||||||
|  |                                                         self.optfontredux, | ||||||
|  |                                                         changed = [(self.srvfile, srv_options['lfile']['def']), | ||||||
|  |                                                                    (srvfilebtnwin, ''), | ||||||
|  |                                                                    (self.srvsize, srv_options['lsize']['def']), | ||||||
|  |                                                                    (self.srvlevel, srv_options['llevel']['def'])], | ||||||
|  |                                                         width = 10, height = 1, borderwidth = 2, relief = 'ridge') | ||||||
|  |  | ||||||
|                 ## Layout widgets (optsrvwin:Srv:PageWin:PageStart) |                 ## Layout widgets (optsrvwin:Srv:PageWin:PageStart) | ||||||
|                 ver.grid(row = 0, column = 0, columnspan = 3, padx = 5, pady = 5, sticky = 'ew') |                 ver.grid(row = 0, column = 0, columnspan = 3, padx = 5, pady = 5, sticky = 'ew') | ||||||
| @@ -344,6 +418,7 @@ class KmsGui(tk.Tk): | |||||||
|                 self.srvfile.grid(row = 10, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.srvfile.grid(row = 10, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 srvfilebtnwin.grid(row = 10, column = 2, padx = 5, pady = 5, sticky = 'ew') |                 srvfilebtnwin.grid(row = 10, column = 2, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 self.chksrvfile.grid(row = 11, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.chksrvfile.grid(row = 11, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|  |                 chksrvasy.grid(row = 11, column = 2, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 srvlevellbl.grid(row = 12, column = 0, padx = 5, pady = 5, sticky = 'e') |                 srvlevellbl.grid(row = 12, column = 0, padx = 5, pady = 5, sticky = 'e') | ||||||
|                 self.srvlevel.grid(row = 12, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.srvlevel.grid(row = 12, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 srvsizelbl.grid(row = 13, column = 0, padx = 5, pady = 5, sticky = 'e') |                 srvsizelbl.grid(row = 13, column = 0, padx = 5, pady = 5, sticky = 'e') | ||||||
| @@ -352,23 +427,25 @@ class KmsGui(tk.Tk): | |||||||
|                 ## Create widgets (optsrvwin:Srv:PageWin:PageEnd)------------------------------------------------------------------------------------------- |                 ## Create widgets (optsrvwin:Srv:PageWin:PageEnd)------------------------------------------------------------------------------------------- | ||||||
|                 # Timeout connection. |                 # Timeout connection. | ||||||
|                 timeout0lbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], text = 'Timeout connection: ', font = self.optfont) |                 timeout0lbl = tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], text = 'Timeout connection: ', font = self.optfont) | ||||||
|                 self.timeout0 = tk.Entry(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], width = 10, font = self.optfont) |                 self.timeout0 = tk.Entry(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], width = 16, font = self.optfont) | ||||||
|                 self.timeout0.insert('end', str(srv_options['time0']['def'])) |                 self.timeout0.insert('end', str(srv_options['time0']['def'])) | ||||||
|                 ToolTip(self.timeout0, text = srv_options['time0']['help'], wraplength = self.wraplength) |                 ToolTip(self.timeout0, text = srv_options['time0']['help'], wraplength = self.wraplength) | ||||||
|                 # Sqlite database. |                 # Sqlite database. | ||||||
|                 self.chkvalsql = tk.BooleanVar() |                 self.chkvalsql = tk.BooleanVar() | ||||||
|                 self.chkvalsql.set(srv_options['sql']['def']) |                 self.chkvalsql.set(srv_options['sql']['def']) | ||||||
|                 chksql = tk.Checkbutton(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], text = 'Create Sqlite\nDatabase', |                 chksql = tk.Checkbutton(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], text = 'Create Sqlite\nDatabase', | ||||||
|                                         font = self.optfont, var = self.chkvalsql) |                                         font = self.optfontredux, var = self.chkvalsql, relief = 'groove') | ||||||
|                 ToolTip(chksql, text = srv_options['sql']['help'], wraplength = self.wraplength) |                 ToolTip(chksql, text = srv_options['sql']['help'], wraplength = self.wraplength) | ||||||
|  |  | ||||||
|                 ## Layout widgets (optsrvwin:Srv:PageWin:PageEnd) |                 ## Layout widgets (optsrvwin:Srv:PageWin:PageEnd) | ||||||
|                 tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], width = 0, height = 0).grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'nw') |                 # a label for vertical aligning with PageStart | ||||||
|  |                 tk.Label(self.pagewidgets["Srv"]["PageWin"]["PageEnd"], width = 0, | ||||||
|  |                          height = 0, bg = self.customcolors['lavender']).grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'nw') | ||||||
|                 timeout0lbl.grid(row = 1, column = 0, padx = 5, pady = 5, sticky = 'e') |                 timeout0lbl.grid(row = 1, column = 0, padx = 5, pady = 5, sticky = 'e') | ||||||
|                 self.timeout0.grid(row = 1, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.timeout0.grid(row = 1, column = 1, padx = 5, pady = 5, sticky = 'w') | ||||||
|                 chksql.grid(row = 2, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 chksql.grid(row = 2, column = 1, padx = 5, pady = 5, sticky = 'w') | ||||||
|  |  | ||||||
|                 # Store Srv widgets. |                 # Store server-side widgets. | ||||||
|                 self.storewidgets_srv = self.gui_store(side = "Srv", typewidgets = ['Button', 'Entry', 'TCombobox', 'Checkbutton']) |                 self.storewidgets_srv = self.gui_store(side = "Srv", typewidgets = ['Button', 'Entry', 'TCombobox', 'Checkbutton']) | ||||||
|                 self.storewidgets_srv.append(self.chksrvfile) |                 self.storewidgets_srv.append(self.chksrvfile) | ||||||
|  |  | ||||||
| @@ -377,28 +454,52 @@ class KmsGui(tk.Tk): | |||||||
|                                                    relief = 'ridge', font = self.msgfont) |                                                    relief = 'ridge', font = self.msgfont) | ||||||
|                 self.textboxsrv.put() |                 self.textboxsrv.put() | ||||||
|  |  | ||||||
|  |         def always_centered(self, geo, centered, refs): | ||||||
|  |                 x = (self.winfo_screenwidth() // 2) - (self.winfo_width() // 2) | ||||||
|  |                 y = (self.winfo_screenheight() // 2) - (self.winfo_height() // 2) | ||||||
|  |                 w, h, dx, dy = geo.split('+')[0].split('x') + geo.split('+')[1:] | ||||||
|  |  | ||||||
|  |                 if w == refs[1]: | ||||||
|  |                         if centered: | ||||||
|  |                                 self.geometry('+%d+%d' %(x, y)) | ||||||
|  |                                 centered = False | ||||||
|  |                 elif w == refs[0]: | ||||||
|  |                         if not centered: | ||||||
|  |                                 self.geometry('+%d+%d' %(x, y)) | ||||||
|  |                                 centered = True | ||||||
|  |  | ||||||
|  |                 if dx != str(x) or dy != str(y): | ||||||
|  |                         self.geometry('+%d+%d' %(x, 0)) | ||||||
|  |  | ||||||
|  |                 self.after(200, self.always_centered, self.geometry(), centered, refs) | ||||||
|  |  | ||||||
|         def gui_complete(self): |         def gui_complete(self): | ||||||
|                 ## Create client widgets (optcltwin, msgcltwin, btncltwin) |                 ## Create client widgets (optcltwin, msgcltwin, btncltwin) | ||||||
|                 self.update_idletasks()   # update Gui to get btnsrvwin values --> btncltwin. |                 self.update_idletasks()   # update Gui to get btnsrvwin values --> btncltwin. | ||||||
|  |                 minw, minh = self.winfo_width(), self.winfo_height() | ||||||
|                 self.iconify()   |                 self.iconify()   | ||||||
|                 self.gui_clt() |                 self.gui_clt() | ||||||
|                 minw, minh = self.winfo_width(), self.winfo_height() |                 maxw, minh = self.winfo_width(), self.winfo_height() | ||||||
|                 # Main window custom background. |                 ## Main window custom background. | ||||||
|                 self.update_idletasks()   # update Gui for custom background |                 self.update_idletasks()   # update Gui for custom background | ||||||
|                 self.iconify() |                 self.iconify() | ||||||
|                 custom_background(self) |                 custom_background(self) | ||||||
|                 # Main window other modifications. |                 ## Main window other modifications. | ||||||
|  |                 self.eval('tk::PlaceWindow %s center' %self.winfo_pathname(self.winfo_id())) | ||||||
|                 self.wm_attributes("-topmost", True) |                 self.wm_attributes("-topmost", True) | ||||||
|                 self.protocol("WM_DELETE_WINDOW", lambda:0)  |                 self.protocol("WM_DELETE_WINDOW", lambda: 0) | ||||||
|                 self.minsize(minw, minh) |                 ## Disable maximize button. | ||||||
|                 self.resizable(True, False) |                 self.resizable(False, False) | ||||||
|  |                 ## Centered window. | ||||||
|  |                 self.always_centered(self.geometry(), False, [minw, maxw]) | ||||||
|  |  | ||||||
|         def get_position(self, genericwidget): |         def get_position(self, widget): | ||||||
|                 x, y = (genericwidget.winfo_x(), genericwidget.winfo_y()) |                 x, y = (widget.winfo_x(), widget.winfo_y()) | ||||||
|                 w, h = (genericwidget.winfo_width(), genericwidget.winfo_height()) |                 w, h = (widget.winfo_width(), widget.winfo_height()) | ||||||
|                 return x, y, w, h |                 return x, y, w, h | ||||||
|                  |                  | ||||||
|         def gui_clt(self): |         def gui_clt(self): | ||||||
|  |                 self.count_clear = 0 | ||||||
|                 self.optcltwin = tk.Canvas(self.masterwin, background = self.customcolors['white'], borderwidth = 3, relief = 'ridge') |                 self.optcltwin = tk.Canvas(self.masterwin, background = self.customcolors['white'], borderwidth = 3, relief = 'ridge') | ||||||
|                 self.msgcltwin = tk.Frame(self.masterwin, background = self.customcolors['black'], relief = 'ridge', width = 300, height = 200) |                 self.msgcltwin = tk.Frame(self.masterwin, background = self.customcolors['black'], relief = 'ridge', width = 300, height = 200) | ||||||
|                 self.btncltwin = tk.Canvas(self.masterwin, background = self.customcolors['white'], borderwidth = 3, relief = 'ridge') |                 self.btncltwin = tk.Canvas(self.masterwin, background = self.customcolors['white'], borderwidth = 3, relief = 'ridge') | ||||||
| @@ -411,29 +512,25 @@ class KmsGui(tk.Tk): | |||||||
|                 self.optcltwin.grid_rowconfigure(0, weight = 1) |                 self.optcltwin.grid_rowconfigure(0, weight = 1) | ||||||
|                 self.optcltwin.grid_columnconfigure(1, weight = 1) |                 self.optcltwin.grid_columnconfigure(1, weight = 1) | ||||||
|  |  | ||||||
|                 # subpages of optcltwin. |                 ## Subpages of "optcltwin". | ||||||
|                 self.gui_pages_create(parent = self.optcltwin, side = "Clt", create = {"PageStart": None, |                 self.gui_pages_create(parent = self.optcltwin, side = "Clt", create = {"PageStart": None, | ||||||
|                                                                                        "PageEnd": None}) |                                                                                        "PageEnd": None}) | ||||||
|  |  | ||||||
|                 # continue to grid. |                 ## Continue to grid. | ||||||
|                 self.msgcltwin.grid(row = 1, column = 4, padx = 1, pady = 1, sticky = 'nsew') |                 self.msgcltwin.grid(row = 1, column = 4, padx = 1, pady = 1, sticky = 'nsew') | ||||||
|                 self.msgcltwin.grid_propagate(False) |                 self.msgcltwin.grid_propagate(False) | ||||||
|                 self.msgcltwin.grid_columnconfigure(0, weight = 1) |                 self.msgcltwin.grid_columnconfigure(0, weight = 1) | ||||||
|                 self.msgcltwin.grid_rowconfigure(0, weight = 1) |                 self.msgcltwin.grid_rowconfigure(0, weight = 1) | ||||||
|  |  | ||||||
|                 # Create widgets (btncltwin) ---------------------------------------------------------------------------------------------------------------- |                 ## Create widgets (btncltwin) ---------------------------------------------------------------------------------------------------------------- | ||||||
|                 self.runbtnclt = tk.Button(self.btncltwin, text = 'START\nCLIENT', background = self.customcolors['blue'], |                 self.runbtnclt = tk.Button(self.btncltwin, text = 'START\nCLIENT', background = self.customcolors['blue'], | ||||||
|                                            foreground = self.customcolors['white'], relief = 'flat', font = self.btnwinfont, |                                            foreground = self.customcolors['white'], relief = 'flat', font = self.btnwinfont, | ||||||
|                                            state = 'disabled', command = self.clt_on_start) |                                            state = 'disabled', command = self.clt_on_start) | ||||||
|  |  | ||||||
| ##                self.othbutt = tk.Button(self.btncltwin, text = 'Botton\n2', background = self.customcolors['green'], |                 ## Layout widgets (btncltwin) | ||||||
| ##                                         foreground = self.customcolors['white'], relief = 'flat', font = self.btnwinfont) |  | ||||||
|                  |  | ||||||
|                 # Layout widgets (btncltwin) |  | ||||||
|                 self.runbtnclt.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = 'ew') |                 self.runbtnclt.grid(row = 0, column = 0, padx = 2, pady = 2, sticky = 'ew') | ||||||
| ##                self.othbutt.grid(row = 1, column = 0, padx = 2, pady = 2, sticky = 'ew') |  | ||||||
|                  |                  | ||||||
|                 # Create widgets (optcltwin:Clt:PageWin:PageStart) ------------------------------------------------------------------------------------------ |                 ## Create widgets (optcltwin:Clt:PageWin:PageStart) ------------------------------------------------------------------------------------------ | ||||||
|                 # Version. |                 # Version. | ||||||
|                 cltver = tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageStart"], text = 'You are running client version: ' + clt_version, |                 cltver = tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageStart"], text = 'You are running client version: ' + clt_version, | ||||||
|                                   foreground = self.customcolors['red'], font = self.othfont) |                                   foreground = self.customcolors['red'], font = self.othfont) | ||||||
| @@ -479,21 +576,30 @@ class KmsGui(tk.Tk): | |||||||
|                 self.cltlevel.set(clt_options['llevel']['def']) |                 self.cltlevel.set(clt_options['llevel']['def']) | ||||||
|                 ToolTip(self.cltlevel, text = clt_options['llevel']['help'], wraplength = self.wraplength) |                 ToolTip(self.cltlevel, text = clt_options['llevel']['help'], wraplength = self.wraplength) | ||||||
|  |  | ||||||
|                 self.chkcltfile = ListboxOfRadiobuttons(self.pagewidgets["Clt"]["PageWin"]["PageStart"], |  | ||||||
|                                                         ['FILE', 'FILEOFF', 'STDOUT', 'STDOUTOFF', 'FILESTDOUT'], |  | ||||||
|                                                         self.optfontredux, |  | ||||||
|                                                         changed = [(self.cltfile, clt_options['lfile']['def']), |  | ||||||
|                                                                    (cltfilebtnwin, ''), |  | ||||||
|                                                                    (self.cltlevel, clt_options['llevel']['def'])], |  | ||||||
|                                                         width = 10, height = 1, borderwidth = 2, relief = 'ridge') |  | ||||||
|                 # Logsize. |                 # Logsize. | ||||||
|                 cltsizelbl = tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageStart"], text = 'Logsize: ', font = self.optfont) |                 cltsizelbl = tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageStart"], text = 'Logsize: ', font = self.optfont) | ||||||
|                 self.cltsize = tk.Entry(self.pagewidgets["Clt"]["PageWin"]["PageStart"], width = 10, font = self.optfont, validate = "key", |                 self.cltsize = tk.Entry(self.pagewidgets["Clt"]["PageWin"]["PageStart"], width = 10, font = self.optfont, validate = "key", | ||||||
|                                         validatecommand = self.validation_float) |                                         validatecommand = self.validation_float) | ||||||
|                 self.cltsize.insert('end', clt_options['lsize']['def']) |                 self.cltsize.insert('end', clt_options['lsize']['def']) | ||||||
|                 ToolTip(self.cltsize, text = clt_options['lsize']['help'], wraplength = self.wraplength) |                 ToolTip(self.cltsize, text = clt_options['lsize']['help'], wraplength = self.wraplength) | ||||||
|  |                 # Asynchronous messages. | ||||||
|  |                 self.chkvalcltasy = tk.BooleanVar() | ||||||
|  |                 self.chkvalcltasy.set(clt_options['asyncmsg']['def']) | ||||||
|  |                 chkcltasy = tk.Checkbutton(self.pagewidgets["Clt"]["PageWin"]["PageStart"], text = 'Async\nMsg', | ||||||
|  |                                            font = self.optfontredux, var = self.chkvalcltasy, relief = 'groove') | ||||||
|  |                 ToolTip(chkcltasy, text = clt_options['asyncmsg']['help'], wraplength = self.wraplength) | ||||||
|  |  | ||||||
|                 # Layout widgets (optcltwin:Clt:PageWin:PageStart) |                 # Listbox radiobuttons client. | ||||||
|  |                 self.chkcltfile = ListboxOfRadiobuttons(self.pagewidgets["Clt"]["PageWin"]["PageStart"], | ||||||
|  |                                                         ['FILE', 'FILEOFF', 'STDOUT', 'STDOUTOFF', 'FILESTDOUT'], | ||||||
|  |                                                         self.optfontredux, | ||||||
|  |                                                         changed = [(self.cltfile, clt_options['lfile']['def']), | ||||||
|  |                                                                    (cltfilebtnwin, ''), | ||||||
|  |                                                                    (self.cltsize, clt_options['lsize']['def']), | ||||||
|  |                                                                    (self.cltlevel, clt_options['llevel']['def'])], | ||||||
|  |                                                         width = 10, height = 1, borderwidth = 2, relief = 'ridge') | ||||||
|  |                 | ||||||
|  |                 ## Layout widgets (optcltwin:Clt:PageWin:PageStart) | ||||||
|                 cltver.grid(row = 0, column = 0, columnspan = 3, padx = 5, pady = 5, sticky = 'ew') |                 cltver.grid(row = 0, column = 0, columnspan = 3, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 cltipaddlbl.grid(row = 1, column = 0, padx = 5, pady = 5, sticky = 'e') |                 cltipaddlbl.grid(row = 1, column = 0, padx = 5, pady = 5, sticky = 'e') | ||||||
|                 self.cltipadd.grid(row = 1, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.cltipadd.grid(row = 1, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
| @@ -509,21 +615,29 @@ class KmsGui(tk.Tk): | |||||||
|                 self.cltfile.grid(row = 6, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.cltfile.grid(row = 6, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 cltfilebtnwin.grid(row = 6, column = 2, padx = 5, pady = 5, sticky = 'ew') |                 cltfilebtnwin.grid(row = 6, column = 2, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 self.chkcltfile.grid(row = 7, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.chkcltfile.grid(row = 7, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|  |                 chkcltasy.grid(row = 7, column = 2, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 cltlevellbl.grid(row = 8, column = 0, padx = 5, pady = 5, sticky = 'e') |                 cltlevellbl.grid(row = 8, column = 0, padx = 5, pady = 5, sticky = 'e') | ||||||
|                 self.cltlevel.grid(row = 8, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.cltlevel.grid(row = 8, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|                 cltsizelbl.grid(row = 9, column = 0, padx = 5, pady = 5, sticky = 'e') |                 cltsizelbl.grid(row = 9, column = 0, padx = 5, pady = 5, sticky = 'e') | ||||||
|                 self.cltsize.grid(row = 9, column = 1, padx = 5, pady = 5, sticky = 'ew') |                 self.cltsize.grid(row = 9, column = 1, padx = 5, pady = 5, sticky = 'ew') | ||||||
|  |  | ||||||
|  |                 # ugly fix when client-side mode is activated. | ||||||
|  |                 templbl = tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageStart"], | ||||||
|  |                                    bg = self.customcolors['lavender']).grid(row = 10, column = 0, | ||||||
|  |                                                                             padx = 35, pady = 54, sticky = 'e') | ||||||
|  |  | ||||||
|                 ## Create widgets (optcltwin:Clt:PageWin:PageEnd) ------------------------------------------------------------------------------------------- |                 ## Create widgets (optcltwin:Clt:PageWin:PageEnd) ------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
|                 ## Layout widgets (optcltwin:Clt:PageWin:PageEnd) |                 ## Layout widgets (optcltwin:Clt:PageWin:PageEnd) | ||||||
|                 tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageEnd"], width = 0, height = 0).grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'nw') |                 # a label for vertical aligning with PageStart | ||||||
|  |                 tk.Label(self.pagewidgets["Clt"]["PageWin"]["PageEnd"], width = 0, | ||||||
|  |                          height = 0, bg = self.customcolors['lavender']).grid(row = 0, column = 0, padx = 5, pady = 5, sticky = 'nw') | ||||||
|  |  | ||||||
|                 # Store Clt widgets. |                 ## Store client-side widgets. | ||||||
|                 self.storewidgets_clt = self.gui_store(side = "Clt", typewidgets = ['Button', 'Entry', 'TCombobox']) |                 self.storewidgets_clt = self.gui_store(side = "Clt", typewidgets = ['Button', 'Entry', 'TCombobox', 'Checkbutton']) | ||||||
|                 self.storewidgets_clt.append(self.chkcltfile) |                 self.storewidgets_clt.append(self.chkcltfile) | ||||||
|                  |                  | ||||||
|                 # Create widgets and layout (msgcltwin) ----------------------------------------------------------------------------------------------------- |                 ## Create widgets and layout (msgcltwin) ----------------------------------------------------------------------------------------------------- | ||||||
|                 self.textboxclt = TextDoubleScroll(self.msgcltwin, background = self.customcolors['black'], wrap = 'none', state = 'disabled', |                 self.textboxclt = TextDoubleScroll(self.msgcltwin, background = self.customcolors['black'], wrap = 'none', state = 'disabled', | ||||||
|                                                    relief = 'ridge', font = self.msgfont) |                                                    relief = 'ridge', font = self.msgfont) | ||||||
|                 self.textboxclt.put() |                 self.textboxclt.put() | ||||||
| @@ -540,22 +654,22 @@ class KmsGui(tk.Tk): | |||||||
|                                 # is a STRING. |                                 # is a STRING. | ||||||
|                                 return value |                                 return value | ||||||
|  |  | ||||||
|         def prep_logfile(self, filepath): |         def prep_logfile(self, filepath, status): | ||||||
|                 # FILE       (pretty on,  log view off, logfile yes) |                 # FILE       (pretty on,  log view off, logfile yes) | ||||||
|                 # FILEOFF    (pretty on,  log view off, no logfile) |                 # FILEOFF    (pretty on,  log view off, no logfile) | ||||||
|                 # STDOUT     (pretty off, log view on,  no logfile) |                 # STDOUT     (pretty off, log view on,  no logfile) | ||||||
|                 # STDOUTOFF  (pretty off, log view off, logfile yes) |                 # STDOUTOFF  (pretty off, log view off, logfile yes) | ||||||
|                 # FILESTDOUT (pretty off, log view on,  logfile yes) |                 # FILESTDOUT (pretty off, log view on,  logfile yes) | ||||||
|                 st = self.chksrvfile.state() |  | ||||||
|                 if st == 'FILE': |                 if status == 'FILE': | ||||||
|                         return filepath |                         return filepath | ||||||
|                 elif st in ['FILESTDOUT', 'STDOUTOFF']: |                 elif status in ['FILESTDOUT', 'STDOUTOFF']: | ||||||
|                         return [st, filepath] |                         return [status, filepath] | ||||||
|                 elif st in ['STDOUT', 'FILEOFF']: |                 elif status in ['STDOUT', 'FILEOFF']: | ||||||
|                         return st |                         return status | ||||||
|  |  | ||||||
|         def validate_int(self, value): |         def validate_int(self, value): | ||||||
|                 return value == '' or value.isdigit() |                 return value == "" or value.isdigit() | ||||||
|  |  | ||||||
|         def validate_float(self, value): |         def validate_float(self, value): | ||||||
|                 if value == "": |                 if value == "": | ||||||
| @@ -566,13 +680,13 @@ class KmsGui(tk.Tk): | |||||||
|                 except ValueError: |                 except ValueError: | ||||||
|                         return False |                         return False | ||||||
|  |  | ||||||
|         def clt_on_show(self, force = False): |         def clt_on_show(self, force_remove = False, force_view = False): | ||||||
|                 if self.optcltwin.winfo_ismapped() or force: |                 if self.optcltwin.winfo_ismapped() or force_remove: | ||||||
|                         self.shbtnclt['text'] = 'SHOW\nCLIENT' |                         self.shbtnclt['text'] = 'SHOW\nCLIENT' | ||||||
|                         self.optcltwin.grid_remove() |                         self.optcltwin.grid_remove() | ||||||
|                         self.msgcltwin.grid_remove() |                         self.msgcltwin.grid_remove() | ||||||
|                         self.btncltwin.place_forget() |                         self.btncltwin.place_forget() | ||||||
|                 else: |                 elif not self.optcltwin.winfo_ismapped() or force_view: | ||||||
|                         self.shbtnclt['text'] = 'HIDE\nCLIENT' |                         self.shbtnclt['text'] = 'HIDE\nCLIENT' | ||||||
|                         self.optcltwin.grid() |                         self.optcltwin.grid() | ||||||
|                         self.msgcltwin.grid() |                         self.msgcltwin.grid() | ||||||
| @@ -580,12 +694,12 @@ class KmsGui(tk.Tk): | |||||||
|  |  | ||||||
|         def srv_on_start(self): |         def srv_on_start(self): | ||||||
|                 if self.runbtnsrv['text'] == 'START\nSERVER': |                 if self.runbtnsrv['text'] == 'START\nSERVER': | ||||||
|  |                         self.on_clear([txsrv, txclt]) | ||||||
|                         self.srv_actions_start() |                         self.srv_actions_start() | ||||||
|                         # wait for switch. |                         # wait for switch. | ||||||
|                         while not serverthread.is_running_server: |                         while not serverthread.is_running_server: | ||||||
|                                 pass |                                 pass | ||||||
|  |  | ||||||
|                         self.on_clear([txsrv, txclt]) |  | ||||||
|                         self.srv_toggle_all(on_start = True) |                         self.srv_toggle_all(on_start = True) | ||||||
|                         # run thread for interrupting server when an error happens. |                         # run thread for interrupting server when an error happens. | ||||||
|                         self.srv_eject_thread = threading.Thread(target = self.srv_eject, name = "Thread-SrvEjt") |                         self.srv_eject_thread = threading.Thread(target = self.srv_eject, name = "Thread-SrvEjt") | ||||||
| @@ -609,12 +723,18 @@ class KmsGui(tk.Tk): | |||||||
|                 srv_config[srv_options['count']['des']] = self.prep_option(self.count.get()) |                 srv_config[srv_options['count']['des']] = self.prep_option(self.count.get()) | ||||||
|                 srv_config[srv_options['activation']['des']] = self.prep_option(self.activ.get()) |                 srv_config[srv_options['activation']['des']] = self.prep_option(self.activ.get()) | ||||||
|                 srv_config[srv_options['renewal']['des']] = self.prep_option(self.renew.get()) |                 srv_config[srv_options['renewal']['des']] = self.prep_option(self.renew.get()) | ||||||
|                 srv_config[srv_options['lfile']['des']] = self.prep_logfile(self.srvfile.get()) |                 srv_config[srv_options['lfile']['des']] = self.prep_logfile(self.srvfile.get(), self.chksrvfile.state()) | ||||||
|  |                 srv_config[srv_options['asyncmsg']['des']] = self.chkvalsrvasy.get() | ||||||
|                 srv_config[srv_options['llevel']['des']] = self.srvlevel.get() |                 srv_config[srv_options['llevel']['des']] = self.srvlevel.get() | ||||||
|                 srv_config[srv_options['sql']['des']] = self.chkvalsql.get() |  | ||||||
|                 srv_config[srv_options['lsize']['des']] = self.prep_option(self.srvsize.get()) |                 srv_config[srv_options['lsize']['des']] = self.prep_option(self.srvsize.get()) | ||||||
|                 srv_config[srv_options['time0']['des']] = self.prep_option(self.timeout0.get()) |  | ||||||
|  |  | ||||||
|  |                 srv_config[srv_options['time0']['des']] = self.prep_option(self.timeout0.get()) | ||||||
|  |                 srv_config[srv_options['sql']['des']] = self.chkvalsql.get() | ||||||
|  |  | ||||||
|  |                 ## Redirect stdout. | ||||||
|  |                 gui_redirector('stdout', redirect_to = TextRedirect.Log, | ||||||
|  |                                redirect_conditio = (srv_config[srv_options['lfile']['des']] in ['STDOUT', 'FILESTDOUT'])) | ||||||
|  |                 gui_redirector_setup() | ||||||
|                 serverqueue.put('start') |                 serverqueue.put('start') | ||||||
|  |  | ||||||
|         def srv_actions_stop(self): |         def srv_actions_stop(self): | ||||||
| @@ -641,6 +761,8 @@ class KmsGui(tk.Tk): | |||||||
|                                          foreground = self.customcolors['white']) |                                          foreground = self.customcolors['white']) | ||||||
|                         for widget in self.storewidgets_srv: |                         for widget in self.storewidgets_srv: | ||||||
|                                 widget.configure(state = 'normal') |                                 widget.configure(state = 'normal') | ||||||
|  |                                 if isinstance(widget, ListboxOfRadiobuttons): | ||||||
|  |                                         widget.change() | ||||||
|                         self.runbtnclt.configure(state = 'disabled') |                         self.runbtnclt.configure(state = 'disabled') | ||||||
|  |  | ||||||
|         def srv_toggle_state(self): |         def srv_toggle_state(self): | ||||||
| @@ -652,13 +774,18 @@ class KmsGui(tk.Tk): | |||||||
|                 self.statesrv.configure(text = txt, foreground = color) |                 self.statesrv.configure(text = txt, foreground = color) | ||||||
|  |  | ||||||
|         def clt_on_start(self): |         def clt_on_start(self): | ||||||
|  |                 if self.onlyclt: | ||||||
|  |                         self.on_clear([txclt]) | ||||||
|  |                 else: | ||||||
|  |                         rng, add_newline = self.on_clear_setup() | ||||||
|  |                         self.on_clear([txsrv, txclt], clear_range = [rng, None], newline_list = [add_newline, False]) | ||||||
|  |  | ||||||
|                 self.clt_actions_start() |                 self.clt_actions_start() | ||||||
|                 # run thread for disabling interrupt server and client, when client running. |                 # run thread for disabling interrupt server and client, when client running. | ||||||
|                 self.clt_eject_thread = threading.Thread(target = self.clt_eject, name = "Thread-CltEjt") |                 self.clt_eject_thread = threading.Thread(target = self.clt_eject, name = "Thread-CltEjt") | ||||||
|                 self.clt_eject_thread.setDaemon(True) |                 self.clt_eject_thread.setDaemon(True) | ||||||
|                 self.clt_eject_thread.start() |                 self.clt_eject_thread.start() | ||||||
|  |  | ||||||
|                 self.on_clear([txsrv, txclt]) |  | ||||||
|                 for widget in self.storewidgets_clt + [self.runbtnsrv, self.runbtnclt]: |                 for widget in self.storewidgets_clt + [self.runbtnsrv, self.runbtnclt]: | ||||||
|                         widget.configure(state = 'disabled') |                         widget.configure(state = 'disabled') | ||||||
|  |  | ||||||
| @@ -668,10 +795,16 @@ class KmsGui(tk.Tk): | |||||||
|                 clt_config[clt_options['mode']['des']] = self.cltmode.get() |                 clt_config[clt_options['mode']['des']] = self.cltmode.get() | ||||||
|                 clt_config[clt_options['cmid']['des']] = self.cltcmid.get() |                 clt_config[clt_options['cmid']['des']] = self.cltcmid.get() | ||||||
|                 clt_config[clt_options['name']['des']] = self.cltname.get() |                 clt_config[clt_options['name']['des']] = self.cltname.get() | ||||||
|  |                 clt_config[clt_options['lfile']['des']] = self.prep_logfile(self.cltfile.get(), self.chkcltfile.state()) | ||||||
|  |                 clt_config[clt_options['asyncmsg']['des']] = self.chkvalcltasy.get() | ||||||
|                 clt_config[clt_options['llevel']['des']] = self.cltlevel.get() |                 clt_config[clt_options['llevel']['des']] = self.cltlevel.get() | ||||||
|                 clt_config[clt_options['lfile']['des']] = self.prep_logfile(self.cltfile.get()) |  | ||||||
|                 clt_config[clt_options['lsize']['des']] = self.prep_option(self.cltsize.get()) |                 clt_config[clt_options['lsize']['des']] = self.prep_option(self.cltsize.get()) | ||||||
|  |  | ||||||
|  |                 ## Redirect stdout. | ||||||
|  |                 gui_redirector('stdout', redirect_to = TextRedirect.Log, | ||||||
|  |                                redirect_conditio = (clt_config[clt_options['lfile']['des']] in ['STDOUT', 'FILESTDOUT'])) | ||||||
|  |                 gui_redirector_setup() | ||||||
|  |  | ||||||
|                 # run client (in a thread). |                 # run client (in a thread). | ||||||
|                 self.clientthread = client_thread(name = "Thread-Clt") |                 self.clientthread = client_thread(name = "Thread-Clt") | ||||||
|                 self.clientthread.setDaemon(True) |                 self.clientthread.setDaemon(True) | ||||||
| @@ -681,8 +814,18 @@ class KmsGui(tk.Tk): | |||||||
|         def clt_eject(self): |         def clt_eject(self): | ||||||
|                 while self.clientthread.is_alive(): |                 while self.clientthread.is_alive(): | ||||||
|                         sleep(0.1) |                         sleep(0.1) | ||||||
|                 for widget in self.storewidgets_clt + [self.runbtnsrv, self.runbtnclt]: |  | ||||||
|  |                 widgets = self.storewidgets_clt + [self.runbtnclt] | ||||||
|  |                 if not self.onlyclt: | ||||||
|  |                         widgets += [self.runbtnsrv] | ||||||
|  |  | ||||||
|  |                 for widget in widgets: | ||||||
|  |                         if isinstance(widget, ttk.Combobox): | ||||||
|  |                                 widget.configure(state = 'readonly') | ||||||
|  |                         else: | ||||||
|                                 widget.configure(state = 'normal') |                                 widget.configure(state = 'normal') | ||||||
|  |                                 if isinstance(widget, ListboxOfRadiobuttons): | ||||||
|  |                                         widget.change() | ||||||
|  |  | ||||||
|         def on_exit(self): |         def on_exit(self): | ||||||
|                 if serverthread.is_running_server: |                 if serverthread.is_running_server: | ||||||
| @@ -693,8 +836,38 @@ class KmsGui(tk.Tk): | |||||||
|                 server_terminate(serverthread, exit_thread = True) |                 server_terminate(serverthread, exit_thread = True) | ||||||
|                 self.destroy() |                 self.destroy() | ||||||
|  |  | ||||||
|         def on_clear(self, widgetlist): |         def on_clear_setup(self): | ||||||
|                 for widget in widgetlist: |                 if any(opt in ['STDOUT', 'FILESTDOUT'] for opt in srv_config[srv_options['lfile']['des']]): | ||||||
|  |                         if self.count_clear == 0: | ||||||
|  |                                 self.ini = txsrv.index('end') | ||||||
|  |                                 add_newline = False | ||||||
|  |                         else: | ||||||
|  |                                 if self.count_clear == 1: | ||||||
|  |                                         self.ini = '%s.0' %(int(self.ini[0]) - 1) | ||||||
|  |                                 else: | ||||||
|  |                                         self.ini = '%s.0' %(int(self.ini[0])) | ||||||
|  |                                 add_newline = True | ||||||
|  |                         rng = [self.ini, 'end'] | ||||||
|  |                         self.count_clear += 1 | ||||||
|  |                 else: | ||||||
|  |                         rng, add_newline = None, False | ||||||
|  |                         self.count_clear = 0 | ||||||
|  |  | ||||||
|  |                 return rng, add_newline | ||||||
|  |  | ||||||
|  |         def on_clear(self, widget_list, clear_range = None, newline_list = []): | ||||||
|  |                 if newline_list == []: | ||||||
|  |                         newline_list = len(widget_list) * [False] | ||||||
|  |  | ||||||
|  |                 for num, couple in enumerate(zip(widget_list, newline_list)): | ||||||
|  |                         widget, add_n = couple | ||||||
|  |                         try: | ||||||
|  |                                 ini, fin = clear_range[num] | ||||||
|  |                         except TypeError: | ||||||
|  |                                 ini, fin = '1.0', 'end' | ||||||
|  |  | ||||||
|                         widget.configure(state = 'normal') |                         widget.configure(state = 'normal') | ||||||
|                         widget.delete('1.0', 'end') |                         widget.delete(ini, fin) | ||||||
|  |                         if add_n: | ||||||
|  |                                 widget.insert('end', '\n') | ||||||
|                         widget.configure(state = 'disabled') |                         widget.configure(state = 'disabled') | ||||||
|   | |||||||
| @@ -120,37 +120,21 @@ class ToolTip(object): | |||||||
|                 self.tw = None |                 self.tw = None | ||||||
|  |  | ||||||
| ##----------------------------------------------------------------------------------------------------------------------------------------------------------- | ##----------------------------------------------------------------------------------------------------------------------------------------------------------- | ||||||
| # https://stackoverflow.com/questions/2914603/segmentation-fault-while-redirecting-sys-stdout-to-tkinter-text-widget |  | ||||||
| # https://stackoverflow.com/questions/7217715/threadsafe-printing-across-multiple-processes-python-2-x |  | ||||||
| # https://stackoverflow.com/questions/3029816/how-do-i-get-a-thread-safe-print-in-python-2-6 |  | ||||||
| # https://stackoverflow.com/questions/20303291/issue-with-redirecting-stdout-to-tkinter-text-widget-with-threads |  | ||||||
|  |  | ||||||
| class TextRedirect(object): | class TextRedirect(object): | ||||||
|         class StdoutRedirect(object): |         class Pretty(object): | ||||||
|                 tag_num = 0 |  | ||||||
|  |  | ||||||
|                 grpmsg = unformat_message([MsgMap[1], MsgMap[7], MsgMap[12], MsgMap[20]]) |                 grpmsg = unformat_message([MsgMap[1], MsgMap[7], MsgMap[12], MsgMap[20]]) | ||||||
|                 arrows = [ item[0] for item in grpmsg  ] |                 arrows = [ item[0] for item in grpmsg  ] | ||||||
|                 clt_msg_nonewline = [ item[1] for item in grpmsg ] |                 clt_msg_nonewline = [ item[1] for item in grpmsg ] | ||||||
|                 arrows = list(set(arrows)) |                 arrows = list(set(arrows)) | ||||||
|                 lenarrow = len(arrows[0]) |                 lenarrow = len(arrows[0]) | ||||||
|                 srv_msg_nonewline = [ item[0] for item in unformat_message([MsgMap[2], MsgMap[5], MsgMap[13], MsgMap[18]]) ] |                 srv_msg_nonewline = [ item[0] for item in unformat_message([MsgMap[2], MsgMap[5], MsgMap[13], MsgMap[18]]) ] | ||||||
|                 terminator = unformat_message([MsgMap[21]])[0][0] |                 msg_align = [ msg[0].replace('\t', '').replace('\n', '') for msg in unformat_message([MsgMap[-2], MsgMap[-4]]) ] | ||||||
|                 msg_align = [ msg[0].replace('\t', '').replace('\n', '') for msg in unformat_message([MsgMap[-2], MsgMap[-4]])] |  | ||||||
|                 newlinecut = [-1, -2, -4, -5] |  | ||||||
|  |  | ||||||
|                 def __init__(self, srv_text_space, clt_text_space, customcolors, str_to_print, where): |                 def __init__(self, srv_text_space, clt_text_space, customcolors): | ||||||
|                         self.srv_text_space = srv_text_space |                         self.srv_text_space = srv_text_space | ||||||
|                         self.clt_text_space = clt_text_space |                         self.clt_text_space = clt_text_space | ||||||
|                         self.customcolors = customcolors |                         self.customcolors = customcolors | ||||||
|                         self.str_to_print = str_to_print |  | ||||||
|                         self.where = where |  | ||||||
|                         self.textbox_do() |  | ||||||
|  |  | ||||||
|                 def textbox_finish(self, message): |  | ||||||
|                         if message == self.terminator: |  | ||||||
|                                 TextRedirect.StdoutRedirect.tag_num = 0 |  | ||||||
|                                 TextRedirect.StdoutRedirect.newlinecut = [-1, -2, -4, -5] |  | ||||||
|  |  | ||||||
|                 def textbox_write(self, tag, message, color, extras): |                 def textbox_write(self, tag, message, color, extras): | ||||||
|                         widget = self.textbox_choose(message) |                         widget = self.textbox_choose(message) | ||||||
| @@ -161,14 +145,15 @@ class TextRedirect(object): | |||||||
|                         self.textbox_color(tag, widget, color, self.customcolors['black'], extras) |                         self.textbox_color(tag, widget, color, self.customcolors['black'], extras) | ||||||
|                         widget.after(100, widget.see('end')) |                         widget.after(100, widget.see('end')) | ||||||
|                         widget.configure(state = 'disabled') |                         widget.configure(state = 'disabled') | ||||||
|                         self.textbox_finish(message) |  | ||||||
|  |  | ||||||
|                 def textbox_choose(self, message): |                 def textbox_choose(self, message): | ||||||
|                         if self.where == "srv": |                         if any(item.startswith('logsrv') for item in [message, self.str_to_print]): | ||||||
|                                 self.srv_text_space.focus_set() |                                 self.srv_text_space.focus_set() | ||||||
|  |                                 self.where = "srv" | ||||||
|                                 return self.srv_text_space |                                 return self.srv_text_space | ||||||
|                         elif self.where == "clt": |                         elif any(item.startswith('logclt') for item in [message, self.str_to_print]): | ||||||
|                                 self.clt_text_space.focus_set() |                                 self.clt_text_space.focus_set() | ||||||
|  |                                 self.where = "clt" | ||||||
|                                 return self.clt_text_space |                                 return self.clt_text_space | ||||||
|  |  | ||||||
|                 def textbox_color(self, tag, widget, forecolor = 'white', backcolor = 'black', extras = []): |                 def textbox_color(self, tag, widget, forecolor = 'white', backcolor = 'black', extras = []): | ||||||
| @@ -211,8 +196,8 @@ class TextRedirect(object): | |||||||
|                                 # horizontal align. |                                 # horizontal align. | ||||||
|                                 if msg_unformat in self.msg_align: |                                 if msg_unformat in self.msg_align: | ||||||
|                                         msg_strip = message.lstrip('\n') |                                         msg_strip = message.lstrip('\n') | ||||||
|                                         message = '\n' * (len(message) - len(msg_strip) + TextRedirect.StdoutRedirect.newlinecut[0]) + msg_strip |                                         message = '\n' * (len(message) - len(msg_strip) + TextRedirect.Pretty.newlinecut[0]) + msg_strip | ||||||
|                                         TextRedirect.StdoutRedirect.newlinecut.pop(0) |                                         TextRedirect.Pretty.newlinecut.pop(0) | ||||||
|  |  | ||||||
|                         count = Counter(message) |                         count = Counter(message) | ||||||
|                         countab = (count['\t'] if count['\t'] != 0 else 1) |                         countab = (count['\t'] if count['\t'] != 0 else 1) | ||||||
| @@ -220,25 +205,49 @@ class TextRedirect(object): | |||||||
|                         return message |                         return message | ||||||
|  |  | ||||||
|                 def textbox_do(self): |                 def textbox_do(self): | ||||||
|                         msgs, TextRedirect.StdoutRedirect.tag_num = unshell_message(self.str_to_print, TextRedirect.StdoutRedirect.tag_num) |                         msgs, TextRedirect.Pretty.tag_num = unshell_message(self.str_to_print, TextRedirect.Pretty.tag_num) | ||||||
|                         for tag in msgs: |                         for tag in msgs: | ||||||
|                                 self.textbox_write(tag, msgs[tag]['text'], self.customcolors[msgs[tag]['color']], msgs[tag]['extra']) |                                 self.textbox_write(tag, msgs[tag]['text'], self.customcolors[msgs[tag]['color']], msgs[tag]['extra']) | ||||||
|  |  | ||||||
|         class StderrRedirect(StdoutRedirect):                 |                 def flush(self): | ||||||
|                 def __init__(self, srv_text_space, clt_text_space, customcolors): |                         pass | ||||||
|  |  | ||||||
|  |                 def write(self, string): | ||||||
|  |                         if string != '\n': | ||||||
|  |                                 self.str_to_print = string | ||||||
|  |                                 self.textbox_do() | ||||||
|  |  | ||||||
|  |         class Stderr(Pretty): | ||||||
|  |                 def __init__(self, srv_text_space, clt_text_space, customcolors, side): | ||||||
|                         self.srv_text_space = srv_text_space |                         self.srv_text_space = srv_text_space | ||||||
|                         self.clt_text_space = clt_text_space |                         self.clt_text_space = clt_text_space | ||||||
|                         self.customcolors = customcolors |                         self.customcolors = customcolors | ||||||
|  |                         self.side = side | ||||||
|                         self.tag_err = 'STDERR' |                         self.tag_err = 'STDERR' | ||||||
|                         self.xfont = tkFont.Font(font = self.srv_text_space['font']) |                         self.xfont = tkFont.Font(font = self.srv_text_space['font']) | ||||||
|  |  | ||||||
|  |                 def textbox_choose(self, message): | ||||||
|  |                         if self.side == "srv": | ||||||
|  |                                 return self.srv_text_space | ||||||
|  |                         elif self.side == "clt": | ||||||
|  |                                 return self.clt_text_space | ||||||
|  |                                                  | ||||||
|                 def write(self, string): |                 def write(self, string): | ||||||
|                         self.textbox_color(self.tag_err, self.srv_text_space, self.customcolors['red'], self.customcolors['black']) |                         widget = self.textbox_choose(string) | ||||||
|  |                         self.textbox_color(self.tag_err, widget, self.customcolors['red'], self.customcolors['black']) | ||||||
|                         self.srv_text_space.configure(state = 'normal') |                         self.srv_text_space.configure(state = 'normal') | ||||||
|                         self.srv_text_space.insert('end', string, self.tag_err) |                         self.srv_text_space.insert('end', string, self.tag_err) | ||||||
|                         self.srv_text_space.see('end') |                         self.srv_text_space.see('end') | ||||||
|                         self.srv_text_space.configure(state = 'disabled') |                         self.srv_text_space.configure(state = 'disabled') | ||||||
|  |  | ||||||
|  |         class Log(Pretty): | ||||||
|  |                 def textbox_format(self, message): | ||||||
|  |                         if message.startswith('logsrv'): | ||||||
|  |                                 message = message.replace('logsrv ', '') | ||||||
|  |                         if message.startswith('logclt'): | ||||||
|  |                                 message = message.replace('logclt ', '') | ||||||
|  |                         return message + '\n' | ||||||
|  |                  | ||||||
| ##----------------------------------------------------------------------------------------------------------------------------------------------------------- | ##----------------------------------------------------------------------------------------------------------------------------------------------------------- | ||||||
| class TextDoubleScroll(tk.Frame):  | class TextDoubleScroll(tk.Frame):  | ||||||
|         def __init__(self, master, **kwargs): |         def __init__(self, master, **kwargs): | ||||||
| @@ -328,7 +337,7 @@ def custom_background(window): | |||||||
|                         widget.configure(background = window.customcolors['lavender']) |                         widget.configure(background = window.customcolors['lavender']) | ||||||
|  |  | ||||||
|         # Hide client. |         # Hide client. | ||||||
|         window.clt_on_show(force = True) |         window.clt_on_show(force_remove = True) | ||||||
|         # Show Gui. |         # Show Gui. | ||||||
|         window.deiconify() |         window.deiconify() | ||||||
|  |  | ||||||
| @@ -488,7 +497,12 @@ class ListboxOfRadiobuttons(tk.Frame): | |||||||
|                         if st in ['STDOUT', 'FILEOFF']: |                         if st in ['STDOUT', 'FILEOFF']: | ||||||
|                                 if wclass == 'Entry': |                                 if wclass == 'Entry': | ||||||
|                                         widget.delete(0, 'end') |                                         widget.delete(0, 'end') | ||||||
|  |                                         widget.configure(state = "disabled") | ||||||
|                                 elif wclass == 'TCombobox': |                                 elif wclass == 'TCombobox': | ||||||
|  |                                         if st == 'STDOUT': | ||||||
|  |                                                 widget.set(default) | ||||||
|  |                                                 widget.configure(state = "readonly") | ||||||
|  |                                         elif st == 'FILEOFF': | ||||||
|                                                 widget.set('') |                                                 widget.set('') | ||||||
|                                                 widget.configure(state = "disabled") |                                                 widget.configure(state = "disabled") | ||||||
|                         elif st in ['FILE', 'FILESTDOUT', 'STDOUTOFF']: |                         elif st in ['FILE', 'FILESTDOUT', 'STDOUTOFF']: | ||||||
|   | |||||||
| @@ -86,28 +86,104 @@ class LevelFormatter(logging.Formatter): | |||||||
|                 formatter = self.formatters.get(record.levelno, self.default_fmt) |                 formatter = self.formatters.get(record.levelno, self.default_fmt) | ||||||
|                 return formatter.format(record) |                 return formatter.format(record) | ||||||
|  |  | ||||||
|  | # based on https://github.com/jruere/multiprocessing-logging (license LGPL-3.0) | ||||||
|  | from multiprocessing import Queue as MPQueue | ||||||
|  | try: | ||||||
|  |     # Python 2.x imports | ||||||
|  |     import Queue as Queue | ||||||
|  | except ImportError: | ||||||
|  |     # Python 3.x imports | ||||||
|  |     import queue as Queue | ||||||
|  | import threading | ||||||
|  |  | ||||||
|  | class MultiProcessingLogHandler(logging.Handler): | ||||||
|  |         def __init__(self, name, handler = None): | ||||||
|  |                 super(MultiProcessingLogHandler, self).__init__() | ||||||
|  |                 self.queue = MPQueue(-1) | ||||||
|  |                 if handler is None: | ||||||
|  |                         handler = logging.StreamHandler() | ||||||
|  |                 self.handler = handler | ||||||
|  |                 self.name = handler.name | ||||||
|  |  | ||||||
|  |                 self.setLevel(self.handler.level) | ||||||
|  |                 self.setFormatter(self.handler.formatter) | ||||||
|  |                 self.filters = self.handler.filters | ||||||
|  |  | ||||||
|  |                 self.is_closed = False | ||||||
|  |                 self.receive_thread = threading.Thread(target = self.receive, name = name) | ||||||
|  |                 self.receive_thread.daemon = True | ||||||
|  |                 self.receive_thread.start() | ||||||
|  |  | ||||||
|  |         def setFormatter(self, fmt): | ||||||
|  |                 super(MultiProcessingLogHandler, self).setFormatter(fmt) | ||||||
|  |                 self.handler.setFormatter(fmt) | ||||||
|  |  | ||||||
|  |         def emit(self, record): | ||||||
|  |                 try: | ||||||
|  |                         if record.args: | ||||||
|  |                                 record.msg = record.msg %record.args | ||||||
|  |                                 record.args = None | ||||||
|  |                         if record.exc_info: | ||||||
|  |                                 dummy = self.format(record) | ||||||
|  |                                 record.exc_info = None | ||||||
|  |                         self.queue.put_nowait(record) | ||||||
|  |                 except (KeyboardInterrupt, SystemExit): | ||||||
|  |                         raise | ||||||
|  |                 except: | ||||||
|  |                         self.handleError(record) | ||||||
|  |  | ||||||
|  |         def receive(self): | ||||||
|  |                 while not (self.is_closed and self.queue.empty()): | ||||||
|  |                         try: | ||||||
|  |                                 record = self.queue.get(timeout = 0.2) | ||||||
|  |                                 self.handler.emit(record) | ||||||
|  |                         except (KeyboardInterrupt, SystemExit): | ||||||
|  |                                 raise | ||||||
|  |                         except EOFError: | ||||||
|  |                                 break | ||||||
|  |                         except Queue.Empty: | ||||||
|  |                                 pass | ||||||
|  |                         except: | ||||||
|  |                                 logging.exception('Error in log handler.') | ||||||
|  |                 self.queue.close() | ||||||
|  |                 self.queue.join_thread() | ||||||
|  |  | ||||||
|  |         def close(self): | ||||||
|  |                 if not self.is_closed: | ||||||
|  |                         self.is_closed = True | ||||||
|  |                         self.receive_thread.join(5.0) | ||||||
|  |                         self.handler.close() | ||||||
|  |                         super(MultiProcessingLogHandler, self).close() | ||||||
|  |  | ||||||
|  |  | ||||||
| def logger_create(log_obj, config, mode = 'a'): | def logger_create(log_obj, config, mode = 'a'): | ||||||
|         # Create new level. |         # Create new level. | ||||||
|         add_logging_level('MINI', logging.CRITICAL + 10) |         add_logging_level('MINI', logging.CRITICAL + 10) | ||||||
|  |         log_handlers = [] | ||||||
|  |  | ||||||
|         # Configure visualization. |         # Configure visualization. | ||||||
|         log_handlers = [] |  | ||||||
|         if any(opt in ['STDOUT', 'FILESTDOUT', 'STDOUTOFF'] for opt in config['logfile']): |         if any(opt in ['STDOUT', 'FILESTDOUT', 'STDOUTOFF'] for opt in config['logfile']): | ||||||
|                 if 'STDOUTOFF' not in config['logfile']: |                 if any(opt in ['STDOUT', 'FILESTDOUT'] for opt in config['logfile']): | ||||||
|                         # STDOUT. |                         # STDOUT or FILESTDOUT. | ||||||
|                         log_handlers.append(logging.StreamHandler(sys.stdout)) |                         hand_stdout = logging.StreamHandler(sys.stdout) | ||||||
|  |                         hand_stdout.name = 'LogStdout' | ||||||
|  |                         log_handlers.append(hand_stdout) | ||||||
|                 if any(opt in ['STDOUTOFF', 'FILESTDOUT'] for opt in config['logfile']): |                 if any(opt in ['STDOUTOFF', 'FILESTDOUT'] for opt in config['logfile']): | ||||||
|                         # FILESTDOUT or STDOUTOFF. |                         # STDOUTOFF or FILESTDOUT. | ||||||
|                         log_handlers.append(RotatingFileHandler(filename = config['logfile'][1], mode = mode, maxBytes = int(config['logsize'] * 1024 * 512), |                         hand_rotate = RotatingFileHandler(filename = config['logfile'][1], mode = mode, maxBytes = int(config['logsize'] * 1024 * 512), | ||||||
|                                                                 backupCount = 1, encoding = None, delay = 0)) |                                                           backupCount = 1, encoding = None, delay = 0) | ||||||
|  |                         hand_rotate.name = 'LogRotate' | ||||||
|  |                         log_handlers.append(hand_rotate) | ||||||
|         elif 'FILEOFF' in config['logfile']: |         elif 'FILEOFF' in config['logfile']: | ||||||
|                 config['loglevel'] = 'ERROR' # for py-kms GUI: set a recognized level never used. |                 hand_null = logging.FileHandler(os.devnull) | ||||||
|                 log_handlers.append(logging.FileHandler(os.devnull)) |                 hand_null.name = 'LogNull' | ||||||
|  |                 log_handlers.append(hand_null) | ||||||
|         else: |         else: | ||||||
|                 # FILE. |                 # FILE. | ||||||
|                 log_handlers.append(RotatingFileHandler(filename = config['logfile'][0], mode = mode, maxBytes = int(config['logsize'] * 1024 * 512), |                 hand_rotate = RotatingFileHandler(filename = config['logfile'][0], mode = mode, maxBytes = int(config['logsize'] * 1024 * 512), | ||||||
|                                                         backupCount = 1, encoding = None, delay = 0)) |                                                   backupCount = 1, encoding = None, delay = 0) | ||||||
|  |                 hand_rotate.name = 'LogRotate' | ||||||
|  |                 log_handlers.append(hand_rotate) | ||||||
|  |  | ||||||
|         # Configure formattation. |         # Configure formattation. | ||||||
|         try: |         try: | ||||||
| @@ -115,27 +191,38 @@ def logger_create(log_obj, config, mode = 'a'): | |||||||
|         except AttributeError: |         except AttributeError: | ||||||
|                 levelnames = logging._levelNames |                 levelnames = logging._levelNames | ||||||
|         levelnum = [k for k in levelnames if k != 0] |         levelnum = [k for k in levelnames if k != 0] | ||||||
|         frmt0 = '%(asctime)s %(levelname)-8s %(message)s' |  | ||||||
|         frmt1 = '[%(asctime)s] [%(levelname)-8s]   %(host)s   %(status)s   %(product)s   %(message)s' |         frmt_gen = '%(asctime)s %(levelname)-8s %(message)s' | ||||||
|  |         frmt_std = '%(name)s %(asctime)s %(levelname)-8s %(message)s' | ||||||
|  |         frmt_min = '[%(asctime)s] [%(levelname)-8s]   %(host)s   %(status)s   %(product)s   %(message)s' | ||||||
|  |  | ||||||
|  |         def apply_formatter(levelnum, formats, handler, color = False): | ||||||
|                 levelformdict = {} |                 levelformdict = {} | ||||||
|                 for num in levelnum: |                 for num in levelnum: | ||||||
|                         if num != logging.CRITICAL + 10: |                         if num != logging.CRITICAL + 10: | ||||||
|                         levelformdict[num] = frmt0 |                                 levelformdict[num] = formats[0] | ||||||
|                         else: |                         else: | ||||||
|                         levelformdict[num] = frmt1 |                                 levelformdict[num] = formats[1] | ||||||
|  |                 handler.setFormatter(LevelFormatter(levelformdict, color = color)) | ||||||
|  |                 return handler | ||||||
|  |  | ||||||
|  |         # Clear old handlers. | ||||||
|  |         if log_obj.handlers: | ||||||
|  |                 log_obj.handlers = [] | ||||||
|  |  | ||||||
|         # Set level and format. |  | ||||||
|         levelformdictcopy = levelformdict.copy() |  | ||||||
|         for log_handler in log_handlers: |         for log_handler in log_handlers: | ||||||
|                 log_handler.setLevel(config['loglevel']) |                 log_handler.setLevel(config['loglevel']) | ||||||
|                 if log_handler.__class__.__name__ == 'StreamHandler': |                 if log_handler.name in ['LogStdout']: | ||||||
|                         log_handler.setFormatter(LevelFormatter(levelformdict, color = True)) |                         log_handler = apply_formatter(levelnum, (frmt_std, frmt_min), log_handler, color = True) | ||||||
|                 elif log_handler.__class__.__name__ == 'RotatingFileHandler': |                 elif log_handler.name in ['LogRotate']: | ||||||
|                         log_handler.setFormatter(LevelFormatter(levelformdictcopy, color = False)) |                         log_handler = apply_formatter(levelnum, (frmt_gen, frmt_min), log_handler) | ||||||
|  |  | ||||||
|                 # Attach. |                 # Attach. | ||||||
|  |                 if config['asyncmsg']: | ||||||
|  |                         log_obj.addHandler(MultiProcessingLogHandler('Thread-AsyncMsg{0}'.format(log_handler.name), handler = log_handler)) | ||||||
|  |                 else: | ||||||
|  |                         log_obj.addHandler(log_handler) | ||||||
|  |  | ||||||
|         log_obj.setLevel(config['loglevel']) |         log_obj.setLevel(config['loglevel']) | ||||||
|         [ log_obj.addHandler(log_handler) for log_handler in log_handlers ] |  | ||||||
|  |  | ||||||
| #------------------------------------------------------------------------------------------------------------------------------------------------------------ | #------------------------------------------------------------------------------------------------------------------------------------------------------------ | ||||||
|  |  | ||||||
| @@ -144,14 +231,16 @@ def check_logfile(optionlog, defaultlog, where): | |||||||
|                 optionlog = [optionlog] |                 optionlog = [optionlog] | ||||||
|  |  | ||||||
|         lenopt = len(optionlog) |         lenopt = len(optionlog) | ||||||
|         msg_dir  = "{reverse}{red}{bold}argument logfile: invalid directory: '%s'. Exiting...{end}" |         msg_dir  = "{reverse}{red}{bold}argument `-F/--logfile`: invalid directory: '%s'. Exiting...{end}" | ||||||
|         msg_long = "{reverse}{red}{bold}argument logfile: too much arguments. Exiting...{end}" |         msg_long = "{reverse}{red}{bold}argument `-F/--logfile`: too much arguments. Exiting...{end}" | ||||||
|         msg_log = "{reverse}{red}{bold}argument logfile: not a log file, invalid extension: '%s'. Exiting...{end}" |         msg_log = "{reverse}{red}{bold}argument `-F/--logfile`: not a log file, invalid extension: '%s'. Exiting...{end}" | ||||||
|  |  | ||||||
|         def checkdir(path): |         def checkdir(path): | ||||||
|                 filename = os.path.basename(path) |                 filename = os.path.basename(path) | ||||||
|                 pathname = os.path.dirname(path) |                 pathname = os.path.dirname(path) | ||||||
|                 if not os.path.isdir(pathname): |                 if not os.path.isdir(pathname): | ||||||
|  |                         if path.count('/') == 0: | ||||||
|  |                                 pathname = filename | ||||||
|                         pretty_printer(put_text = msg_dir %pathname, where = where, to_exit = True) |                         pretty_printer(put_text = msg_dir %pathname, where = where, to_exit = True) | ||||||
|                 elif not filename.lower().endswith('.log'): |                 elif not filename.lower().endswith('.log'): | ||||||
|                         pretty_printer(put_text = msg_log %filename, where = where, to_exit = True) |                         pretty_printer(put_text = msg_log %filename, where = where, to_exit = True) | ||||||
| @@ -159,7 +248,6 @@ def check_logfile(optionlog, defaultlog, where): | |||||||
|         if lenopt > 2: |         if lenopt > 2: | ||||||
|                 pretty_printer(put_text = msg_long, where = where, to_exit = True) |                 pretty_printer(put_text = msg_long, where = where, to_exit = True) | ||||||
|  |  | ||||||
|  |  | ||||||
|         if (any(opt in ['FILESTDOUT', 'STDOUTOFF'] for opt in optionlog)): |         if (any(opt in ['FILESTDOUT', 'STDOUTOFF'] for opt in optionlog)): | ||||||
|                 if lenopt == 1: |                 if lenopt == 1: | ||||||
|                         # add default logfile. |                         # add default logfile. | ||||||
| @@ -215,8 +303,7 @@ def check_lcid(lcid, log_obj): | |||||||
|                                 fixlcid = next(k for k, v in locale.windows_locale.items() if v == locale.getdefaultlocale()[0]) |                                 fixlcid = next(k for k, v in locale.windows_locale.items() if v == locale.getdefaultlocale()[0]) | ||||||
|                         except StopIteration: |                         except StopIteration: | ||||||
|                                 fixlcid = 1033 |                                 fixlcid = 1033 | ||||||
|                 pretty_printer(log_obj = log_obj, |                 pretty_printer(log_obj = log_obj, put_text = "{reverse}{yellow}{bold}LCID '%s' auto-fixed with LCID '%s'{end}" %(lcid, fixlcid)) | ||||||
|                                put_text = "{reverse}{yellow}{bold}LCID %s auto-fixed with LCID %s{end}" %(lcid, fixlcid)) |  | ||||||
|                 return fixlcid |                 return fixlcid | ||||||
|         return lcid |         return lcid | ||||||
|  |  | ||||||
| @@ -262,28 +349,123 @@ class KmsParserHelp(object): | |||||||
|                 print(parser_base.epilog + '\n') |                 print(parser_base.epilog + '\n') | ||||||
|                 parser_base.exit() |                 parser_base.exit() | ||||||
|  |  | ||||||
|  | def kms_parser_get(parser): | ||||||
|  |         zeroarg, onearg = ([] for _ in range(2)) | ||||||
|  |         act = vars(parser)['_actions'] | ||||||
|  |         for i in range(len(act)): | ||||||
|  |                 if act[i].option_strings not in ([], ['-h', '--help']): | ||||||
|  |                         if isinstance(act[i], argparse._StoreAction): | ||||||
|  |                                 onearg.append(act[i].option_strings) | ||||||
|  |                         else: | ||||||
|  |                                 zeroarg.append(act[i].option_strings) | ||||||
|  |         return zeroarg, onearg | ||||||
|  |  | ||||||
|  | def kms_parser_check_optionals(userarg, zeroarg, onearg, msg = 'optional py-kms server', exclude_opt_len = []): | ||||||
|  |         """ | ||||||
|  |         For optionals arguments: | ||||||
|  |         Don't allow duplicates, | ||||||
|  |         Don't allow abbreviations, | ||||||
|  |         Don't allow joining and not existing arguments, | ||||||
|  |         Checks length values passed to arguments. | ||||||
|  |         """ | ||||||
|  |         zeroarg = [item for sublist in zeroarg for item in sublist] | ||||||
|  |         onearg = [item for sublist in onearg for item in sublist] | ||||||
|  |         allarg = zeroarg + onearg | ||||||
|  |  | ||||||
|  |         def is_abbrev(allarg, arg_to_check): | ||||||
|  |                 for opt in allarg: | ||||||
|  |                         if len(opt) > 2 and opt[2] == arg_to_check[2]: | ||||||
|  |                                 for indx in range(-1, -len(opt), -1): | ||||||
|  |                                         if opt[:indx] == arg_to_check: | ||||||
|  |                                                 raise KmsParserException("%s argument `%s` abbreviation not allowed for `%s`" %(msg, arg_to_check, opt)) | ||||||
|  |                 return False | ||||||
|  |  | ||||||
|  |         # Check abbreviations, joining, not existing. | ||||||
|  |         for arg in userarg: | ||||||
|  |                 if arg not in allarg: | ||||||
|  |                         if arg.startswith('-'): | ||||||
|  |                                 if arg == '--' or arg[:2] != '--' or not is_abbrev(allarg, arg): | ||||||
|  |                                         raise KmsParserException("unrecognized %s arguments: `%s`" %(msg, arg)) | ||||||
|  |  | ||||||
|  |         # Check duplicates. | ||||||
|  |         founds = [i for i in userarg if i in allarg] | ||||||
|  |         dup = [item for item in set(founds) if founds.count(item) > 1] | ||||||
|  |         if dup != []: | ||||||
|  |                 raise KmsParserException("%s argument `%s` appears several times" %(msg, ', '.join(dup))) | ||||||
|  |  | ||||||
|  |         # Check length. | ||||||
|  |         elem = None | ||||||
|  |         for found in founds: | ||||||
|  |                 if found not in exclude_opt_len: | ||||||
|  |                         pos = userarg.index(found) | ||||||
|  |                         try: | ||||||
|  |                                 if found in zeroarg: | ||||||
|  |                                         elem = userarg[pos + 1] | ||||||
|  |                                         num = "zero arguments," | ||||||
|  |                                 elif found in onearg: | ||||||
|  |                                         elem = userarg[pos + 2] | ||||||
|  |                                         num = "one argument," | ||||||
|  |                         except IndexError: | ||||||
|  |                                 pass | ||||||
|  |  | ||||||
|  |                         if elem and elem not in allarg: | ||||||
|  |                                 raise KmsParserException("%s argument `" %msg + found + "`:" + " expected " + num + " unrecognized: '%s'" %elem) | ||||||
|  |  | ||||||
|  | def kms_parser_check_positionals(config, parse_method, arguments = None, msg = 'positional py-kms server'): | ||||||
|  |         try: | ||||||
|  |                 if arguments: | ||||||
|  |                         config.update(vars(parse_method(arguments))) | ||||||
|  |                 else: | ||||||
|  |                         config.update(vars(parse_method())) | ||||||
|  |         except KmsParserException as e: | ||||||
|  |                 e = str(e) | ||||||
|  |                 if e.startswith('argument'): | ||||||
|  |                         raise | ||||||
|  |                 else: | ||||||
|  |                         raise KmsParserException("unrecognized %s arguments: '%s'" %(msg, e.split(': ')[1])) | ||||||
|  |  | ||||||
| #------------------------------------------------------------------------------------------------------------------------------------------------------------ | #------------------------------------------------------------------------------------------------------------------------------------------------------------ | ||||||
| def proper_none(dictionary): | def proper_none(dictionary): | ||||||
|         for key in dictionary.keys(): |         for key in dictionary.keys(): | ||||||
|                 dictionary[key] = None if dictionary[key] == 'None' else dictionary[key] |                 dictionary[key] = None if dictionary[key] == 'None' else dictionary[key] | ||||||
|  |  | ||||||
| def check_setup(config, options, logger, where): | def check_setup(config, options, logger, where): | ||||||
|  |         # 'None'--> None. | ||||||
|  |         proper_none(config) | ||||||
|  |  | ||||||
|         # Check logfile. |         # Check logfile. | ||||||
|         config['logfile'] = check_logfile(config['logfile'], options['lfile']['def'], where = where) |         config['logfile'] = check_logfile(config['logfile'], options['lfile']['def'], where = where) | ||||||
|  |  | ||||||
|         # Setup hidden or not messages. |         # Check logsize (py-kms Gui). | ||||||
|  |         if config['logsize'] == "": | ||||||
|  |                 if any(opt in ['STDOUT', 'FILEOFF'] for opt in config['logfile']): | ||||||
|  |                         # set a recognized size never used. | ||||||
|  |                         config['logsize'] = 0 | ||||||
|  |                 else: | ||||||
|  |                         pretty_printer(put_text = "{reverse}{red}{bold}argument `-S/--logsize`: invalid with: '%s'. Exiting...{end}" %config['logsize'], | ||||||
|  |                                        where = where, to_exit = True) | ||||||
|  |  | ||||||
|  |         # Check loglevel (py-kms Gui). | ||||||
|  |         if config['loglevel'] == "": | ||||||
|  |                 # set a recognized level never used. | ||||||
|  |                 config['loglevel'] = 'ERROR' | ||||||
|  |  | ||||||
|  |         # Setup hidden / asynchronous messages. | ||||||
|         hidden = ['STDOUT', 'FILESTDOUT', 'STDOUTOFF'] |         hidden = ['STDOUT', 'FILESTDOUT', 'STDOUTOFF'] | ||||||
|         ShellMessage.view = (False if any(opt in hidden for opt in config['logfile']) else True) |         view_flag = (False if any(opt in hidden for opt in config['logfile']) else True) | ||||||
|  |         if where == 'srv': | ||||||
|  |                 ShellMessage.viewsrv = view_flag | ||||||
|  |                 ShellMessage.asyncmsgsrv = config['asyncmsg'] | ||||||
|  |         elif where == 'clt': | ||||||
|  |                 ShellMessage.viewclt = view_flag | ||||||
|  |                 ShellMessage.asyncmsgclt = config['asyncmsg'] | ||||||
|  |  | ||||||
|         # Create log. |         # Create log. | ||||||
|         logger_create(logger, config, mode = 'a') |         logger_create(logger, config, mode = 'a') | ||||||
|  |  | ||||||
|         # 'None'--> None. |  | ||||||
|         proper_none(config) |  | ||||||
|  |  | ||||||
|         # Check port. |         # Check port. | ||||||
|         if not 1 <= config['port'] <= 65535: |         if (config['port'] == "") or (not 1 <= config['port'] <= 65535): | ||||||
|                 pretty_printer(log_obj = logger.error, to_exit = True, |                 pretty_printer(log_obj = logger.error, where = where, to_exit = True, | ||||||
|                                put_text = "{reverse}{red}{bold}Port number '%s' is invalid. Enter between 1 - 65535. Exiting...{end}" %config['port']) |                                put_text = "{reverse}{red}{bold}Port number '%s' is invalid. Enter between 1 - 65535. Exiting...{end}" %config['port']) | ||||||
|  |  | ||||||
| #------------------------------------------------------------------------------------------------------------------------------------------------------------ | #------------------------------------------------------------------------------------------------------------------------------------------------------------ | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ from pykms_RpcBase import rpcBase | |||||||
| from pykms_Dcerpc import MSRPCHeader | from pykms_Dcerpc import MSRPCHeader | ||||||
| from pykms_Misc import check_setup, check_lcid | from pykms_Misc import check_setup, check_lcid | ||||||
| from pykms_Misc import KmsParser, KmsParserException, KmsParserHelp | from pykms_Misc import KmsParser, KmsParserException, KmsParserHelp | ||||||
|  | from pykms_Misc import kms_parser_get, kms_parser_check_optionals, kms_parser_check_positionals | ||||||
| from pykms_Format import enco, deco, pretty_printer | from pykms_Format import enco, deco, pretty_printer | ||||||
| from Etrigan import Etrigan, Etrigan_parser, Etrigan_check, Etrigan_job | from Etrigan import Etrigan, Etrigan_parser, Etrigan_check, Etrigan_job | ||||||
|  |  | ||||||
| @@ -148,12 +149,15 @@ class server_thread(threading.Thread): | |||||||
|                                                 # Create and run server. |                                                 # Create and run server. | ||||||
|                                                 self.server = server_create() |                                                 self.server = server_create() | ||||||
|                                                 self.server.pykms_serve() |                                                 self.server.pykms_serve() | ||||||
|                                 except SystemExit as e: |                                 except (SystemExit, Exception) as e: | ||||||
|                                         self.eject = True |                                         self.eject = True | ||||||
|                                         if not self.with_gui: |                                         if not self.with_gui: | ||||||
|                                                 raise |                                                 raise | ||||||
|                                         else: |                                         else: | ||||||
|  |                                                 if isinstance(e, SystemExit): | ||||||
|                                                         continue |                                                         continue | ||||||
|  |                                                 else: | ||||||
|  |                                                         raise | ||||||
|  |  | ||||||
| ##--------------------------------------------------------------------------------------------------------------------------------------------------------- | ##--------------------------------------------------------------------------------------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| @@ -168,17 +172,19 @@ srv_options = { | |||||||
|         'lcid' : {'help' : 'Use this option to manually specify an LCID for use with randomly generated ePIDs. Default is \"1033\" (en-us)', |         'lcid' : {'help' : 'Use this option to manually specify an LCID for use with randomly generated ePIDs. Default is \"1033\" (en-us)', | ||||||
|                   'def' : 1033, 'des' : "lcid"}, |                   'def' : 1033, 'des' : "lcid"}, | ||||||
|         'count' : {'help' : 'Use this option to specify the current client count. A number >=25 is required to enable activation of client OSes; \ |         'count' : {'help' : 'Use this option to specify the current client count. A number >=25 is required to enable activation of client OSes; \ | ||||||
| for server OSes and Office >=5', 'def' : None, 'des' : "CurrentClientCount"}, | for server OSes and Office >=5', 'def' : None, 'des' : "clientcount"}, | ||||||
|         'activation' : {'help' : 'Use this option to specify the activation interval (in minutes). Default is \"120\" minutes (2 hours).', |         'activation' : {'help' : 'Use this option to specify the activation interval (in minutes). Default is \"120\" minutes (2 hours).', | ||||||
|                         'def' : 120, 'des': "VLActivationInterval"}, |                         'def' : 120, 'des': "activation"}, | ||||||
|         'renewal' : {'help' : 'Use this option to specify the renewal interval (in minutes). Default is \"10080\" minutes (7 days).', |         'renewal' : {'help' : 'Use this option to specify the renewal interval (in minutes). Default is \"10080\" minutes (7 days).', | ||||||
|                      'def' : 1440 * 7, 'des' : "VLRenewalInterval"}, |                      'def' : 1440 * 7, 'des' : "renewal"}, | ||||||
|         'sql' : {'help' : 'Use this option to store request information from unique clients in an SQLite database. Desactivated by default.', |         'sql' : {'help' : 'Use this option to store request information from unique clients in an SQLite database. Desactivated by default.', | ||||||
|                  'def' : False, 'des' : "sqlite"}, |                  'def' : False, 'des' : "sqlite"}, | ||||||
|         'hwid' : {'help' : 'Use this option to specify a HWID. The HWID must be an 16-character string of hex characters. \ |         'hwid' : {'help' : 'Use this option to specify a HWID. The HWID must be an 16-character string of hex characters. \ | ||||||
| The default is \"364F463A8863D35F\" or type \"RANDOM\" to auto generate the HWID.', 'def' : "364F463A8863D35F", 'des' : "hwid"}, | The default is \"364F463A8863D35F\" or type \"RANDOM\" to auto generate the HWID.', 'def' : "364F463A8863D35F", 'des' : "hwid"}, | ||||||
|         'time0' : {'help' : 'Maximum inactivity time (in seconds) after which the connection with the client is closed. If \"None\" (default) serve forever.', |         'time0' : {'help' : 'Maximum inactivity time (in seconds) after which the connection with the client is closed. If \"None\" (default) serve forever.', | ||||||
|                    'def' : None, 'des' : "timeout_idle"}, |                    'def' : None, 'des' : "timeoutidle"}, | ||||||
|  |         'asyncmsg' : {'help' : 'Prints pretty / logging messages asynchronously. Desactivated by default.', | ||||||
|  |                       'def' : False, 'des' : "asyncmsg"}, | ||||||
|         'llevel' : {'help' : 'Use this option to set a log level. The default is \"ERROR\".', 'def' : "ERROR", 'des' : "loglevel", |         'llevel' : {'help' : 'Use this option to set a log level. The default is \"ERROR\".', 'def' : "ERROR", 'des' : "loglevel", | ||||||
|                     'choi' : ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "MINI"]}, |                     'choi' : ["CRITICAL", "ERROR", "WARNING", "INFO", "DEBUG", "MINI"]}, | ||||||
|         'lfile' : {'help' : 'Use this option to set an output log file. The default is \"pykms_logserver.log\". \ |         'lfile' : {'help' : 'Use this option to set an output log file. The default is \"pykms_logserver.log\". \ | ||||||
| @@ -189,11 +195,7 @@ Use \"STDOUTOFF\" to disable stdout messages. Use \"FILEOFF\" if you not want to | |||||||
|         } |         } | ||||||
|  |  | ||||||
| def server_options(): | def server_options(): | ||||||
|         try: |  | ||||||
|                 server_parser = KmsParser(description = srv_description, epilog = 'version: ' + srv_version, add_help = False, allow_abbrev = False) |  | ||||||
|         except TypeError: |  | ||||||
|         server_parser = KmsParser(description = srv_description, epilog = 'version: ' + srv_version, add_help = False) |         server_parser = KmsParser(description = srv_description, epilog = 'version: ' + srv_version, add_help = False) | ||||||
|  |  | ||||||
|         server_parser.add_argument("ip", nargs = "?", action = "store", default = srv_options['ip']['def'], help = srv_options['ip']['help'], type = str) |         server_parser.add_argument("ip", nargs = "?", action = "store", default = srv_options['ip']['def'], help = srv_options['ip']['help'], type = str) | ||||||
|         server_parser.add_argument("port", nargs = "?", action = "store", default = srv_options['port']['def'], help = srv_options['port']['help'], type = int) |         server_parser.add_argument("port", nargs = "?", action = "store", default = srv_options['port']['def'], help = srv_options['port']['help'], type = int) | ||||||
|         server_parser.add_argument("-e", "--epid", action = "store", dest = srv_options['epid']['des'], default = srv_options['epid']['def'], |         server_parser.add_argument("-e", "--epid", action = "store", dest = srv_options['epid']['des'], default = srv_options['epid']['def'], | ||||||
| @@ -204,85 +206,114 @@ def server_options(): | |||||||
|                                    help = srv_options['count']['help'], type = str) |                                    help = srv_options['count']['help'], type = str) | ||||||
|         server_parser.add_argument("-a", "--activation-interval", action = "store", dest = srv_options['activation']['des'], |         server_parser.add_argument("-a", "--activation-interval", action = "store", dest = srv_options['activation']['des'], | ||||||
|                                    default = srv_options['activation']['def'], help = srv_options['activation']['help'], type = int) |                                    default = srv_options['activation']['def'], help = srv_options['activation']['help'], type = int) | ||||||
|         server_parser.add_argument("-r", "--renewal-interval", action = "store", dest = srv_options['renewal']['des'], default = srv_options['renewal']['def'], |         server_parser.add_argument("-r", "--renewal-interval", action = "store", dest = srv_options['renewal']['des'], | ||||||
|                                    help = srv_options['renewal']['help'], type = int) |                                    default = srv_options['renewal']['def'], help = srv_options['renewal']['help'], type = int) | ||||||
|         server_parser.add_argument("-s", "--sqlite", action = "store_const", dest = srv_options['sql']['des'], const = True, default = srv_options['sql']['def'], |         server_parser.add_argument("-s", "--sqlite", action = "store_true", dest = srv_options['sql']['des'], | ||||||
|                                    help = srv_options['sql']['help']) |                                    default = srv_options['sql']['def'], help = srv_options['sql']['help']) | ||||||
|         server_parser.add_argument("-w", "--hwid", action = "store", dest = srv_options['hwid']['des'], default = srv_options['hwid']['def'], |         server_parser.add_argument("-w", "--hwid", action = "store", dest = srv_options['hwid']['des'], default = srv_options['hwid']['def'], | ||||||
|                                    help = srv_options['hwid']['help'], type = str) |                                    help = srv_options['hwid']['help'], type = str) | ||||||
|         server_parser.add_argument("-t0", "--timeout-idle", action = "store", dest = srv_options['time0']['des'], default = srv_options['time0']['def'], |         server_parser.add_argument("-t0", "--timeout-idle", action = "store", dest = srv_options['time0']['des'], default = srv_options['time0']['def'], | ||||||
|                                    help = srv_options['time0']['help'], type = str) |                                    help = srv_options['time0']['help'], type = str) | ||||||
|  |         server_parser.add_argument("-y", "--async-msg", action = "store_true", dest = srv_options['asyncmsg']['des'], | ||||||
|  |                                    default = srv_options['asyncmsg']['def'], help = srv_options['asyncmsg']['help']) | ||||||
|         server_parser.add_argument("-V", "--loglevel", action = "store", dest = srv_options['llevel']['des'], choices = srv_options['llevel']['choi'], |         server_parser.add_argument("-V", "--loglevel", action = "store", dest = srv_options['llevel']['des'], choices = srv_options['llevel']['choi'], | ||||||
|                                    default = srv_options['llevel']['def'], help = srv_options['llevel']['help'], type = str) |                                    default = srv_options['llevel']['def'], help = srv_options['llevel']['help'], type = str) | ||||||
|         server_parser.add_argument("-F", "--logfile", nargs = "+", action = "store", dest = srv_options['lfile']['des'], default = srv_options['lfile']['def'], |         server_parser.add_argument("-F", "--logfile", nargs = "+", action = "store", dest = srv_options['lfile']['des'], | ||||||
|                                    help = srv_options['lfile']['help'], type = str) |                                    default = srv_options['lfile']['def'], help = srv_options['lfile']['help'], type = str) | ||||||
|         server_parser.add_argument("-S", "--logsize", action = "store", dest = srv_options['lsize']['des'], default = srv_options['lsize']['def'], |         server_parser.add_argument("-S", "--logsize", action = "store", dest = srv_options['lsize']['des'], default = srv_options['lsize']['def'], | ||||||
|                                    help = srv_options['lsize']['help'], type = float) |                                    help = srv_options['lsize']['help'], type = float) | ||||||
|  |  | ||||||
|         server_parser.add_argument("-h", "--help", action = "help", help = "show this help message and exit") |         server_parser.add_argument("-h", "--help", action = "help", help = "show this help message and exit") | ||||||
|  |  | ||||||
|         try: |  | ||||||
|                 daemon_parser = KmsParser(description = "daemon options inherited from Etrigan", add_help = False, allow_abbrev = False) |  | ||||||
|         except TypeError: |  | ||||||
|         daemon_parser = KmsParser(description = "daemon options inherited from Etrigan", add_help = False) |         daemon_parser = KmsParser(description = "daemon options inherited from Etrigan", add_help = False) | ||||||
|  |  | ||||||
|         daemon_subparser = daemon_parser.add_subparsers(dest = "mode") |         daemon_subparser = daemon_parser.add_subparsers(dest = "mode") | ||||||
|         try: |  | ||||||
|                 etrigan_parser = daemon_subparser.add_parser("etrigan", add_help = False, allow_abbrev = False) |  | ||||||
|         except TypeError: |  | ||||||
|         etrigan_parser = daemon_subparser.add_parser("etrigan", add_help = False) |         etrigan_parser = daemon_subparser.add_parser("etrigan", add_help = False) | ||||||
|         etrigan_parser.add_argument("-g", "--gui", action = "store_const", dest = 'gui', const = True, default = False, |         etrigan_parser.add_argument("-g", "--gui", action = "store_const", dest = 'gui', const = True, default = False, | ||||||
|                                     help = "Enable py-kms GUI usage.") |                                     help = "Enable py-kms GUI usage.") | ||||||
|         etrigan_parser = Etrigan_parser(parser = etrigan_parser) |         etrigan_parser = Etrigan_parser(parser = etrigan_parser) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|                 if "-h" in sys.argv[1:]: |                 userarg = sys.argv[1:] | ||||||
|  |  | ||||||
|  |                 # Run help. | ||||||
|  |                 if any(arg in ["-h", "--help"] for arg in userarg): | ||||||
|                         KmsParserHelp().printer(parsers = [server_parser, daemon_parser, etrigan_parser]) |                         KmsParserHelp().printer(parsers = [server_parser, daemon_parser, etrigan_parser]) | ||||||
|  |  | ||||||
|                 # Set defaults for config. |                 # Get stored arguments. | ||||||
|                 # case: python3 pykms_Server.py |                 pykmssrv_zeroarg, pykmssrv_onearg = kms_parser_get(server_parser) | ||||||
|                 srv_config.update(vars(server_parser.parse_args([]))) |                 etrigan_zeroarg, etrigan_onearg = kms_parser_get(etrigan_parser) | ||||||
|                 # Eventually set daemon values for config. |                 pykmssrv_zeroarg += ['etrigan'] # add subparser | ||||||
|                 if 'etrigan' in sys.argv[1:]: |  | ||||||
|                         if 'etrigan' == sys.argv[1]: |  | ||||||
|                                 # case: python3 pykms_Server.py etrigan start --daemon_optionals |  | ||||||
|                                 srv_config.update(vars(daemon_parser.parse_args(sys.argv[1:]))) |  | ||||||
|                         elif 'etrigan' == sys.argv[2]: |  | ||||||
|                                 # case: python3 pykms_Server.py 1.2.3.4 etrigan start --daemon_optionals |  | ||||||
|                                 srv_config['ip'] = sys.argv[1] |  | ||||||
|                                 srv_config.update(vars(daemon_parser.parse_args(sys.argv[2:]))) |  | ||||||
|                         else: |  | ||||||
|                                 # case: python3 pykms_Server.py 1.2.3.4 1234 --main_optionals etrigan start --daemon_optionals |  | ||||||
|                                 knw_args, knw_extras = server_parser.parse_known_args() |  | ||||||
|                                 # fix for logfile option (at the end) that catchs etrigan parser options. |  | ||||||
|                                 if 'etrigan' in knw_args.logfile: |  | ||||||
|                                         indx = knw_args.logfile.index('etrigan') |  | ||||||
|                                         for num, elem in enumerate(knw_args.logfile[indx:]): |  | ||||||
|                                                 knw_extras.insert(num, elem) |  | ||||||
|                                         knw_args.logfile = knw_args.logfile[:indx] |  | ||||||
|  |  | ||||||
|                                 # continue parsing. |                 # Set defaults for config. | ||||||
|                                 if len(knw_extras) > 0 and knw_extras[0] in ['etrigan']: |                 # example case: | ||||||
|                                         daemon_parser.parse_args(knw_extras, namespace = knw_args) |                 #               python3 pykms_Server.py | ||||||
|                                 srv_config.update(vars(knw_args)) |                 srv_config.update(vars(server_parser.parse_args([]))) | ||||||
|                 else: |  | ||||||
|                         # Update dict config. |                 try: | ||||||
|                         # case: python3 pykms_Server.py 1.2.3.4 1234 --main_optionals |                         # Eventually set daemon options for dict server config. | ||||||
|                         knw_args, knw_extras = server_parser.parse_known_args() |                         pos = sys.argv[1:].index('etrigan') | ||||||
|                         if knw_extras != []: |                         # example cases: | ||||||
|                                 raise KmsParserException("unrecognized arguments: %s" %' '.join(knw_extras)) |                         #               python3 pykms_Server.py etrigan start | ||||||
|                         else: |                         #               python3 pykms_Server.py etrigan start --daemon_optionals | ||||||
|                                 srv_config.update(vars(knw_args)) |                         #               python3 pykms_Server.py 1.2.3.4 etrigan start | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 etrigan start --daemon_optionals | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 1234 etrigan start | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 1234 etrigan start --daemon_optionals | ||||||
|  |                         #               python3 pykms_Server.py --pykms_optionals etrigan start | ||||||
|  |                         #               python3 pykms_Server.py --pykms_optionals etrigan start --daemon_optionals | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 --pykms_optionals etrigan start | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 --pykms_optionals etrigan start --daemon_optionals | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 1234 --pykms_optionals etrigan start | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 1234 --pykms_optionals etrigan start --daemon_optionals | ||||||
|  |  | ||||||
|  |                         kms_parser_check_optionals(userarg[0:pos], pykmssrv_zeroarg, pykmssrv_onearg, exclude_opt_len = ['-F', '--logfile']) | ||||||
|  |                         kms_parser_check_positionals(srv_config, server_parser.parse_args, arguments = userarg[0:pos]) | ||||||
|  |                         kms_parser_check_optionals(userarg[pos:], etrigan_zeroarg, etrigan_onearg, msg = 'optional etrigan') | ||||||
|  |                         kms_parser_check_positionals(srv_config, daemon_parser.parse_args, arguments = userarg[pos:], msg = 'positional etrigan') | ||||||
|  |  | ||||||
|  |                 except ValueError: | ||||||
|  |                         # Update pykms options for dict server config. | ||||||
|  |                         # example cases: | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 --pykms_optionals | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 1234 | ||||||
|  |                         #               python3 pykms_Server.py 1.2.3.4 1234 --pykms_optionals | ||||||
|  |                         #               python3 pykms_Server.py --pykms_optionals | ||||||
|  |  | ||||||
|  |                         kms_parser_check_optionals(userarg, pykmssrv_zeroarg, pykmssrv_onearg, exclude_opt_len = ['-F', '--logfile']) | ||||||
|  |                         kms_parser_check_positionals(srv_config, server_parser.parse_args) | ||||||
|  |  | ||||||
|         except KmsParserException as e: |         except KmsParserException as e: | ||||||
|                 pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) |                 pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Etrigan_Check(Etrigan_check): | ||||||
|  |         def emit_opt_err(self, msg): | ||||||
|  |                 pretty_printer(put_text = "{reverse}{red}{bold}%s{end}" %msg, to_exit = True) | ||||||
|  |  | ||||||
|  | class Etrigan(Etrigan): | ||||||
|  |         def emit_message(self, message, to_exit = False): | ||||||
|  |                 if not self.mute: | ||||||
|  |                         pretty_printer(put_text = "{reverse}{green}{bold}%s{end}" %message) | ||||||
|  |                 if to_exit: | ||||||
|  |                         sys.exit(0) | ||||||
|  |  | ||||||
|  |         def emit_error(self, message, to_exit = True): | ||||||
|  |                 if not self.mute: | ||||||
|  |                         pretty_printer(put_text = "{reverse}{red}{bold}%s{end}" %message, to_exit = True) | ||||||
|  |  | ||||||
| def server_daemon(): | def server_daemon(): | ||||||
|         if 'etrigan' in srv_config.values(): |         if 'etrigan' in srv_config.values(): | ||||||
|                 path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pykms_config.pickle') |                 path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'pykms_config.pickle') | ||||||
|  |  | ||||||
|                 if srv_config['operation'] in ['stop', 'restart', 'status'] and len(sys.argv[1:]) > 2: |                 if srv_config['operation'] in ['stop', 'restart', 'status'] and len(sys.argv[1:]) > 2: | ||||||
|                         pretty_printer(put_text = "{reverse}{red}{bold}too much arguments. Exiting...{end}", to_exit = True) |                         pretty_printer(put_text = "{reverse}{red}{bold}too much arguments with etrigan '%s'. Exiting...{end}" %srv_config['operation'], | ||||||
|  |                                        to_exit = True) | ||||||
|  |  | ||||||
|  |                 # Check file arguments. | ||||||
|  |                 Etrigan_Check().checkfile(srv_config['etriganpid'], '--etrigan-pid', '.pid') | ||||||
|  |                 Etrigan_Check().checkfile(srv_config['etriganlog'], '--etrigan-log', '.log') | ||||||
|  |  | ||||||
|                 if srv_config['gui']: |                 if srv_config['gui']: | ||||||
|                         pass |                         pass | ||||||
| @@ -357,21 +388,30 @@ def server_check(): | |||||||
|         else: |         else: | ||||||
|                 srv_config['dbSupport'] = True |                 srv_config['dbSupport'] = True | ||||||
|  |  | ||||||
|         # Check client count, timeout. |  | ||||||
|         list_dest = ['CurrentClientCount', 'timeout_idle'] |         # Check other specific server options. | ||||||
|         list_opt = ['--client-count', '--timeout-idle'] |         list_dest = ['clientcount', 'timeoutidle'] | ||||||
|  |         list_opt = ['-c/--client-count', '-t0/--timeout-idle'] | ||||||
|  |  | ||||||
|  |         if serverthread.with_gui: | ||||||
|  |                 list_dest += ['activation', 'renewal'] | ||||||
|  |                 list_opt += ['-a/--activation-interval', '-r/--renewal-interval'] | ||||||
|  |  | ||||||
|         for dest, opt in zip(list_dest, list_opt): |         for dest, opt in zip(list_dest, list_opt): | ||||||
|                 if srv_config[dest] is not None: |                 value = srv_config[dest] | ||||||
|                         if not srv_config[dest].isdigit(): |                 if (value is not None) and (not isinstance(value, int)): | ||||||
|                         pretty_printer(log_obj = loggersrv.error, to_exit = True, |                         pretty_printer(log_obj = loggersrv.error, to_exit = True, | ||||||
|                                                put_text = "{reverse}{red}{bold}Option %s is invalid with '%s'. Exiting...{end}" |                                        put_text = "{reverse}{red}{bold}argument `%s`: invalid with: '%s'. Exiting...{end}" %(opt, value)) | ||||||
|                                                %(opt, srv_config[dest])) |  | ||||||
|                         else: |  | ||||||
|                                 srv_config[dest] = int(srv_config[dest]) |  | ||||||
|  |  | ||||||
| def server_create(): | def server_create(): | ||||||
|  |         try: | ||||||
|                 server = KeyServer((srv_config['ip'], srv_config['port']), kmsServerHandler) |                 server = KeyServer((srv_config['ip'], srv_config['port']), kmsServerHandler) | ||||||
|         server.timeout = srv_config['timeout_idle'] |         except (socket.gaierror, socket.error) as e: | ||||||
|  |                 pretty_printer(log_obj = loggersrv.error, to_exit = True, | ||||||
|  |                                put_text = "{reverse}{red}{bold}Connection failed '%s:%d': %s. Exiting...{end}" %(srv_config['ip'], | ||||||
|  |                                                                                                                 srv_config['port'], | ||||||
|  |                                                                                                                 str(e))) | ||||||
|  |         server.timeout = srv_config['timeoutidle'] | ||||||
|         loggersrv.info("TCP server listening at %s on port %d." % (srv_config['ip'], srv_config['port'])) |         loggersrv.info("TCP server listening at %s on port %d." % (srv_config['ip'], srv_config['port'])) | ||||||
|         loggersrv.info("HWID: %s" % deco(binascii.b2a_hex(srv_config['hwid']), 'utf-8').upper()) |         loggersrv.info("HWID: %s" % deco(binascii.b2a_hex(srv_config['hwid']), 'utf-8').upper()) | ||||||
|         return server |         return server | ||||||
| @@ -426,20 +466,8 @@ def server_main_terminal(): | |||||||
| def server_with_gui(): | def server_with_gui(): | ||||||
|         import pykms_GuiBase |         import pykms_GuiBase | ||||||
|  |  | ||||||
|         width = 950 |  | ||||||
|         height = 660 |  | ||||||
|  |  | ||||||
|         root = pykms_GuiBase.KmsGui() |         root = pykms_GuiBase.KmsGui() | ||||||
|         root.title(pykms_GuiBase.gui_description + ' (' + pykms_GuiBase.gui_version + ')') |         root.title(pykms_GuiBase.gui_description + ' (' + pykms_GuiBase.gui_version + ')') | ||||||
|         # Main window initial position. |  | ||||||
|         ## https://stackoverflow.com/questions/14910858/how-to-specify-where-a-tkinter-window-opens |  | ||||||
|         ws = root.winfo_screenwidth() |  | ||||||
|         hs = root.winfo_screenheight() |  | ||||||
|         x = (ws / 2) - (width / 2) |  | ||||||
|         y = (hs / 2) - (height / 2) |  | ||||||
|         root.geometry('+%d+%d' %(x, y)) |  | ||||||
|         # disable maximize button. |  | ||||||
|         root.resizable(0, 0) |  | ||||||
|         root.mainloop() |         root.mainloop() | ||||||
|  |  | ||||||
| def server_main_no_terminal(): | def server_main_no_terminal(): | ||||||
| @@ -449,7 +477,7 @@ def server_main_no_terminal(): | |||||||
|  |  | ||||||
| class kmsServerHandler(socketserver.BaseRequestHandler): | class kmsServerHandler(socketserver.BaseRequestHandler): | ||||||
|         def setup(self): |         def setup(self): | ||||||
|                 loggersrv.info("Connection accepted: %s:%d" % (self.client_address[0], self.client_address[1])) |                 loggersrv.info("Connection accepted: %s:%d" %(self.client_address[0], self.client_address[1])) | ||||||
|  |  | ||||||
|         def handle(self): |         def handle(self): | ||||||
|                 while True: |                 while True: | ||||||
| @@ -499,7 +527,7 @@ class kmsServerHandler(socketserver.BaseRequestHandler): | |||||||
|  |  | ||||||
|         def finish(self): |         def finish(self): | ||||||
|                 self.request.close() |                 self.request.close() | ||||||
|                 loggersrv.info("Connection closed: %s:%d" % (self.client_address[0], self.client_address[1])) |                 loggersrv.info("Connection closed: %s:%d" %(self.client_address[0], self.client_address[1])) | ||||||
|  |  | ||||||
|  |  | ||||||
| serverqueue = Queue.Queue(maxsize = 0) | serverqueue = Queue.Queue(maxsize = 0) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user