117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
import os
|
|
import sys
|
|
import threading
|
|
import subprocess
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
import mimetypes
|
|
from jsmin import jsmin # pip install jsmin
|
|
|
|
from log.Logger import *
|
|
logger = Logger()
|
|
import PyPost
|
|
|
|
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
|
|
HTML_DIR = os.path.join(PROJECT_ROOT, "html")
|
|
BASE_FILE = os.path.join(HTML_DIR, "base", "index.html")
|
|
|
|
def get_html_files(directory=HTML_DIR):
|
|
html_files = []
|
|
for entry in os.listdir(directory):
|
|
full_path = os.path.join(directory, entry)
|
|
if os.path.isfile(full_path) and entry.endswith(".html"):
|
|
html_files.append(entry)
|
|
return html_files
|
|
|
|
def build_index_page():
|
|
with open(BASE_FILE, "r", encoding="utf-8") as f:
|
|
base_html = f.read()
|
|
html_files = get_html_files(HTML_DIR)
|
|
links = "\n".join(f'<li><a href="/html/{fname}">{fname}</a></li>' for fname in html_files)
|
|
content = f"<ul>{links}</ul>"
|
|
# Insert footer after content
|
|
full_content = content + index_footer()
|
|
return base_html.replace("<!-- CONTENT -->", full_content)
|
|
|
|
import base64
|
|
import random
|
|
|
|
from hashes.hashes import hash_list
|
|
|
|
def index_footer():
|
|
return f"""
|
|
<footer style="
|
|
position: absolute;
|
|
bottom: 0;
|
|
width: 100%;
|
|
">
|
|
<hr style="border: 1px solid #ccc;" />
|
|
<p>
|
|
Hash 1 (<b>UTF-8</b>)<i>:{base64.b64encode(random.choice(hash_list).encode("utf-8")).decode("utf-8")}</i><br />
|
|
Hash 2 (<b>ASCII</b>)<i>:{base64.b64encode(random.choice(hash_list).encode("ascii")).decode("ascii")}</i><br />
|
|
<i>Decode Hashes to identify pages</i>
|
|
</p>
|
|
</footer>
|
|
"""
|
|
|
|
class MyHandler(BaseHTTPRequestHandler):
|
|
def do_GET(self):
|
|
req_path = self.path.lstrip("/")
|
|
if req_path == "" or req_path == "index.html":
|
|
content = build_index_page()
|
|
self.send_response(200)
|
|
self.send_header("Content-type", "text/html")
|
|
self.end_headers()
|
|
self.wfile.write(content.encode("utf-8"))
|
|
return
|
|
|
|
file_path = os.path.normpath(os.path.join(PROJECT_ROOT, req_path))
|
|
if not file_path.startswith(PROJECT_ROOT):
|
|
self.send_response(403)
|
|
self.end_headers()
|
|
self.wfile.write(b"403 - Forbidden")
|
|
return
|
|
|
|
if os.path.isfile(file_path):
|
|
mime_type, _ = mimetypes.guess_type(file_path)
|
|
if mime_type is None:
|
|
mime_type = "application/octet-stream"
|
|
|
|
with open(file_path, "rb") as f:
|
|
content = f.read()
|
|
|
|
# Obfuscate JS on the fly
|
|
if mime_type == "application/javascript" or file_path.endswith(".js"):
|
|
try:
|
|
content = jsmin(content.decode("utf-8")).encode("utf-8")
|
|
except Exception as e:
|
|
logger.log_error(f"Error minifying JS file {file_path}: {e}")
|
|
|
|
self.send_response(200)
|
|
self.send_header("Content-type", mime_type)
|
|
self.end_headers()
|
|
self.wfile.write(content)
|
|
return
|
|
|
|
self.send_response(404)
|
|
self.end_headers()
|
|
self.wfile.write(b"404 - Not Found")
|
|
|
|
def run_pypost():
|
|
"""Run PyPost.py in a separate process."""
|
|
script = os.path.join(PROJECT_ROOT, "PyPost.py")
|
|
subprocess.run([sys.executable, script])
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
threading.Thread(target=run_pypost, daemon=True).start()
|
|
logger.log_debug("Started PyPost.py in background watcher thread.")
|
|
|
|
server_address = ("localhost", 8000)
|
|
httpd = HTTPServer(server_address, MyHandler)
|
|
logger.log_info(f"Serving on http://{server_address[0]}:{server_address[1]}")
|
|
httpd.serve_forever()
|
|
except (Exception, KeyboardInterrupt) as e:
|
|
logger.log_info(f"Shutting down server.\n Reason: {e}")
|
|
httpd.server_close()
|
|
|