from flask import Flask,redirect,url_for,request,render_template,make_response from datetime import datetime from hashlib import sha256 from uuid import uuid4 as uuid ## Import db class from func.py and initialise it from func import db ## import all config variables from config import * db=db() db.startup() app = Flask(__name__) ## CUSTOM FILTERS @app.template_filter('ctime') def timectime(s): return datetime.utcfromtimestamp(s).strftime('%Y-%m-%d %H:%M') @app.template_filter('spacer') def convsize(s): sizes=("B","KB","MB","GB","TB") n=0 while s >= 1000: n+=1 s=s/1000 return str("%.2f" % s)+sizes[n] ## WEB FRONTEND @app.route('/') def homepage(): # try to get userdata, else logout state logged_in,userdata=get_login_info(request.cookies.get('session')) archives=db.get_n_archives() return render_template("home.html", title="Homepage",userdata=userdata,login=logged_in,archives=archives) @app.route('/user') @app.route('/user/') def userpage(userid:int=0): logged_in,userdata=get_login_info(request.cookies.get('session')) if not logged_in: return make_response(redirect('/')) @app.route('/add', methods=['GET','POST']) def addpage(): # try to get userdata, else yeet to the homepage logged_in,userdata=get_login_info(request.cookies.get('session')) if not logged_in: return make_response(redirect('/')) # POST: check and add archive, show confirmation/error message at the end if request.method == 'POST': postdict={} # get and save all inputs, error if one doesn't exist or is wrong type for i,itype in [("name",str),("hash",str),("category",int),("size",float)]: try: postdict[i]=itype(request.form[i]) except Exception as e: return errorpage("All fields need to be filled and don't play with their names!") try: postdict["size"]=postdict["size"]*int(request.form['size_multiplier']) except Exception as e: return errorpage("All fields need to be filled and don't play with their names!") postdict["owner"]=userdata[0] res,archid=db.add_archive(postdict) if res: return make_response(redirect(f"/view/{str(archid)}")) else: return errorpage(archid), 400 # GET: return normal page htmlcatlist=get_category_selection(False) return render_template("add.html", title="Add Archive",categories=htmlcatlist) @app.route('/login', methods=["GET","POST"]) def loginpage(): # POST: Process login request if request.method == 'POST': username=request.form['username'] password=sha256(request.form['password'].encode()).hexdigest() code,userid,passhash=db.get_passhash(username) if code != 200: return passhash # if passwords match, create session and return cookie if password.upper() == passhash.upper(): lifetime=RAR_COOKIE_LIFETIME # lifetime of the sesskey in seconds sesskey=str(uuid()) db.set_sesskey(sesskey,userid,lifetime) resp=setcookie("session",sesskey,lifetime) return resp else: return errorpage("You've entered the wrong password. This incident will be reported.") # GET: Login form else: return render_template("login.html", title="Login") @app.route('/view/') def viewpage(archid:int): logged_in,userdata=get_login_info(request.cookies.get('session')) archive,category,labels=db.get_archive_info(archid) return render_template("view.html", title="View Archive",userdata=userdata,login=logged_in,archive=archive,category=category,labels=labels) @app.route('/delete/', methods=["GET","POST"]) def deletepage(archid:int): logged_in,userdata=get_login_info(request.cookies.get('session')) archive,category,labels=db.get_archive_info(archid) if not logged_in or userdata[0] != archive[8]: return make_response(redirect(f"/view/{archid}")) if request.method == 'POST': if not request.form['archname'] == archive[1]: return errorpage("The name input doesn't match!") db.delete_archive(archid) return make_response(redirect('/')) # GET: return normal deletion page return render_template("delete.html", title="Delete Archive",userdata=userdata,login=logged_in,archive=archive) @app.route('/labels/', methods=["GET","POST"]) def labeleditpage(archid:int): logged_in,userdata=get_login_info(request.cookies.get('session')) archive,category,labels=db.get_archive_info(archid) label_dict=db.get_label_labeltypes(category[3]) if not logged_in or userdata[0] != archive[8]: return make_response(redirect(f"/view/{archid}")) # POST: parse everything and update labels if request.method == 'POST': on_labels=[] print(request.form) for i in request.form: on_labels.append(i) res, data=db.update_labels(archid, on_labels) if not res: return errorpage(data) return make_response(redirect(f"/view/{archid}")) # GET: return normal labels page labels_name_list=[] for i in labels: labels_name_list.append(i[0]) return render_template("labels.html", title="Edit Labels",userdata=userdata,login=logged_in,archive=archive,res_labels=label_dict,labels_names=labels_name_list) @app.route('/search') def searchpage(): # try to get userdata, else logout state logged_in,userdata=get_login_info(request.cookies.get('session')) # try to set all required variables, else defaults try: sorttype=request.args['sort'] except Exception as e: sorttype="time" try: category=request.args['category'] except Exception as e: category=0 try: keywords=request.args['q'] keywords="".join(keywords).split(" ") except Exception as e: keywords=[] try: count=request.args['count'] except Exception as e: count=20 archives=db.get_n_archives(sorttype,category,keywords,count) htmlcatlist=get_category_selection() return render_template("search.html", title="Advanced Search",categories=htmlcatlist,userdata=userdata,login=logged_in,archives=archives) ## FUNCTIONS def errorpage(message): return "

ERROR: " + message + "

Go back and try again" ## Checks if given sesskey is valid and returns user data ## OUTPUT: (if sesskey valid) logged_in:bool=True, userdata:tuple ## (if sesskey invalid) logged_in:bool=False, userdata:tuple=() def get_login_info(sesskey:str): if not sesskey: return False,() logged_in,userid=db.check_sesskey(sesskey) if logged_in: userdata=db.get_user_info(userid) else: userdata=() return logged_in,userdata def setcookie(name:str,value:str,lifetime:int=10000): resp = make_response(redirect('/')) resp.set_cookie(name, value, max_age=lifetime) return resp ## Gets all categories and returns them (with or without parents) ## OUTPUT: […,(ID:int,NAME:str),…] def get_category_selection(include_parents:bool=True): catlist=db.get_categories() htmlcatlist=[] # parse all categories and sort them into list for cat in catlist: if not cat[2]: if include_parents: htmlcatlist.append((cat[0],cat[1])) parent=cat[1] parentid=cat[0] for i in catlist: if i[2] == parentid: htmlcatlist.append((i[0],f"{parent}/{i[1]}")) return htmlcatlist ## API CALLS (NO THANKS) # main driver function if __name__ == '__main__': # run app if executed directly app.run()