Added quality of life functions

* Ability to use full path for image path
*  Ability to configure the wait time between images
*  Added protection from escaping the image directory
This commit is contained in:
brammp committed 2026-09-21 23:13:19 +02:00
1 parent d0564914e8
commit f6c2b9dd5b
4 files changed
+65 -7

No files matched your search

+58 -3
View File
@@ -7,6 +7,8 @@ from PIL import Image
from PIL.ExifTags import TAGS
import urllib.parse
from datetime import datetime
import mimetypes
from pathlib import Path
# --
# Configuration
@@ -21,6 +23,8 @@ class SlideshowHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
self.send_slideshow_page()
elif self.path == "/config.js":
self.send_clientconf()
elif self.path == "/images.json":
self.send_image_list()
elif self.path == "/weather":
@@ -30,8 +34,10 @@ class SlideshowHandler(http.server.SimpleHTTPRequestHandler):
self.get_METNOweather()
elif self.path.startswith("/exif"):
self.send_exif_data()
elif self.path.startswith("/img"):
self.send_image()
else:
super().do_GET()
self.send_error(404, "Not found")
#--
# Main Page
@@ -49,13 +55,51 @@ class SlideshowHandler(http.server.SimpleHTTPRequestHandler):
self.end_headers()
self.wfile.write(content)
#--
# Image depot
#--
def send_image(self):
parsed = urllib.parse.urlparse(self.path)
params = urllib.parse.parse_qs(parsed.query)
filename = params.get("file", [None])[0]
if not filename:
self.send_error(400, "Missing ?file= parameter")
return
base_dir = Path(cfg["IMAGE_DIR"]).resolve()
print(base_dir)
file_path = (base_dir / filename).resolve()
try:
file_path.relative_to(base_dir)
except ValueError:
self.send_error(403, "Forbidden")
return
content_type, _ = mimetypes.guess_type(filename)
self.send_response(200)
self.send_header("Content-Type", content_type or "application/octet-stream")
self.end_headers()
with open(cfg['IMAGE_DIR'] + "/" + filename, 'rb') as file:
self.wfile.write(file.read())
#--
# Client config
#--
def send_clientconf(self):
self.send_response(200)
self.send_header("Content-type", "text/javascript")
self.end_headers()
response = f"""const ImgDuration = "{cfg["IMAGE_TIMEOUT"]}";"""
self.wfile.write(response.encode("utf-8"))
#--
# Image list
#--
def send_image_list(self):
files = os.listdir(cfg['IMAGE_DIR'])
images = [
f"/{cfg['IMAGE_DIR']}/{f}"
f"{f}"
for f in files
if f.lower().endswith((".jpg", ".jpeg", ".png", ".gif", ".webp"))
]
@@ -145,6 +189,7 @@ class SlideshowHandler(http.server.SimpleHTTPRequestHandler):
self.send_header("Content-Length", str(len(payload)))
self.end_headers()
self.wfile.write(payload)
#--
# Image info
#--
@@ -157,7 +202,17 @@ class SlideshowHandler(http.server.SimpleHTTPRequestHandler):
self.send_error(400, "Missing ?file= parameter")
return
filepath = filename.lstrip("/")
base_dir = Path(cfg["IMAGE_DIR"]).resolve()
print(base_dir)
file_path = (base_dir / filename).resolve()
try:
file_path.relative_to(base_dir)
except ValueError:
self.send_error(403, "Forbidden")
return
filepath = cfg['IMAGE_DIR'] +"/"+ filename
if not os.path.exists(filepath):
self.send_error(404, "File not found")