first commit
This commit is contained in:
commit
5a394ea2d0
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/textServer/
|
209
clientBlaster.py
Normal file
209
clientBlaster.py
Normal file
@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
oldexcepthook = sys.excepthook
|
||||
def newexcepthook(type,value,traceback):
|
||||
oldexcepthook(type,value,traceback)
|
||||
input("Press ENTER to quit.")
|
||||
sys.excepthook = newexcepthook
|
||||
|
||||
import os
|
||||
p = os.path.join
|
||||
pUp = os.path.dirname
|
||||
s = False
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
s = os.path.realpath(sys.executable)
|
||||
else:
|
||||
s = os.path.realpath(__file__)
|
||||
sp = pUp(s)
|
||||
|
||||
# script start
|
||||
import threading
|
||||
import socket
|
||||
import struct
|
||||
|
||||
addr = ("127.0.0.1",21779)
|
||||
|
||||
threads = {}
|
||||
threadId = 0
|
||||
threadsLock = threading.Lock()
|
||||
close = False
|
||||
|
||||
eventHandlers = {}
|
||||
eventHandlersLock = threading.Lock()
|
||||
|
||||
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
|
||||
|
||||
def triggerEvent(event,*args,**kwargs):
|
||||
eventHandlersLock.acquire()
|
||||
handlers = eventHandlers.copy()
|
||||
eventHandlersLock.release()
|
||||
|
||||
if not event in handlers: return
|
||||
for func in handlers[event]:
|
||||
cancel = func(event,*args,**kwargs)
|
||||
if cancel: return True
|
||||
|
||||
return False
|
||||
|
||||
def addEventHandler(event,func):
|
||||
eventHandlersLock.acquire()
|
||||
if not event in eventHandlers: eventHandlers[event] = []
|
||||
eventHandlers[event].append(func)
|
||||
eventHandlersLock.release()
|
||||
|
||||
def sendResponse(connection,data):
|
||||
connection.sendall(len(data).to_bytes(4,"big") + data)
|
||||
|
||||
class connectionThread(threading.Thread):
|
||||
global threadsLock
|
||||
|
||||
def __init__(self,threadId,connection,address):
|
||||
threading.Thread.__init__(self)
|
||||
self.threadId = threadId
|
||||
self.connection = connection
|
||||
self.address = address
|
||||
self.closed = False
|
||||
self.user = False
|
||||
self.lock = threading.Lock()
|
||||
|
||||
def closeThread(self):
|
||||
self.lock.acquire()
|
||||
threadsLock.acquire()
|
||||
try:
|
||||
self.connection.close()
|
||||
except:
|
||||
print("failed to close connection, ignoring.")
|
||||
pass
|
||||
|
||||
del threads[str(self.threadId)]
|
||||
print("thread closed: " +str(self.threadId)+ " (open: " +str(len(threads))+ ")")
|
||||
self.closed = True
|
||||
threadsLock.release()
|
||||
self.lock.release()
|
||||
|
||||
def run(self):
|
||||
self.lock.acquire()
|
||||
# inform about connection
|
||||
print("thread opened: " +", ".join((str(self.threadId),str(self.address))))
|
||||
self.lock.release()
|
||||
|
||||
while True:
|
||||
try:
|
||||
# get request length
|
||||
data = b''
|
||||
data = self.connection.recv(4)
|
||||
|
||||
if not data:
|
||||
self.closeThread()
|
||||
return
|
||||
|
||||
requestLength = int.from_bytes(data,"big")
|
||||
|
||||
# inform about request
|
||||
cancel = triggerEvent("onPreRequest",self,requestLength)
|
||||
self.lock.acquire()
|
||||
if self.closed:
|
||||
self.lock.release()
|
||||
return
|
||||
self.lock.release()
|
||||
if cancel: continue
|
||||
|
||||
# process request
|
||||
cancel = triggerEvent("onRequest",self,requestLength)
|
||||
self.lock.acquire()
|
||||
if self.closed:
|
||||
self.lock.release()
|
||||
return
|
||||
self.lock.release()
|
||||
if cancel: continue
|
||||
except Exception as e:
|
||||
#self.lock.release() - fix this
|
||||
cancel = False
|
||||
try:
|
||||
cancel = triggerEvent("onException",self,e)
|
||||
except:
|
||||
self.closeThread()
|
||||
raise
|
||||
|
||||
if cancel: continue
|
||||
self.closeThread()
|
||||
raise e
|
||||
|
||||
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 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)
|
||||
|
||||
print("\nServing on " +":".join(map(str,addr))+ "!")
|
||||
|
||||
global socketServer
|
||||
socketServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
socketServer.bind(addr)
|
||||
socketServer.listen(1000)
|
||||
|
||||
global threadId
|
||||
global close
|
||||
while True:
|
||||
connection, address = socketServer.accept()
|
||||
threadsLock.acquire()
|
||||
if close: threadsLock.release(); break
|
||||
cancel = triggerEvent("onConnect",connection,address)
|
||||
if close: threadsLock.release(); break
|
||||
if cancel: continue
|
||||
|
||||
threadId += 1
|
||||
while str(threadId) in threads:
|
||||
threadId += 1
|
||||
|
||||
thread = connectionThread(threadId,connection,address)
|
||||
threads[str(threadId)] = thread
|
||||
thread.start()
|
||||
threadsLock.release()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
23
modules/[example modules]/-parrot text server/module.py
Normal file
23
modules/[example modules]/-parrot text server/module.py
Normal file
@ -0,0 +1,23 @@
|
||||
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":
|
||||
threadsLock.acquire()
|
||||
global close
|
||||
close = True
|
||||
threadsLock.release()
|
||||
|
||||
self.closeThread()
|
||||
return True
|
||||
addEventHandler("onRequest",textRequest)
|
71
modules/[text server]/[api]/commands/module.py
Normal file
71
modules/[text server]/[api]/commands/module.py
Normal file
@ -0,0 +1,71 @@
|
||||
global textCommands
|
||||
textCommands = {}
|
||||
global textCommandsLock
|
||||
textCommandsLock = threading.Lock()
|
||||
|
||||
global textCommandRun
|
||||
def textCommandRun(self,args):
|
||||
textCommandsLock.acquire()
|
||||
commands = textCommands.copy()
|
||||
textCommandsLock.release()
|
||||
|
||||
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):
|
||||
textCommandsLock.acquire()
|
||||
textCommands[command] = function
|
||||
textCommandsLock.release()
|
||||
|
||||
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)
|
5
modules/[text server]/[api]/main/module.py
Normal file
5
modules/[text server]/[api]/main/module.py
Normal file
@ -0,0 +1,5 @@
|
||||
moduleDepends(p("[text server]","[api]","utils"))
|
||||
|
||||
global textBaseFolder
|
||||
textBaseFolder = p(sp,"textServer")
|
||||
textQuickFolder(textBaseFolder)
|
10
modules/[text server]/[api]/requests/module.py
Normal file
10
modules/[text server]/[api]/requests/module.py
Normal file
@ -0,0 +1,10 @@
|
||||
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)
|
2
modules/[text server]/[api]/threadedFiles/module.py
Normal file
2
modules/[text server]/[api]/threadedFiles/module.py
Normal file
@ -0,0 +1,2 @@
|
||||
global fileLock
|
||||
fileLock = threading.Lock()
|
92
modules/[text server]/[api]/users/module.py
Normal file
92
modules/[text server]/[api]/users/module.py
Normal file
@ -0,0 +1,92 @@
|
||||
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)
|
||||
fileLock.acquire()
|
||||
|
||||
if os.path.isdir(userpath):
|
||||
fileLock.release()
|
||||
return ["error","nonfatal","user_exists"]
|
||||
|
||||
password = args[1]
|
||||
|
||||
os.makedirs(userpath)
|
||||
passFile = open(p(userpath,"pass.txt"),"w")
|
||||
passFile.write(password)
|
||||
passFile.close()
|
||||
fileLock.release()
|
||||
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:
|
||||
fileLock.release()
|
||||
return ["error","nonfatal","invalid_name","Allowed characters: " +", ".join([char for char in textUserAllowedCharacters])]
|
||||
|
||||
userpath = textUserGetPath(user)
|
||||
fileLock.acquire()
|
||||
|
||||
if not os.path.isdir(userpath):
|
||||
fileLock.release()
|
||||
return ["error","nonfatal","wrong_user_or_password"]
|
||||
|
||||
password = args[1]
|
||||
|
||||
passFile = open(p(userpath,"pass.txt"),"r")
|
||||
passw = passFile.read()
|
||||
passFile.close()
|
||||
fileLock.release()
|
||||
if password != passw:
|
||||
return ["error","nonfatal","wrong_user_or_password"]
|
||||
|
||||
self.lock.acquire()
|
||||
self.user = user
|
||||
self.lock.release()
|
||||
return ["ok"]
|
||||
textCommandAddHandler("login",textUserLogin)
|
||||
|
||||
global textUserGet
|
||||
def textUserGet(self,command,args):
|
||||
self.lock.acquire()
|
||||
user = self.user
|
||||
self.lock.release()
|
||||
if not user:
|
||||
return ["error","nonfatal","not_logged_in"]
|
||||
|
||||
return [user]
|
||||
textCommandAddHandler("whoami",textUserGet)
|
4
modules/[text server]/[api]/utils/module.py
Normal file
4
modules/[text server]/[api]/utils/module.py
Normal file
@ -0,0 +1,4 @@
|
||||
global textQuickFolder
|
||||
def textQuickFolder(path):
|
||||
if not os.path.isdir(path):
|
||||
os.makedirs(path)
|
60
modules/[text server]/main/module.py
Normal file
60
modules/[text server]/main/module.py
Normal file
@ -0,0 +1,60 @@
|
||||
global textTimeout
|
||||
textTimeout = 30
|
||||
global textKeepAliveTimeout
|
||||
textKeepAliveTimeout = 600 # set to 0 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 <= 128: 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)
|
||||
if text == "close":
|
||||
threadsLock.acquire()
|
||||
global close
|
||||
close = True
|
||||
threadsLock.release()
|
||||
|
||||
self.closeThread()
|
||||
return True
|
||||
|
||||
response = textCommandRun(self,textCommandToList(text))
|
||||
print("response: " +textListToCommand(response))
|
||||
sendResponse(self.connection,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:
|
||||
sendResponse(self.connection,textListToCommand(["error","fatal","timeout"]).encode("utf-8"))
|
||||
return
|
||||
|
||||
sendResponse(self.connection,textListToCommand(["error","fatal","unhandled",str(exc)]).encode("utf-8"))
|
||||
addEventHandler("onException",textOnException)
|
61
parrot text client.py
Normal file
61
parrot text client.py
Normal file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
oldexcepthook = sys.excepthook
|
||||
def newexcepthook(type,value,traceback):
|
||||
oldexcepthook(type,value,traceback)
|
||||
input("Press ENTER to quit.")
|
||||
sys.excepthook = newexcepthook
|
||||
|
||||
import os
|
||||
p = os.path.join
|
||||
pUp = os.path.dirname
|
||||
s = False
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
s = os.path.realpath(sys.executable)
|
||||
else:
|
||||
s = os.path.realpath(__file__)
|
||||
sp = pUp(s)
|
||||
|
||||
# script start
|
||||
import socket
|
||||
|
||||
def sendRequest(connection,data):
|
||||
connection.sendall(len(data).to_bytes(4,"big") + data)
|
||||
|
||||
def getResponse(connection):
|
||||
data = b''
|
||||
data = connection.recv(4)
|
||||
|
||||
if not data:
|
||||
connection.close()
|
||||
return
|
||||
|
||||
requestLength = int.from_bytes(data,"big")
|
||||
data = connection.recv(requestLength)
|
||||
return data
|
||||
|
||||
def main():
|
||||
global connection
|
||||
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
connection.connect(("127.0.0.1",21779))
|
||||
while True:
|
||||
text = input("data: ")
|
||||
data = text.encode("utf-8")
|
||||
sendRequest(connection,data)
|
||||
response = getResponse(connection).decode("utf-8")
|
||||
print("server: " +response)
|
||||
|
||||
if text == "exit":
|
||||
connection.close()
|
||||
break
|
||||
|
||||
if text == "close":
|
||||
connection.close()
|
||||
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
connection.connect(("127.0.0.1",21779))
|
||||
connection.close()
|
||||
break
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
61
serverBlaster.py
Normal file
61
serverBlaster.py
Normal file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
|
||||
oldexcepthook = sys.excepthook
|
||||
def newexcepthook(type,value,traceback):
|
||||
oldexcepthook(type,value,traceback)
|
||||
input("Press ENTER to quit.")
|
||||
sys.excepthook = newexcepthook
|
||||
|
||||
import os
|
||||
p = os.path.join
|
||||
pUp = os.path.dirname
|
||||
s = False
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
s = os.path.realpath(sys.executable)
|
||||
else:
|
||||
s = os.path.realpath(__file__)
|
||||
sp = pUp(s)
|
||||
|
||||
# script start
|
||||
import socket
|
||||
|
||||
def sendRequest(connection,data):
|
||||
connection.sendall(len(data).to_bytes(4,"big") + data)
|
||||
|
||||
def getResponse(connection):
|
||||
data = b''
|
||||
data = connection.recv(4)
|
||||
|
||||
if not data:
|
||||
connection.close()
|
||||
return
|
||||
|
||||
requestLength = int.from_bytes(data,"big")
|
||||
data = connection.recv(requestLength)
|
||||
return data
|
||||
|
||||
def main():
|
||||
global connection
|
||||
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
connection.connect(("127.0.0.1",21779))
|
||||
while True:
|
||||
text = input("data: ")
|
||||
data = text.encode("utf-8")
|
||||
sendRequest(connection,data)
|
||||
response = getResponse(connection).decode("utf-8")
|
||||
print("server: " +response)
|
||||
|
||||
if text == "exit":
|
||||
connection.close()
|
||||
break
|
||||
|
||||
if text == "close":
|
||||
connection.close()
|
||||
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
connection.connect(("127.0.0.1",21779))
|
||||
connection.close()
|
||||
break
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue
Block a user