Blender-Pipeline/network/http_server.py
2023-12-21 20:33:35 +02:00

272 lines
8.4 KiB
Python

# (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()