Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions flask-app/application/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def create_app(
dict(
APPLICATION_ROOT=url_prefix,
APP_NAME="MTW",
APP_VER="1.7.7",
APP_VER="1.7.8",
API_VER="1.0.0",
DBVERSION=1.0,
CACHE_DIR=mtu.get_instance_dir(app, "cache"),
Expand Down Expand Up @@ -171,7 +171,7 @@ def create_app(
if not relax and not app.debug:
# Paranoid
paranoid.init_app(app)
paranoid.redirect_view = "/"
paranoid.redirect_view = url_prefix.rstrip("/") + "/"

talisman = Talisman( # noqa: F841
app,
Expand Down
51 changes: 43 additions & 8 deletions flask-app/application/modules/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from contextlib import closing
from timeit import default_timer as timer
from urllib.parse import urlparse
from urllib.parse import unquote, urlparse

from flask import current_app as app

Expand Down Expand Up @@ -44,14 +44,49 @@ def close_db(error):


def ref_redirect():
fallback = url_for("intro")
referrer = request.referrer

if not referrer:
return fallback

try:
purl = urlparse(request.referrer)
new_url = purl.path
if purl.query:
new_url += "?" + purl.query
return new_url
except: # noqa: E722
return url_for("intro")
purl = urlparse(referrer)
decoded_path = unquote(purl.path or "/")
except (TypeError, ValueError, UnicodeError):
return fallback

# Allow only HTTP(S) URLs.
if purl.scheme and purl.scheme not in {"http", "https"}:
return fallback

# Reject referrers from another host.
if purl.netloc and purl.netloc.lower() != request.host.lower():
return fallback

# Require a local absolute path.
if not decoded_path.startswith("/"):
return fallback

# Reject protocol-relative paths, including encoded variants.
if decoded_path.startswith("//"):
return fallback

# Some clients interpret backslashes as path separators.
if "\\" in decoded_path:
return fallback

# Reject control characters.
if any(ord(char) < 32 for char in decoded_path):
return fallback

# Return the original encoded path to preserve URL semantics.
new_url = purl.path or "/"

if purl.query:
new_url = f"{new_url}?{purl.query}"

return new_url


def show_elapsed(begin, started=None, tag="", msg=False):
Expand Down
2 changes: 1 addition & 1 deletion flask-app/mtw-server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
DEFAULT_PREFIX = "mtw"

appname = "mtw-server"
appdesc = "MTW Server 1.7.7"
appdesc = "MTW Server 1.7.8"
appusage = "Help: " + appname + " -h \n"
appauthor = "Filip Kriz"

Expand Down
23 changes: 13 additions & 10 deletions flask-app/mtw_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
### Version 1.7.7 ###
### Version 1.7.8 ###
### Python 3.12 ###
arrow==1.4.0
bcrypt==5.0.0 ## NOT python-bcrypt !!!
cachelib==0.13.0
bcrypt==5.0.0 # NOT python-bcrypt !!!
cachelib==0.17.0
certifi==2026.10.19
cffi==2.1.1
click==8.5.0
colorama==0.4.6
diff_match_patch==20241021
Flask==3.1.3
Flask-Caching==2.3.1
Flask-Caching==2.5.1
Flask-Paranoid==0.3.0
Flask-SeaSurf==2.0.0
Flask-Session==0.8.0
flask-talisman==1.1.0
future==1.0.0
idna==3.19
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.3
pip_audit==2.10.0 ## Run: pip freeze > requirements.txt ; pip-audit ; pip-audit -r mtw_requirements.txt
pip_audit==2.10.1 # Run outside the IDE(!) in venv: py -m pip_audit
pyuca==1.2
rdflib==7.6.0
requests==2.33.1
requests==2.34.2
requests_futures==1.0.2
SPARQLWrapper==2.0.0
tqdm==4.67.3
tqdm==4.70.1
urllib3==2.8.0
waitress==3.0.2
Werkzeug==3.1.9
### (optional) If building for Windows:
pyinstaller==6.19.0; sys_platform == "win32"
pyinstaller-hooks-contrib==2026.4; sys_platform == "win32"
pyinstaller==6.22.3; sys_platform == "win32"
pyinstaller-hooks-contrib==2026.7; sys_platform == "win32"
## Install pywin32
pywin32==311; sys_platform == "win32"
pywin32==312; sys_platform == "win32"
## and run in CMD as Admin with activated VENV (!):
## python venv\Scripts\pywin32_postinstall.py -install
Loading