Re-add module support, get rid of old modules

This commit is contained in:
Fierelier 2021-06-30 17:26:55 +02:00
parent 4cea08c314
commit d8f4ccc893
12 changed files with 127 additions and 286 deletions

View File

@ -44,11 +44,99 @@ heartbeatTime = 600
threadCount = 0
threadCountLock = threading.Lock()
commands = {}
def commandlineToList(cmd):
args = []
cArg = ""
escape = False
quoted = False
for letter in cmd:
if escape == True:
cArg += letter
escape = False
continue
if letter == "\\":
escape = True
continue
#if quoted == False and letter == ",":
if letter == ",":
if cArg == "": continue
args.append(cArg)
cArg = ""
continue
#if letter == '"':
# quoted = not quoted
# continue
cArg += letter
args.append(cArg)
return args
def listToCommandline(lst):
cmd = ""
for arg in lst:
arg = arg.replace("\\","\\\\")
arg = arg.replace(",","\\,")
#arg = arg.replace('"','\\"')
#if " " in arg: arg = '"' +arg+ '"'
cmd += arg + ","
return cmd[:-1]
printLock = threading.Lock()
def tprint(st):
with printLock:
print(st)
def runCode(str, lcs = False, description = "loose-code"):
if lcs == False: lcs = {}
code = compile(str,description,"exec")
exec(code,globals(),lcs)
return lcs
def runScript(sf, lcs = False):
if lcs == False: lcs = {}
with open(sf) as script:
runCode(script.read(),lcs,sf)
return lcs
def getModlist(path):
modList = []
for root,dirs,files in os.walk(path):
for file in dirs:
ffile = p(root,file)
lfile = ffile.replace(path + os.path.sep,"",1)
if lfile[0] == "-": continue
if lfile[0] == "[" and lfile[-1] == "]":
modList = modList + sorted(getModlist(ffile))
continue
modList.append(ffile)
break
return modList
modulesLoaded = []
modulePath = p(sp,"modules")
def moduleRun(localModule):
if not localModule in modulesLoaded: modulesLoaded.append(localModule)
print("> " +localModule+ "...")
runScript(p(modulePath,localModule,"module.py"))
def moduleDepends(localModules):
if type(localModules) == str: localModules = [localModules]
for localModule in localModules:
if localModule in modulesLoaded: return
print("depend ",end="")
moduleRun(localModule)
def addThread():
global threadCount
with threadCountLock:
@ -138,6 +226,15 @@ class connectionThreadIn(threading.Thread):
return connections[self.connectionId]["connection"]
return False
def runCommand(self,cmd):
command = False
if not cmd[0] in commands:
return ["error","nonfatal","command_not_found"]
command = commands[cmd[0]]
rtn = command["function"](self,cmd)
time.sleep(pauseBetweenCommands)
return rtn
def run(self):
try:
while True:
@ -151,14 +248,16 @@ class connectionThreadIn(threading.Thread):
with connectionsLock: closeConnection(self.connectionId)
return
queue = False
with connectionsLock:
if self.connectionId in connections:
queue = connections[self.connectionId]["threadOut"].queue
if queue.qsize() >= maxQueueSize:
closeConnection(self.connectionId)
return
queue.put(data)
time.sleep(pauseBetweenCommands)
queue = connections[self.connectionId]["threadOut"].queue
if queue.qsize() >= maxQueueSize:
closeConnection(self.connectionId)
return
dataString = data.decode(encoding="utf-8")
commandList = commandlineToList(dataString)
queue.put(listToCommandline(self.runCommand(commandList)).encode(encoding="utf-8"))
except Exception as e:
with connectionsLock: closeConnection(self.connectionId)
with printLock:
@ -169,6 +268,13 @@ class connectionThreadIn(threading.Thread):
removeThread()
def main():
print("Loading modules...")
for path in getModlist(modulePath):
if os.path.isfile(p(path,"module.py")):
localModule = path.replace(modulePath + os.path.sep,"",1)
if not localModule in modulesLoaded:
moduleRun(localModule)
global connectionsId
serverSocket.bind(serverAddr)
serverSocket.listen(65535)

View File

@ -1,22 +0,0 @@
global textPreRequest
def textPreRequest(event,self,requestLength):
if requestLength <= 128: return
sendResponse(self.connection,"error: too long".encode("utf-8"))
self.closeThread()
return True
addEventHandler("onPreRequest",textPreRequest)
global textRequest
def textRequest(event,self,requestLength):
data = self.connection.recv(requestLength)
sendResponse(self.connection,data)
text = data.decode("utf-8")
print(":".join(map(str,self.address))+ " > " +text)
if text == "exit":
with threadsLock:
global close
close = True
self.closeThread()
return True
addEventHandler("onRequest",textRequest)

View File

@ -1,69 +0,0 @@
global textCommands
textCommands = {}
global textCommandsLock
textCommandsLock = threading.Lock()
global textCommandRun
def textCommandRun(self,args):
with textCommandsLock:
commands = textCommands.copy()
if not args[0] in commands:
return ["error","nonfatal","command_not_found"]
return commands[args[0]](self,args[0],args[1:])
global textCommandAddHandler
def textCommandAddHandler(command,function):
with textCommandsLock:
textCommands[command] = function
global textCommandToList
def textCommandToList(cmd):
args = []
cArg = ""
escape = False
quoted = False
for letter in cmd:
if escape == True:
cArg += letter
escape = False
continue
if letter == "\\":
escape = True
continue
#if quoted == False and letter == ",":
if letter == ",":
if cArg == "": continue
args.append(cArg)
cArg = ""
continue
#if letter == '"':
# quoted = not quoted
# continue
cArg += letter
args.append(cArg)
return args
global textListToCommand
def textListToCommand(lst):
cmd = ""
for arg in lst:
arg = arg.replace("\\","\\\\")
arg = arg.replace(",","\\,")
#arg = arg.replace('"','\\"')
#if " " in arg: arg = '"' +arg+ '"'
cmd += arg + ","
return cmd[:-1]
global textNop
def textNop(self,command,args):
return [""]
textCommandAddHandler("nop",textNop)

View File

@ -1,29 +0,0 @@
moduleDepends([
p("[text server]","[api]","commands"),
])
global textSend
def textSend(self,command,args):
if len(args) < 2:
return ["error","nonfatal","syntax","Correct syntax: " +command+ ",<user>,<command>,[argument 1],[argument 2],..."]
user = args[0].lower()
if len(user) < 1:
return ["error","nonfatal","name_too_short","Needs to be at least 1 character in length."]
me = ""
with self.lock:
me = self.user
if not me:
return ["error","nonfatal","not_logged_in"]
with threadsLock:
for threadId in threads:
thread = threads[threadId]
with thread.lock:
if thread.user != user: continue
thread.sendResponse(textListToCommand(["send",me] + args[1:]).encode("utf-8"),lock = False)
return ["ok"]
textCommandAddHandler("send",textSend)

View File

@ -1,5 +0,0 @@
moduleDepends(p("[text server]","[api]","utils"))
global textBaseFolder
textBaseFolder = p(sp,"textServer")
textQuickFolder(textBaseFolder)

View File

@ -1,10 +0,0 @@
moduleDepends(p("[text server]","[api]","commands"))
global textRequest
def textRequest(self,command,args):
if len(args) < 2:
return ["error","nonfatal","syntax","Correct syntax: " +command+ ",<id>,<command>,[arg1],[arg2],..."]
response = [command,args[0]] + textCommandRun(self,args[1:])
return response
textCommandAddHandler("req",textRequest)

View File

@ -1,2 +0,0 @@
global fileLock
fileLock = threading.Lock()

View File

@ -1,87 +0,0 @@
moduleDepends([
p("[text server]","[api]","commands"),
p("[text server]","[api]","threadedFiles")
])
global textUserFolder
textUserFolder = p(textBaseFolder,"users")
textQuickFolder(textUserFolder)
global textUserAllowedCharacters
textUserAllowedCharacters = "abcdefghijklmnopqrstuvwxyz0123456789.-_ "
global textUserGetPath
def textUserGetPath(user):
return p(textUserFolder,user)
global textUserRegister
def textUserRegister(self,command,args):
if len(args) != 2:
return ["error","nonfatal","syntax","Correct syntax: " +command+ ",<user>,<password>"]
user = args[0].lower()
if len(user) < 1:
return ["error","nonfatal","name_too_short","Needs to be at least 1 character in length."]
for symbol in user:
if not symbol in textUserAllowedCharacters:
return ["error","nonfatal","invalid_name","Allowed characters: " +", ".join([char for char in textUserAllowedCharacters])]
userpath = textUserGetPath(user)
with fileLock:
if os.path.isdir(userpath):
return ["error","nonfatal","user_exists"]
password = args[1]
os.makedirs(userpath)
passFile = open(p(userpath,"pass.txt"),"w")
passFile.write(password)
passFile.close()
return ["ok"]
textCommandAddHandler("register",textUserRegister)
global textUserLogin
def textUserLogin(self,command,args):
if len(args) != 2:
return ["error","nonfatal","syntax","Correct syntax: " +command+ ",<user>,<password>"]
user = args[0].lower()
if len(user) < 1:
return ["error","nonfatal","name_too_short","Needs to be at least 1 character in length."]
for symbol in user:
if not symbol in textUserAllowedCharacters:
return ["error","nonfatal","invalid_name","Allowed characters: " +", ".join([char for char in textUserAllowedCharacters])]
userpath = textUserGetPath(user)
with fileLock:
if not os.path.isdir(userpath):
return ["error","nonfatal","wrong_user_or_password"]
password = args[1]
passFile = open(p(userpath,"pass.txt"),"r")
passw = passFile.read()
passFile.close()
if password != passw:
return ["error","nonfatal","wrong_user_or_password"]
with self.lock:
self.user = user
return ["ok"]
textCommandAddHandler("login",textUserLogin)
global textUserGet
def textUserGet(self,command,args):
with self.lock:
user = self.user
if not user:
return ["error","nonfatal","not_logged_in"]
return ["user",user]
textCommandAddHandler("whoami",textUserGet)

View File

@ -1,4 +0,0 @@
global textQuickFolder
def textQuickFolder(path):
if not os.path.isdir(path):
os.makedirs(path)

View File

@ -0,0 +1,5 @@
global commands
commands["nop"] = {}
def f(self,cmd):
return [""]
commands["nop"]["function"] = f

View File

@ -0,0 +1,9 @@
global commands
commands["req"] = {}
def f(self,cmd):
if len(cmd) < 3:
return ["error","nonfatal","syntax","need at least 3 arguments"]
rtn = cmd[:2] + self.runCommand(cmd[2:])
return rtn
commands["req"]["function"] = f

View File

@ -1,51 +0,0 @@
global textTimeout
textTimeout = 30
global textKeepAliveTimeout
textKeepAliveTimeout = 600 # set to None for infinite time (not recommended)
global textOnConnect
def textOnConnect(event,connection,address):
global textKeepAliveTimeout
connection.settimeout(textKeepAliveTimeout)
addEventHandler("onConnect",textOnConnect)
global textOnPreRequest
def textOnPreRequest(event,self,requestLength):
global textTimeout
self.connection.settimeout(textTimeout)
if requestLength <= 100000: return
try:
sendResponse(self.connection,textListToCommand(["error","fatal","request_too_long"]).encode("utf-8"))
except threading.timeout:
pass
self.closeThread()
return True
addEventHandler("onPreRequest",textOnPreRequest)
global textOnRequest
def textOnRequest(event,self,requestLength):
global textTimeout
global textKeepAliveTimeout
self.connection.settimeout(textTimeout)
data = self.connection.recv(requestLength)
text = data.decode("utf-8")
print(":".join(map(str,self.address))+ " > " +text)
response = textCommandRun(self,textCommandToList(text))
print("response: " +textListToCommand(response))
self.sendResponse(textListToCommand(response).encode("utf-8"))
self.connection.settimeout(textKeepAliveTimeout)
addEventHandler("onRequest",textOnRequest)
global textOnException
def textOnException(event,self,exc):
self.connection.settimeout(textTimeout)
if type(exc) == socket.timeout:
self.sendResponse(textListToCommand(["error","fatal","timeout"]).encode("utf-8"))
return
self.sendResponse(textListToCommand(["error","fatal","unhandled",str(exc)]).encode("utf-8"))
addEventHandler("onException",textOnException)