diff --git a/py-kms/pykms_Client.py b/py-kms/pykms_Client.py index 8a97ff7..6ed5a27 100644 --- a/py-kms/pykms_Client.py +++ b/py-kms/pykms_Client.py @@ -10,6 +10,7 @@ import sys import uuid import logging import os +import threading import pykms_RpcBind, pykms_RpcRequest from pykms_Filetimes import dt_to_filetime @@ -28,6 +29,16 @@ clt_description = 'KMS Client Emulator written in Python' clt_version = 'py-kms_2019-05-15' clt_config = {} +#--------------------------------------------------------------------------------------------------------------------------------------------------------- +class client_thread(threading.Thread): + def __init__(self, name): + threading.Thread.__init__(self) + self.name = name + self.with_gui = False + + def run(self): + clt_main(with_gui = self.with_gui) + #--------------------------------------------------------------------------------------------------------------------------------------------------------- loggerclt = logging.getLogger('logclt') @@ -69,13 +80,22 @@ def client_options(): try: clt_config.update(vars(parser.parse_args())) # Check logfile. - clt_config['logfile'] = check_logfile(clt_config['logfile'], clt_options['lfile']['def']) + clt_config['logfile'] = check_logfile(clt_config['logfile'], clt_options['lfile']['def'], where = "clt") except KmsException as e: pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) def client_check(): + # Check logfile (only for GUI). + try: + from pykms_GuiBase import clientthread + if clientthread.with_gui: + clt_config['logfile'] = check_logfile(clt_config['logfile'], clt_options['lfile']['def'], where = "clt") + except ImportError: + pass + # Setup hidden or not messages. ShellMessage.view = ( False if any(i in ['STDOUT', 'FILESTDOUT'] for i in clt_config['logfile']) else True ) + # Create log. logger_create(loggerclt, clt_config, mode = 'a') @@ -84,12 +104,12 @@ def client_check(): try: uuid.UUID(clt_config['cmid']) except ValueError: - pretty_printer(log_obj = loggerclt.error, to_exit = True, + pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}Bad CMID. Exiting...{end}") # Check machineName. if clt_config['machineName'] is not None: if len(clt_config['machineName']) < 2 or len(clt_config['machineName']) > 63: - pretty_printer(log_obj = loggerclt.error, to_exit = True, + 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 @@ -131,16 +151,16 @@ def client_create(): pretty_printer(num_text = [-1, 1], where = "clt") s.send(RPC_Bind) except socket.error as e: - pretty_printer(log_obj = loggerclt.error, to_exit = True, + pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While sending: %s{end}" %str(e)) try: bindResponse = s.recv(1024) if bindResponse == '' or not bindResponse: - pretty_printer(log_obj = loggerclt.warning, to_exit = True, + pretty_printer(log_obj = loggerclt.warning, to_exit = True, where = "clt", put_text = "{reverse}{yellow}{bold}No data received.{end}") pretty_printer(num_text = [-4, 7], where = "clt") except socket.error as e: - pretty_printer(log_obj = loggerclt.error, to_exit = True, + pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While receiving: %s{end}" %str(e)) packetType = MSRPCHeader(bindResponse)['type'] @@ -156,13 +176,13 @@ def client_create(): pretty_printer(num_text = [-1, 12], where = "clt") s.send(RPC_Actv) except socket.error as e: - pretty_printer(log_obj = loggerclt.error, to_exit = True, + pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While sending: %s{end}" %str(e)) try: response = s.recv(1024) pretty_printer(num_text = [-4, 20], where = "clt") except socket.error as e: - pretty_printer(log_obj = loggerclt.error, to_exit = True, + pretty_printer(log_obj = loggerclt.error, to_exit = True, where = "clt", put_text = "{reverse}{red}{bold}While receiving: %s{end}" %str(e)) loggerclt.debug("Response: \n%s\n" % justify(deco(binascii.b2a_hex(response), 'latin-1'))) @@ -191,7 +211,7 @@ def client_create(): loggerclt.info(justify(MSRPCBindNak(bindResponse).dump(print_to_stdout = False))) sys.exit(0) else: - pretty_printer(log_obj = loggerclt.warning, to_exit = True, + pretty_printer(log_obj = loggerclt.warning, to_exit = True, where = "clt", put_text = "{reverse}{magenta}{bold}Something went wrong.{end}") def clt_main(with_gui = False): diff --git a/py-kms/pykms_GuiBase.py b/py-kms/pykms_GuiBase.py index 87bc01b..85c413d 100644 --- a/py-kms/pykms_GuiBase.py +++ b/py-kms/pykms_GuiBase.py @@ -22,9 +22,8 @@ except ImportError: from pykms_Server import srv_options, srv_version, srv_config, srv_terminate, serverqueue, serverthread from pykms_GuiMisc import ToolTip, TextDoubleScroll, TextRedirect, custom_background -from pykms_Client import clt_options, clt_version, clt_config, clt_main +from pykms_Client import clt_options, clt_version, clt_config, client_thread -from pykms_Misc import check_logfile gui_description = 'py-kms GUI' gui_version = 'v1.0' @@ -42,26 +41,14 @@ def get_ip_address(): import socket ip = socket.gethostbyname(socket.gethostname()) else: - ip = '' - print('Error: Couldn\'t get local ip') + ip = 'Unknown' return ip - -def switch_dir(path): - if os.path.isdir(path): - os.chdir(path) - return True - - if path == '': - os.chdir(os.getcwd()) - return True - else: - return def gui_redirect(str_to_print, where): - global txsrv, txclt, txcol, rclt + global txsrv, txclt, txcol try: - TextRedirect.StdoutRedirect(txsrv, txclt, txcol, rclt, str_to_print, where) + TextRedirect.StdoutRedirect(txsrv, txclt, txcol, str_to_print, where) except: print(str_to_print) @@ -79,7 +66,8 @@ class KmsGui(tk.Tk): tk.Tk.__init__(self, *args, **kwargs) self.wraplength = 200 serverthread.with_gui = True - + self.validation_int = self.register(self.validate_int) + ## Define fonts and colors. self.btnwinfont = tkFont.Font(family = 'Times', size = 12, weight = 'bold') self.othfont = tkFont.Font(family = 'Times', size = 9, weight = 'bold') @@ -105,11 +93,10 @@ class KmsGui(tk.Tk): ## Create client gui + other operations. self.gui_complete() ## Create globals for printing process (redirect stdout). - global txsrv, txclt, txcol, rclt + global txsrv, txclt, txcol txsrv = self.textboxsrv.get() txclt = self.textboxclt.get() txcol = self.customcolors - rclt = self.runbtnclt ## Redirect stderr. sys.stderr = TextRedirect.StderrRedirect(txsrv, txclt, txcol) @@ -154,73 +141,86 @@ class KmsGui(tk.Tk): # Version. ver = tk.Label(self.optsrvwin, text = 'You are running server version: ' + srv_version, foreground = self.customcolors['red'], font = self.othfont) + self.allopts_srv = [] # Ip Address. - ipaddlbl = tk.Label(self.optsrvwin, text = 'IP Address: ', font = self.optfont) - self.ipadd = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) - self.ipadd.insert('end', srv_options['ip']['def']) - ToolTip(self.ipadd, text = srv_options['ip']['help'], wraplength = self.wraplength) + srvipaddlbl = tk.Label(self.optsrvwin, text = 'IP Address: ', font = self.optfont) + self.srvipadd = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) + self.srvipadd.insert('end', srv_options['ip']['def']) + ToolTip(self.srvipadd, text = srv_options['ip']['help'], wraplength = self.wraplength) myipadd = tk.Label(self.optsrvwin, text = 'Your IP address is: {}'.format(get_ip_address()), foreground = self.customcolors['red'], font = self.othfont) + self.allopts_srv.append(self.srvipadd) # Port. - portlbl = tk.Label(self.optsrvwin, text = 'Port: ', font = self.optfont) - self.port = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) - self.port.insert('end', str(srv_options['port']['def'])) - ToolTip(self.port, text = srv_options['port']['help'], wraplength = self.wraplength) + srvportlbl = tk.Label(self.optsrvwin, text = 'Port: ', font = self.optfont) + self.srvport = tk.Entry(self.optsrvwin, width = 10, font = self.optfont, validate = "key", validatecommand = (self.validation_int, "%S")) + self.srvport.insert('end', str(srv_options['port']['def'])) + ToolTip(self.srvport, text = srv_options['port']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.srvport) # EPID. epidlbl = tk.Label(self.optsrvwin, text = 'EPID: ', font = self.optfont) self.epid = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) self.epid.insert('end', str(srv_options['epid']['def'])) ToolTip(self.epid, text = srv_options['epid']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.epid) # LCID. lcidlbl = tk.Label(self.optsrvwin, text = 'LCID: ', font = self.optfont) - self.lcid = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) + self.lcid = tk.Entry(self.optsrvwin, width = 10, font = self.optfont, validate = "key", validatecommand = (self.validation_int, "%S")) self.lcid.insert('end', str(srv_options['lcid']['def'])) ToolTip(self.lcid, text = srv_options['lcid']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.lcid) # HWID. hwidlbl = tk.Label(self.optsrvwin, text = 'HWID: ', font = self.optfont) self.hwid = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) self.hwid.insert('end', srv_options['hwid']['def']) ToolTip(self.hwid, text = srv_options['hwid']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.hwid) # Client Count countlbl = tk.Label(self.optsrvwin, text = 'Client Count: ', font = self.optfont) self.count = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) self.count.insert('end', str(srv_options['count']['def'])) ToolTip(self.count, text = srv_options['count']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.count) # Activation Interval. activlbl = tk.Label(self.optsrvwin, text = 'Activation Interval: ', font = self.optfont) - self.activ = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) + self.activ = tk.Entry(self.optsrvwin, width = 10, font = self.optfont, validate = "key", validatecommand = (self.validation_int, "%S")) self.activ.insert('end', str(srv_options['activation']['def'])) ToolTip(self.activ, text = srv_options['activation']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.activ) # Renewal Interval. renewlbl = tk.Label(self.optsrvwin, text = 'Activation Interval: ', font = self.optfont) - self.renew = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) + self.renew = tk.Entry(self.optsrvwin, width = 10, font = self.optfont, validate = "key", validatecommand = (self.validation_int, "%S")) self.renew.insert('end', str(srv_options['renewal']['def'])) ToolTip(self.renew, text = srv_options['renewal']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.renew) # Logfile. - filelbl = tk.Label(self.optsrvwin, text = 'Logfile Path / Name: ', font = self.optfont) - self.file = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) - self.file.insert('end', srv_options['lfile']['def']) - self.file.xview_moveto(1) - ToolTip(self.file, text = srv_options['lfile']['help'], wraplength = self.wraplength) - filebtnwin = tk.Button(self.optsrvwin, text = 'Browse', command = lambda: self.browse(self.file, srv_options)) + srvfilelbl = tk.Label(self.optsrvwin, text = 'Logfile Path / Name: ', font = self.optfont) + self.srvfile = tk.Entry(self.optsrvwin, width = 10, font = self.optfont) + self.srvfile.insert('end', srv_options['lfile']['def']) + self.srvfile.xview_moveto(1) + ToolTip(self.srvfile, text = srv_options['lfile']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.srvfile) + filebtnwin = tk.Button(self.optsrvwin, text = 'Browse', command = lambda: self.browse(self.srvfile, srv_options)) + self.allopts_srv.append(filebtnwin) # Loglevel. - levellbl = tk.Label(self.optsrvwin, text = 'Loglevel: ', font = self.optfont) - self.level = ttk.Combobox(self.optsrvwin, values = tuple(srv_options['llevel']['choi']), width = 10) - self.level.set(srv_options['llevel']['def']) - ToolTip(self.level, text = srv_options['llevel']['help'], wraplength = self.wraplength) + srvlevellbl = tk.Label(self.optsrvwin, text = 'Loglevel: ', font = self.optfont) + self.srvlevel = ttk.Combobox(self.optsrvwin, values = tuple(srv_options['llevel']['choi']), width = 10) + self.srvlevel.set(srv_options['llevel']['def']) + ToolTip(self.srvlevel, text = srv_options['llevel']['help'], wraplength = self.wraplength) + self.allopts_srv.append(self.srvlevel) # Sqlite database. self.chkval = tk.BooleanVar() self.chkval.set(srv_options['sql']['def']) chksql = tk.Checkbutton(self.optsrvwin, text = 'Create Sqlite\nDatabase', font = self.optfont, var = self.chkval) ToolTip(chksql, text = srv_options['sql']['help'], wraplength = self.wraplength) + self.allopts_srv.append(chksql) ## Layout widgets (optsrvwin) ver.grid(row = 0, column = 0, columnspan = 3, padx = 5, pady = 5, sticky = 'ew') - ipaddlbl.grid(row = 1, column = 0, padx = 5, pady = 5, sticky = 'e') - self.ipadd.grid(row = 1, column = 1, padx = 5, pady = 5, sticky = 'ew') + srvipaddlbl.grid(row = 1, column = 0, padx = 5, pady = 5, sticky = 'e') + self.srvipadd.grid(row = 1, column = 1, padx = 5, pady = 5, sticky = 'ew') myipadd.grid(row = 2, column = 1, columnspan = 2, padx = 5, pady = 5, sticky = 'ew') - portlbl.grid(row = 3, column = 0, padx = 5, pady = 5, sticky = 'e') - self.port.grid(row = 3, column = 1, padx = 5, pady = 5, sticky = 'ew') + srvportlbl.grid(row = 3, column = 0, padx = 5, pady = 5, sticky = 'e') + self.srvport.grid(row = 3, column = 1, padx = 5, pady = 5, sticky = 'ew') epidlbl.grid(row = 4, column = 0, padx = 5, pady = 5, sticky = 'e') self.epid.grid(row = 4, column = 1, padx = 5, pady = 5, sticky = 'ew') lcidlbl.grid(row = 5, column = 0, padx = 5, pady = 5, sticky = 'e') @@ -233,11 +233,11 @@ class KmsGui(tk.Tk): self.activ.grid(row = 8, column = 1, padx = 5, pady = 5, sticky = 'ew') renewlbl.grid(row = 9, column = 0, padx = 5, pady = 5, sticky = 'e') self.renew.grid(row = 9, column = 1, padx = 5, pady = 5, sticky = 'ew') - filelbl.grid(row = 10, column = 0, padx = 5, pady = 5, sticky = 'e') - self.file.grid(row = 10, column = 1, padx = 5, pady = 5, sticky = 'ew') + srvfilelbl.grid(row = 10, column = 0, padx = 5, pady = 5, sticky = 'e') + self.srvfile.grid(row = 10, column = 1, padx = 5, pady = 5, sticky = 'ew') filebtnwin.grid(row = 10, column = 2, padx = 5, pady = 5, sticky = 'ew') - levellbl.grid(row = 11, column = 0, padx = 5, pady = 5, sticky = 'e') - self.level.grid(row = 11, column = 1, padx = 5, pady = 5, sticky = 'ew') + srvlevellbl.grid(row = 11, column = 0, padx = 5, pady = 5, sticky = 'e') + self.srvlevel.grid(row = 11, column = 1, padx = 5, pady = 5, sticky = 'ew') chksql.grid(row = 12, column = 1, padx = 5, pady = 5, sticky = 'ew') ## Create widgets and layout (msgsrvwin) ----------------------------------------------------------------------------------------------- @@ -303,43 +303,52 @@ class KmsGui(tk.Tk): # Version. cltver = tk.Label(self.optcltwin, text = 'You are running client version: ' + clt_version, foreground = self.customcolors['red'], font = self.othfont) + self.allopts_clt = [] # Ip Address. cltipaddlbl = tk.Label(self.optcltwin, text = 'IP Address: ', font = self.optfont) self.cltipadd = tk.Entry(self.optcltwin, width = 10, font = self.optfont) self.cltipadd.insert('end', clt_options['ip']['def']) ToolTip(self.cltipadd, text = clt_options['ip']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltipadd) # Port. cltportlbl = tk.Label(self.optcltwin, text = 'Port: ', font = self.optfont) - self.cltport = tk.Entry(self.optcltwin, width = 10, font = self.optfont) + self.cltport = tk.Entry(self.optcltwin, width = 10, font = self.optfont, validate = "key", validatecommand = (self.validation_int, "%S")) self.cltport.insert('end', str(clt_options['port']['def'])) ToolTip(self.cltport, text = clt_options['port']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltport) # Mode. cltmodelbl = tk.Label(self.optcltwin, text = 'Mode: ', font = self.optfont) self.cltmode = ttk.Combobox(self.optcltwin, values = tuple(clt_options['mode']['choi']), width = 10) self.cltmode.set(clt_options['mode']['def']) ToolTip(self.cltmode, text = clt_options['mode']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltmode) # CMID. cltcmidlbl = tk.Label(self.optcltwin, text = 'CMID: ', font = self.optfont) self.cltcmid = tk.Entry(self.optcltwin, width = 10, font = self.optfont) self.cltcmid.insert('end', str(clt_options['cmid']['def'])) ToolTip(self.cltcmid, text = clt_options['cmid']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltcmid) # Machine Name. cltnamelbl = tk.Label(self.optcltwin, text = 'Machine Name: ', font = self.optfont) self.cltname = tk.Entry(self.optcltwin, width = 10, font = self.optfont) self.cltname.insert('end', str(clt_options['name']['def'])) ToolTip(self.cltname, text = clt_options['name']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltname) # Logfile. cltfilelbl = tk.Label(self.optcltwin, text = 'Logfile Path / Name: ', font = self.optfont) self.cltfile = tk.Entry(self.optcltwin, width = 10, font = self.optfont) self.cltfile.insert('end', clt_options['lfile']['def']) self.cltfile.xview_moveto(1) ToolTip(self.cltfile, text = clt_options['lfile']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltfile) cltfilebtnwin = tk.Button(self.optcltwin, text = 'Browse', command = lambda: self.browse(self.cltfile, clt_options)) + self.allopts_clt.append(cltfilebtnwin) # Loglevel. cltlevellbl = tk.Label(self.optcltwin, text = 'Loglevel: ', font = self.optfont) self.cltlevel = ttk.Combobox(self.optcltwin, values = tuple(clt_options['llevel']['choi']), width = 10) self.cltlevel.set(clt_options['llevel']['def']) ToolTip(self.cltlevel, text = clt_options['llevel']['help'], wraplength = self.wraplength) + self.allopts_clt.append(self.cltlevel) # Layout widgets (optcltwin) cltver.grid(row = 0, column = 0, columnspan = 3, padx = 5, pady = 5, sticky = 'ew') @@ -364,12 +373,28 @@ class KmsGui(tk.Tk): relief = 'ridge', font = self.msgfont) self.textboxclt.put() - def proper_none(self, value): + def prep_option(self, value): value = None if value == 'None' else value try: return int(value) - except TypeError: + except (TypeError, ValueError): + # is NONE or is a STRING. return value + + def prep_logfile(self, optionlog): + if optionlog.startswith('FILESTDOUT '): + split = optionlog.split('FILESTDOUT ') + split[0] = 'FILESTDOUT' + return split + elif optionlog.startswith('STDOUT '): + split = optionlog.split('STDOUT ') + split[0] = 'STDOUT' + return split + else: + return optionlog + + def validate_int(self, value): + return value.isdigit() def clt_on_show(self, force = False): if self.optcltwin.winfo_ismapped() or force: @@ -385,16 +410,17 @@ class KmsGui(tk.Tk): def srv_on_start(self): if self.runbtnsrv['text'] == 'START\nSERVER': - if self.srv_actions_start(): - self.on_clear([txsrv, txclt]) - self.runbtnsrv.configure(text = 'STOP\nSERVER', background = self.customcolors['red'], - foreground = self.customcolors['white']) - self.runbtnclt.configure(state = 'normal') + self.srv_actions_start() + # wait for switch. + while not serverthread.is_running_server: + pass - # run thread for interrupting. - self.ejectthread = threading.Thread(target = self.srv_eject, name = "Thread-Ejt") - self.ejectthread.setDaemon(True) - self.ejectthread.start() + self.on_clear([txsrv, txclt]) + self.srv_toggle_all(on_start = True) + # 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.setDaemon(True) + self.srv_eject_thread.start() elif self.runbtnsrv['text'] == 'STOP\nSERVER': serverthread.terminate_eject() @@ -405,49 +431,51 @@ class KmsGui(tk.Tk): self.srv_actions_stop() def srv_actions_start(self): - ok = False - if switch_dir(os.path.dirname(self.file.get())): - if self.file.get().lower().endswith('.log'): - # Load dict. - srv_config[srv_options['ip']['des']] = self.ipadd.get() - srv_config[srv_options['port']['des']] = int(self.port.get()) - srv_config[srv_options['epid']['des']] = self.proper_none(self.epid.get()) - srv_config[srv_options['lcid']['des']] = int(self.lcid.get()) - srv_config[srv_options['hwid']['des']] = self.hwid.get() - srv_config[srv_options['count']['des']] = self.proper_none(self.count.get()) - srv_config[srv_options['activation']['des']] = int(self.activ.get()) - srv_config[srv_options['renewal']['des']] = int(self.renew.get()) - srv_config[srv_options['lfile']['des']] = check_logfile(self.file.get(), srv_options['lfile']['def']) - srv_config[srv_options['llevel']['des']] = self.level.get() - srv_config[srv_options['sql']['des']] = self.chkval.get() - ## TODO. - srv_config[srv_options['lsize']['des']] = 0 - srv_config[srv_options['time']['des']] = None + srv_config[srv_options['ip']['des']] = self.srvipadd.get() + srv_config[srv_options['port']['des']] = self.prep_option(self.srvport.get()) + srv_config[srv_options['epid']['des']] = self.prep_option(self.epid.get()) + srv_config[srv_options['lcid']['des']] = self.prep_option(self.lcid.get()) + srv_config[srv_options['hwid']['des']] = self.hwid.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['renewal']['des']] = self.prep_option(self.renew.get()) + srv_config[srv_options['lfile']['des']] = self.prep_logfile(self.srvfile.get()) + srv_config[srv_options['llevel']['des']] = self.srvlevel.get() + srv_config[srv_options['sql']['des']] = self.chkval.get() - serverqueue.put('start') - # wait for switch. - while not serverthread.is_running_server: - pass - self.srv_toggle() - ok = True - else: - messagebox.showerror('Invalid extension', 'Not a .log file !') - else: - messagebox.showerror('Invalid path', 'Path you have provided not found !') - return ok + ## TODO. + srv_config[srv_options['lsize']['des']] = 0 + srv_config[srv_options['time']['des']] = None + + serverqueue.put('start') def srv_actions_stop(self): if serverthread.is_running_server: - srv_terminate(exit_server = True) - # wait for switch. - while serverthread.is_running_server: - pass - self.srv_toggle() - self.runbtnsrv.configure(text = 'START\nSERVER', background = self.customcolors['green'], + if serverthread.server is not None: + srv_terminate(exit_server = True) + # wait for switch. + while serverthread.is_running_server: + pass + else: + serverthread.is_running_server = False + self.srv_toggle_all(on_start = False) + + def srv_toggle_all(self, on_start = True): + self.srv_toggle_state() + if on_start: + self.runbtnsrv.configure(text = 'STOP\nSERVER', background = self.customcolors['red'], foreground = self.customcolors['white']) + for widget in self.allopts_srv: + widget.configure(state = 'disabled') + self.runbtnclt.configure(state = 'normal') + else: + self.runbtnsrv.configure(text = 'START\nSERVER', background = self.customcolors['green'], + foreground = self.customcolors['white']) + for widget in self.allopts_srv: + widget.configure(state = 'normal') self.runbtnclt.configure(state = 'disabled') - def srv_toggle(self): + def srv_toggle_state(self): if serverthread.is_running_server: txt, color = ('Server\nState:\nServing', self.customcolors['green']) else: @@ -456,35 +484,47 @@ class KmsGui(tk.Tk): self.statesrv.configure(text = txt, foreground = color) def clt_on_start(self): - self.on_clear([txsrv, txclt]) self.clt_actions_start() + # run thread for disable interrupting server and client, when client running. + self.clt_eject_thread = threading.Thread(target = self.clt_eject, name = "Thread-CltEjt") + self.clt_eject_thread.setDaemon(True) + self.clt_eject_thread.start() + + self.on_clear([txsrv, txclt]) + for widget in self.allopts_clt + [self.runbtnsrv, self.runbtnclt]: + widget.configure(state = 'disabled') def clt_actions_start(self): - if switch_dir(os.path.dirname(self.cltfile.get())): - if self.cltfile.get().lower().endswith('.log'): - # Load dict. - clt_config[clt_options['ip']['des']] = self.cltipadd.get() - clt_config[clt_options['port']['des']] = int(self.cltport.get()) - clt_config[clt_options['mode']['des']] = self.cltmode.get() - clt_config[clt_options['cmid']['des']] = self.proper_none(self.cltcmid.get()) - clt_config[clt_options['name']['des']] = self.proper_none(self.cltname.get()) - clt_config[clt_options['lfile']['des']] = check_logfile(self.cltfile.get(), clt_options['lfile']['def']) - clt_config[clt_options['llevel']['des']] = self.cltlevel.get() - ## TODO - clt_config[clt_options['lsize']['des']] = 0 + clt_config[clt_options['ip']['des']] = self.cltipadd.get() + clt_config[clt_options['port']['des']] = self.prep_option(self.cltport.get()) + clt_config[clt_options['mode']['des']] = self.cltmode.get() + clt_config[clt_options['cmid']['des']] = self.prep_option(self.cltcmid.get()) + clt_config[clt_options['name']['des']] = self.prep_option(self.cltname.get()) + clt_config[clt_options['llevel']['des']] = self.cltlevel.get() + clt_config[clt_options['lfile']['des']] = self.prep_logfile(self.cltfile.get()) - - self.clientthread = threading.Thread(target = clt_main, name = 'Thread-Clt', args=(True,)) - self.clientthread.setDaemon(True) - self.clientthread.start() - else: - messagebox.showerror('Invalid extension', 'Not a .log file !') - else: - messagebox.showerror('Invalid path', 'Path you have provided not found !') + ## TODO. + clt_config[clt_options['lsize']['des']] = 0 + + # run client (in a thread). + global clientthread + clientthread = client_thread(name = "Thread-Clt") + clientthread.setDaemon(True) + clientthread.with_gui = True + clientthread.start() + + def clt_eject(self): + while clientthread.is_alive(): + sleep(0.1) + for widget in self.allopts_clt + [self.runbtnsrv, self.runbtnclt]: + widget.configure(state = 'normal') def on_exit(self): if serverthread.is_running_server: - srv_terminate(exit_server = True) + if serverthread.server is not None: + srv_terminate(exit_server = True) + else: + serverthread.is_running_server = False srv_terminate(exit_thread = True) self.destroy() diff --git a/py-kms/pykms_GuiMisc.py b/py-kms/pykms_GuiMisc.py index e395cdf..74bcb64 100644 --- a/py-kms/pykms_GuiMisc.py +++ b/py-kms/pykms_GuiMisc.py @@ -137,12 +137,10 @@ class TextRedirect(object): 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, runclt, str_to_print, where): + def __init__(self, srv_text_space, clt_text_space, customcolors, str_to_print, where): self.srv_text_space = srv_text_space self.clt_text_space = clt_text_space self.customcolors = customcolors - self.runclt = runclt - self.runclt.configure(state = 'disabled') self.str_to_print = str_to_print self.where = where self.textbox_do() @@ -151,7 +149,6 @@ class TextRedirect(object): if message == self.terminator: TextRedirect.StdoutRedirect.tag_num = 0 TextRedirect.StdoutRedirect.newlinecut = [-1, -2, -4, -5] - self.runclt.configure(state = 'normal') def textbox_write(self, tag, message, color, extras): widget = self.textbox_choose(message) @@ -231,9 +228,9 @@ class TextRedirect(object): self.clt_text_space = clt_text_space self.customcolors = customcolors self.tag_err = 'STDERR' + self.xfont = tkFont.Font(font = self.srv_text_space['font']) def write(self, string): - self.textbox_clear() self.textbox_color(self.tag_err, self.srv_text_space, self.customcolors['red'], self.customcolors['black']) self.srv_text_space.configure(state = 'normal') self.srv_text_space.insert('end', string, self.tag_err) diff --git a/py-kms/pykms_Misc.py b/py-kms/pykms_Misc.py index c4433f4..d6cb7b2 100644 --- a/py-kms/pykms_Misc.py +++ b/py-kms/pykms_Misc.py @@ -133,20 +133,25 @@ def logger_create(log_obj, config, mode = 'a'): #---------------------------------------------------------------------------------------------------------------------------------------------------------- -def check_logfile(optionlog, defaultlog): +def check_logfile(optionlog, defaultlog, where): if not isinstance(optionlog, list): optionlog = [optionlog] lenopt = len(optionlog) - msg_dir = "{reverse}{red}{bold}argument logfile: no such file or directory: %s. Exiting...{end}" + msg_dir = "{reverse}{red}{bold}argument logfile: invalid directory: '%s'. Exiting...{end}" msg_long = "{reverse}{red}{bold}argument logfile: too much arguments. Exiting...{end}" + msg_log = "{reverse}{red}{bold}argument logfile: not a log file, invalid extension: '%s'. Exiting...{end}" def checkdir(path): - if not os.path.isdir(os.path.dirname(path)): - pretty_printer(put_text = msg_dir %path, to_exit = True) + filename = os.path.basename(path) + pathname = os.path.dirname(path) + if not os.path.isdir(pathname): + pretty_printer(put_text = msg_dir %pathname, where = where, to_exit = True) + elif not filename.lower().endswith('.log'): + pretty_printer(put_text = msg_log %filename, where = where, to_exit = True) if lenopt > 2: - pretty_printer(put_text = msg_long, to_exit = True) + pretty_printer(put_text = msg_long, where = where, to_exit = True) if 'FILESTDOUT' in optionlog: if lenopt == 1: @@ -157,7 +162,7 @@ def check_logfile(optionlog, defaultlog): checkdir(optionlog[1]) else: if lenopt == 2: - pretty_printer(put_text = msg_long, to_exit = True) + pretty_printer(put_text = msg_long, where = where, to_exit = True) elif lenopt == 1 and 'STDOUT' not in optionlog: # check directory path. checkdir(optionlog[0]) diff --git a/py-kms/pykms_Server.py b/py-kms/pykms_Server.py index 9f01cc5..7176ac7 100755 --- a/py-kms/pykms_Server.py +++ b/py-kms/pykms_Server.py @@ -105,8 +105,9 @@ class KeyServer(socketserver.ThreadingMixIn, socketserver.TCPServer): class server_thread(threading.Thread): - def __init__(self, queue): + def __init__(self, queue, name): threading.Thread.__init__(self) + self.name = name self.queue = queue self.server = None self.is_running_server, self.with_gui = [False for _ in range(2)] @@ -210,13 +211,18 @@ def server_options(): try: srv_config.update(vars(parser.parse_args())) # Check logfile. - srv_config['logfile'] = check_logfile(srv_config['logfile'], srv_options['lfile']['def']) + srv_config['logfile'] = check_logfile(srv_config['logfile'], srv_options['lfile']['def'], where = "srv") except KmsException as e: pretty_printer(put_text = "{reverse}{red}{bold}%s. Exiting...{end}" %str(e), to_exit = True) def server_check(): + # Check logfile (only for GUI). + if serverthread.with_gui: + srv_config['logfile'] = check_logfile(srv_config['logfile'], srv_options['lfile']['def'], where = "srv") + # Setup hidden or not messages. ShellMessage.view = ( False if any(i in ['STDOUT', 'FILESTDOUT'] for i in srv_config['logfile']) else True ) + # Create log. logger_create(loggersrv, srv_config, mode = 'a') @@ -304,6 +310,8 @@ def srv_main_with_gui(width = 950, height = 660): 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() class kmsServerHandler(socketserver.BaseRequestHandler): @@ -362,7 +370,7 @@ class kmsServerHandler(socketserver.BaseRequestHandler): serverqueue = Queue.Queue(maxsize = 0) -serverthread = server_thread(serverqueue) +serverthread = server_thread(serverqueue, name = "Thread-Srv") serverthread.setDaemon(True) serverthread.start()