From 14f34f1a566715834e0a5e3a0886f6496c19e5f3 Mon Sep 17 00:00:00 2001 From: falkTX Date: Mon, 4 Sep 2023 20:45:16 +0200 Subject: [PATCH] Allow plugin bundle uploads via websocket Signed-off-by: falkTX --- html/js/host.js | 2 +- mod/webserver.py | 54 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/html/js/host.js b/html/js/host.js index 688d4fa7..fc8637b0 100644 --- a/html/js/host.js +++ b/html/js/host.js @@ -28,7 +28,7 @@ $('document').ready(function() { } } - ws.onclose = function (evt) { + ws.onclose = function () { desktop && desktop.blockUI() } diff --git a/mod/webserver.py b/mod/webserver.py index 147ed773..fe62a8c7 100644 --- a/mod/webserver.py +++ b/mod/webserver.py @@ -752,6 +752,18 @@ def get(self): self.write(data) class SDKEffectInstaller(EffectInstaller): + def set_default_headers(self): + if 'Origin' not in self.request.headers.keys(): + return + origin = self.request.headers['Origin'] + match = re.match(r'^(\w+)://([^/]*)/?', origin) + if match is None: + return + protocol, domain = match.groups() + if protocol != "http" and not domain.endswith(":9000") and not domain.endswith(".mod.audio"): + return + self.set_header("Access-Control-Allow-Origin", origin) + @web.asynchronous @gen.engine def post(self): @@ -777,7 +789,7 @@ def set_default_headers(self): if match is None: return protocol, domain = match.groups() - if protocol != "http" or not domain.endswith(":9000"): + if protocol != "http" and not domain.endswith(":9000") and not domain.endswith(".mod.audio"): return self.set_header("Access-Control-Allow-Origin", origin) @@ -1096,7 +1108,7 @@ def get(self, instance): logging.exception(e) self.write(ok) -class RemoteWebSocket(websocket.WebSocketHandler): +class RemotePedalboardWebSocket(websocket.WebSocketHandler): def check_origin(self, origin): match = re.match(r'^(\w+)://([^/]*)/?', origin) if match is None: @@ -1117,6 +1129,41 @@ def on_message(self, pedalboard_id): self.write_message("true") self.close() +class RemotePluginWebSocket(websocket.WebSocketHandler): + def check_origin(self, origin): + match = re.match(r'^(\w+)://([^/]*)/?', origin) + if match is None: + return False + protocol, domain = match.groups() + if protocol not in ("http", "https"): + return False + if domain != "mod.audio" and not domain.endswith(".mod.audio"): + return False + return True + + @gen.coroutine + def on_message(self, package): + if not package: + hwdesc = get_hardware_descriptor() + self.write_message(json.dumps({ + 'bin-compat': hwdesc.get('bin-compat', "Unknown"), + 'platform': hwdesc.get('platform', "Unknown"), + 'version': IMAGE_VERSION, + })) + return + + filename = os.path.join(DOWNLOAD_TMP_DIR, "remote.tar.gz") + + with open(filename, 'wb') as fh: + fh.write(b64decode(package)) + + resp = yield gen.Task(install_package, filename) + + if resp['ok']: + SESSION.msg_callback("rescan " + b64encode(json.dumps(resp).encode("utf-8")).decode("utf-8")) + + self.write_message(json.dumps(resp)) + class ServerWebSocket(websocket.WebSocketHandler): @gen.coroutine def open(self): @@ -2324,7 +2371,8 @@ def get(self): (r"/js/templates.js$", BulkTemplateLoader), (r"/websocket/?$", ServerWebSocket), - (r"/rpbsocket/?$", RemoteWebSocket), + (r"/rpbsocket/?$", RemotePedalboardWebSocket), + (r"/rplsocket/?$", RemotePluginWebSocket), (r"/(.*)", TimelessStaticFileHandler, {"path": HTML_DIR}), ],