diff --git a/interface.py b/interface.py index 85878b2..7ce7fc1 100644 --- a/interface.py +++ b/interface.py @@ -1,12 +1,13 @@ #!/usr/bin/python3 -from flask import Flask, render_template, request, redirect +from flask import Flask, render_template, request, redirect, send_file import variables as var import util import os.path from os import listdir import random from werkzeug.utils import secure_filename +import errno class ReverseProxied(object): '''Wrap the application in this middleware and configure the @@ -107,27 +108,80 @@ def index(): music_library=music_library) -@web.route('/download', methods=["POST"]) -def download(): - print(request.form) - - file = request.files['music_file'] +@web.route('/upload', methods=["POST"]) +def upload(): + file = request.files['file'] if not file: return redirect("./", code=406) - elif file.filename == '': - return redirect("./", code=406) - elif '..' in request.form['directory']: + + filename = secure_filename(file.filename).strip() + if filename == '': return redirect("./", code=406) - if file.name == "music_file" and "audio" in file.headers.to_list()[1][1]: - web.config['UPLOAD_FOLDER'] = var.music_folder + request.form['directory'] - filename = secure_filename(file.filename) - print(filename) - file.save(os.path.join(web.config['UPLOAD_FOLDER'], filename)) + targetdir = request.form['targetdir'].strip() + if targetdir == '': + targetdir = 'uploads/' + elif '../' in targetdir: + return redirect("./", code=406) + + #print('Uploading file:') + #print('filename:', filename) + #print('targetdir:', targetdir) + #print('mimetype:', file.mimetype) + + if "audio" in file.mimetype: + storagepath = os.path.abspath(os.path.join(var.music_folder, targetdir)) + if not storagepath.startswith(var.music_folder): + return redirect("./", code=406) + + try: + os.makedirs(storagepath) + except OSError as ee: + if ee.errno != errno.EEXIST: + return redirect("./", code=500) + + filepath = os.path.join(storagepath, filename) + if os.path.exists(filepath): + return redirect("./", code=406) + + file.save(filepath) return redirect("./", code=302) else: return redirect("./", code=409) +@web.route('/download', methods=["GET"]) +def download(): + if 'file' in request.args: + requested_file = request.args['file'] + if '../' not in requested_file: + folder_path = var.music_folder + files = util.get_recursive_filelist_sorted(var.music_folder) + + if requested_file in files: + filepath = os.path.join(folder_path, requested_file) + try: + return send_file(filepath, as_attachment=True) + except Exception as e: + self.log.exception(e) + self.Error(400) + elif 'directory' in request.args: + requested_dir = request.args['directory'] + folder_path = var.music_folder + requested_dir_fullpath = os.path.abspath(os.path.join(folder_path, requested_dir)) + '/' + if requested_dir_fullpath.startswith(folder_path): + if os.path.samefile(requested_dir_fullpath, folder_path): + prefix = 'all' + else: + prefix = secure_filename(os.path.relpath(requested_dir_fullpath, folder_path)) + zipfile = util.zipdir(requested_dir_fullpath, prefix) + try: + return send_file(zipfile, as_attachment=True) + except Exception as e: + self.log.exception(e) + self.Error(400) + + return redirect("./", code=400) + if __name__ == '__main__': web.run(port=8181, host="127.0.0.1") diff --git a/static/index.css b/static/index.css index e69de29..011d00c 100644 --- a/static/index.css +++ b/static/index.css @@ -0,0 +1,53 @@ +/* necessary to place both forms/buttons next to each other */ +li.file { + clear: both; + list-style-position: outside; +} + +/* necessary to place both forms/buttons next to each other */ +form.file { + /* Float both forms to the left */ + float: left; +} + +form.file.file_add { + margin-left: 5px; + margin-right: 5px; +} + +/* necessary to place both forms/buttons next to each other */ +form.file.file_download { + clear: right; + /* with some space to the left of the second form */ + margin-right: 20px; +} + +/* necessary to place all forms/buttons of the directory entries next to each other */ +li.directory { + clear: both; + list-style-position: outside; + margin-top: 15px; + margin-bottom: 15px; +} + +li.directory span { + float: left; +} + +form.directory { + float: left; +} + +form.directory.form1 { + margin-left: 5px; + margin-right: 5px; +} + +form.directory.form2 { + margin-right: 5px; +} + +form.directory.form3 { + clear: right; + margin-right: 5px; +} diff --git a/templates/index.html b/templates/index.html index 09009b2..1a68822 100644 --- a/templates/index.html +++ b/templates/index.html @@ -2,8 +2,21 @@ @@ -34,19 +56,24 @@
Refresh

-{% if False %} -
-
- - + Upload into + + +
-{% endif %} + +
+
Current Playing : {% if current_music %} @@ -54,7 +81,7 @@ {% else %} No music {% endif %} -
+
Playlist :
@@ -66,6 +93,11 @@ {% endfor %}

Music library:

+
+ + +
+
{{ dirlisting() }} diff --git a/util.py b/util.py index 85a4331..e2868c6 100644 --- a/util.py +++ b/util.py @@ -1,8 +1,10 @@ #!/usr/bin/python3 import configparser +import hashlib import os import variables as var +import zipfile __CONFIG = configparser.ConfigParser(interpolation=None) __CONFIG.read("configuration.ini", encoding='latin-1') @@ -23,6 +25,36 @@ def get_recursive_filelist_sorted(path): filelist.sort() return filelist +# - zips all files of the given zippath (must be a directory) +# - returns the absolute path of the created zip file +# - zip file will be in the applications tmp folder (according to configuration) +# - format of the filename itself = prefix_hash.zip +# - prefix can be controlled by the caller +# - hash is a sha1 of the string representation of the directories' contents (which are +# zipped) +def zipdir(zippath, zipname_prefix=None): + zipname = __CONFIG.get('bot', 'tmp_folder') + if zipname_prefix and '../' not in zipname_prefix: + zipname += zipname_prefix.strip().replace('/', '_') + '_' + + files = get_recursive_filelist_sorted(zippath) + hash = hashlib.sha1((str(files).encode())).hexdigest() + zipname += hash + '.zip' + + if os.path.exists(zipname): + return zipname + + zipf = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) + + for file in files: + filepath = os.path.dirname(file) + file_to_add = os.path.join(zippath, file) + add_file_as = os.path.relpath(os.path.join(zippath, file), os.path.join(zippath, '..')) + zipf.write(file_to_add, add_file_as) + + zipf.close() + return zipname + class Dir(object): def __init__(self, name): self.name = name @@ -57,6 +89,22 @@ class Dir(object): return subdirs + def get_subdirs_recursively(self, path=None): + subdirs = [] + if path and path != '': + subdir = path.split('/')[0] + if subdir in self.subdirs: + searchpath = '/'.join(path.split('/')[1::]) + subdirs = self.subdirs[subdir].get_subdirs_recursively(searchpath) + else: + subdirs = list(self.subdirs.keys()) + + for key, val in self.subdirs.items(): + subdirs.extend(map(lambda subdir: key + '/' + subdir,val.get_subdirs_recursively())) + + subdirs.sort() + return subdirs + def get_files(self, path=None): files = [] if path and path != '':