Commit d3940b31 authored by Xavier Thompson's avatar Xavier Thompson

simplehttpserver: Remove root-path option

parent 3c5efa14
......@@ -41,29 +41,18 @@ def issubpathof(subpath, path):
class Recipe(GenericBaseRecipe):
def __init__(self, buildout, name, options):
base_path = options['base-path']
root_path = options.get('root-path')
if root_path:
if not issubpathof(root_path, base_path):
raise UserError("root-path must be a subpath of base-path")
else:
root_path = base_path
self.server_parameters = {
'host': options['host'],
'port': int(options['port']),
'cwd': base_path,
'log-file': options['log-file'],
'cert-file': options.get('cert-file', ''),
'key-file': options.get('key-file', ''),
'root-path': root_path,
'allow-write': bool_option(options, 'allow-write', 'false')
}
return GenericBaseRecipe.__init__(self, buildout, name, options)
def install(self):
parameters = {
'host': self.options['host'],
'port': int(self.options['port']),
'cwd': self.options['base-path'],
'log-file': self.options['log-file'],
'cert-file': self.options.get('cert-file', ''),
'key-file': self.options.get('key-file', ''),
'allow-write': bool_option(self.options, 'allow-write', 'false')
}
return self.createPythonScript(
self.options['wrapper'].strip(),
__name__ + '.simplehttpserver.run',
(self.server_parameters,)
(parameters,)
)
......@@ -15,8 +15,6 @@ from . import issubpathof
class ServerHandler(SimpleHTTPRequestHandler):
base_path = None # set by run
root_path = None # set by run
restrict_path = False # set by run
restrict_write = True # set by run
def respond(self, code=200, type='text/html'):
......@@ -24,15 +22,7 @@ class ServerHandler(SimpleHTTPRequestHandler):
self.send_header("Content-type", type)
self.end_headers()
def restrictedAccess(self):
if self.restrict_path:
path = os.path.join(self.base_path, os.path.relpath(self.path, '/'))
if not issubpathof(path, self.root_path):
logging.info('TOTO %s %s', path, self.root_path)
# no access outside root path
self.respond(403)
self.wfile.write(b"Forbidden")
return True
def restrictedWriteAccess(self):
if self.restrict_write and self.command not in ('GET', 'HEAD'):
# no write access
self.respond(403)
......@@ -42,8 +32,6 @@ class ServerHandler(SimpleHTTPRequestHandler):
def do_GET(self):
logging.info('%s - GET: %s \n%s' % (self.client_address[0], self.path, self.headers))
if self.restrictedAccess():
return
SimpleHTTPRequestHandler.do_GET(self)
def do_POST(self):
......@@ -57,7 +45,7 @@ class ServerHandler(SimpleHTTPRequestHandler):
request can be encoded as application/x-www-form-urlencoded or multipart/form-data
"""
logging.info('%s - POST: %s \n%s' % (self.client_address[0], self.path, self.headers))
if self.restrictedAccess():
if self.restrictedWriteAccess():
return
form = cgi.FieldStorage(
......@@ -80,9 +68,9 @@ class ServerHandler(SimpleHTTPRequestHandler):
self.writeFile(file_path, file_content, file_open_mode)
def writeFile(self, filename, content, method='ab'):
file_path = os.path.abspath(os.path.join(self.root_path, filename))
file_path = os.path.abspath(os.path.join(self.base_path, filename))
# Check writing there is allowed
if not issubpathof(file_path, self.root_path):
if not issubpathof(file_path, self.base_path):
self.respond(403, 'text/plain')
self.wfile.write(b"Forbidden")
return
......@@ -119,14 +107,11 @@ def run(args):
port = args['port']
host = args['host']
cwd = args['cwd']
root_path = args['root-path']
os.chdir(cwd)
Handler = ServerHandler
Handler.base_path = cwd
Handler.root_path = root_path
Handler.restrict_path = (root_path != cwd)
Handler.restrict_write = not args['allow-write']
if valid_ipv6(host):
......
......@@ -73,13 +73,6 @@ class SimpleHTTPServerTest(unittest.TestCase):
self.process.communicate() # close pipes
self.process = None
def test_options_valid_root_path(self):
self.assertRaises(
simplehttpserver.UserError,
self.setUpRecipe,
{'root-path': '/'}
)
def write_should_fail(self, url, hack_path, hack_content):
# post with multipart/form-data encoding
resp = requests.post(
......@@ -114,39 +107,6 @@ class SimpleHTTPServerTest(unittest.TestCase):
self.write_should_fail(server_base_url, hack_path, hack_content)
self.assertFalse(os.path.exists(os.path.dirname(hack_path)))
def test_write_outside_root_path_should_fail(self):
root_path = os.path.join(self.base_path, 'forbidden', 'allowed')
os.makedirs(root_path)
self.setUpRecipe({'allow-write': 'true', 'root-path': root_path})
server_base_url = self.startServer()
# A file outside the server's root directory
hack_path = os.path.join(self.base_path, 'forbidden', 'hack.txt')
hack_content = "You should not be able to write to hack.txt"
self.write_should_fail(server_base_url, hack_path, hack_content)
def test_access_outside_root_path_should_fail(self):
root_path = os.path.join(self.base_path, 'forbidden', 'allowed')
os.makedirs(root_path)
self.setUpRecipe({'root-path': root_path})
server_base_url = self.startServer()
forbiddenurl = os.path.join(server_base_url, 'forbidden')
resp = requests.get(forbiddenurl)
self.assertEqual(resp.status_code, requests.codes.forbidden)
self.assertEqual(resp.text, 'Forbidden')
resp = requests.post(
forbiddenurl,
files={
'path': 'index.txt',
'content': 'Not forbidden after all',
},
)
self.assertEqual(resp.status_code, requests.codes.forbidden)
def test_write(self):
self.setUpRecipe({'allow-write': 'true'})
server_base_url = self.startServer()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment