diff --git a/code/app.py b/code/app.py index b7752db..8b384f3 100644 --- a/code/app.py +++ b/code/app.py @@ -19,6 +19,7 @@ app = Flask(__name__) app.config.from_object(__name__) # Read config from json ! config_values = json.load(open(os.getenv('FLEES_CONFIG'),'rt')) +app.config['PUBLIC_URL'] = config_values['public_url'] app.config['SITE_NAME'] = config_values['site_name'] app.config['UPLOAD_FOLDER'] = config_values['data_folder'] app.config['SHARES_FILE'] = config_values['shares_file'] @@ -81,6 +82,8 @@ def authenticate(name): if request.method == 'POST': user_password = request.form['password'].encode('utf-8') session[name] = password_hash(user_password, app.secret_key) + if name + 'Token' in session: + del session[name + 'Token'] return redirect(url_for('list_view',name=name)) @@ -262,6 +265,7 @@ def list_view(name, token = None): return share if token != None and 'pass_hash' in share: session[name] = share['pass_hash'] + session[name + 'Token'] = token return redirect(url_for('list_view',name=name)) files = [] @@ -275,6 +279,11 @@ def list_view(name, token = None): allow_direct = get_or_none('direct_links', share) if get_or_none('pass_hash', share) else False upload = get_or_none('upload', share) overwrite = get_or_none('overwrite', share) + if name + 'Token' in session: + used_token = session[name + 'Token'] + else: + used_token = '[TOKEN]' + script_api = [get_script_url(app.config['PUBLIC_URL'], share, x, used_token) for x in ('client', 'download', 'upload_split')] if not upload: overwrite = False return render_template( @@ -287,7 +296,8 @@ def list_view(name, token = None): overwrite = overwrite, direct = allow_direct, expire = get_or_none('expire', share), - description = get_or_none('description', share, "") + description = get_or_none('description', share, ""), + script_api = script_api ) @@ -295,6 +305,8 @@ def list_view(name, token = None): def logout(name): if name in session: del session[name] + if name + 'Token' in session: + del session[name + 'Token'] return render_template( "logout.html", name = name @@ -600,9 +612,11 @@ def get_share(name, require_auth = True, token = None): return (False, 'Share has expired') authenticated = "no-pass" if not token == None: + require_auth = False if has_token(token, share): - require_auth = False authenticated = "token" + else: + authenticated = False if require_auth: if 'pass_hash' in share: authenticated = False diff --git a/code/static/css/styles.css b/code/static/css/styles.css index 8e85857..37b6ca9 100644 --- a/code/static/css/styles.css +++ b/code/static/css/styles.css @@ -1,13 +1,14 @@ html { - min-height: 100%; - position: relative; + min-height: 100%; + position: relative; } body { color: #0E6251; - background-color: #FDF2E9; - min-height: 600px; - font: 14px/1.3 'Segoe UI',Arial, sans-serif; + background-color: #FDF2E9; + min-height: 600px; + font: 14px/1.3 'Segoe UI',Arial, sans-serif; + margin: 8px; } a:visited { @@ -79,7 +80,7 @@ tr:nth-child(odd) { margin-left: 2em; margin-bottom: 1em; } -#list_menu { +#list_menu, #list_script { float:right; padding: 8px; border: 4px solid #148F77; @@ -91,7 +92,7 @@ tr:nth-child(odd) { border-bottom-left-radius: 15px; } -#list_menu ul { +#list_menu ul, #list_script ul { margin-top: 0px; margin-bottom: 0px; } @@ -117,6 +118,7 @@ tr:nth-child(odd) { margin-top: 24px; cursor: pointer; text-align: right; + text-decoration: underline; } #list_info { display: none; @@ -129,10 +131,38 @@ tr:nth-child(odd) { margin-bottom: 33px; } +#list_script { + display: none; + z-index: 99; + position: absolute; + padding-top: 2em; + padding-bottom: 2em; + right: 8px; +} + +#list_script_toggle { + cursor: pointer; + text-decoration: underline; +} + .direct { margin-right: 1em; } +.upper_corner { + position: absolute; + top: 0.5em; + right: 0.5em; +} + +.code { + background-color: #FDF2E9; + font-family: monospace; + margin-right: 2em; + margin-bottom: 1em; + word-wrap: break-word; +} + /* index */ #index_title { diff --git a/code/static/js/scripts.js b/code/static/js/scripts.js index 019b6c6..614c276 100644 --- a/code/static/js/scripts.js +++ b/code/static/js/scripts.js @@ -27,6 +27,12 @@ function infoToggle() { } +function scriptToggle() { + var el = document.getElementById("list_script"); + el.style.display = el.style.display === 'block' ? 'none' : 'block'; +} + + function UploadFile(file,file_no,files_total) { if (uploadTurn != file_no) { // Wait for our turn to upload. check every 0.5s diff --git a/code/templates/list.html b/code/templates/list.html index fcc5045..038ba44 100644 --- a/code/templates/list.html +++ b/code/templates/list.html @@ -50,6 +50,7 @@ {% endif %} {% endif %}
  • Download as zip +
  • Command line info
  • Logout @@ -79,4 +80,14 @@ +
    + Close X +
    Command line tools for using the share:
    + +
    {% endblock %} diff --git a/code/utils/utils.py b/code/utils/utils.py index 609f6a9..f8c78b8 100644 --- a/code/utils/utils.py +++ b/code/utils/utils.py @@ -69,6 +69,29 @@ def get_or_none(key,d,none = None): return none +def get_script_url(public_url, share, end_point, token = "[TOKEN]"): + cmd = None + doc = None + if get_or_none("direct_links", share) and end_point == "download": + end_point = "direct" + url = "%s/script/%s/%s/%s"%( + public_url, + end_point, + share['name'], + token + ) + if end_point in ( "download", "direct"): + cmd = 'curl -s %s | bash /dev/stdin [-f]'%( url, ) + doc = 'Download all files in the share.' + if end_point == "client": + cmd = 'python <( curl -s %s )'%( url, ) + doc = 'Console client to download and upload files.' + if end_point == "upload_split": + cmd = 'curl -s %s | python - [-s split_size_in_Mb] file_to_upload.ext [second.file.ext]'%( url, ) + doc = 'Upload files to the share.' + return {'cmd': cmd, 'doc': doc} + + def is_path_safe(path): if path.startswith("."): return False @@ -112,6 +135,7 @@ def iter_folder_files(path, recursive = True): def path2url(path): return pathname2url(path) + def safe_name(s): return safe_string(s, "-_")