Added link expiry timer, file icons, and in-site file viewing
This commit is contained in:
parent
ed49d343f8
commit
6acada7c75
@ -1,2 +1,4 @@
|
||||
# BinBin
|
||||
Simple Database Website
|
||||
Personal Drive Web App
|
||||
|
||||
This web application acts as a web interface for a cloud storage service. Users are assigned drives with permissions to read and/or write. There are two types of drives: real and virtual. A real drive is a physical folder on the host, with all subdirectories of the drive correlating to real subdirectories. A virtual drive is an emulated storage space, with all files being stored under a single directory, and a directory layout is mapped internally in the database.
|
||||
|
||||
171
binbin.py
171
binbin.py
@ -1,8 +1,10 @@
|
||||
import sys, os, time, hashlib, uuid, threading, atexit, flask, \
|
||||
configparser as cp
|
||||
configparser as cp, magic
|
||||
from flask import Flask, render_template, url_for, request, session, \
|
||||
send_from_directory, send_file, redirect
|
||||
send_from_directory, send_file, redirect, abort, Response
|
||||
from flask_pymongo import PyMongo, ObjectId
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from pytz import utc
|
||||
|
||||
FILTERS = {
|
||||
'name': 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
|
||||
@ -22,17 +24,31 @@ def apply_config():
|
||||
else:
|
||||
app.config[k] = v
|
||||
|
||||
def expire():
|
||||
links = LINKS.find()
|
||||
for l in links:
|
||||
if l['expiry'] < time.time():
|
||||
print(l['expiry'])
|
||||
print(time.time())
|
||||
print("deleted")
|
||||
LINKS.delete_one({'_id': l['_id']})
|
||||
|
||||
|
||||
|
||||
os.chdir(os.path.dirname(__file__))
|
||||
|
||||
app = Flask(__name__)
|
||||
apply_config()
|
||||
mongo = PyMongo(app)
|
||||
|
||||
scheduler = BackgroundScheduler(timezone=utc)
|
||||
scheduler.add_job(expire, 'interval', seconds=20)
|
||||
scheduler.start()
|
||||
atexit.register(lambda: scheduler.shutdown())
|
||||
|
||||
USERS, DRIVES, LINKS = mongo.db['users'], mongo.db['drives'], \
|
||||
mongo.db['links']
|
||||
|
||||
CHECK_PERIOD = 60
|
||||
expire_thread = threading.Thread()
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
@ -41,10 +57,12 @@ def index():
|
||||
else:
|
||||
return render_template('index.html')
|
||||
|
||||
|
||||
@app.route('/main/<method>')
|
||||
def main(method):
|
||||
return render_template(method+'.html')
|
||||
|
||||
|
||||
@app.route('/login', methods=['POST'])
|
||||
def login():
|
||||
error = None
|
||||
@ -56,11 +74,13 @@ def login():
|
||||
else:
|
||||
return flask.jsonify(False)
|
||||
|
||||
|
||||
@app.route('/logout')
|
||||
def logout():
|
||||
session.pop('username', None)
|
||||
return redirect(url_for('index'))
|
||||
|
||||
|
||||
@app.route('/mydrives')
|
||||
def mydrives():
|
||||
if 'username' not in session:
|
||||
@ -94,56 +114,89 @@ def mydrives():
|
||||
|
||||
return flask.jsonify(info)
|
||||
|
||||
@app.route('/files', methods=['POST'])
|
||||
def files():
|
||||
|
||||
@app.route('/files/<method>', methods=['POST'])
|
||||
def files(method):
|
||||
err_msgs = {
|
||||
'list': 'Error: This directory does not exist.',
|
||||
'zip': 'Error: Folder downloading not supported.'
|
||||
}
|
||||
check = verify_data('files', request.form, session)
|
||||
if not check[0]: return check[1]
|
||||
if not check[0]: return check[1], 400
|
||||
form = check[1]
|
||||
|
||||
if form['is_fol']: # If request is a folder.
|
||||
if method == 'list':
|
||||
if not form['is_fol']: return err_msgs['list']
|
||||
info = dir_info(form['path'], form['drive']['type'], \
|
||||
form['drive']['_id'])
|
||||
return flask.jsonify(info)
|
||||
else: # If request is a file.
|
||||
if form['drive']['type'] == 'real':
|
||||
link = LINKS.insert_one({
|
||||
'path': form['path'],
|
||||
'name': form['path'].split("/")[-1],
|
||||
'shared': [get_user(session)['_id']],
|
||||
'expiry': -1
|
||||
}).inserted_id
|
||||
elif form['drive']['type'] == 'virtual':
|
||||
r_path = form['drive']['path'] + '/' + form['real_file']
|
||||
link = LINKS.insert_one({
|
||||
'path': r_path,
|
||||
'name': form['path'].split("/")[-1],
|
||||
'shared': [get_user(session)['_id']],
|
||||
'expiry': -1
|
||||
}).inserted_id
|
||||
else:
|
||||
raise Exception("Invalid method for file link creation.")
|
||||
### QUEUE DELETION
|
||||
return str(link)
|
||||
|
||||
elif method == 'download' or method == 'stream':
|
||||
if form['is_fol']:
|
||||
return err_msgs['zip']
|
||||
else:
|
||||
link_uuid = str(uuid.uuid4()).replace("-","")
|
||||
if method == 'download':
|
||||
expire = -1
|
||||
else:
|
||||
expire = time.time() + 20*60 # 20 minutes
|
||||
|
||||
if form['drive']['type'] == 'real':
|
||||
link = LINKS.insert_one({
|
||||
'path': form['path'],
|
||||
'uuid': link_uuid,
|
||||
'name': form['path'].split("/")[-1],
|
||||
'shared': [get_user(session)['_id']],\
|
||||
'expiry': expire
|
||||
})
|
||||
elif form['drive']['type'] == 'virtual':
|
||||
r_path = form['drive']['path'] + '/' \
|
||||
+ form['real_file']
|
||||
link = LINKS.insert_one({
|
||||
'path': r_path,
|
||||
'uuid': link_uuid,
|
||||
'name': form['path'].split("/")[-1],
|
||||
'shared': [get_user(session)['_id']],
|
||||
'expiry': expire
|
||||
})
|
||||
else:
|
||||
raise Exception('Drive not real or virtual.')
|
||||
return link_uuid
|
||||
else:
|
||||
return redirect(url_for('index'))
|
||||
|
||||
|
||||
@app.route('/d/<_id>')
|
||||
def download(_id):
|
||||
@app.route('/d/<uuid>')
|
||||
def download(uuid):
|
||||
if 'username' not in session:
|
||||
return redirect(url_for('index'))
|
||||
|
||||
uuid = uuid.split('.')[0]
|
||||
try:
|
||||
link = LINKS.find_one({'_id': ObjectId(_id)})
|
||||
link = LINKS.find_one({'uuid': uuid})
|
||||
except:
|
||||
return redirect(url_for('index'))
|
||||
|
||||
if link == None: return redirect(url_for('index'))
|
||||
if get_user(session)['_id'] not in link['shared']:
|
||||
return redirect(url_for('index'))
|
||||
|
||||
if link['expiry'] == -1:
|
||||
LINKS.delete_one({'uuid': uuid})
|
||||
else:
|
||||
LINKS.update_one({'uuid': uuid}, {
|
||||
'$set': {'expiry': time.time() + 20*60}
|
||||
})
|
||||
|
||||
if 'pdf' in magic.from_file(link['path'], mime=True):
|
||||
r = send_file(link['path'])
|
||||
header = 'inline; filename=\"' + link['name'] + '\"'
|
||||
r.headers['Content-Disposition'] = header
|
||||
return r
|
||||
else:
|
||||
if link['expiry'] == -1:
|
||||
LINKS.delete_one({'_id': ObjectId(_id)})
|
||||
return send_file(link['path'], as_attachment=True,
|
||||
attachment_filename=link['name'])
|
||||
attachment_filename=link['name'],
|
||||
conditional=True)
|
||||
|
||||
|
||||
@app.route('/users/<method>', methods=['POST'])
|
||||
@ -155,7 +208,7 @@ def users(method):
|
||||
|
||||
if method == 'create':
|
||||
check = verify_data('users.create', request.form, session)
|
||||
if not check[0]: return check[1]
|
||||
if not check[0]: return check[1], 400
|
||||
form = check[1]
|
||||
|
||||
salt = uuid.uuid4().hex
|
||||
@ -171,7 +224,7 @@ def users(method):
|
||||
|
||||
elif method == 'delete':
|
||||
check = verify_data('users.delete', request.form, session)
|
||||
if not check[0]: return check[1]
|
||||
if not check[0]: return check[1], 400
|
||||
form = check[1]
|
||||
USERS.delete_one({'username': form['username']})
|
||||
|
||||
@ -183,6 +236,7 @@ def users(method):
|
||||
def drive_path():
|
||||
pass
|
||||
|
||||
|
||||
@app.errorhandler(404)
|
||||
def page_not_found(e):
|
||||
return render_template('404.html'), 404
|
||||
@ -201,6 +255,10 @@ def js(path):
|
||||
def assets(path):
|
||||
return send_from_directory('assets', path)
|
||||
|
||||
@app.route('/test/<path:path>')
|
||||
def test(path):
|
||||
return send_from_directory('test', path)
|
||||
|
||||
# End temporary
|
||||
|
||||
def get_user(sess):
|
||||
@ -217,15 +275,15 @@ def validate_login(u, p):
|
||||
|
||||
|
||||
def sizeof_fmt(num, suffix='B'):
|
||||
for unit in ['','K','M','G','T','P','E','Z']:
|
||||
if abs(num) < 1024.0:
|
||||
return '%3.1f%s%s' % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return '%.1f%s%s' % (num, 'Y', suffix)
|
||||
for unit in ['','K','M','G','T','P','E','Z']:
|
||||
if abs(num) < 1024.0:
|
||||
return '%3.1f%s%s' % (num, unit, suffix)
|
||||
num /= 1024.0
|
||||
return '%.1f%s%s' % (num, 'Y', suffix)
|
||||
|
||||
|
||||
def dir_info(path, t, drive_id):
|
||||
def info_dict(item, stats, is_fol):
|
||||
def info_dict(item, stats, is_fol, filetype):
|
||||
if is_fol:
|
||||
my_item = ({
|
||||
'folder': True,
|
||||
@ -233,12 +291,12 @@ def dir_info(path, t, drive_id):
|
||||
})
|
||||
else:
|
||||
my_item = ({
|
||||
'folder': False,
|
||||
'name': item,
|
||||
'date': time.strftime('%Y-%m-%d %H:%M:%S UTC', \
|
||||
time.gmtime(stats[8])),
|
||||
'size': sizeof_fmt(stats[6]),
|
||||
'real_size': stats[6]
|
||||
'real_size': stats[6],
|
||||
'filetype': filetype
|
||||
})
|
||||
return my_item
|
||||
full_items = []
|
||||
@ -246,9 +304,15 @@ def dir_info(path, t, drive_id):
|
||||
if t == 'real':
|
||||
items = os.listdir(path)
|
||||
for item in items:
|
||||
stats = list(os.stat(path + '/' + item))
|
||||
is_fol = os.path.isdir(path + '/' + item)
|
||||
full_items.append(info_dict(item, stats, is_fol))
|
||||
f_path = path + '/' + item
|
||||
stats = list(os.stat(f_path))
|
||||
is_fol = os.path.isdir(f_path)
|
||||
if not is_fol:
|
||||
kind = magic.from_file(f_path, mime=True)
|
||||
else:
|
||||
kind = None
|
||||
|
||||
full_items.append(info_dict(item, stats, is_fol, kind))
|
||||
|
||||
elif t == 'virtual':
|
||||
drives = DRIVES.find_one({'_id': drive_id})
|
||||
@ -260,11 +324,14 @@ def dir_info(path, t, drive_id):
|
||||
for k,v in tree.items():
|
||||
is_fol = type(v).__name__ != 'str'
|
||||
if is_fol:
|
||||
stats = None
|
||||
stats, kind = None, None
|
||||
else:
|
||||
stats = list(os.stat(drives['path'] + '/' + v))
|
||||
kind = magic.from_file(drives['path'] + '/' + v,
|
||||
mime=True)
|
||||
|
||||
full_items.append(info_dict(k.replace(':','.'), \
|
||||
stats, is_fol))
|
||||
stats, is_fol, kind))
|
||||
|
||||
return full_items
|
||||
|
||||
@ -451,11 +518,5 @@ def create_drive(method, owner, form=None):
|
||||
return 'Operation completed.'
|
||||
|
||||
|
||||
def manage_expiry():
|
||||
links = LINKS.find()
|
||||
#print(links)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True)
|
||||
@ -31,12 +31,6 @@
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
@ -64,6 +58,15 @@ a {
|
||||
-ms-transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
|
||||
}
|
||||
|
||||
.noSelect {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#header1 {
|
||||
display: grid;
|
||||
background-color: #1b1a1a;
|
||||
@ -332,11 +335,11 @@ canvas {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.fileIcon .fa {
|
||||
.fileIcon i {
|
||||
padding: .6em;
|
||||
}
|
||||
|
||||
.fileIcon .fa:hover {
|
||||
.fileIcon i:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@ -371,10 +374,6 @@ canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#directoryLocation i {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
.subdir:hover {
|
||||
background-color: rgba(255,255,255, 0.1);
|
||||
}
|
||||
@ -386,10 +385,6 @@ canvas {
|
||||
background-color: rgba(255,255,255,0.1);
|
||||
}
|
||||
|
||||
audio {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#playback div {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
@ -198,7 +198,7 @@ a {
|
||||
margin: auto auto auto 0 !important;
|
||||
}
|
||||
|
||||
.item div .fa {
|
||||
.item div i {
|
||||
padding: 1.5vh;
|
||||
}
|
||||
|
||||
|
||||
44
js/alert.js
44
js/alert.js
@ -1,38 +1,38 @@
|
||||
// Loads alert box into HTML first.
|
||||
|
||||
var box = document.createElement("div");
|
||||
var p = document.createElement("p");
|
||||
var box = document.createElement('div');
|
||||
var p = document.createElement('p');
|
||||
|
||||
box.id = "alert";
|
||||
box.style.position = "absolute";
|
||||
box.style.top = "-4em";
|
||||
box.style.width = "100%";
|
||||
box.style.color = "#fefefe";
|
||||
box.style.textAlign = "center";
|
||||
box.id = 'alert';
|
||||
box.style.position = 'absolute';
|
||||
box.style.top = '-4em';
|
||||
box.style.width = '100%';
|
||||
box.style.color = '#fefefe';
|
||||
box.style.textAlign = 'center';
|
||||
|
||||
box.style.setProperty("-webkit-transition", " top 0.3s cubic-bezier(.25, .8, .25, 1)");
|
||||
box.style.setProperty("transition:", "top 0.3s cubic-bezier(.25, .8, .25, 1)");
|
||||
box.style.setProperty("-moz-transition", " top 0.3s cubic-bezier(.25, .8, .25, 1)");
|
||||
box.style.setProperty("-ms-transition", " top 0.3s cubic-bezier(.25, .8, .25, 1)");
|
||||
box.style.setProperty('-webkit-transition', ' top 0.3s cubic-bezier(.25, .8, .25, 1)');
|
||||
box.style.setProperty('transition:', 'top 0.3s cubic-bezier(.25, .8, .25, 1)');
|
||||
box.style.setProperty('-moz-transition', ' top 0.3s cubic-bezier(.25, .8, .25, 1)');
|
||||
box.style.setProperty('-ms-transition', ' top 0.3s cubic-bezier(.25, .8, .25, 1)');
|
||||
|
||||
p.style.backgroundColor = "#000";
|
||||
p.style.display = "inline";
|
||||
p.style.padding = "1em";
|
||||
p.style.borderRadius = "4px";
|
||||
p.style.backgroundColor = '#000';
|
||||
p.style.display = 'inline';
|
||||
p.style.padding = '1em';
|
||||
p.style.borderRadius = '4px';
|
||||
|
||||
box.appendChild(p);
|
||||
|
||||
get("body").appendChild(box);
|
||||
get('body').appendChild(box);
|
||||
|
||||
function alertBox(s, type) {
|
||||
colors = {
|
||||
"error": "#d24242",
|
||||
"msg": "#4d9e53"
|
||||
'error': '#d24242',
|
||||
'msg': '#4d9e53'
|
||||
};
|
||||
box.childNodes[0].textContent = s;
|
||||
box.childNodes[0].style.backgroundColor = colors[type];
|
||||
box.style.top = "2em";
|
||||
box.style.top = '2em';
|
||||
setTimeout(function() {
|
||||
box.style.top = "-4em";
|
||||
}, 1000);
|
||||
box.style.top = '-4em';
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
124
js/desktop.js
124
js/desktop.js
@ -8,8 +8,8 @@ var navSelect; // Stores current selected sidebar option.
|
||||
var clickable = true; // Prevents actions being run more than once.
|
||||
var selectDiv; // Stores selected file or folder div.
|
||||
var currDir = ''; // Stores the current directory.
|
||||
var version = 'desktop';
|
||||
|
||||
// FIX THE DATE
|
||||
function sortFiles(type, direction) {
|
||||
if(type === 'name') data[0] = sortSection(type, direction, data[0]);
|
||||
data[1] = sortSection(type, direction, data[1]);
|
||||
@ -39,124 +39,6 @@ function sortFiles(type, direction) {
|
||||
}
|
||||
};
|
||||
|
||||
function dispDir() {
|
||||
updateLocation();
|
||||
try {
|
||||
get('#directory').removeChild(get('#directoryCont'));
|
||||
} catch(err) {}
|
||||
|
||||
var cont = element('div', {
|
||||
id: 'directoryCont',
|
||||
class: 'transition',
|
||||
style: 'opacity:0'
|
||||
});
|
||||
|
||||
if(data[0].length === 0 && data[1].length === 0) {
|
||||
cont.appendChild(element('p', {
|
||||
text: 'Nothing here!',
|
||||
style: 'font-weight: 100'
|
||||
}));
|
||||
}
|
||||
|
||||
for(var i = 0; i < data.length; i++) {
|
||||
for(var j = 0; j < data[i].length; j++) {
|
||||
var itemInfo = data[i][j];
|
||||
|
||||
var ext = (itemInfo.folder) ? "fol" :
|
||||
itemInfo.name.substring(
|
||||
itemInfo.name.lastIndexOf(".") + 1,
|
||||
itemInfo.name.length)
|
||||
.toLowerCase();
|
||||
|
||||
var item = element('div', {
|
||||
class: 'item transition',
|
||||
ext: ext,
|
||||
filename: itemInfo.name
|
||||
});
|
||||
|
||||
item.appendChild(element('p', {
|
||||
class: 'name',
|
||||
text: itemInfo.name
|
||||
}));
|
||||
|
||||
item.appendChild(element('p', {
|
||||
class: 'modified',
|
||||
text: (itemInfo.folder) ? "----" : dateStr(itemInfo.date)
|
||||
}));
|
||||
|
||||
item.appendChild(element('p', {
|
||||
class: 'size',
|
||||
text: itemInfo.size || "----"
|
||||
}));
|
||||
|
||||
if(!itemInfo.folder) {
|
||||
var a = element('div', {
|
||||
onclick: function() {
|
||||
console.log("generating download link");
|
||||
// DO EXPIRY LINKS HERE
|
||||
// update link to get('copy') and copy
|
||||
}
|
||||
});
|
||||
|
||||
a.appendChild(element('i', {
|
||||
class: 'fa fa-files-o transition'
|
||||
}));
|
||||
|
||||
item.appendChild(a);
|
||||
}
|
||||
|
||||
var ico = element('div', {
|
||||
class: 'fileIcon',
|
||||
});
|
||||
|
||||
ico.appendChild(element('i', {
|
||||
class: `fa fa-${(faIcons[ext] || faIcons["other"])}`
|
||||
}));
|
||||
|
||||
item.appendChild(ico);
|
||||
|
||||
item.onclick = function() {
|
||||
if(!clickable) return;
|
||||
// DO WITH SHIFT AND CONTROL LATER.
|
||||
|
||||
if(this.className.search( 'selectedItem') === -1) {
|
||||
get('.item').forEach(function(ele) {
|
||||
ele.style.backgroundColor = "";
|
||||
ele.className = ele.className.replace(' selectedItem',
|
||||
'');
|
||||
});
|
||||
this.className += ' selectedItem';
|
||||
this.style.backgroundColor = "rgba(255,255,255,0.2)";
|
||||
return;
|
||||
}
|
||||
|
||||
// Below executes only after user has clicked twice.
|
||||
var name = this.getAttribute('filename');
|
||||
var ext = this.getAttribute('ext');
|
||||
|
||||
clickable = false;
|
||||
if(ext == 'fol') {
|
||||
clearTbl();
|
||||
setTimeout(function() {
|
||||
currDir += '/' + name;
|
||||
listDir(currDir, 0);
|
||||
}, 300);
|
||||
} else {
|
||||
downloadFile(currDir + "/" + name);
|
||||
}
|
||||
clickable = true;
|
||||
|
||||
}
|
||||
cont.appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
get('#directory').appendChild(cont);
|
||||
setTimeout(function() {
|
||||
get('#directoryCont').style.opacity = "1";
|
||||
}, 100);
|
||||
};
|
||||
|
||||
function updateLocation() {
|
||||
var loc = get('#directoryLocation');
|
||||
while(loc.firstChild) loc.removeChild(loc.firstChild);
|
||||
@ -176,7 +58,7 @@ function updateLocation() {
|
||||
currDir = '';
|
||||
} else {
|
||||
currDir = subdir.slice(0, subdirNum+1)
|
||||
.reduce(function(a,b) { return a + '/' + b; }) + '/';
|
||||
.reduce(function(a,b) { return a + '/' + b; });
|
||||
}
|
||||
listDir(currDir, 0);
|
||||
}
|
||||
@ -184,7 +66,7 @@ function updateLocation() {
|
||||
|
||||
if(i > 0) {
|
||||
loc.appendChild(element('i', {
|
||||
class: 'fa fa-angle-right'
|
||||
class: 'fas fa-chevron-right'
|
||||
}));
|
||||
}
|
||||
loc.appendChild(p);
|
||||
|
||||
24
js/index.js
24
js/index.js
@ -3,32 +3,32 @@ var t = 0;
|
||||
function login(form) {
|
||||
u = form.username.value;
|
||||
p = form.password.value;
|
||||
uEmpty = u === "", pEmpty = p === "";
|
||||
uEmpty = u === '', pEmpty = p === '';
|
||||
|
||||
if(uEmpty && pEmpty) {
|
||||
alertBox("Please enter a username and password!", "error");
|
||||
alertBox('Please enter a username and password!', 'error');
|
||||
return;
|
||||
} else if (uEmpty && !pEmpty) {
|
||||
alertBox("Please enter a username!", "error");
|
||||
alertBox('Please enter a username!', 'error');
|
||||
return;
|
||||
} else if (!uEmpty && pEmpty) {
|
||||
alertBox("Please enter a password!", "error");
|
||||
alertBox('Please enter a password!', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
data = {username: u, password: p}
|
||||
$.post("./login", data).done(function(data) {
|
||||
$.post('./login', data).done(function(data) {
|
||||
if(data) {
|
||||
location.reload(true);
|
||||
} else {
|
||||
alertBox("Wrong username or password!");
|
||||
alertBox('Wrong username or password!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function drawCanvas() {
|
||||
var el = get("canvas")
|
||||
var c = el.getContext("2d")
|
||||
var el = get('canvas')
|
||||
var c = el.getContext('2d')
|
||||
var block = 10, space = 2, size = block+space;
|
||||
var period = 100, freq = 2*Math.PI/period, step = 1.4, base = 0.05;
|
||||
|
||||
@ -44,7 +44,7 @@ function drawCanvas() {
|
||||
el.width = w, el.height = h;
|
||||
|
||||
|
||||
c.fillStyle = "#0e0e0e";
|
||||
c.fillStyle = '#0e0e0e';
|
||||
c.fillRect(0, 0, w, h);
|
||||
for(var i = 0; i < x+1; i++) {
|
||||
for(var j = 0; j < y+1; j++) {
|
||||
@ -87,12 +87,12 @@ function drawCanvas() {
|
||||
|
||||
drawCanvas();
|
||||
|
||||
inputs = get("input"), button = get("button")
|
||||
inputs = get('input'), button = get('button')
|
||||
|
||||
inputs[0].addEventListener("keyup", function(e) {
|
||||
inputs[0].addEventListener('keyup', function(e) {
|
||||
if(e.keyCode === 13) button.click();
|
||||
});
|
||||
|
||||
inputs[1].addEventListener("keyup", function(e) {
|
||||
inputs[1].addEventListener('keyup', function(e) {
|
||||
if(e.keyCode === 13) button.click();
|
||||
});
|
||||
@ -8,6 +8,7 @@ var navSelect; // Stores current selected sidebar option.
|
||||
var clickable = true; // Prevents actions being run more than once.
|
||||
var selectDiv; // Stores selected file or folder div.
|
||||
var currDir = ''; // Stores the current directory.
|
||||
var version = 'mobile';
|
||||
|
||||
function sortFiles(type, direction) {
|
||||
if(type === 'name') data[0] = sortSection(type, direction, data[0]);
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
function videoOverlay(url) {
|
||||
var overlay = getDefaultOverlay();
|
||||
|
||||
var video = document.createElement("video");
|
||||
video.onclick = function() {event.stopPropagation();}
|
||||
video.src = url;
|
||||
video.controls = true;
|
||||
video.autoplay = true;
|
||||
video.type = "video/mp4";
|
||||
|
||||
video.style.margin = "auto";
|
||||
video.style.backgroundColor = "black";
|
||||
|
||||
video.onloadedmetadata = function() {
|
||||
if((video.videoHeight/video.videoWidth) > (window.innerHeight/window.innerWidth)) {
|
||||
video.style.height = (window.innerHeight * 0.9).toString() + "px";
|
||||
} else {
|
||||
video.style.width = (window.innerWidth * 0.9).toString() + "px";
|
||||
}
|
||||
}
|
||||
|
||||
var div = document.createElement("div");
|
||||
div.style.margin = "auto";
|
||||
div.style.gridRow = "1";
|
||||
div.style.gridColumn = "1";
|
||||
div.appendChild(video);
|
||||
overlay.appendChild(div);
|
||||
|
||||
var close = getClose();
|
||||
overlay.appendChild(close);
|
||||
|
||||
document.getElementsByTagName("body")[0].appendChild(overlay);
|
||||
setTimeout(function() {
|
||||
overlay.style.opacity = "1";
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function audioOverlay(url) {
|
||||
var overlay = getDefaultOverlay();
|
||||
var audio = document.createElement("audio");
|
||||
audio.onclick = function() {event.stopPropagation();}
|
||||
audio.src = url;
|
||||
audio.controls = true;
|
||||
audio.autoplay = true;
|
||||
|
||||
audio.style.margin = "auto";
|
||||
audio.style.width = (window.innerWidth * 0.9).toString() + "px";
|
||||
|
||||
var div = document.createElement("div");
|
||||
div.style.margin = "auto";
|
||||
div.style.gridRow = "1";
|
||||
div.style.gridColumn = "1";
|
||||
div.appendChild(audio);
|
||||
overlay.appendChild(div);
|
||||
|
||||
var close = getClose();
|
||||
overlay.appendChild(close);
|
||||
|
||||
document.getElementsByTagName("body")[0].appendChild(overlay);
|
||||
setTimeout(function() {
|
||||
overlay.style.opacity = "1";
|
||||
}, 10);
|
||||
}
|
||||
|
||||
|
||||
function imageOverlay(url) {
|
||||
var overlay = getDefaultOverlay();
|
||||
var img = new Image();
|
||||
img.src = url;
|
||||
img.style.margin = "auto";
|
||||
|
||||
var image = document.createElement("img");
|
||||
image.src = url;
|
||||
img.onload = function() {
|
||||
var height = img.height;
|
||||
var width = img.width;
|
||||
|
||||
|
||||
if((height/width) > (window.innerHeight/window.innerWidth)) {
|
||||
image.style.height = (window.innerHeight * 0.9).toString() + "px";
|
||||
} else {
|
||||
image.style.width = (window.innerWidth * 0.9).toString() + "px";
|
||||
}
|
||||
};
|
||||
|
||||
var div = document.createElement("div");
|
||||
div.style.margin = "auto";
|
||||
div.style.gridRow = "1";
|
||||
div.style.gridColumn = "1";
|
||||
div.appendChild(image);
|
||||
overlay.appendChild(div);
|
||||
|
||||
var close = getClose();
|
||||
overlay.appendChild(close);
|
||||
|
||||
document.getElementsByTagName("body")[0].appendChild(overlay);
|
||||
setTimeout(function() {
|
||||
overlay.style.opacity = "1";
|
||||
}, 10);
|
||||
}
|
||||
307
js/tools.js
307
js/tools.js
@ -5,12 +5,13 @@ var themeColors = { // For reference and for quick changing if need-be.
|
||||
};
|
||||
|
||||
var faIcons = {
|
||||
'fol': 'folder',
|
||||
'mp3': 'music',
|
||||
'ogg': 'music',
|
||||
'mp4': 'video-camera',
|
||||
'zip': 'file-zip-o',
|
||||
'other': 'file-o'
|
||||
'fol': 'fas fa-folder',
|
||||
'audio': 'fas fa-file-audio',
|
||||
'video': 'fas fa-file-video',
|
||||
'image': 'fas fa-file-image',
|
||||
'zip': 'fas fa-file-archive',
|
||||
'pdf': 'fas fa-file-pdf',
|
||||
'other': 'fas fa-file'
|
||||
};
|
||||
|
||||
var sort = { // Default sorting directions.
|
||||
@ -30,8 +31,8 @@ var navi = [ // Necessary arguments: id, alias, fa | Optional arguments: subnav.
|
||||
*/
|
||||
|
||||
function get(name) {
|
||||
ele = document.querySelectorAll(name)
|
||||
return (ele.length === 1) ? ele[0] : ele;
|
||||
ele = document.querySelectorAll(name)
|
||||
return (ele.length === 1) ? ele[0] : ele;
|
||||
};
|
||||
|
||||
function element(type, dict) {
|
||||
@ -61,8 +62,7 @@ function getDrives() {
|
||||
'onclick': function() {
|
||||
if(this.id === navSelect) return;
|
||||
updateNav(this.id);
|
||||
sidebar = get('.closeable');
|
||||
if(sidebar) moveSidebar('close');
|
||||
if(version === 'mobile') moveSidebar('close');
|
||||
currDir = '';
|
||||
listDir(currDir, 0);
|
||||
}
|
||||
@ -74,6 +74,10 @@ function getDrives() {
|
||||
navLayout();
|
||||
updateNav(navSelect);
|
||||
listDir(currDir, 0);
|
||||
})
|
||||
.fail(function(e) {
|
||||
alertBox(e.responseText, 'error');
|
||||
console.log(e.responseText);
|
||||
});
|
||||
};
|
||||
|
||||
@ -81,7 +85,7 @@ function getDrives() {
|
||||
// if files need to be split up into sections.
|
||||
|
||||
function listDir(dir, sec) {
|
||||
$.post('./files', {'drive_id': navSelect, 'path': currDir})
|
||||
$.post('./files/list', {'drive_id': navSelect, 'path': currDir})
|
||||
.done(function(d) {
|
||||
data = [[],[]];
|
||||
for(var i = 0; i < d.length; i++) {
|
||||
@ -94,13 +98,43 @@ function listDir(dir, sec) {
|
||||
}
|
||||
sortFiles('name', -1);
|
||||
clickable = true;
|
||||
})
|
||||
.fail(function(e) {
|
||||
alertBox(e.responseText, 'error');
|
||||
console.log(e.responseText);
|
||||
});
|
||||
};
|
||||
|
||||
function downloadFile(path) {
|
||||
function downloadFile(type, ext, path) {
|
||||
alertBox('Downloading file...', 'msg');
|
||||
$.post('./files', {'drive_id': navSelect, 'path': path}).done(function(d) {
|
||||
window.location = './d/' + d;
|
||||
$.post('./files/download', {'drive_id': navSelect, 'path': path})
|
||||
.done(function(d) {
|
||||
if(type === 'download') {
|
||||
if(ext.includes('pdf')) {
|
||||
window.open('./d/' + d);
|
||||
} else {
|
||||
window.location = './d/' + d;
|
||||
}
|
||||
} else if(type === 'image') {
|
||||
overlay(type, './d/' + d, ext)
|
||||
}
|
||||
|
||||
})
|
||||
.fail(function(e) {
|
||||
alertBox(e.responseText, 'error');
|
||||
console.log(e.responseText);
|
||||
});
|
||||
};
|
||||
|
||||
function streamFile(type, ext, path) {
|
||||
alertBox('Getting file...', 'msg');
|
||||
$.post('./files/stream', {'drive_id': navSelect, 'path': path})
|
||||
.done(function(d) {
|
||||
overlay(type, './d/' + d, ext)
|
||||
})
|
||||
.fail(function(e) {
|
||||
alertBox(e.responseText, 'error');
|
||||
console.log(e.responseText);
|
||||
});
|
||||
};
|
||||
|
||||
@ -124,7 +158,135 @@ function sortSection(type, direc, arr) {
|
||||
break;
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
};
|
||||
|
||||
function dispDir() {
|
||||
updateLocation();
|
||||
try {
|
||||
get('#directory').removeChild(get('#directoryCont'));
|
||||
} catch(err) {}
|
||||
|
||||
var cont = element('div', {
|
||||
id: 'directoryCont',
|
||||
class: 'transition',
|
||||
style: 'opacity:0'
|
||||
});
|
||||
|
||||
if(data[0].length === 0 && data[1].length === 0) {
|
||||
cont.appendChild(element('p', {
|
||||
text: 'Nothing here!',
|
||||
style: 'font-weight: 100'
|
||||
}));
|
||||
}
|
||||
|
||||
for(var i = 0; i < data.length; i++) {
|
||||
for(var j = 0; j < data[i].length; j++) {
|
||||
var itemInfo = data[i][j];
|
||||
|
||||
var ext = (itemInfo.folder) ? 'fol' : itemInfo.filetype
|
||||
|
||||
var item = element('div', {
|
||||
class: 'item transition',
|
||||
ext: ext,
|
||||
filename: itemInfo.name
|
||||
});
|
||||
|
||||
item.appendChild(element('p', {
|
||||
class: 'name',
|
||||
text: itemInfo.name
|
||||
}));
|
||||
|
||||
if(version === 'desktop') {
|
||||
item.appendChild(element('p', {
|
||||
class: 'modified',
|
||||
text: (itemInfo.folder) ? '----' : dateStr(itemInfo.date)
|
||||
}));
|
||||
|
||||
item.appendChild(element('p', {
|
||||
class: 'size',
|
||||
text: itemInfo.size || '----'
|
||||
}));
|
||||
} else if(version === 'mobile') {
|
||||
item.appendChild(element('p', {
|
||||
class: 'otherInfo',
|
||||
text: (itemInfo.folder) ? '----' :
|
||||
dateStr(itemInfo.date, 'date') + ' | ' + itemInfo.size
|
||||
}));
|
||||
}
|
||||
|
||||
if(!itemInfo.folder) {
|
||||
var a = element('div', {
|
||||
onclick: function() {
|
||||
console.log('generating download link');
|
||||
// DO EXPIRY LINKS HERE
|
||||
// update link to get('copy') and copy
|
||||
}
|
||||
});
|
||||
|
||||
a.appendChild(element('i', {
|
||||
class: 'fa fa-files-o transition'
|
||||
}));
|
||||
|
||||
item.appendChild(a);
|
||||
}
|
||||
|
||||
var ico = element('div', {
|
||||
class: 'fileIcon',
|
||||
});
|
||||
|
||||
ico.appendChild(element('i', {
|
||||
class: faIcons[fileType(ext)]
|
||||
}));
|
||||
|
||||
item.appendChild(ico);
|
||||
|
||||
item.onclick = function() {
|
||||
if(!clickable) return;
|
||||
// DO WITH SHIFT AND CONTROL LATER.
|
||||
|
||||
if(this.className.search( 'selectedItem') === -1) {
|
||||
get('.item').forEach(function(ele) {
|
||||
ele.style.backgroundColor = '';
|
||||
ele.className = ele.className.replace(' selectedItem',
|
||||
'');
|
||||
});
|
||||
this.className += ' selectedItem';
|
||||
this.style.backgroundColor = 'rgba(255,255,255,0.2)';
|
||||
return;
|
||||
}
|
||||
|
||||
// Below executes only after user has clicked twice.
|
||||
var name = this.getAttribute('filename');
|
||||
var ext = this.getAttribute('ext');
|
||||
|
||||
clickable = false;
|
||||
if(ext == 'fol') {
|
||||
clearTbl();
|
||||
setTimeout(function() {
|
||||
currDir += '/' + name;
|
||||
listDir(currDir, 0);
|
||||
}, 300);
|
||||
} else if(ext.includes('image')) {
|
||||
downloadFile('image', ext, currDir + '/' + name);
|
||||
} else if(ext.includes('audio')) {
|
||||
streamFile('audio', ext, currDir + '/' + name);
|
||||
} else if(ext.includes('video')) {
|
||||
streamFile('video', ext, currDir + '/' + name);
|
||||
} else {
|
||||
downloadFile('download', ext, currDir + '/' + name);
|
||||
}
|
||||
clickable = true;
|
||||
|
||||
}
|
||||
cont.appendChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
get('#directory').appendChild(cont);
|
||||
setTimeout(function() {
|
||||
get('#directoryCont').style.opacity = '1';
|
||||
}, 100);
|
||||
};
|
||||
|
||||
function navLayout() {
|
||||
function createNavHeader(text) {
|
||||
@ -172,10 +334,99 @@ function updateNav(op) { // Updates the sidebar navigation.
|
||||
};
|
||||
|
||||
function clearTbl() {
|
||||
selectDiv = undefined;
|
||||
get('#directoryCont').style.opacity = '0';
|
||||
selectDiv = undefined;
|
||||
get('#directoryCont').style.opacity = '0';
|
||||
};
|
||||
|
||||
function overlay(type, src, mime) {
|
||||
function resize(item, vH, vW) {
|
||||
wH = window.innerHeight, wW = window.innerWidth;
|
||||
if((vH/vW) > (wH/wW)) {
|
||||
item.style.height = (wH * 0.9).toString() + "px";
|
||||
} else {
|
||||
item.style.width = (wW * 0.9).toString() + "px";
|
||||
}
|
||||
}
|
||||
|
||||
var div = element('div', {
|
||||
id: 'overlay',
|
||||
class: 'transition',
|
||||
style: `width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0,0,0,0.7);
|
||||
opacity: 0;
|
||||
display: grid;`,
|
||||
onclick: function() {
|
||||
this.style.opacity = '0';
|
||||
that = this;
|
||||
setTimeout(function() {
|
||||
that.parentNode.removeChild(that);
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
|
||||
var inner;
|
||||
|
||||
if(type === 'image') {
|
||||
var img = element('img', {
|
||||
style: 'margin: auto;',
|
||||
src: src,
|
||||
onclick: function(event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
img.onload = function() {
|
||||
resize(this, this.height, this.width);
|
||||
};
|
||||
|
||||
inner = img;
|
||||
|
||||
} else if (type === 'audio') {
|
||||
var audio = element('audio', {
|
||||
class: 'noSelect',
|
||||
style: 'margin: auto; outline: none',
|
||||
controls: true,
|
||||
autoplay: true,
|
||||
src: src,
|
||||
type: mime,
|
||||
onclick: function(event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
inner = audio;
|
||||
|
||||
} else if (type === 'video') {
|
||||
var vid = element('video', {
|
||||
style: 'margin: auto; background-color: black;',
|
||||
controls: true,
|
||||
autoplay: true,
|
||||
src: src,
|
||||
type: mime,
|
||||
onclick: function(event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
vid.onloadedmetadata = function() {
|
||||
resize(this, this.videoHeight, this.videoWidth);
|
||||
};
|
||||
|
||||
inner = vid;
|
||||
}
|
||||
|
||||
div.appendChild(inner);
|
||||
get('body').appendChild(div);
|
||||
|
||||
setTimeout(function() {
|
||||
div.style.opacity = '1';
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function animFade(type, div) {
|
||||
if(type === 'open') {
|
||||
div.style.display = 'block';
|
||||
@ -200,4 +451,24 @@ function dateStr(date, type) {
|
||||
} else if(Type === 'time') {
|
||||
return str.substring(str.indexOf(',') + 1, str.length);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function fileType(ext) {
|
||||
if(ext === 'fol') return 'fol';
|
||||
if(ext.includes('image')) {
|
||||
return 'image';
|
||||
} else if(ext.includes('video')) {
|
||||
return 'video';
|
||||
} else if(ext.includes('pdf')) {
|
||||
return 'pdf';
|
||||
} else if(ext.includes('audio')) {
|
||||
return 'audio';
|
||||
} else if(ext.includes('zip') ||
|
||||
ext.includes('x-rar') ||
|
||||
ext.includes('x-7z-compressed') ||
|
||||
ext.includes('gzip')) {
|
||||
return 'zip';
|
||||
} else {
|
||||
return 'other'
|
||||
}
|
||||
}
|
||||
@ -19,9 +19,9 @@
|
||||
<h1>BinBin</h1>
|
||||
<form id="login" onsubmit="login(form);">
|
||||
<p>Username:</p>
|
||||
<input class="transition" type="text" name="username">
|
||||
<input class="transition noSelect" type="text" name="username">
|
||||
<p>Password:</p>
|
||||
<input class="transition" type="password" name="password">
|
||||
<input class="transition noSelect" type="password" name="password">
|
||||
</form>
|
||||
<div>
|
||||
<button class="transition" onclick="login(get('#login'));" >Login</button>
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:100,300" rel="stylesheet">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script src="https://use.fontawesome.com/c8d5486cd8.js"></script>
|
||||
<script src="https://kit.fontawesome.com/54cafaf1a9.js"></script>
|
||||
<script src="./js/tools.js"></script>
|
||||
<script id="version">
|
||||
scripts = {
|
||||
@ -18,7 +18,8 @@
|
||||
};
|
||||
|
||||
function isMobileDevice() {
|
||||
return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1);
|
||||
return (typeof window.orientation !== "undefined") ||
|
||||
(navigator.userAgent.indexOf('IEMobile') !== -1);
|
||||
};
|
||||
|
||||
function setPage(method, html) {
|
||||
@ -34,6 +35,7 @@
|
||||
};
|
||||
|
||||
var method = (isMobileDevice()) ? "mobile" : "desktop";
|
||||
console.log(method)
|
||||
get('head').appendChild(element('link', {
|
||||
rel: 'stylesheet',
|
||||
href: `./css/${method}.css`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user