generator
This commit is contained in:
47
code/app.py
47
code/app.py
@@ -12,8 +12,12 @@ from revprox import ReverseProxied
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_object(__name__)
|
app.config.from_object(__name__)
|
||||||
|
# Read config from json !
|
||||||
app.config['UPLOAD_FOLDER'] = 'data/'
|
app.config['UPLOAD_FOLDER'] = 'data/'
|
||||||
app.config['SHARES_FILE'] = 'data/shares.json'
|
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.secret_key = 'Cz2dw5NiRt3PSMFBSLTAJJi7U2CdW7iPQqEeOaU6'
|
||||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||||
|
|
||||||
@@ -27,7 +31,8 @@ def index():
|
|||||||
public_shares = []
|
public_shares = []
|
||||||
for share in g.shares:
|
for share in g.shares:
|
||||||
public = get_or_none(share,'public')
|
public = get_or_none(share,'public')
|
||||||
if public:
|
expired = is_expired(share)
|
||||||
|
if public and not expired:
|
||||||
public_shares.append({
|
public_shares.append({
|
||||||
'name': share['name'],
|
'name': share['name'],
|
||||||
'expire': get_or_none(share,'expire'),
|
'expire': get_or_none(share,'expire'),
|
||||||
@@ -61,6 +66,7 @@ def upload():
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
file.save(filename)
|
file.save(filename)
|
||||||
|
os.chown(filename, app.config['UID'], -1)
|
||||||
return redirect(url_for('list_view',name=name))
|
return redirect(url_for('list_view',name=name))
|
||||||
|
|
||||||
@app.route('/send/<name>', methods=['GET'])
|
@app.route('/send/<name>', methods=['GET'])
|
||||||
@@ -78,7 +84,14 @@ def list_view(name):
|
|||||||
files = []
|
files = []
|
||||||
for file in sorted(os.listdir(share['path'])):
|
for file in sorted(os.listdir(share['path'])):
|
||||||
files.append(file_stat(os.path.join(share['path'],file)))
|
files.append(file_stat(os.path.join(share['path'],file)))
|
||||||
return render_template("list.html",name = share['name'], entries = files)
|
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})
|
#~ return jsonify({"share":share, "files": files})
|
||||||
|
|
||||||
@app.route('/download/<name>/<filename>', methods=['GET'])
|
@app.route('/download/<name>/<filename>', methods=['GET'])
|
||||||
@@ -94,11 +107,27 @@ def download_file(name,filename):
|
|||||||
def file_stat(filename):
|
def file_stat(filename):
|
||||||
s = os.stat(filename)
|
s = os.stat(filename)
|
||||||
return {
|
return {
|
||||||
'size': s.st_size,
|
'size': file_size_human(s.st_size),
|
||||||
'mtime': s.st_mtime,
|
'mtime': file_date_human(s.st_mtime),
|
||||||
'name': os.path.basename(filename)
|
'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):
|
def get_or_none(d,key):
|
||||||
if key in d:
|
if key in d:
|
||||||
return d[key]
|
return d[key]
|
||||||
@@ -110,6 +139,8 @@ def get_share(name):
|
|||||||
if len(share) < 1:
|
if len(share) < 1:
|
||||||
return (False,'No such share')
|
return (False,'No such share')
|
||||||
share = share[0]
|
share = share[0]
|
||||||
|
if is_expired(share):
|
||||||
|
return (False, 'Share has expired')
|
||||||
authenticated = True
|
authenticated = True
|
||||||
if 'pass_hash' in share:
|
if 'pass_hash' in share:
|
||||||
authenticated = False
|
authenticated = False
|
||||||
@@ -132,8 +163,16 @@ def get_share(name):
|
|||||||
})
|
})
|
||||||
if not os.path.exists(share['path']):
|
if not os.path.exists(share['path']):
|
||||||
os.makedirs(share['path'])
|
os.makedirs(share['path'])
|
||||||
|
os.chown(share['path'], app.config['UID'], -1)
|
||||||
return (True,share)
|
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):
|
def printerr(s):
|
||||||
sys.stderr.write(str(s)+"\n")
|
sys.stderr.write(str(s)+"\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
|||||||
@@ -1,22 +1,36 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
<h1>{{ name }}</h1>
|
||||||
|
{% if upload %}
|
||||||
<a href="{{ url_for('send', name=name) }}">+ upload</a>
|
<a href="{{ url_for('send', name=name) }}">+ upload</a>
|
||||||
|
{% else %}
|
||||||
|
Grayed out + upload
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
{% if public %}
|
||||||
|
Share is public
|
||||||
|
{% else %}
|
||||||
|
Share is private
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
{% if expire %}
|
||||||
|
Share expires {{ expire }}
|
||||||
|
{% else %}
|
||||||
|
Share never expires
|
||||||
|
{% endif %}
|
||||||
|
<br>
|
||||||
|
|
||||||
<table class=entriesall>
|
<table class=entriesall>
|
||||||
<tr>
|
<tr>
|
||||||
<th>name
|
<th>name
|
||||||
<th>time
|
<th>size
|
||||||
<th>trip
|
<th>mtime
|
||||||
<th>kmδ
|
|
||||||
<th>daysδ
|
|
||||||
<th>km/d
|
|
||||||
</tr>
|
</tr>
|
||||||
{% for entry in entries %}
|
{% for entry in entries %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ entry.name }}
|
<td><a href="{{ url_for('download_file', name = name, filename = entry.name) }}">{{ entry.name }}</a>
|
||||||
<td>{{ entry.size|safe }}
|
<td>{{ entry.size|safe }}
|
||||||
<td>{{ entry.mtime|safe }}
|
<td>{{ entry.mtime|safe }}
|
||||||
{% else %}
|
|
||||||
<li>no files
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
19
data/shares.json.example
Normal file
19
data/shares.json.example
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"path": "files",
|
||||||
|
"pass_hash": "86d2db203591135ea63473e49759a1d2e43fdc4d9857aeee642713c4e837be12",
|
||||||
|
"pass_plain": "tissit",
|
||||||
|
"upload": true,
|
||||||
|
"public": false,
|
||||||
|
"expire": "2018-02-28 10:30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "foo",
|
||||||
|
"path": "foo",
|
||||||
|
"pass_hash": "86d2db203591135ea63473e49759a1d2e43fdc4d9857aeee642713c4e837be12",
|
||||||
|
"pass_plain": "tissit",
|
||||||
|
"upload": false,
|
||||||
|
"public": true
|
||||||
|
}
|
||||||
|
]
|
||||||
43
utils/share_template.py
Executable file
43
utils/share_template.py
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import hashlib,argparse,json,sys
|
||||||
|
from datetime import datetime
|
||||||
|
parser = argparse.ArgumentParser(description='Flees share template generator')
|
||||||
|
|
||||||
|
parser.add_argument('-n','--name', action="store", dest="name", required = True)
|
||||||
|
parser.add_argument('-p','--path', action="store", dest="path", required = True,help= "path relative to data folder")
|
||||||
|
parser.add_argument('-P','--public', action="store_true", dest="public", default = False)
|
||||||
|
parser.add_argument('-u','--upload', action="store_true", dest="upload", default = False)
|
||||||
|
parser.add_argument('--pass-plain', action="store", dest="plain", default = False)
|
||||||
|
parser.add_argument('--pass-hashed', action="store", dest="hashed", default = False)
|
||||||
|
parser.add_argument('-e','--expire', action="store", dest="expire", default = False, help = "expire date in format 2018-12-24 21:00")
|
||||||
|
|
||||||
|
opts = parser.parse_args()
|
||||||
|
|
||||||
|
share = {
|
||||||
|
'name': opts.name,
|
||||||
|
'path': opts.path,
|
||||||
|
'public': opts.public,
|
||||||
|
'upload': opts.upload,
|
||||||
|
}
|
||||||
|
if opts.plain:
|
||||||
|
share.update({
|
||||||
|
'pass_plain': opts.plain
|
||||||
|
})
|
||||||
|
if opts.hashed:
|
||||||
|
share.update({
|
||||||
|
'pass_hash': hashlib.sha256(opts.hashed).hexdigest()
|
||||||
|
})
|
||||||
|
if opts.expire:
|
||||||
|
try:
|
||||||
|
date_object = datetime.strptime(opts.expire,"%Y-%m-%d %H:%M")
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
share.update({
|
||||||
|
'expire': opts.expire
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
print(json.dumps(share, indent = 2))
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user