Commit 5ef4c869 authored by iv's avatar iv

Add possibility to specify the local file system directory + fix uri2local/local2uri.

parent 819484e1
...@@ -10,8 +10,6 @@ import os ...@@ -10,8 +10,6 @@ import os
app = Flask(__name__.split('.')[0]) app = Flask(__name__.split('.')[0])
app.config.from_object(__name__) app.config.from_object(__name__)
FS_PATH = '/tmp/couscous'
ALLOWED_METHODS = ['GET', 'PUT', 'PROPFIND', 'PROPPATCH', 'MKCOL', 'DELETE', ALLOWED_METHODS = ['GET', 'PUT', 'PROPFIND', 'PROPPATCH', 'MKCOL', 'DELETE',
'COPY', 'MOVE', 'OPTIONS'] 'COPY', 'MOVE', 'OPTIONS']
...@@ -73,7 +71,6 @@ def is_authorized(cookies_list): ...@@ -73,7 +71,6 @@ def is_authorized(cookies_list):
return True return True
return verify_cookie(base64_encode(origin)) return verify_cookie(base64_encode(origin))
FS_HANDLER = utils.FilesystemHandler(FS_PATH, URI_BEGINNING_PATH['webdav'])
@app.before_request @app.before_request
def before_request(): def before_request():
...@@ -106,7 +103,6 @@ def before_request(): ...@@ -106,7 +103,6 @@ def before_request():
# tells the world we do CORS when authorized # tells the world we do CORS when authorized
debug('OPTIONS request special header: ' + specific_header) debug('OPTIONS request special header: ' + specific_header)
headers['Access-Control-Request-Headers'] = specific_header headers['Access-Control-Request-Headers'] = specific_header
headers['Access-Control-Allow-Origin'] = origin
headers['Access-Control-Allow-Methods'] = ', '.join(ALLOWED_METHODS) headers['Access-Control-Allow-Methods'] = ', '.join(ALLOWED_METHODS)
response = make_response(content, 200) response = make_response(content, 200)
response.headers = headers response.headers = headers
...@@ -132,9 +128,18 @@ class WebDAV(MethodView): ...@@ -132,9 +128,18 @@ class WebDAV(MethodView):
self.baseuri = URI_BEGINNING_PATH['webdav'] self.baseuri = URI_BEGINNING_PATH['webdav']
def get_body(self): def get_body(self):
""" get the request's body """ """
get the request's body
"""
request_data = request.data request_data = request.data
if not request_data and int(request.headers['Content-length']):
try:
length = int(request.headers.get('Content-length'))
except ValueError:
length = 0
if not request_data and length:
try: try:
request_data = request.form.items()[0][0] request_data = request.form.items()[0][0]
except IndexError: except IndexError:
...@@ -147,15 +152,15 @@ class WebDAV(MethodView): ...@@ -147,15 +152,15 @@ class WebDAV(MethodView):
return headers + body (resource content or list of resources) return headers + body (resource content or list of resources)
""" """
response = g.response response = g.response
localpath = FS_HANDLER.uri2local(pathname) localpath = app.fs_handler.uri2local(request.path)
# TODO if into a collection => list of the ressources # TODO if into a collection => list of the ressources
data = '' data = ''
if os.path.isdir(localpath): if os.path.isdir(localpath):
data = "\n".join(FS_HANDLER.get_children(pathname)) data = "\n".join(app.fs_handler.get_children(request.path))
elif os.path.isfile(localpath): elif os.path.isfile(localpath):
try: try:
data_resource = FS_HANDLER.get_data(pathname) data_resource = app.fs_handler.get_data(request.path)
# TODO send large response by chunks would be nice for big # TODO send large response by chunks would be nice for big
# files... http://flask.pocoo.org/docs/0.10/patterns/streaming/ # files... http://flask.pocoo.org/docs/0.10/patterns/streaming/
data = data_resource.read() data = data_resource.read()
...@@ -177,7 +182,7 @@ class WebDAV(MethodView): ...@@ -177,7 +182,7 @@ class WebDAV(MethodView):
response = g.response response = g.response
localpath = FS_HANDLER.uri2local(pathname) localpath = app.fs_handler.uri2local(request.path)
# TODO: get large request chunk by chunk... # TODO: get large request chunk by chunk...
request_body = self.get_body() request_body = self.get_body()
if request_body is None: if request_body is None:
...@@ -185,7 +190,7 @@ class WebDAV(MethodView): ...@@ -185,7 +190,7 @@ class WebDAV(MethodView):
elif os.path.isdir(localpath): elif os.path.isdir(localpath):
response.status = '405' response.status = '405'
else: else:
response.status = str(FS_HANDLER.put(pathname, request_body)) response.status = str(app.fs_handler.put(request.path, request_body))
return response return response
...@@ -214,7 +219,7 @@ class WebDAV(MethodView): ...@@ -214,7 +219,7 @@ class WebDAV(MethodView):
response = g.response response = g.response
response.status = str(FS_HANDLER.mkcol(pathname)) response.status = str(app.fs_handler.mkcol(request.path))
return response return response
def delete(self, pathname): def delete(self, pathname):
...@@ -225,7 +230,7 @@ class WebDAV(MethodView): ...@@ -225,7 +230,7 @@ class WebDAV(MethodView):
response = g.response response = g.response
localpath = FS_HANDLER.uri2local(pathname) localpath = app.fs_handler.uri2local(request.path)
if not os.path.exists(localpath): if not os.path.exists(localpath):
response.status = '404' response.status = '404'
if os.path.isdir(localpath): if os.path.isdir(localpath):
...@@ -250,11 +255,11 @@ class WebDAV(MethodView): ...@@ -250,11 +255,11 @@ class WebDAV(MethodView):
response = g.response response = g.response
localpath = FS_HANDLER.uri2local(pathname) localpath = app.fs_handler.uri2local(request.path)
destination = request.headers['Destination'] destination = request.headers['Destination']
host = request.headers['Host'] host = request.headers['Host']
destination = destination.split(host + URI_BEGINNING_PATH['webdav'], 1)[-1] destination = destination.split(host + URI_BEGINNING_PATH['webdav'], 1)[-1]
destination_path = FS_HANDLER.uri2local(destination) destination_path = app.fs_handler.uri2local(destination)
debug('COPY: %s -> %s' % (localpath, destination_path)) debug('COPY: %s -> %s' % (localpath, destination_path))
if not os.path.exists(localpath): if not os.path.exists(localpath):
...@@ -290,10 +295,10 @@ class WebDAV(MethodView): ...@@ -290,10 +295,10 @@ class WebDAV(MethodView):
response = g.response response = g.response
copy_response = self.copy(pathname) copy_response = self.copy(request.path)
response.status = copy_response.status response.status = copy_response.status
if copy_response.status == '201' or copy_response.status == '204': if copy_response.status == '201' or copy_response.status == '204':
delete_response = self.delete(pathname) delete_response = self.delete(request.path)
if delete_response.status != '204': if delete_response.status != '204':
response.status = '424' response.status = '424'
return response return response
...@@ -370,11 +375,12 @@ def links(): ...@@ -370,11 +375,12 @@ def links():
return 'TODO: nice set of links to useful local pages: %s <br> + HOWTO' % the_links return 'TODO: nice set of links to useful local pages: %s <br> + HOWTO' % the_links
if __name__ == '__main__': if __name__ == '__main__':
import argparse import argparse
parser = argparse.ArgumentParser(description='Run a local webdav/HTTP server.') parser = argparse.ArgumentParser(description='Run a local webdav/HTTP server.')
parser.add_argument('-d', '--debug', action='store_true', parser.add_argument('-d', '--debug', action='store_true',
help='Run flask app in debug mode (not recommended for use in production).') help='Run flask app in debug mode (not recommended for use in production).')
parser.add_argument('-p', '--path', action='store',
help='Run flask app in debug mode (not recommended for use in production).')
https = parser.add_argument_group('HTTPS', 'Arguments required for HTTPS support.') https = parser.add_argument_group('HTTPS', 'Arguments required for HTTPS support.')
https.add_argument('--key', type=str, action='store', default=None, https.add_argument('--key', type=str, action='store', default=None,
help='SSL/TLS private key. Required for HTTPS support.') help='SSL/TLS private key. Required for HTTPS support.')
...@@ -384,6 +390,9 @@ if __name__ == '__main__': ...@@ -384,6 +390,9 @@ if __name__ == '__main__':
args = parser.parse_args() args = parser.parse_args()
app.debug = args.debug app.debug = args.debug
app.fs_path = '/tmp/' if not args.path else args.path
app.fs_handler = utils.FilesystemHandler(app.fs_path, URI_BEGINNING_PATH['webdav'])
context = None context = None
if args.key and args.cert and os.path.isfile(args.key) and os.path.isfile(args.cert): if args.key and args.cert and os.path.isfile(args.key) and os.path.isfile(args.cert):
from OpenSSL import SSL from OpenSSL import SSL
......
...@@ -58,9 +58,9 @@ class FilesystemHandler(): ...@@ -58,9 +58,9 @@ class FilesystemHandler():
""" Sets the directory """ """ Sets the directory """
if not os.path.isdir(path): if not os.path.isdir(path):
raise Exception, '%s not must be a directory!' % path raise Exception, '%s must be a directory!' % path
self.directory = path self.directory = os.path.normpath(path)
def setBaseURI(self, uri): def setBaseURI(self, uri):
""" Sets the base uri """ """ Sets the base uri """
...@@ -73,21 +73,21 @@ class FilesystemHandler(): ...@@ -73,21 +73,21 @@ class FilesystemHandler():
def uri2local(self,uri): def uri2local(self,uri):
""" map uri in baseuri and local part """ """ map uri in baseuri and local part """
path=urlparse.urlparse(uri).path.strip('/') path = os.path.normpath(uri)
fileloc=path if path.startswith(self.baseuri):
filename=os.path.join(self.directory,fileloc) path = path[len(self.baseuri):]
filename=os.path.normpath(filename) filepath = os.path.join(self.directory, path)
print('uri2local: %s -> %s' % (uri, filename)) filepath = os.path.normpath(filepath)
return filename #print('uri2local: %s -> %s' % (uri, filepath))
return filepath
def local2uri(self,filename):
""" map local filename to self.baseuri """ def local2uri(self,filepath):
""" map local path to file to self.baseuri """
pnum=len(split(self.directory.replace("\\","/"),"/")) filepath = os.path.normpath(filepath)
parts=split(filename.replace("\\","/"),"/")[pnum:] if filepath.startswith(self.directory):
sparts= joinfields(parts,"/") uri = filepath[len(self.directory):]
uri=urlparse.urljoin(self.baseuri, sparts) uri = os.path.normpath(self.baseuri + uri)
print('local2uri: %s -> %s' % (filename, uri)) #print('local2uri: %s -> %s' % (filepath, uri))
return uri return uri
def get_children(self, uri, filter=None): def get_children(self, uri, filter=None):
...@@ -100,8 +100,8 @@ class FilesystemHandler(): ...@@ -100,8 +100,8 @@ class FilesystemHandler():
if os.path.isdir(fileloc): if os.path.isdir(fileloc):
try: try:
files=os.listdir(fileloc) files=os.listdir(fileloc)
except: except Exception:
raise 404 raise ValueError
for file in files: for file in files:
newloc=os.path.join(fileloc,file) newloc=os.path.join(fileloc,file)
...@@ -165,7 +165,7 @@ class FilesystemHandler(): ...@@ -165,7 +165,7 @@ class FilesystemHandler():
fp.close() fp.close()
status = 201 status = 201
except: except:
status = 409 status = 424
return status return status
......
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