diff --git a/code/app.py b/code/app.py index ab4750c..ceba560 100644 --- a/code/app.py +++ b/code/app.py @@ -14,7 +14,7 @@ from utils.utils import * from utils.crypt import * -__FLEES_VERSION__ = "20180720.0" +__FLEES_VERSION__ = "20180721.0" app = Flask(__name__) app.config.from_object(__name__) # Read config from json ! @@ -29,6 +29,7 @@ app.config['DATE_FORMAT'] = config_values['date_format'] app.config['UID'] = config_values['uid'] app.config['GID'] = config_values['gid'] app.config['DEBUG'] = config_values['debug'] +app.config['VERSION_FOLDER'] = config_values['version_folder'] if 'notifier' in config_values: if len(config_values['notifier']) > 0: notifier_config = config_values['notifier'].split(":") @@ -313,7 +314,7 @@ def file_list(name, token): if not ok: return share files = [] - for file in iter_folder_files(share['path']): + for file in iter_folder_files(share['path'], version_folder = app.config['VERSION_FOLDER']): files.append(path2url(file)) files.append("") return "\n".join(files), 200 @@ -325,7 +326,7 @@ def file_details(name, token): if not ok: return share files = [] - for file in iter_folder_files(share['path']): + for file in iter_folder_files(share['path'], version_folder = app.config['VERSION_FOLDER']): status = file_stat(share['path'],file) files.append(status) return jsonify(files), 200 @@ -362,7 +363,7 @@ def list_view(name, token = None): return redirect(url_for('list_view',name=name)) files = [] - for file in iter_folder_files(share['path']): + for file in iter_folder_files(share['path'], version_folder = app.config['VERSION_FOLDER']): status = file_stat(share['path'],file) status.update({ 'token': get_direct_token(share, file), @@ -514,7 +515,7 @@ def script_download(name = None, token = None): if not ok: return share commands = [] - for file in iter_folder_files(share['path']): + for file in iter_folder_files(share['path'], version_folder = app.config['VERSION_FOLDER']): status = file_stat(share['path'], file) commands.append('get_file "%s"'%( status['url'], @@ -534,7 +535,7 @@ def script_direct(name = None, token = None): if not ok: return share commands = [] - for file in iter_folder_files(share['path']): + for file in iter_folder_files(share['path'], version_folder = app.config['VERSION_FOLDER']): status = file_stat(share['path'], file) commands.append('get_file "%s" "%s"'%( status['url'], @@ -695,22 +696,20 @@ def file_versionize(full_path): """ Move file to versioned with integer """ file_dir = os.path.dirname(full_path) file_name = os.path.basename(full_path) - basename, extension = os.path.splitext(file_name) - version = 1 - while True: - new_name = os.path.join( - file_dir, - secure_filename("%s.v%d%s"%( - basename, - version, - extension - )) - ) - if os.path.exists(new_name): - version += 1 - else: - break - os.rename(full_path,new_name) + new_name = file_name_version(full_path) + new_path = os.path.join( + file_dir, + app.config['VERSION_FOLDER'], + new_name + ) + + if os.path.exists(new_path): + return + makedirs_rights(os.path.join( + file_dir, + app.config['VERSION_FOLDER'] + )) + os.rename(full_path, new_path) def get_share(name, require_auth = True, token = None): @@ -809,7 +808,7 @@ def zip_share(share): ) ) zf = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) - for file in iter_folder_files(share['path']): + for file in iter_folder_files(share['path'], version_folder = app.config['VERSION_FOLDER']): fp = os.path.join(share['path'], file) if os.path.isdir(fp): continue diff --git a/code/flees-manager.py b/code/flees-manager.py index c5f9e4c..63a4cc9 100755 --- a/code/flees-manager.py +++ b/code/flees-manager.py @@ -93,6 +93,68 @@ def list_folders(shares,config): print(tabulate(table, headers = "firstrow")) +def list_versions(shares, config, opts): + if 'data_folder' not in config: + print("data_folder not defined in config") + sys.exit(1) + data_folder = os.path.join(config['__root_path__'], config['data_folder']) + table = [] + header = ['Share', 'Path', 'File', 'Size', 'Unit'] + if opts.delete == None: + header.append('Age') + else: + header.append('Delete') + table.append(header) + now = datetime.now() + for share in shares: + if opts.name: + if share['name'] != opts.name: + continue + version_folder = os.path.join( + data_folder, + share['path'], + config['version_folder'] + ) + if not os.path.isdir(version_folder): + table.append(( + share['name'], + share['path']+'/', + '-', '-', '-', '-' + )) + else: + for filename in sorted(os.listdir(version_folder)): + full_path = os.path.join(version_folder, filename) + if os.path.isdir(full_path): + size = get_folder_size(full_path) + else: + size = os.path.getsize(full_path) + (size_num, size_unit) = file_size_human( + size, + HTML=False + ).split(" ",1) + parsed_date = version_date(filename) + if parsed_date == None: + age_str = '-' + else: + age = now - parsed_date + age_str = "%d d"%( age.days, ) + if opts.delete != None: + to_delete = age.days >= opts.delete + age_str = "To Del" if to_delete else "Keep" + if not opts.dry and to_delete: + age_str = "Deleted" + os.remove(full_path) + table.append(( + share['name'], + share['path'] + '/', + filename, + size_num, + size_unit, + age_str + )) + print(tabulate(table, headers = "firstrow")) + + def add_share(shares, config, opts): # Make name and path safe: @@ -408,7 +470,7 @@ def print_rest_api_download(config, share, token, show_filename): if not os.path.exists(share_path): print("no files") sys.exit(0) - for filename in iter_folder_files(share_path): + for filename in iter_folder_files(share_path, version_folder = config['version_folder']): if show_filename: if filename != show_filename: continue @@ -441,7 +503,7 @@ def print_rest_api_direct(config, share, token, show_filename): if not os.path.exists(share_path): print("no files") sys.exit(0) - for filename in iter_folder_files(share_path): + for filename in iter_folder_files(share_path, version_folder = config['version_folder']): if show_filename: if filename != show_filename: continue @@ -540,6 +602,14 @@ def parse_options(): parser_list = subparsers.add_parser('list', help = "List shares") ## list folders parser_folders = subparsers.add_parser('folders', help = "List the subfolders in data folder, and their disk usage") + ## list versions + parser_versions = subparsers.add_parser('versions', help = "List the old versions stored in shares, and their disk usage") + parser_versions.add_argument('--delete', action="store", dest="delete", default = None, type = int, + help = "Delete old versions, older than N days.") + parser_versions.add_argument('--dry', action="store_true", dest="dry", default = False, + help = "Do not actually delete files.") + parser_versions.add_argument('-n','--name', action="store", dest="name", required = False, default = None, + help = "Show / Delete only this share versions. If omitted, applies to all shares") ## Show parser_show = subparsers.add_parser('show', help = "Show share") parser_show.add_argument('-P', action="store_true", dest="show_password", default = False, @@ -655,6 +725,8 @@ if __name__ == "__main__": if opts.subparser_name == 'list': list_shares(shares,opts) + if opts.subparser_name == 'versions': + list_versions(shares,config,opts) elif opts.subparser_name == 'folders': list_folders(shares,config) elif opts.subparser_name == 'show': diff --git a/code/static/css/styles.css b/code/static/css/styles.css index 16690b9..cebb221 100644 --- a/code/static/css/styles.css +++ b/code/static/css/styles.css @@ -272,3 +272,9 @@ tr:nth-child(odd) { .sortarrow { font-size: large; } + +/* editor */ + +.href_button { + margin-left: 3em; +} diff --git a/code/static/js/scripts.js b/code/static/js/scripts.js index 6587387..bbffbda 100644 --- a/code/static/js/scripts.js +++ b/code/static/js/scripts.js @@ -155,9 +155,6 @@ function changeTitle(newTitle) { document.title = "Flees - " + newTitle; } -function back() { - window.history.back(); -} function keyboardEntry(ev){ var kC=ev.keyCode; @@ -168,6 +165,9 @@ function keyboardEntry(ev){ if (/T/.test(k)) { infoToggle(); } + if (/C/.test(k)) { + scriptToggle(); + } } document.onkeyup = keyboardEntry; diff --git a/code/templates/editor.html b/code/templates/editor.html index 6a86a5b..f28a892 100644 --- a/code/templates/editor.html +++ b/code/templates/editor.html @@ -1,21 +1,21 @@ {% extends "layout.html" %} {% block body %}
- + {% endblock %} diff --git a/code/templates/list.html b/code/templates/list.html index ddd3e65..de41454 100644 --- a/code/templates/list.html +++ b/code/templates/list.html @@ -53,7 +53,7 @@