From ab44901dc07722ff8bcfec6042e8c13bf9ef8eb3 Mon Sep 17 00:00:00 2001 From: csd4ni3l Date: Fri, 24 Oct 2025 18:01:50 +0200 Subject: [PATCH] Make Posts id autoincrement, make working posts page on home which shows the pumpkins and comment, reduce bloat by making a lightbtn setup function, fix XSS --- app.py | 28 ++++++++++++++++++------ static/pumpkin.js | 34 +++++++++++++++++----------- templates/countdown.jinja2 | 13 +---------- templates/index.jinja2 | 45 +++++++++++++++++++++++++++++--------- 4 files changed, 78 insertions(+), 42 deletions(-) diff --git a/app.py b/app.py index 350b8a8..8b0e8df 100644 --- a/app.py +++ b/app.py @@ -1,10 +1,11 @@ -from flask import Flask, Response, render_template, redirect, url_for, g, request +from flask import Flask, Response, render_template, redirect, url_for, g, request, json from flask_login import LoginManager, login_required +from datetime import datetime from pattern import Pattern -import sqlite3, os, flask_login, dotenv, secrets +import sqlite3, os, flask_login, dotenv, secrets, html if os.path.exists(".env"): dotenv.load_dotenv(".env") @@ -31,8 +32,8 @@ def get_db(): db.execute(""" CREATE TABLE IF NOT EXISTS Posts ( - id INTEGER PRIMARY KEY, - username TEXT NOT NULL UNIQUE, + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL, comment TEXT NOT NULL, pattern TEXT NOT NULL, creation_time INTEGER NOT NULL @@ -69,13 +70,23 @@ def main(): cur = get_db().cursor() - cur.execute("SELECT * FROM Posts LIMIT 20") + cur.execute("SELECT * FROM Posts LIMIT 15") posts = cur.fetchall() cur.close() - return render_template("index.jinja2", username=username, posts=posts) + for post in posts: + if not isinstance(post[0], int): + print("Post ID is not int. Exiting for safety.") + return "Post ID is not int. Exiting for safety." + if not isinstance(post[4], int): + print("Post Timestamp is not int. Exiting for safety.") + return "Post Timestamp is not int. Exiting for safety." + + new_posts = [[post[0], html.escape(post[1], quote=True), html.escape(post[2], quote=True), [html.escape(f"{pos[0]},{pos[1]}", quote=True) for pos in json.loads(post[3])], datetime.fromtimestamp(post[4]).strftime('%Y-%m-%d %H:%M:%S')] for post in posts] + + return render_template("index.jinja2", username=username, posts=new_posts, grid_size=os.getenv("GRID_SIZE", 15)) @app.route("/countdown") def countdown(): @@ -120,7 +131,10 @@ def register(): return render_template("register.jinja2", grid_size=os.getenv("GRID_SIZE", 15)) elif request.method == "POST": - username = request.form["username"] + if request.form["username"] != html.escape(request.form["username"], quote=True): + return "No XSS please" + + username = html.escape(request.form["username"], quote=True) pattern = Pattern.from_str(request.form["pattern"]) cur = get_db().cursor() diff --git a/static/pumpkin.js b/static/pumpkin.js index bfb26b9..0e1b892 100644 --- a/static/pumpkin.js +++ b/static/pumpkin.js @@ -151,6 +151,23 @@ function unlight_pumpkin(ctx, cell_size, currentPattern) { } } +function setup_lightbtn(ctx, cell_size, lightbtn_id, pattern) { + let lit = { value: false }; + + document.getElementById(lightbtn_id).addEventListener('click', function(event) { + if (lit.value) { + lit.value = false; + unlight_pumpkin(ctx, cell_size, pattern); + } + else { + lit.value = true; + light_pumpkin(ctx, cell_size, pattern); + } + }); + + return lit; +} + function setup_pumpkin(canvas_id, clearbtn_id, lightbtn_id, form_id, pattern_field_id, grid_size, allow_drawing=true) { const canvas = document.getElementById(canvas_id); const ctx = canvas.getContext('2d'); @@ -160,29 +177,20 @@ function setup_pumpkin(canvas_id, clearbtn_id, lightbtn_id, form_id, pattern_fie const CELL_SIZE = canvas.width / GRID_SIZE; let currentPattern = []; + let lit = { value: false }; img.onload = () => { clearCanvas(ctx, canvas, img, GRID_SIZE, currentPattern); }; if (allow_drawing) { - let lit = false; - document.getElementById(lightbtn_id).addEventListener('click', function(event) { - if (lit) { - lit = false; - unlight_pumpkin(ctx, CELL_SIZE, currentPattern); - } - else { - lit = true; - light_pumpkin(ctx, CELL_SIZE, currentPattern); - } - }); + lit = setup_lightbtn(ctx, CELL_SIZE, lightbtn_id, currentPattern); let drawing = false; canvas.addEventListener('mousedown', () => { drawing = true; }); canvas.addEventListener('mouseup', () => { drawing = false; }); - canvas.addEventListener('mousemove', (e) => draw(e, ctx, CELL_SIZE, drawing, canvas, currentPattern, lit)); - canvas.addEventListener('click', (e) => {draw(e, ctx, CELL_SIZE, true, canvas, currentPattern, lit)}); + canvas.addEventListener('mousemove', (e) => draw(e, ctx, CELL_SIZE, drawing, canvas, currentPattern, lit.value)); + canvas.addEventListener('click', (e) => {draw(e, ctx, CELL_SIZE, true, canvas, currentPattern, lit.value)}); document.getElementById(clearbtn_id).addEventListener('click', () => clearCanvas(ctx, canvas, img, GRID_SIZE, currentPattern)); document.getElementById(form_id).addEventListener('submit', function(event) { diff --git a/templates/countdown.jinja2 b/templates/countdown.jinja2 index df5f510..a33d6fa 100644 --- a/templates/countdown.jinja2 +++ b/templates/countdown.jinja2 @@ -90,18 +90,7 @@ img.addEventListener('load', function() { setInterval(update, 1500); }); - -let lit = false; -document.getElementById("lightBtn").addEventListener('click', function(event) { - if (lit) { - lit = false; - unlight_pumpkin(ctx, CELL_SIZE, pattern.slice(0, pattern.length - last_days)); - } - else { - lit = true; - light_pumpkin(ctx, CELL_SIZE, pattern.slice(0, pattern.length - last_days)); - } -}); +setup_lightbtn(ctx, CELL_SIZE, "lightBtn", pattern.slice(0, pattern.length - last_days)); {% endblock body %} \ No newline at end of file diff --git a/templates/index.jinja2 b/templates/index.jinja2 index 3a7fba8..1fab799 100644 --- a/templates/index.jinja2 +++ b/templates/index.jinja2 @@ -18,15 +18,40 @@ {% endblock %} {% block body %} -
- {% for post in posts %} -
- -
-
{{ post.1 }}: {{ post.3 }}
-

{{ post.2 }}

-
-
- {% endfor %} +
+

Posts

+
+
+ {% for post in posts %} +
+
+ +
+
{{ post.2 }}
+

By: {{ post.1 }}
Created at: {{ post.4 }}

+ +
+
+
+ {% endfor %} +
+
+ + {% endblock body %} \ No newline at end of file