Re-add module support, get rid of old modules
This commit is contained in:
parent
4cea08c314
commit
d8f4ccc893
112
clientBlaster.py
112
clientBlaster.py
@ -44,11 +44,99 @@ heartbeatTime = 600
|
|||||||
threadCount = 0
|
threadCount = 0
|
||||||
threadCountLock = threading.Lock()
|
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()
|
printLock = threading.Lock()
|
||||||
def tprint(st):
|
def tprint(st):
|
||||||
with printLock:
|
with printLock:
|
||||||
print(st)
|
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():
|
def addThread():
|
||||||
global threadCount
|
global threadCount
|
||||||
with threadCountLock:
|
with threadCountLock:
|
||||||
@ -138,6 +226,15 @@ class connectionThreadIn(threading.Thread):
|
|||||||
return connections[self.connectionId]["connection"]
|
return connections[self.connectionId]["connection"]
|
||||||
return False
|
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):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
@ -151,14 +248,16 @@ class connectionThreadIn(threading.Thread):
|
|||||||
with connectionsLock: closeConnection(self.connectionId)
|
with connectionsLock: closeConnection(self.connectionId)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
queue = False
|
||||||
with connectionsLock:
|
with connectionsLock:
|
||||||
if self.connectionId in connections:
|
|
||||||
queue = connections[self.connectionId]["threadOut"].queue
|
queue = connections[self.connectionId]["threadOut"].queue
|
||||||
if queue.qsize() >= maxQueueSize:
|
if queue.qsize() >= maxQueueSize:
|
||||||
closeConnection(self.connectionId)
|
closeConnection(self.connectionId)
|
||||||
return
|
return
|
||||||
queue.put(data)
|
|
||||||
time.sleep(pauseBetweenCommands)
|
dataString = data.decode(encoding="utf-8")
|
||||||
|
commandList = commandlineToList(dataString)
|
||||||
|
queue.put(listToCommandline(self.runCommand(commandList)).encode(encoding="utf-8"))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
with connectionsLock: closeConnection(self.connectionId)
|
with connectionsLock: closeConnection(self.connectionId)
|
||||||
with printLock:
|
with printLock:
|
||||||
@ -169,6 +268,13 @@ class connectionThreadIn(threading.Thread):
|
|||||||
removeThread()
|
removeThread()
|
||||||
|
|
||||||
def main():
|
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
|
global connectionsId
|
||||||
serverSocket.bind(serverAddr)
|
serverSocket.bind(serverAddr)
|
||||||
serverSocket.listen(65535)
|
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