From 454ea7875c7d0987f767aefd272db517bc953de5 Mon Sep 17 00:00:00 2001 From: Ville Rantanen Date: Fri, 26 Jan 2018 14:49:23 +0200 Subject: [PATCH] zip download, and proper config --- code/app.py | 82 ++++++++++++++++++++++++++++++++++---- code/static/css/styles.css | 17 +++++++- code/templates/layout.html | 9 +++-- code/templates/list.html | 39 +++++++++--------- docker-compose.yaml | 3 ++ env.example | 1 + 6 files changed, 119 insertions(+), 32 deletions(-) diff --git a/code/app.py b/code/app.py index 2ebd66b..41bcf97 100644 --- a/code/app.py +++ b/code/app.py @@ -1,23 +1,26 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -import os,sys +import os,sys,time import json from datetime import datetime from flask import Flask, render_template, jsonify, \ - redirect, url_for, request, g, session, send_from_directory + redirect, url_for, request, g, session, send_file, send_from_directory from werkzeug.utils import secure_filename import hashlib +import zipfile from revprox import ReverseProxied app = Flask(__name__) app.config.from_object(__name__) # Read config from json ! -app.config['UPLOAD_FOLDER'] = 'data/' -app.config['SHARES_FILE'] = 'data/shares.json' -app.config['DATE_FORMAT'] = "%Y-%m-%d %H:%M" -app.config['UID'] = 1000 -app.config['DEBUG'] = False +config_values = json.load(open(os.getenv('FLEES_CONFIG'),'rt')) +app.config['UPLOAD_FOLDER'] = config_values['data_folder'] +app.config['SHARES_FILE'] = config_values['shares_file'] +app.config['ZIP_FOLDER'] = config_values['zip_folder'] +app.config['DATE_FORMAT'] = config_values['date_format'] +app.config['UID'] = config_values['uid'] +app.config['DEBUG'] = config_values['debug'] app.secret_key = 'Cz2dw5NiRt3PSMFBSLTAJJi7U2CdW7iPQqEeOaU6' app.wsgi_app = ReverseProxied(app.wsgi_app) @@ -151,6 +154,8 @@ def download_direct(name,password,filename): @app.route('/download///', methods=['GET']) @app.route('/download//', methods=['GET']) def download_file(name,filename,password = None): + if password != None: + session[name] = password (ok,share) = get_share(name) if not ok: return share @@ -159,14 +164,33 @@ def download_file(name,filename,password = None): return 'no such file', 404 return send_from_directory(directory=share['path'], filename=filename) + +@app.route('/zip//', methods=['GET']) +@app.route('/zip/', methods=['GET']) +def download_zip(name,password = None): + if password != None: + session[name] = password + (ok,share) = get_share(name) + if not ok: + return share + zip_clean() + zip_path = zip_share(share) + return send_file( + zip_path, + as_attachment = True, + attachment_filename = name + ".zip" + ) + + def file_stat(filename): s = os.stat(filename) return { - 'size': file_size_human(s.st_size), + 'size': file_size_MB(s.st_size), 'mtime': file_date_human(s.st_mtime), 'name': os.path.basename(filename) } + def file_size_human(num): for x in [' B','KB','MB','GB','TB']: if num < 1024.0: @@ -175,6 +199,10 @@ def file_size_human(num): return "%3.1f %s" % (num, x) num /= 1024.0 +def file_size_MB(num): + return "%0.2f"%(num/(1024*1024),) + + def file_date_human(num): return datetime.fromtimestamp( num @@ -244,6 +272,44 @@ def print_debug(s): sys.stderr.write(str(s)+"\n") sys.stderr.flush() + +def zip_share(share): + + if not os.path.exists(app.config['ZIP_FOLDER']): + os.makedirs(app.config['ZIP_FOLDER']) + os.chown(app.config['ZIP_FOLDER'], app.config['UID'], -1) + + zip_path = os.path.join( + app.config['ZIP_FOLDER'], + "%s-%d.zip"%( + share['name'], + time.time() + ) + ) + zf = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) + for file in sorted(os.listdir(share['path'])): + print_debug(os.path.join(share['path'],file)) + zf.write( + os.path.join(share['path'],file), + arcname = os.path.join(share['name'],file) + ) + zf.close() + os.chown(zip_path, app.config['UID'], -1) + return zip_path + +def zip_clean(): + """ delete zip files older than 1 hour """ + if not os.path.exists(app.config['ZIP_FOLDER']): + return + for file in os.listdir(app.config['ZIP_FOLDER']): + if not file.endswith("zip"): + continue + mtime = os.stat( + os.path.join(app.config['ZIP_FOLDER'],file) + ).st_mtime + if mtime + 3600 < time.time(): + os.remove(os.path.join(app.config['ZIP_FOLDER'],file)) + if __name__ == "__main__": app.run(debug=True) diff --git a/code/static/css/styles.css b/code/static/css/styles.css index 5004370..42fc7c0 100755 --- a/code/static/css/styles.css +++ b/code/static/css/styles.css @@ -49,8 +49,11 @@ tr:nth-child(even) { clear: both; } +#list_left { + float: left; +} + #list_title { - float:left; margin-left: 5em; } @@ -59,10 +62,21 @@ tr:nth-child(even) { padding: 8px; border: 4px solid lightslategray; background-color: #f3f3fb; + line-height: 1.5em; } + +#list_menu ul { + margin-top: 0px; +} + #list_table { border-collapse: collapse; margin-left: 2em; + line-height: 1.5em; +} + +.direct { + margin-right: 1em; } /* index */ @@ -77,6 +91,7 @@ tr:nth-child(even) { padding: 8px; border: 4px solid lightslategray; background-color: #f3f3fb; + line-height: 2em; } #index_table { diff --git a/code/templates/layout.html b/code/templates/layout.html index a4694fb..cdde1ae 100644 --- a/code/templates/layout.html +++ b/code/templates/layout.html @@ -1,9 +1,10 @@ -Flees - - - + Flees + + + +
diff --git a/code/templates/list.html b/code/templates/list.html index 9d9b9db..7eafc08 100644 --- a/code/templates/list.html +++ b/code/templates/list.html @@ -1,6 +1,5 @@ {% extends "layout.html" %} {% block body %} -

{{ name }}

{% if upload %}
@@ -9,9 +8,6 @@ - {% if overwrite == false %} - Overwriting disabled - {% endif %}
{% else %}
@@ -19,44 +15,49 @@
{% endif %} -
+
+ Share: +
-
{% if expire %} - Share expires {{ expire }} +
  • expires {{ expire }} {% else %} - Share never expires +
  • never expires {% endif %} + {% if overwrite == false %} +
  • overwriting is disabled + {% endif %} +
  • Download as zip +
  • Logout +
  • -
    - Logout from this share -
    -
    -
    +
    +

    {{ name }}

    {% for entry in entries %} - {% endfor %}
    Name - Size + Size(MB) Mod.Time
    {{ entry.name }} + {% if direct %} -   + {% endif %} + {{ entry.name }} {{ entry.size|safe }} {{ entry.mtime|safe }}
    +
    {% endblock %} diff --git a/docker-compose.yaml b/docker-compose.yaml index 61daecc..c581c34 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -9,6 +9,9 @@ services: - "${FLEES_EXPOSE}:80" volumes: - ./data/:/code/data/ + environment: + - FLEES_CONFIG + restart: unless-stopped diff --git a/env.example b/env.example index 71e64c3..5e1f3e7 100644 --- a/env.example +++ b/env.example @@ -1 +1,2 @@ FLEES_EXPOSE=127.0.0.1:8136 +FLEES_CONFIG=data/config.json