From 5680f23bc9ff2d16f9b99833cc54b41ddd0b8139 Mon Sep 17 00:00:00 2001 From: MasterofJOKers Date: Sun, 17 Feb 2019 14:25:53 +0100 Subject: [PATCH] Make `targetDir` absolute by default When serving a `../` as directory (with `-l`), servefile creates an endless 301-redirect loop. Having an absolute path fixes this. Since this error might come up any time again, we're setting `targetDir` to its absolute path right from the beginning and never have to worry about it later on. --- servefile | 6 +++--- tests/test_servefile.py | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/servefile b/servefile index b594cf3..79e87ce 100755 --- a/servefile +++ b/servefile @@ -312,7 +312,7 @@ class DirListingHandler(FileBaseHandler): path = self.getCleanPath() # check if path is in current serving directory - currBaseDir = os.path.abspath(self.targetDir) + os.path.sep + currBaseDir = self.targetDir + os.path.sep requestPath = os.path.normpath(os.path.join(currBaseDir, path)) + os.path.sep if not requestPath.startswith(currBaseDir): self.send_response(301) @@ -1041,7 +1041,7 @@ class ServeFile(): raise ServeFileException("Error: Could not create directory '%s' for uploads, %r" % (self.target, str(e))) else: raise ServeFileException("Error: Upload directory already exists and is a file.") - FilePutter.targetDir = self.target + FilePutter.targetDir = os.path.abspath(self.target) FilePutter.maxUploadSize = self.maxUploadSize handler = FilePutter elif self.serveMode == self.MODE_LISTDIR: @@ -1050,7 +1050,7 @@ class ServeFile(): if not os.path.isdir(self.target): raise ServeFileException("Error: '%s' is not a directory." % (self.target,)) handler = DirListingHandler - handler.targetDir = self.target + handler.targetDir = os.path.abspath(self.target) if self.auth: # do authentication diff --git a/tests/test_servefile.py b/tests/test_servefile.py index afc587b..66acc23 100644 --- a/tests/test_servefile.py +++ b/tests/test_servefile.py @@ -167,6 +167,33 @@ def test_serve_directory(run_servefile, datadir): check_download('jup!', '/bar/thisisaverylongfilenamefortestingthatthisstillworksproperly') +def test_serve_relative_directory(run_servefile, datadir): + d = { + 'foo': {'kratzbaum': 'cat', 'I like Cats!': 'kitteh', '&&&&&&&': 'wheee'}, + 'bar': {'thisisaverylongfilenamefortestingthatthisstillworksproperly': 'jup!'}, + 'noot': 'still data in here', + 'bigfile': 'x' * (10 * 1024 ** 2), + } + p = datadir(d) + run_servefile(['../', '-l'], cwd=os.path.join(str(p), 'foo')) + + # check if all files are in directory listing + # (could be made more sophisticated with beautifulsoup) + for path in '/', '/../': + r = make_request(path) + for k in d: + assert k in r.text + + for fname, content in d['foo'].items(): + check_download(content, '/foo/' + fname) + + r = make_request('/unknown') + assert r.status_code == 404 + + # download + check_download('jup!', '/bar/thisisaverylongfilenamefortestingthatthisstillworksproperly') + + def test_upload(run_servefile, tmp_path): data = ('this is my live now\n' 'uploading strings to servers\n'