# (c) J.Y.Amihud 2023 # GPL-3 or any later version # This is a http server that will serve files over network, for multiusering # across the internet. # Server side from http.server import BaseHTTPRequestHandler, HTTPServer from subprocess import * import json import os import zlib import sys import time import random import mimetypes import datetime import hashlib import urllib.request import urllib.parse import subprocess # Colors are used to make the clr = { "norm":"\033[00m", # Reset to normal "bold":"\033[01m", # Bold Text "ital":"\033[03m", # Italic Text "undr":"\033[04m", # Underlined "blnk":"\033[05m", # Blinking # Text "tdbl":"\033[30m", # Dark Black "tdrd":"\033[31m", # Dark Red "tdgr":"\033[32m", # Dark Green "tdyl":"\033[33m", # Dark Yellow "tdbu":"\033[34m", # Dark Blue "tdma":"\033[35m", # Dark Magenta "tdcy":"\033[36m", # Dark Cyan "tdwh":"\033[37m", # Dark White "tbbl":"\033[90m", # Bright Black "tbrd":"\033[91m", # Bright Red "tbgr":"\033[92m", # Bright Green "tbyl":"\033[93m", # Bright Yellow "tbbu":"\033[94m", # Bright Blue "tbma":"\033[95m", # Bright Magenta "tbcy":"\033[96m", # Bright Cyan "tbwh":"\033[97m", # Bright White # Background "bdbl":"\033[40m", # Dark Black "bdrd":"\033[41m", # Dark Red "bdgr":"\033[42m", # Dark Green "bdyl":"\033[43m", # Dark Yellow "bdbu":"\033[44m", # Dark Blue "bdma":"\033[45m", # Dark Magenta "bdcy":"\033[46m", # Dark Cyan "bdwh":"\033[47m", # Dark White "bbbl":"\033[100m", # Bright Black "bbrd":"\033[101m", # Bright Red "bbgr":"\033[102m", # Bright Green "bbyl":"\033[103m", # Bright Yellow "bbbu":"\033[104m", # Bright Blue "bbma":"\033[105m", # Bright Magenta "bbcy":"\033[106m", # Bright Cyan "bbwh":"\033[108m" # Bright White } # TODO: Make this not stupidly hardcoded. blender = "/home/vcs/Software/blender-3.3.0-linux-x64/blender" try: PROJECT = sys.argv[2] except: print("Please specify a port number and then project folder.") exit() try: ORIGINAL_PROJECT = sys.argv[3] except: print("Orignal Project Name Was Not Specified.") ORIGINAL_PROJECT = " not a folder that can exist " def fileinfo(filename): fd = {} fd["md5"] = hashlib.md5(open(filename,'rb').read()).hexdigest() fd["filesize"] = os.path.getsize(filename) return fd class handler(BaseHTTPRequestHandler): def start_page(self, code): self.send_response(code) def do_GET(self): # Basic security measure self.path = self.path.replace("/..", "/") self.path = self.path.replace("//", "/") if self.path == "/": self.start_page(200) self.wfile.write(b"Welcome to Blender-Pipeline Http Server.\nUse /list/[Folder Name] to list contents of a specific folder.\nUse /download/[File Name] to download the file.\nUse /blend/[Blender File Name] to see Blend File Dependencies.") elif self.path.startswith("/list/"): foldername = self.path[5:] folder = PROJECT+foldername walk = list(os.walk(folder))[0] # folders data = {"folders":walk[1], "files":{}} for i in walk[2]: fd = fileinfo(folder+"/"+i) data["files"][i] = fd senddata = json.dumps(data).encode("utf-8") self.start_page(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(senddata) # THIS WAS A GOOD IDEA ON PAPER, BUT WITH A 100 GB PROJECT # IT TOOK FOREVER TO DO THIS FOR ONE PART OF THIS PROJECT. # elif self.path.startswith("/tree/"): # foldername = self.path[5:] # folder = PROJECT+foldername # walk = list(os.walk(folder)) # data = {"folders":[], # "files":{}} # for i in walk: # fol = i[0].replace(PROJECT, "")[1:] # data["folders"].append(fol) # for fil in i[2]: # fd = fileinfo(PROJECT+"/"+fol+"/"+fil) # data["files"][fol+"/"+fil] = fd # senddata = json.dumps(data).encode("utf-8") # self.start_page(200) # self.send_header('Content-type', 'application/json') # self.end_headers() # self.wfile.write(senddata) elif self.path.startswith("/blend/"): filename = self.path[6:] fullfilename = PROJECT+filename if os.path.exists(fullfilename): try: linked = subprocess.check_output([blender, "-b", fullfilename, "-P", os.getcwd()+"/network/get_linked_files.py"]).decode("utf-8") except: linked = "" linked = linked[linked.find("!START_DATA!")+13:linked.rfind("!END_DATA!")] linked = linked.split("\n") while "" in linked: linked.remove("") parsed = [] for i in linked: # This is a little weird, sometimes the files have the full URL # to the data. if i.startswith(PROJECT): # This is good when the server is on the same machine as the orignal project parsed.append(i[len(PROJECT):]) elif i.startswith(ORIGINAL_PROJECT): # This is when the server is a mirror parsed.append(i[len(ORIGINAL_PROJECT):]) else: backward = i.count("/..") foldername = filename[:filename.rfind("/")] f = foldername for g in range(backward): f = f[:f.rfind("/")] cleanname = f+i.replace("//..", "").replace("/..", "").replace( "//", "/") parsed.append(cleanname) data = {"files":{}} for f in parsed: try: fd = fileinfo(PROJECT+"/"+f) data["files"][f] = fd except Exception as e: print(e) linked = json.dumps(data) self.start_page(200) self.send_header('Content-type', 'application/json') self.end_headers() self.wfile.write(linked.encode("utf-8")) else: self.start_page(404) self.wfile.write(b"File: "+filename.encode("utf-8")+b" doesn't exist on server.") elif self.path.startswith("/download/"): filename = self.path[9:] fullfilename = PROJECT+filename if os.path.exists(fullfilename): self.start_page(200) self.send_header('Content-type', mimetypes.guess_type(filename)) self.end_headers() f = open(fullfilename, "rb") f = f.read() self.wfile.write(f) else: self.start_page(404) self.wfile.write(b"File: "+filename.encode("utf-8")+b" doesn't exist") elif self.path.startswith("/download_z/"): filename = self.path[11:] fullfilename = PROJECT+filename if os.path.exists(fullfilename): self.start_page(200) self.send_header('Content-type', mimetypes.guess_type(filename)) f = open(fullfilename, "rb") f = f.read() z = zlib.compress(f) self.send_header('Content-length', len(z)) self.end_headers() self.wfile.write(z) else: self.start_page(404) self.wfile.write(b"File: "+filename.encode("utf-8")+b" doesn't exist") try: PORT = int(sys.argv[1]) except: print("Please specify a port number and then project folder.") exit() serve = HTTPServer(("", PORT), handler) serve.serve_forever()