#!/usr/bin/python # -*- coding: utf-8 -*- import os,sys import json from datetime import datetime from flask import Flask, render_template, jsonify, \ redirect, url_for, request, g, session, send_from_directory from werkzeug.utils import secure_filename import hashlib 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.secret_key = 'Cz2dw5NiRt3PSMFBSLTAJJi7U2CdW7iPQqEeOaU6' app.wsgi_app = ReverseProxied(app.wsgi_app) @app.before_request def before_request(): g.shares = json.load(open(app.config['SHARES_FILE'],'rt')) @app.route("/") def index(): printerr(g.shares) public_shares = [] for share in g.shares: public = get_or_none(share,'public') expired = is_expired(share) if public and not expired: public_shares.append({ 'name': share['name'], 'expire': get_or_none(share,'expire'), 'upload': get_or_none(share,'upload') }) return render_template("index.html", entries=public_shares) @app.route('/authenticate/', methods=['GET','POST']) def authenticate(name): if request.method == 'GET': return render_template('authenticate.html',name=name) if request.method == 'POST': user_password = request.form['password'].encode('utf-8') session[name] = hashlib.sha256(user_password).hexdigest() return redirect(url_for('list_view',name=name)) @app.route('/upload', methods=['POST']) def upload(): if request.method == 'POST': file = request.files['file'] name = request.form['name'] (ok,share) = get_share(name) if not ok: return share if file: filename = os.path.join( share['path'], secure_filename( file.filename ) ) file.save(filename) os.chown(filename, app.config['UID'], -1) return redirect(url_for('list_view',name=name)) @app.route('/send/', methods=['GET']) def send(name): (ok,share) = get_share(name) if not ok: return share return render_template('send.html',name=name) @app.route('/list/', methods=['GET']) def list_view(name): (ok,share) = get_share(name) if not ok: return share files = [] for file in sorted(os.listdir(share['path'])): files.append(file_stat(os.path.join(share['path'],file))) return render_template( "list.html", name = share['name'], entries = files, public = get_or_none(share,'public'), upload = get_or_none(share,'upload'), expire = get_or_none(share,'expire') ) #~ return jsonify({"share":share, "files": files}) @app.route('/download//', methods=['GET']) def download_file(name,filename): (ok,share) = get_share(name) if not ok: return share file_path = os.path.join(share['path'], filename) if not os.path.exists(file_path): return 'no such file' return send_from_directory(directory=share['path'], filename=filename) def file_stat(filename): s = os.stat(filename) return { 'size': file_size_human(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: if x==' B': return "%d %s" % (num, x) return "%3.1f %s" % (num, x) num /= 1024.0 def file_date_human(num): return datetime.fromtimestamp( num ).strftime(app.config['DATE_FORMAT']) def get_or_none(d,key): if key in d: return d[key] else: return None def get_share(name): share = [x for x in g.shares if x['name'] == name] if len(share) < 1: return (False,'No such share') share = share[0] if is_expired(share): return (False, 'Share has expired') authenticated = True if 'pass_hash' in share: authenticated = False printerr(session) if name in session: printerr(share['pass_hash']) if session[name] == share['pass_hash']: printerr(session[name]) printerr(share['pass_hash']) authenticated = True if not authenticated: return (False,redirect(url_for('authenticate',name=name))) if not 'path' in share: return (False,'no path defined') share.update({ "path": os.path.join( app.config['UPLOAD_FOLDER'], share['path'] ) }) if not os.path.exists(share['path']): os.makedirs(share['path']) os.chown(share['path'], app.config['UID'], -1) return (True,share) def is_expired(share): expires = get_or_none(share, 'expire') if expires: if datetime.now() > datetime.strptime(expires, app.config['DATE_FORMAT']): return True return False def printerr(s): sys.stderr.write(str(s)+"\n") sys.stderr.flush() if __name__ == "__main__": app.run(debug=True)