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:
4 files changed
+65
-7
No files matched your search
@@ -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")
|
||||
|
||||
Reference in new issue
Block a user