new version allows downloads from subfolders
This commit is contained in:
91
code/app.py
91
code/app.py
@@ -1,4 +1,3 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os,sys,time,stat
|
||||
@@ -8,13 +7,13 @@ from flask import Flask, render_template, jsonify, current_app, Response, \
|
||||
redirect, url_for, request, g, session, send_file, send_from_directory
|
||||
from werkzeug.utils import secure_filename
|
||||
import zipfile
|
||||
import urllib
|
||||
from multiprocessing import Process
|
||||
from revprox import ReverseProxied
|
||||
from utils.utils import *
|
||||
from utils.crypt import *
|
||||
|
||||
__FLEES_VERSION__ = "20180302.0"
|
||||
|
||||
__FLEES_VERSION__ = "20180310.0"
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(__name__)
|
||||
# Read config from json !
|
||||
@@ -42,6 +41,7 @@ if 'notifier' in config_values:
|
||||
app.secret_key = config_values['app_secret_key']
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||
|
||||
|
||||
@app.before_request
|
||||
def before_request():
|
||||
g.shares = json.load(open(app.config['SHARES_FILE'],'rt'))
|
||||
@@ -49,6 +49,7 @@ def before_request():
|
||||
g.site_name = app.config['SITE_NAME']
|
||||
g.max_zip_size = app.config['MAX_ZIP_SIZE']
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
public_shares = []
|
||||
@@ -71,6 +72,7 @@ def index():
|
||||
|
||||
return render_template("index.html", entries=public_shares)
|
||||
|
||||
|
||||
@app.route('/authenticate/<name>', methods=['GET','POST'])
|
||||
def authenticate(name):
|
||||
if request.method == 'GET':
|
||||
@@ -80,6 +82,7 @@ def authenticate(name):
|
||||
session[name] = password_hash(user_password, app.secret_key)
|
||||
return redirect(url_for('list_view',name=name))
|
||||
|
||||
|
||||
@app.route('/upload/<name>/<token>', methods=['POST'])
|
||||
@app.route('/upload', methods=['POST'])
|
||||
def upload(name = None, token = None):
|
||||
@@ -158,9 +161,6 @@ def upload_join_splitted(name, token):
|
||||
except:
|
||||
return "Joining failed\n", 400
|
||||
return "Joining started\n", 200
|
||||
#~ return Response(joiner(target_name, parts), mimetype="text/plain", content_type="text/event-stream")
|
||||
|
||||
#~ return "%d parts joined"%(len(parts),), 200
|
||||
|
||||
|
||||
@app.route('/send/<name>', methods=['GET'])
|
||||
@@ -170,22 +170,19 @@ def send(name):
|
||||
return share
|
||||
return render_template('send.html',name=name)
|
||||
|
||||
|
||||
@app.route('/files/<name>/<token>', methods=['GET'])
|
||||
def list_files(name, token):
|
||||
(ok,share) = get_share(name, token = token)
|
||||
if not ok:
|
||||
return share
|
||||
files = []
|
||||
for file in sorted(os.listdir(share['path'])):
|
||||
fp = os.path.join(share['path'],file)
|
||||
if os.path.isdir(fp):
|
||||
continue
|
||||
if file.startswith("."):
|
||||
continue
|
||||
files.append(urllib.parse.quote_plus(file))
|
||||
for file in iter_folder_files(share['path']):
|
||||
files.append(path2url(file))
|
||||
files.append("")
|
||||
return "\n".join(files), 200
|
||||
|
||||
|
||||
@app.route('/list/<name>/<token>', methods=['GET'])
|
||||
@app.route('/list/<name>', methods=['GET'])
|
||||
def list_view(name, token = None):
|
||||
@@ -197,15 +194,13 @@ def list_view(name, token = None):
|
||||
return redirect(url_for('list_view',name=name))
|
||||
|
||||
files = []
|
||||
for file in sorted(os.listdir(share['path'])):
|
||||
for file in iter_folder_files(share['path']):
|
||||
fp = os.path.join(share['path'],file)
|
||||
if os.path.isdir(fp):
|
||||
continue
|
||||
if file.startswith("."):
|
||||
continue
|
||||
status = file_stat(fp)
|
||||
status.update({
|
||||
'token': get_direct_token(share, file)
|
||||
'token': get_direct_token(share, file),
|
||||
'name': file,
|
||||
'url': path2url(file)
|
||||
})
|
||||
files.append(status)
|
||||
# direct share links not allowed if password isnt set
|
||||
@@ -227,6 +222,7 @@ def list_view(name, token = None):
|
||||
description = get_or_none('description', share, "")
|
||||
)
|
||||
|
||||
|
||||
@app.route('/logout/<name>', methods=['GET'])
|
||||
def logout(name):
|
||||
if name in session:
|
||||
@@ -236,7 +232,8 @@ def logout(name):
|
||||
name = name
|
||||
)
|
||||
|
||||
@app.route('/direct/<name>/<token>/<filename>', methods=['GET'])
|
||||
|
||||
@app.route('/direct/<name>/<token>/<path:filename>', methods=['GET'])
|
||||
def download_direct(name,token,filename):
|
||||
(ok,share) = get_share(name, require_auth = False)
|
||||
if not ok:
|
||||
@@ -244,6 +241,8 @@ def download_direct(name,token,filename):
|
||||
allow_direct = get_or_none('direct_links', share)
|
||||
if allow_direct != True:
|
||||
return 'Direct download not allowed', 403
|
||||
if not is_path_safe(filename):
|
||||
return 'Incorrect relative path'+filename, 403
|
||||
file_token = get_direct_token(share, filename)
|
||||
if file_token == None:
|
||||
return 'Cannot generate token', 400
|
||||
@@ -251,7 +250,7 @@ def download_direct(name,token,filename):
|
||||
return 'Incorrect token', 403
|
||||
file_path = os.path.join(share['path'], filename)
|
||||
if not os.path.exists(file_path):
|
||||
return 'no such file', 404
|
||||
return 'No such file', 404
|
||||
notify({
|
||||
"recipient": get_or_none('recipient', share),
|
||||
"share": name,
|
||||
@@ -261,22 +260,14 @@ def download_direct(name,token,filename):
|
||||
return send_from_directory(directory=share['path'], filename=filename)
|
||||
|
||||
|
||||
@app.route('/download/<name>/<token>/<filename>', methods=['GET'])
|
||||
@app.route('/download/<name>/<filename>', methods=['GET'])
|
||||
def download_file(name, filename, token = None):
|
||||
(ok,share) = get_share(name, token = token)
|
||||
if not ok:
|
||||
return share
|
||||
file_path = os.path.join(share['path'], filename)
|
||||
if not os.path.exists(file_path):
|
||||
return 'no such file', 404
|
||||
notify({
|
||||
"recipient": get_or_none('recipient', share),
|
||||
"share": name,
|
||||
"filename": file_path,
|
||||
"operation": "download"
|
||||
})
|
||||
return send_from_directory(directory=share['path'], filename=filename)
|
||||
@app.route('/download/gui/<name>/<path:filename>', methods=['GET'])
|
||||
def download_gui(name, filename):
|
||||
return download_file(name, filename, token = None)
|
||||
|
||||
|
||||
@app.route('/download/<name>/<token>/<path:filename>', methods=['GET'])
|
||||
def download_token(name, filename, token):
|
||||
return download_file(name, filename, token = token)
|
||||
|
||||
|
||||
@app.route('/zip/<name>/<token>', methods=['GET'])
|
||||
@@ -302,6 +293,7 @@ def download_zip(name, token = None):
|
||||
attachment_filename = name + ".zip"
|
||||
)
|
||||
|
||||
|
||||
@app.route('/script/upload/<name>/<token>', methods=['GET'])
|
||||
def script_upload(name = None, token = None):
|
||||
(ok,share) = get_share(name, token = token)
|
||||
@@ -518,8 +510,8 @@ done
|
||||
token
|
||||
)
|
||||
|
||||
class uploadJoiner:
|
||||
|
||||
class uploadJoiner:
|
||||
def __init__(self, target_name, parts):
|
||||
self.target_name = target_name
|
||||
self.parts = parts
|
||||
@@ -528,6 +520,7 @@ class uploadJoiner:
|
||||
p.daemon = True
|
||||
p.start()
|
||||
|
||||
|
||||
def run(self):
|
||||
with open(self.target_name,'wb') as writer:
|
||||
for part in self.parts:
|
||||
@@ -539,6 +532,24 @@ class uploadJoiner:
|
||||
os.remove(part)
|
||||
|
||||
|
||||
def download_file(name, filename, token = None):
|
||||
(ok,share) = get_share(name, token = token)
|
||||
if not ok:
|
||||
return share
|
||||
if not is_path_safe(filename):
|
||||
return "Incorrect path", 403
|
||||
file_path = os.path.join(share['path'], filename)
|
||||
if not os.path.exists(file_path):
|
||||
return 'No such file, '+file_path, 404
|
||||
notify({
|
||||
"recipient": get_or_none('recipient', share),
|
||||
"share": name,
|
||||
"filename": file_path,
|
||||
"operation": "download"
|
||||
})
|
||||
return send_from_directory(directory=share['path'], filename=filename)
|
||||
|
||||
|
||||
def file_versionize(filename):
|
||||
""" Move file to versioned with integer """
|
||||
stats = file_stat(filename)
|
||||
@@ -635,7 +646,6 @@ def set_rights(path):
|
||||
|
||||
|
||||
def zip_share(share):
|
||||
|
||||
if not os.path.exists(app.config['ZIP_FOLDER']):
|
||||
os.makedirs(app.config['ZIP_FOLDER'])
|
||||
set_rights(app.config['ZIP_FOLDER'])
|
||||
@@ -648,7 +658,7 @@ def zip_share(share):
|
||||
)
|
||||
)
|
||||
zf = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED)
|
||||
for file in sorted(os.listdir(share['path'])):
|
||||
for file in iter_folder_files(share['path']):
|
||||
fp = os.path.join(share['path'], file)
|
||||
if os.path.isdir(fp):
|
||||
continue
|
||||
@@ -677,6 +687,7 @@ def zip_clean():
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
zip_clean()
|
||||
app.run(debug=True)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user