Re-add module support, get rid of old modules
This commit is contained in:
parent
4cea08c314
commit
d8f4ccc893
120
clientBlaster.py
120
clientBlaster.py
@ -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)
|
||||
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -1,5 +0,0 @@
|
||||
moduleDepends(p("[text server]","[api]","utils"))
|
||||
|
||||
global textBaseFolder
|
||||
textBaseFolder = p(sp,"textServer")
|
||||
textQuickFolder(textBaseFolder)
|
@ -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)
|
@ -1,2 +0,0 @@
|
||||
global fileLock
|
||||
fileLock = threading.Lock()
|
@ -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)
|
@ -1,4 +0,0 @@
|
||||
global textQuickFolder
|
||||
def textQuickFolder(path):
|
||||
if not os.path.isdir(path):
|
||||
os.makedirs(path)
|
5
modules/[text server]/[commands]/nop/module.py
Normal file
5
modules/[text server]/[commands]/nop/module.py
Normal file
@ -0,0 +1,5 @@
|
||||
global commands
|
||||
commands["nop"] = {}
|
||||
def f(self,cmd):
|
||||
return [""]
|
||||
commands["nop"]["function"] = f
|
9
modules/[text server]/[commands]/req/module.py
Normal file
9
modules/[text server]/[commands]/req/module.py
Normal 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
|
@ -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)
|
Loading…
Reference in New Issue
Block a user