Changed treehug again
This commit is contained in:
		
							parent
							
								
									5f30b430ff
								
							
						
					
					
						commit
						cc472c0df4
					
				
							
								
								
									
										136
									
								
								src/treehug/frmWrk/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										136
									
								
								src/treehug/frmWrk/.gitignore
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -1,136 +0,0 @@
 | 
				
			||||||
# Byte-compiled / optimized / DLL files
 | 
					 | 
				
			||||||
clearLogs.py
 | 
					 | 
				
			||||||
__pycache__/
 | 
					 | 
				
			||||||
*.py[cod]
 | 
					 | 
				
			||||||
*$py.class
 | 
					 | 
				
			||||||
test.py
 | 
					 | 
				
			||||||
test/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# website/
 | 
					 | 
				
			||||||
.vscode/
 | 
					 | 
				
			||||||
log.txt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# C extensions
 | 
					 | 
				
			||||||
*.so
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Distribution / packaging
 | 
					 | 
				
			||||||
.Python
 | 
					 | 
				
			||||||
build/
 | 
					 | 
				
			||||||
develop-eggs/
 | 
					 | 
				
			||||||
dist/
 | 
					 | 
				
			||||||
downloads/
 | 
					 | 
				
			||||||
eggs/
 | 
					 | 
				
			||||||
.eggs/
 | 
					 | 
				
			||||||
lib/
 | 
					 | 
				
			||||||
lib64/
 | 
					 | 
				
			||||||
parts/
 | 
					 | 
				
			||||||
sdist/
 | 
					 | 
				
			||||||
var/
 | 
					 | 
				
			||||||
wheels/
 | 
					 | 
				
			||||||
pip-wheel-metadata/
 | 
					 | 
				
			||||||
share/python-wheels/
 | 
					 | 
				
			||||||
*.egg-info/
 | 
					 | 
				
			||||||
.installed.cfg
 | 
					 | 
				
			||||||
*.egg
 | 
					 | 
				
			||||||
MANIFEST
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# PyInstaller
 | 
					 | 
				
			||||||
#  Usually these files are written by a python script from a template
 | 
					 | 
				
			||||||
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
 | 
					 | 
				
			||||||
*.manifest
 | 
					 | 
				
			||||||
*.spec
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Installer logs
 | 
					 | 
				
			||||||
pip-log.txt
 | 
					 | 
				
			||||||
pip-delete-this-directory.txt
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Unit test / coverage reports
 | 
					 | 
				
			||||||
htmlcov/
 | 
					 | 
				
			||||||
.tox/
 | 
					 | 
				
			||||||
.nox/
 | 
					 | 
				
			||||||
.coverage
 | 
					 | 
				
			||||||
.coverage.*
 | 
					 | 
				
			||||||
.cache
 | 
					 | 
				
			||||||
nosetests.xml
 | 
					 | 
				
			||||||
coverage.xml
 | 
					 | 
				
			||||||
*.cover
 | 
					 | 
				
			||||||
*.py,cover
 | 
					 | 
				
			||||||
.hypothesis/
 | 
					 | 
				
			||||||
.pytest_cache/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Translations
 | 
					 | 
				
			||||||
*.mo
 | 
					 | 
				
			||||||
*.pot
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Django stuff:
 | 
					 | 
				
			||||||
*.log
 | 
					 | 
				
			||||||
local_settings.py
 | 
					 | 
				
			||||||
db.sqlite3
 | 
					 | 
				
			||||||
db.sqlite3-journal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Flask stuff:
 | 
					 | 
				
			||||||
instance/
 | 
					 | 
				
			||||||
.webassets-cache
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Scrapy stuff:
 | 
					 | 
				
			||||||
.scrapy
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Sphinx documentation
 | 
					 | 
				
			||||||
docs/_build/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# PyBuilder
 | 
					 | 
				
			||||||
target/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Jupyter Notebook
 | 
					 | 
				
			||||||
.ipynb_checkpoints
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# IPython
 | 
					 | 
				
			||||||
profile_default/
 | 
					 | 
				
			||||||
ipython_config.py
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# pyenv
 | 
					 | 
				
			||||||
.python-version
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# pipenv
 | 
					 | 
				
			||||||
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
 | 
					 | 
				
			||||||
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
 | 
					 | 
				
			||||||
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
 | 
					 | 
				
			||||||
#   install all needed dependencies.
 | 
					 | 
				
			||||||
#Pipfile.lock
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
 | 
					 | 
				
			||||||
__pypackages__/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Celery stuff
 | 
					 | 
				
			||||||
celerybeat-schedule
 | 
					 | 
				
			||||||
celerybeat.pid
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# SageMath parsed files
 | 
					 | 
				
			||||||
*.sage.py
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Environments
 | 
					 | 
				
			||||||
.env
 | 
					 | 
				
			||||||
.venv
 | 
					 | 
				
			||||||
env/
 | 
					 | 
				
			||||||
venv/
 | 
					 | 
				
			||||||
ENV/
 | 
					 | 
				
			||||||
env.bak/
 | 
					 | 
				
			||||||
venv.bak/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Spyder project settings
 | 
					 | 
				
			||||||
.spyderproject
 | 
					 | 
				
			||||||
.spyproject
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Rope project settings
 | 
					 | 
				
			||||||
.ropeproject
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# mkdocs documentation
 | 
					 | 
				
			||||||
/site
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# mypy
 | 
					 | 
				
			||||||
.mypy_cache/
 | 
					 | 
				
			||||||
.dmypy.json
 | 
					 | 
				
			||||||
dmypy.json
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Pyre type checker
 | 
					 | 
				
			||||||
.pyre/
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,62 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Installation](#installing)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Quickstart](#usage)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[Documentation](#documentation)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Installing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Open terminal in project folder.
 | 
					 | 
				
			||||||
Run:
 | 
					 | 
				
			||||||
```bash
 | 
					 | 
				
			||||||
git clone https://github.com/vanten-s/frmWrk frmWrk
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Done. Look at usage for quickstart.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Usage
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
With a index.html in the working directory this will make host a website at 127.0.0.1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```python
 | 
					 | 
				
			||||||
# Example for website
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import frmWrk.website as frw
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Start the server on 127.0.0.1:80 with parent folder as root directory
 | 
					 | 
				
			||||||
website = frw.WebServer("127.0.0.1", 80, "./")
 | 
					 | 
				
			||||||
website.start()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Close the server when we get input
 | 
					 | 
				
			||||||
input()
 | 
					 | 
				
			||||||
website.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Documentation
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```python
 | 
					 | 
				
			||||||
# Import everything
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import frmWrk
 | 
					 | 
				
			||||||
import time
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Create the webserver. Directory is where the server should look for files
 | 
					 | 
				
			||||||
website = frmWrk.website.WebServer(ip, port, directory)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Run the server
 | 
					 | 
				
			||||||
website.start()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Wait 10 seconds and close the server
 | 
					 | 
				
			||||||
time.sleep(10)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
website.close()
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
frmWrk will replace substrings in the format of {ip:port:prompt} by connecting to (ip, port) and sending "{promt} {path}" where path is the URL that the user is on. Then they replace the whole substring with the response (max 1024 bytes).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
frmWrk.databases should not be used.
 | 
					 | 
				
			||||||
It Can be used but please dont use it.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,2 +0,0 @@
 | 
				
			||||||
import frmWrk.website
 | 
					 | 
				
			||||||
import frmWrk.decorators
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,192 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import socket
 | 
					 | 
				
			||||||
import threading
 | 
					 | 
				
			||||||
import datetime
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enable_logging = True
 | 
					 | 
				
			||||||
log_file = "log.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def log(func):
 | 
					 | 
				
			||||||
    def wrapper(*args, **kwargs):
 | 
					 | 
				
			||||||
        if not enable_logging: return func(*args, **kwargs)
 | 
					 | 
				
			||||||
        returnVal = func(*args, **kwargs)
 | 
					 | 
				
			||||||
        with open(log_file, "a") as f:
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                if len(returnVal) < 100:
 | 
					 | 
				
			||||||
                    f.write(f"{func.__name__} was called at {datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')} and returned {returnVal}\n")
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    f.write(f"{func.__name__} was called at {datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}\n")
 | 
					 | 
				
			||||||
            except TypeError as e:
 | 
					 | 
				
			||||||
                f.write(f"{func.__name__} was called at {datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}\n")    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return returnVal
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return wrapper
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def log_string(string):
 | 
					 | 
				
			||||||
    if not enable_logging: return string
 | 
					 | 
				
			||||||
    with open(log_file, "a") as f:
 | 
					 | 
				
			||||||
        f.write(f"{string}\n")
 | 
					 | 
				
			||||||
    return string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
databases = {}
 | 
					 | 
				
			||||||
__using_remote_access = False
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
Usage:
 | 
					 | 
				
			||||||
    CREATE <name> # Creates a new database
 | 
					 | 
				
			||||||
    ADDATTRIBUTE <name> <attribute> # Adds an attribute to a database
 | 
					 | 
				
			||||||
    ADD <name> <database> # Adds an entry to a database
 | 
					 | 
				
			||||||
    LIST # Lists all databases
 | 
					 | 
				
			||||||
    GET <entry> <database> <attribute> # Gets an entry from a database
 | 
					 | 
				
			||||||
    SET <entry> <database> <attribute> <value> # Sets an attribute of an entry in a database
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def help():
 | 
					 | 
				
			||||||
    return "Usage: CREATE <name> # Creates a new database\nADDATTRIBUTE <name> <attribute> # Adds an attribute to a database\nADD <name> <database> # Adds an entry to a database\nLIST # Lists all databases\nGET <entry> <database> # Gets an entry from a database\nSET <entry> <database> <attribute> <value> # Sets an attribute of an entry in a database"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Database:
 | 
					 | 
				
			||||||
    def __init__(self, name):
 | 
					 | 
				
			||||||
        self.name = name
 | 
					 | 
				
			||||||
        self.attributes = []
 | 
					 | 
				
			||||||
        self.entrys = {}
 | 
					 | 
				
			||||||
        databases[name] = self
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    def __hash__(self):
 | 
					 | 
				
			||||||
        return self.name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __eq__(self, other):
 | 
					 | 
				
			||||||
        return self.name == other.name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __str__(self):
 | 
					 | 
				
			||||||
        return self.name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __repr__(self):
 | 
					 | 
				
			||||||
        return self.name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def addAttribute(self, attribute):
 | 
					 | 
				
			||||||
        self.attributes.append(attribute)
 | 
					 | 
				
			||||||
        for entry in self.entrys:
 | 
					 | 
				
			||||||
            entry.__setAttribute(attribute)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getAttribute(self, attribute):
 | 
					 | 
				
			||||||
        return self.attributes[attribute]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Entry:
 | 
					 | 
				
			||||||
    def __init__(self, name, parent):
 | 
					 | 
				
			||||||
        self.name = name
 | 
					 | 
				
			||||||
        self.parent = parent
 | 
					 | 
				
			||||||
        self.attributes = {attr:None for attr in parent.attributes}
 | 
					 | 
				
			||||||
        self.parent.entrys[name] = self
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __hash__(self):
 | 
					 | 
				
			||||||
        return self.name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __eq__(self, other):
 | 
					 | 
				
			||||||
        return self.name == other.name
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __str__(self):
 | 
					 | 
				
			||||||
        return self.attributes.__str__()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __repr__(self):
 | 
					 | 
				
			||||||
        return self.name + " with " + self.attributes.__str__()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __setAttribute(self, attribute):
 | 
					 | 
				
			||||||
        self.attributes[attribute] = ""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def setAttribute(self, attribute, value):
 | 
					 | 
				
			||||||
        if attribute in self.attributes.keys():
 | 
					 | 
				
			||||||
            self.attributes[attribute] = value
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise Exception("Attribute not found")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getAttribute(self, attribute):
 | 
					 | 
				
			||||||
        if attribute in self.attributes.keys():
 | 
					 | 
				
			||||||
            return self.attributes[attribute]
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise Exception("Attribute not found")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def executeInstruction(instruction):
 | 
					 | 
				
			||||||
    tokens = instruction.split(" ")
 | 
					 | 
				
			||||||
    log_string(f"Executing instruction: {instruction}")
 | 
					 | 
				
			||||||
    if tokens[0] == "CREATE":
 | 
					 | 
				
			||||||
        database = Database(tokens[1])
 | 
					 | 
				
			||||||
        return database
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    elif tokens[0] == "ADDATTRIBUTE":
 | 
					 | 
				
			||||||
        databases[tokens[1]].addAttribute(tokens[2])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    elif tokens[0] == "ADD":
 | 
					 | 
				
			||||||
        Entry(tokens[1], databases[tokens[2]])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    elif tokens[0] == "LIST":
 | 
					 | 
				
			||||||
        if len(databases) == 0:
 | 
					 | 
				
			||||||
            return "No databases"
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if len(tokens) == 2:
 | 
					 | 
				
			||||||
            return databases[tokens[1]].entrys
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if len(tokens) == 3:
 | 
					 | 
				
			||||||
            return databases[tokens[1]].entrys[tokens[2]]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return databases
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    elif tokens[0] == "GET":
 | 
					 | 
				
			||||||
        return databases[tokens[1]].entrys[tokens[2]].getAttribute(tokens[3]).__str__()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    elif tokens[0] == "SET":
 | 
					 | 
				
			||||||
        database = databases[tokens[1]].entrys[tokens[2]].setAttribute(tokens[3], tokens[4])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        print(instruction)
 | 
					 | 
				
			||||||
        return "Invalid instruction"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return "Success"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def __enable_remote_access(ip, port):
 | 
					 | 
				
			||||||
    HOST = ip  # The server's hostname or IP address
 | 
					 | 
				
			||||||
    PORT = port        # The port used by the server
 | 
					 | 
				
			||||||
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
					 | 
				
			||||||
    s.bind((HOST, PORT))
 | 
					 | 
				
			||||||
    s.listen(1)
 | 
					 | 
				
			||||||
    while True and __using_remote_access:
 | 
					 | 
				
			||||||
        conn, addr = s.accept()
 | 
					 | 
				
			||||||
        with conn:
 | 
					 | 
				
			||||||
            print('Connected by', addr)
 | 
					 | 
				
			||||||
            while True:
 | 
					 | 
				
			||||||
                data = conn.recv(1024).decode()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                firstLine = data.split("\n")[0]
 | 
					 | 
				
			||||||
                instruction = " ".join(firstLine.split(" ")[1:-1])
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                conn.send(executeInstruction(instruction).encode())
 | 
					 | 
				
			||||||
                if not data: break
 | 
					 | 
				
			||||||
                
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    print('Connection closed')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@log
 | 
					 | 
				
			||||||
def enable_remote_access(ip, port):
 | 
					 | 
				
			||||||
    global __using_remote_access
 | 
					 | 
				
			||||||
    __using_remote_access = True
 | 
					 | 
				
			||||||
    t = threading.Thread(target=__enable_remote_access, args=(ip, port))
 | 
					 | 
				
			||||||
    t.start()
 | 
					 | 
				
			||||||
    return "Enabled remote access"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def disable_remote_access():
 | 
					 | 
				
			||||||
    global __using_remote_access
 | 
					 | 
				
			||||||
    __using_remote_access = False
 | 
					 | 
				
			||||||
    return "Disabled remote access"
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,32 +0,0 @@
 | 
				
			||||||
import datetime
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enable_logging = True
 | 
					 | 
				
			||||||
log_file = "log.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def log(func):
 | 
					 | 
				
			||||||
    def wrapper(*args, **kwargs):
 | 
					 | 
				
			||||||
        if not enable_logging: return func(*args, **kwargs)
 | 
					 | 
				
			||||||
        returnVal = func(*args, **kwargs)
 | 
					 | 
				
			||||||
        with open(log_file, "a") as f:
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                if len(returnVal) < 100:
 | 
					 | 
				
			||||||
                    f.write(f"{func.__name__} was called at {datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')} and returned {returnVal}\n")
 | 
					 | 
				
			||||||
                else:
 | 
					 | 
				
			||||||
                    f.write(f"{func.__name__} was called at {datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}\n")
 | 
					 | 
				
			||||||
            except TypeError as e:
 | 
					 | 
				
			||||||
                f.write(f"{func.__name__} was called at {datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}\n")    
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return returnVal
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return wrapper
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def log_string(string):
 | 
					 | 
				
			||||||
    if not enable_logging: return string
 | 
					 | 
				
			||||||
    with open(log_file, "a") as f:
 | 
					 | 
				
			||||||
        f.write(f"{string}\n")
 | 
					 | 
				
			||||||
    return string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 3.7 KiB  | 
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
					@ -1,300 +0,0 @@
 | 
				
			||||||
 | 
					 | 
				
			||||||
import socket
 | 
					 | 
				
			||||||
import threading
 | 
					 | 
				
			||||||
import datetime
 | 
					 | 
				
			||||||
import os
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def boron (code: str, path: str) -> str:
 | 
					 | 
				
			||||||
    total = []
 | 
					 | 
				
			||||||
    none = []
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while "{" in code and "}" in code:
 | 
					 | 
				
			||||||
        startIndex = code.index("{")
 | 
					 | 
				
			||||||
        endIndex = code.index("}")
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            string = code[startIndex+1:endIndex]
 | 
					 | 
				
			||||||
            ip = string.split(":")[0]
 | 
					 | 
				
			||||||
            port = int(string.split(":")[1])
 | 
					 | 
				
			||||||
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
					 | 
				
			||||||
            addr = (ip, port)
 | 
					 | 
				
			||||||
            print(addr)
 | 
					 | 
				
			||||||
            s.connect(addr)
 | 
					 | 
				
			||||||
            s.send((string.split(":")[2] + " " + path).encode('utf-8'))
 | 
					 | 
				
			||||||
            response = s.recv(1024).decode()
 | 
					 | 
				
			||||||
            s.close()
 | 
					 | 
				
			||||||
            code = code.replace("{" + string + "}", response)
 | 
					 | 
				
			||||||
            print("{" + string + "}")
 | 
					 | 
				
			||||||
            print(code)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        except Exception as e:
 | 
					 | 
				
			||||||
            print(e)
 | 
					 | 
				
			||||||
            code = code.replace("{" + string + "}", string)
 | 
					 | 
				
			||||||
            none.append(string)
 | 
					 | 
				
			||||||
            print("{" + string + "}")
 | 
					 | 
				
			||||||
            print(code)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for string in none:
 | 
					 | 
				
			||||||
        code = code.replace(string, "{" + string + "}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return code
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enable_logging = True
 | 
					 | 
				
			||||||
log_file = "log.txt"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def log(func):
 | 
					 | 
				
			||||||
    def wrapper(*args, **kwargs):
 | 
					 | 
				
			||||||
        if not enable_logging: return func(*args, **kwargs)
 | 
					 | 
				
			||||||
        returnVal = func(*args, **kwargs)
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            if len(returnVal) < 10:
 | 
					 | 
				
			||||||
                log_string(f"[{datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}] {func.__name__} was called and returned {returnVal}\n")
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                log_string(f"[{datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}] {func.__name__} was called\n")
 | 
					 | 
				
			||||||
        except TypeError as e:
 | 
					 | 
				
			||||||
            log_string(f"[{datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}] {func.__name__} was called\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return returnVal
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return wrapper
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def log_string(string):
 | 
					 | 
				
			||||||
    global log_file, enable_logging
 | 
					 | 
				
			||||||
    if not enable_logging: return
 | 
					 | 
				
			||||||
    with open(log_file, "a") as f:
 | 
					 | 
				
			||||||
        f.write(f"[{datetime.datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}] {string}\n")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
AASCI_404_NOT_FOUND = """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<!DOCTYPE html>
 | 
					 | 
				
			||||||
<html lang="en">
 | 
					 | 
				
			||||||
<head>
 | 
					 | 
				
			||||||
    <meta charset="utf-8">
 | 
					 | 
				
			||||||
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 | 
					 | 
				
			||||||
    <meta name="description" content="">
 | 
					 | 
				
			||||||
    <meta name="author" content="">
 | 
					 | 
				
			||||||
</head>
 | 
					 | 
				
			||||||
<body>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <h1>404 Not Found</h1>
 | 
					 | 
				
			||||||
 <pre style="font-size: xx-large;">
 | 
					 | 
				
			||||||
   _  _    ___  _  _                 _      __                      _
 | 
					 | 
				
			||||||
  | || |  / _ \| || |               | |    / _|                    | |
 | 
					 | 
				
			||||||
  | || |_| | | | || |_   _ __   ___ | |_  | |_ ___  _   _ _ __   __| |
 | 
					 | 
				
			||||||
  |__   _| | | |__   _| | '_ \ / _ \| __| |  _/ _ \| | | | '_ \ / _` |
 | 
					 | 
				
			||||||
     | | | |_| |  | |   | | | | (_) | |_  | || (_) | |_| | | | | (_| |
 | 
					 | 
				
			||||||
     |_|  \___/   |_|   |_| |_|\___/ \__| |_| \___/ \__,_|_| |_|\__,_|</pre>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</body>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
content_type = {
 | 
					 | 
				
			||||||
                'html': 'text/html; charset=\'utf-8\'',
 | 
					 | 
				
			||||||
                'css': 'text/css; charset=\'utf-8\'',
 | 
					 | 
				
			||||||
                'js': 'application/javascript; charset=\'utf-8\'',
 | 
					 | 
				
			||||||
                'xml': 'application/xml; charset=\'utf-8\'',
 | 
					 | 
				
			||||||
                'png': 'image/png',
 | 
					 | 
				
			||||||
                'jpg': 'image/jpeg',
 | 
					 | 
				
			||||||
                'jpeg': 'image/jpeg',
 | 
					 | 
				
			||||||
                'gif': 'image/gif',
 | 
					 | 
				
			||||||
                'ico': 'image/x-icon',
 | 
					 | 
				
			||||||
                'svg': 'image/svg+xml',
 | 
					 | 
				
			||||||
                'json': 'application/json; charset=\'utf-8\'',
 | 
					 | 
				
			||||||
                'txt': 'text/plain; charset=\'utf-8\'',
 | 
					 | 
				
			||||||
                'pdf': 'application/pdf',
 | 
					 | 
				
			||||||
                'zip': 'application/zip',
 | 
					 | 
				
			||||||
                'rar': 'application/x-rar-compressed',
 | 
					 | 
				
			||||||
                '7z': 'application/x-7z-compressed',
 | 
					 | 
				
			||||||
                'doc': 'application/msword',
 | 
					 | 
				
			||||||
                'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
 | 
					 | 
				
			||||||
                'xls': 'application/vnd.ms-excel',
 | 
					 | 
				
			||||||
                'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
 | 
					 | 
				
			||||||
                'ppt': 'application/vnd.ms-powerpoint',
 | 
					 | 
				
			||||||
                'pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
 | 
					 | 
				
			||||||
                'mp3': 'audio/mpeg',
 | 
					 | 
				
			||||||
                'wav': 'audio/x-wav',
 | 
					 | 
				
			||||||
                'mp4': 'video/mp4',
 | 
					 | 
				
			||||||
                'm4v': 'video/x-m4v',
 | 
					 | 
				
			||||||
                'mov': 'video/quicktime',
 | 
					 | 
				
			||||||
                'wmv': 'video/x-ms-wmv',
 | 
					 | 
				
			||||||
                'flv': 'video/x-flv',
 | 
					 | 
				
			||||||
                'avi': 'video/x-msvideo',
 | 
					 | 
				
			||||||
                'mkv': 'video/x-matroska',
 | 
					 | 
				
			||||||
                'm3u': 'application/x-mpegURL',
 | 
					 | 
				
			||||||
                'm3u8': 'application/vnd.apple.mpegurl',
 | 
					 | 
				
			||||||
                'ts': 'video/MP2T',
 | 
					 | 
				
			||||||
                '3gp': 'video/3gpp',
 | 
					 | 
				
			||||||
                '3g2': 'video/3gpp2',
 | 
					 | 
				
			||||||
                'mpd': 'video/vnd.mpeg.dash.mpd',
 | 
					 | 
				
			||||||
                'mp4': 'video/mp4',
 | 
					 | 
				
			||||||
                'webm': 'video/webm',
 | 
					 | 
				
			||||||
                'ogv': 'video/ogg',
 | 
					 | 
				
			||||||
                'ogm': 'video/ogg',
 | 
					 | 
				
			||||||
                'ogg': 'video/ogg',
 | 
					 | 
				
			||||||
                'ogx': 'application/ogg',
 | 
					 | 
				
			||||||
                'oga': 'audio/ogg',
 | 
					 | 
				
			||||||
                'spx': 'audio/ogg',
 | 
					 | 
				
			||||||
                'opus': 'audio/ogg',
 | 
					 | 
				
			||||||
                'flac': 'audio/flac'
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class WebServer:
 | 
					 | 
				
			||||||
    def __init__(self, ip, port, directory, site404="/404.html", event_handler=None, overwrites={}, custom_router=None):
 | 
					 | 
				
			||||||
        self.directory = directory
 | 
					 | 
				
			||||||
        self.ip = ip
 | 
					 | 
				
			||||||
        self.port = port
 | 
					 | 
				
			||||||
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
					 | 
				
			||||||
        self.s.bind((ip,port))
 | 
					 | 
				
			||||||
        self.threads = []
 | 
					 | 
				
			||||||
        self.running = True
 | 
					 | 
				
			||||||
        self.site404 = directory + "/404.html"
 | 
					 | 
				
			||||||
        self.event_handler = event_handler
 | 
					 | 
				
			||||||
        self.overwrites = overwrites
 | 
					 | 
				
			||||||
        self.custom_router = custom_router
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __getContentType(self, path):
 | 
					 | 
				
			||||||
        path = path.split(".")[-1]
 | 
					 | 
				
			||||||
        if not path in content_type.keys():
 | 
					 | 
				
			||||||
            return 'application/octet-stream'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return content_type[path]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __getResponse(self, code, content_type, payload, custom_headers={}):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        response = b'HTTP/1.1 ' + code.encode("utf-8") + b'\n'
 | 
					 | 
				
			||||||
        response += b'Content-Type: ' + content_type.encode("utf-8") + b'\n'
 | 
					 | 
				
			||||||
        response += b'Content-Length: ' + str(len(payload)).encode("utf-8") + b'\n'
 | 
					 | 
				
			||||||
        response += b'server: frmWrk\n'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for header_key in custom_headers.keys():
 | 
					 | 
				
			||||||
            response += header_key.encode("utf-8") + custom_headers[header_key].encode("utf-8") + b'\n'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        response += b'\n'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        response += payload + b'\n\n'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return response
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __get(self, path):
 | 
					 | 
				
			||||||
        # Remove data after the ?
 | 
					 | 
				
			||||||
        original = path
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ".." in path:
 | 
					 | 
				
			||||||
            return self.__getResponse("404 Not Found", self.__getContentType("/index.html"), b'')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if "?" in path:
 | 
					 | 
				
			||||||
            path = path[:path.index("?")]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if path == "/":
 | 
					 | 
				
			||||||
            path = "/index.html"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if os.path.isdir(self.directory + path):
 | 
					 | 
				
			||||||
            if path.endswith("/"):
 | 
					 | 
				
			||||||
                path = path + "/index.html"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                return self.__getResponse("301 Moved Permanently", self.__getContentType("/index.html"), b'', custom_headers={"location: ": path + "/"})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if path in self.overwrites.keys():
 | 
					 | 
				
			||||||
            return self.__getResponse("200 OK", self.__getContentType(path), self.overwrites[path](original).encode("utf-8"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        path = self.directory + path
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            with open(path, "rb") as f:
 | 
					 | 
				
			||||||
                content = f.read()
 | 
					 | 
				
			||||||
                content_type = self.__getContentType(path)
 | 
					 | 
				
			||||||
                # if content_type.startswith("text/html"):
 | 
					 | 
				
			||||||
                #     content = boron(content.decode('utf-8'), path).encode('utf-8')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return self.__getResponse("200 OK", content_type, content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        except FileNotFoundError:
 | 
					 | 
				
			||||||
            if "favicon.ico" in path:
 | 
					 | 
				
			||||||
                with open(os.path.dirname(os.path.abspath(__file__)) + "/favicon.ico", "rb") as f:
 | 
					 | 
				
			||||||
                    content = f.read()
 | 
					 | 
				
			||||||
                    return self.__getResponse("200 OK", "image/x-icon", content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                print(log_string("404 Not Found: " + path))
 | 
					 | 
				
			||||||
                with open(self.site404, "rb") as f:
 | 
					 | 
				
			||||||
                    content = f.read()
 | 
					 | 
				
			||||||
                    content_type = self.__getContentType(self.site404)
 | 
					 | 
				
			||||||
                    return self.__getResponse("404 Not Found", content_type, content)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            except FileNotFoundError:
 | 
					 | 
				
			||||||
                return self.__getResponse("404 Not Found", "text/html; charset=\"utf-8\"", AASCI_404_NOT_FOUND.encode("utf-8"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __handleRequest(self, request):
 | 
					 | 
				
			||||||
        tokens = request.split(" ")
 | 
					 | 
				
			||||||
        method = tokens[0]
 | 
					 | 
				
			||||||
        path = tokens[1]
 | 
					 | 
				
			||||||
        version = tokens[2]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.event_handler:
 | 
					 | 
				
			||||||
            self.event_handler(method, (path))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if self.custom_router:
 | 
					 | 
				
			||||||
            return self.custom_router(method, path, {})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if method == "GET":
 | 
					 | 
				
			||||||
            return self.__get(path)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return "Only GET Requests Supported Yet Sorry."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __handleClient(self, c: socket.socket, addr):
 | 
					 | 
				
			||||||
        global running
 | 
					 | 
				
			||||||
        while True and self.running:
 | 
					 | 
				
			||||||
            data = c.recv(1024)
 | 
					 | 
				
			||||||
            if not data:
 | 
					 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            request = data.decode("utf-8")
 | 
					 | 
				
			||||||
            response = self.__handleRequest(request)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            log_string(f"{addr} asked for {request.split(' ')[1]}")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            c.send(response)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        c.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __startServer(self):
 | 
					 | 
				
			||||||
        global running, s
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        log_string("Server started on port " + str(self.port))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while self.running:
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                c, addr = self.s.accept()
 | 
					 | 
				
			||||||
                p = threading.Thread(target=self.__handleClient, args=(c, addr))
 | 
					 | 
				
			||||||
                p.start()
 | 
					 | 
				
			||||||
                self.threads.append(p)
 | 
					 | 
				
			||||||
            except Exception as e:
 | 
					 | 
				
			||||||
                log_string(e)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def start(self):
 | 
					 | 
				
			||||||
        print("Starting server...")
 | 
					 | 
				
			||||||
        self.s.listen(1)
 | 
					 | 
				
			||||||
        t = threading.Thread(target=self.__startServer)
 | 
					 | 
				
			||||||
        t.start()
 | 
					 | 
				
			||||||
        self.main_process = t
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def close(self):
 | 
					 | 
				
			||||||
        self.running = False
 | 
					 | 
				
			||||||
        print("Closing server...")
 | 
					 | 
				
			||||||
        self.s.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for thread in self.threads:
 | 
					 | 
				
			||||||
            thread.join()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.main_process.join()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        print("Server closed")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,4 +0,0 @@
 | 
				
			||||||
import frmWrk.website
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
webserver = frmWrk.website.WebServer("127.0.0.1", 4000, "./")
 | 
					 | 
				
			||||||
webserver.start()
 | 
					 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
  margin-bottom: 1em;
 | 
					  margin-bottom: 1em;
 | 
				
			||||||
  height: 80%;
 | 
					  height: 80%;
 | 
				
			||||||
  width: 30em;
 | 
					  width: 30em;
 | 
				
			||||||
  max-width: 30em;
 | 
					  max-width: 90%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.search_bar {
 | 
					.search_bar {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue