You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
5.8 KiB
201 lines
5.8 KiB
from flask import Flask, Response, redirect, url_for, request, session, abort, render_template, send_file
|
|
from flask_login import LoginManager, UserMixin, login_required, login_user, logout_user, current_user
|
|
from PIL import Image, ImageFont, ImageDraw
|
|
import qrcode
|
|
from io import BytesIO
|
|
import json, random, re, string, hashlib, base64
|
|
|
|
app = Flask(__name__)
|
|
systemURL = 'http://192.168.0.11:5000/' #FULL URL with a '/' at the end
|
|
systemURL = 'http://10.0.1.115:5000/'
|
|
randomchars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789' #note the lack of zero
|
|
|
|
# flask-login
|
|
login_manager = LoginManager()
|
|
login_manager.init_app(app)
|
|
login_manager.login_view = "login"
|
|
|
|
admins={}
|
|
class Admin(UserMixin):
|
|
def __init__(self, name, password):
|
|
self.id = name
|
|
self.password = password
|
|
admins[name] = self
|
|
|
|
with open('links.json', 'r') as infile:
|
|
links = json.load(infile)
|
|
|
|
with open('admins.json', 'r') as infile:
|
|
adminfile = json.load(infile)
|
|
for key, value in adminfile.items():
|
|
if key=='secret_key':
|
|
app.secret_key = value
|
|
elif key=='secret_cookie':
|
|
secret_cookie = value.encode('utf-8')
|
|
else:
|
|
a = Admin(key, value['password'])
|
|
|
|
|
|
def saveFile():
|
|
with open('links.json', 'w') as outfile:
|
|
json.dump(links, outfile)
|
|
|
|
def randomToken():
|
|
code = ""
|
|
for i in range(0,6):
|
|
code += random.choice(randomchars)
|
|
return code
|
|
|
|
def codeValidation(code):
|
|
if len(code) not in range (3,10):
|
|
return False
|
|
if re.match('^[\w-]+$', code) is None:
|
|
return False
|
|
return True
|
|
|
|
def codeLink(code):
|
|
global links
|
|
if code not in links:
|
|
return False
|
|
if len(links[code]['url'])==0:
|
|
return None
|
|
return links[code]['url']
|
|
|
|
def createNewCode():
|
|
code=randomToken()
|
|
while code in links: #danger!
|
|
code=randomToken()
|
|
links[code]={'url':''}
|
|
return code
|
|
|
|
def serveImage(img):
|
|
img_io = BytesIO()
|
|
img.save(img_io, 'PNG')
|
|
img_io.seek(0)
|
|
return send_file(img_io, mimetype='image/png')
|
|
|
|
@app.route('/code/<code>')
|
|
def serveCode(code):
|
|
code = code[:code.find('.')]
|
|
if codeValidation(code) is False:
|
|
return send_file('static/invalid.png', mimetype='image/png')
|
|
qr = qrcode.QRCode(
|
|
version=1,
|
|
error_correction=qrcode.constants.ERROR_CORRECT_M,
|
|
box_size=8,
|
|
border=3,
|
|
)
|
|
qr.add_data(systemURL + code)
|
|
qr.make(fit=True)
|
|
img = qr.make_image(fill_color="black", back_color="white")
|
|
return serveImage(img)
|
|
|
|
@app.route("/edit", methods=['GET', 'POST'])
|
|
def edit():
|
|
code = request.form.get("code") if request.form.get("code") is not None else request.args.get("code")
|
|
url = request.form.get("url")
|
|
|
|
if codeLink(code) is False:
|
|
return render_template('invalid.html', code=code)
|
|
if current_user.is_authenticated:
|
|
if url==None:
|
|
return render_template('editlink.html', code=code, url=codeLink(code), admin=current_user.is_authenticated)
|
|
else:
|
|
if url=='remove':
|
|
url = ''
|
|
links[code]['url']=url
|
|
saveFile()
|
|
return render_template('message.html', message="Done Mr. Admin person")
|
|
else:
|
|
if codeLink(code) is not None:
|
|
return render_template('cantedit.html', url=codeLink(code))
|
|
|
|
if url is None:
|
|
return render_template('editlink.html', code=code, url='', admin=current_user.is_authenticated)
|
|
|
|
#Saving the link:
|
|
if url.lower().startswith('https://') is False and url.lower().startswith('http://') is False:
|
|
return render_template('message.html', message="Only http:// and https:// links alowed. Plz fix your link!")
|
|
if len(url)>1000:
|
|
return render_template('message.html', message="This link is too long! It probably contains tracking data or other crap. Please find a shorter link.")
|
|
links[code]['url']=url
|
|
saveFile()
|
|
return render_template('success.html')
|
|
|
|
@app.route("/admin")
|
|
@login_required
|
|
def admin():
|
|
return render_template('admin.html')
|
|
|
|
# somewhere to login
|
|
@app.route("/login", methods=["GET", "POST"])
|
|
def login():
|
|
if request.method == 'POST':
|
|
username = request.form['username']
|
|
password = request.form['password']
|
|
hasher = hashlib.sha256()
|
|
hasher.update(password.encode('utf-8'))
|
|
hasher.update(secret_cookie)
|
|
hashedpassword = base64.b64encode(hasher.digest()).decode('utf-8')
|
|
if admins[username].password == hashedpassword:
|
|
login_user(admins[username])
|
|
return redirect(request.args.get("next"))
|
|
return abort(401)
|
|
else:
|
|
return render_template('login.html')
|
|
|
|
@app.route("/logout")
|
|
@login_required
|
|
def logout():
|
|
logout_user()
|
|
return redirect('/')
|
|
|
|
# callback to reload the user object
|
|
@login_manager.user_loader
|
|
def load_user(userid):
|
|
return admins[userid]
|
|
|
|
@app.route("/generate", methods=['GET', 'POST'])
|
|
def generate():
|
|
howmany = request.form.get("howmany")
|
|
if howmany is None:
|
|
return render_template('generate.html')
|
|
codes = []
|
|
for i in range(0, int(howmany)):
|
|
codes.append(createNewCode())
|
|
columns = 4
|
|
codesarray = [codes[i:i+columns] for i in range(0, len(codes), columns)]
|
|
saveFile()
|
|
humanSystemURL = systemURL[systemURL.find('//')+2:]
|
|
return render_template("printlabels.html", codes=codesarray, systemURL=humanSystemURL, codegenURL=systemURL+'code/', format='.png')
|
|
|
|
@app.route("/list")
|
|
@login_required
|
|
def list():
|
|
linklist = []
|
|
for key, value in links.items():
|
|
if len(value['url'])>0:
|
|
linklist.append({'code':key, 'url':value['url']})
|
|
return render_template('list.html', linklist=linklist, count=len(linklist))
|
|
|
|
@app.route("/empty")
|
|
@login_required
|
|
def showEmptyCodes():
|
|
linklist = []
|
|
for key, value in links.items():
|
|
if value['url']=='':
|
|
linklist.append({'code':key, 'url':value['url']})
|
|
return render_template('listempty.html', linklist=linklist, count=len(linklist))
|
|
|
|
@app.route('/', defaults={'path': ''})
|
|
@app.route('/<path:path>')
|
|
def catch_all(path):
|
|
if len(path)==0:
|
|
return render_template('welcome.html')
|
|
if path in links:
|
|
if codeLink(path) is not None:
|
|
return redirect(links[path]['url'], code=302)
|
|
else:
|
|
return render_template('newcode.html', code=path)
|
|
else:
|
|
return render_template('invalid.html', code=path) |