From febdea6c64220e1da12f0e9f752e2c69fdf3ba93 Mon Sep 17 00:00:00 2001 From: shortcutme Date: Sun, 9 Jul 2017 14:10:01 +0200 Subject: [PATCH] Serve files without wrapper if requested using /raw/ prefix --- plugins/FilePack/FilePackPlugin.py | 4 +-- plugins/TranslateSite/TranslateSitePlugin.py | 7 +++-- plugins/Zeroname/UiRequestPlugin.py | 2 +- src/Ui/UiRequest.py | 33 +++++++++++++++----- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/plugins/FilePack/FilePackPlugin.py b/plugins/FilePack/FilePackPlugin.py index e80f9de5..0d413b60 100644 --- a/plugins/FilePack/FilePackPlugin.py +++ b/plugins/FilePack/FilePackPlugin.py @@ -38,7 +38,7 @@ def openArchive(archive_path, path_within): @PluginManager.registerTo("UiRequest") class UiRequestPlugin(object): - def actionSiteMedia(self, path, header_length=True): + def actionSiteMedia(self, path, **kwargs): if ".zip/" in path or ".tar.gz/" in path: path_parts = self.parsePath(path) file_path = u"%s/%s/%s" % (config.data_dir, path_parts["address"], path_parts["inner_path"].decode("utf8")) @@ -63,7 +63,7 @@ class UiRequestPlugin(object): self.log.debug("Error opening archive file: %s" % err) return self.error404(path) - return super(UiRequestPlugin, self).actionSiteMedia(path, header_length=header_length) + return super(UiRequestPlugin, self).actionSiteMedia(path, **kwargs) def streamFile(self, file): while 1: diff --git a/plugins/TranslateSite/TranslateSitePlugin.py b/plugins/TranslateSite/TranslateSitePlugin.py index f0112c11..a7bc65b0 100644 --- a/plugins/TranslateSite/TranslateSitePlugin.py +++ b/plugins/TranslateSite/TranslateSitePlugin.py @@ -6,14 +6,15 @@ from Translate import translate @PluginManager.registerTo("UiRequest") class UiRequestPlugin(object): - def actionSiteMedia(self, path, header_length=True): + def actionSiteMedia(self, path, **kwargs): file_name = path.split("/")[-1] if not file_name: # Path ends with / file_name = "index.html" extension = file_name.split(".")[-1] if translate.lang != "en" and extension in ["js", "html"]: path_parts = self.parsePath(path) - file_generator = super(UiRequestPlugin, self).actionSiteMedia(path, header_length=False) + kwargs["header_length"] = False + file_generator = super(UiRequestPlugin, self).actionSiteMedia(path, **kwargs) if "next" in dir(file_generator): # File found and generator returned site = self.server.sites.get(path_parts["address"]) return self.actionPatchFile(site, path_parts["inner_path"], file_generator) @@ -21,7 +22,7 @@ class UiRequestPlugin(object): return file_generator else: - return super(UiRequestPlugin, self).actionSiteMedia(path) + return super(UiRequestPlugin, self).actionSiteMedia(path, **kwargs) def actionUiMedia(self, path): file_generator = super(UiRequestPlugin, self).actionUiMedia(path) diff --git a/plugins/Zeroname/UiRequestPlugin.py b/plugins/Zeroname/UiRequestPlugin.py index ea9bfcbe..dca5ae47 100644 --- a/plugins/Zeroname/UiRequestPlugin.py +++ b/plugins/Zeroname/UiRequestPlugin.py @@ -12,7 +12,7 @@ class UiRequestPlugin(object): super(UiRequestPlugin, self).__init__(*args, **kwargs) # Media request - def actionSiteMedia(self, path, header_length=True): + def actionSiteMedia(self, path, **kwargs): match = re.match("/media/(?P
[A-Za-z0-9-]+\.[A-Za-z0-9\.-]+)(?P/.*|$)", path) if match: # Its a valid domain, resolve first domain = match.group("address") diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 817557a4..b97d867b 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -99,6 +99,9 @@ class UiRequest(object): return self.actionDebug() elif path == "/Console" and config.debug: return self.actionConsole() + # Wrapper-less static files + elif path.startswith("/raw/"): + return self.actionSiteMedia(path.replace("/raw", "/media", 1), header_noscript=True) # Site media wrapper else: if self.get.get("wrapper_nonce"): @@ -164,6 +167,22 @@ class UiRequest(object): self.user = UserManager.user_manager.create() return self.user + def getRequestUrl(self): + if self.isProxyRequest(): + if self.env["PATH_INFO"].startswith("http://zero"): + return self.env["PATH_INFO"] + else: # Add http://zero to direct domain access + return self.env["PATH_INFO"].replace("http://", "http://zero/", 1) + else: + return self.env["wsgi.url_scheme"] + "://" + self.env["HTTP_HOST"] + self.env["PATH_INFO"] + + def getReferer(self): + referer = self.env.get("HTTP_REFERER") + if referer and self.isProxyRequest() and not referer.startswith("http://zero"): + return referer.replace("http://", "http://zero/", 1) + else: + return referer + # Send response headers def sendHeader(self, status=200, content_type="text/html", extra_headers=[]): headers = [] @@ -383,7 +402,7 @@ class UiRequest(object): return None # Serve a media for site - def actionSiteMedia(self, path, header_length=True): + def actionSiteMedia(self, path, header_length=True, header_noscript=False): if ".." in path: # File not in allowed path return self.error403("Invalid file path") @@ -391,7 +410,7 @@ class UiRequest(object): # Check wrapper nonce content_type = self.getContentType(path_parts["inner_path"]) - if "htm" in content_type: # Valid nonce must present to render html files + if "htm" in content_type and not header_noscript: # Valid nonce must present to render html files wrapper_nonce = self.get.get("wrapper_nonce") if wrapper_nonce not in self.server.wrapper_nonces: return self.error403("Wrapper nonce error. Please reload the page.") @@ -415,7 +434,7 @@ class UiRequest(object): if not address or address == ".": return self.error403(path_parts["inner_path"]) if os.path.isfile(file_path): # File exists - return self.actionFile(file_path, header_length=header_length) + return self.actionFile(file_path, header_length=header_length, header_noscript=header_noscript) elif os.path.isdir(file_path): # If this is actually a folder, add "/" and redirect return self.actionRedirect("./{0}/".format(path_parts["inner_path"].split("/")[-1])) else: # File not exists, try to download @@ -429,7 +448,7 @@ class UiRequest(object): result = site.needFile(path_parts["inner_path"], priority=15) # Wait until file downloads if result: - return self.actionFile(file_path, header_length=header_length) + return self.actionFile(file_path, header_length=header_length, header_noscript=header_noscript) else: self.log.debug("File not found: %s" % path_parts["inner_path"]) # Site larger than allowed, re-add wrapper nonce to allow reload @@ -459,15 +478,13 @@ class UiRequest(object): return self.error400() # Stream a file to client - def actionFile(self, file_path, block_size=64 * 1024, send_header=True, header_length=True): + def actionFile(self, file_path, block_size=64 * 1024, send_header=True, header_length=True, header_noscript=False): if ".." in file_path: raise Exception("Invalid path") if os.path.isfile(file_path): # Try to figure out content type by extension content_type = self.getContentType(file_path) - # TODO: Dont allow external access: extra_headers= - # [("Content-Security-Policy", "default-src 'unsafe-inline' data: http://localhost:43110 ws://localhost:43110")] range = self.env.get("HTTP_RANGE") range_start = None if send_header: @@ -476,6 +493,8 @@ class UiRequest(object): extra_headers["Accept-Ranges"] = "bytes" if header_length: extra_headers["Content-Length"] = str(file_size) + if header_noscript: + extra_headers["Content-Security-Policy"] = "default-src 'none'; sandbox allow-top-navigation; img-src 'self'; style-src 'self' 'unsafe-inline';" if range: range_start = int(re.match(".*?([0-9]+)", range).group(1)) if re.match(".*?-([0-9]+)", range):