Enforce webp for remote images

This commit is contained in:
Mark Qvist
2026-09-05 22:33:03 +02:00
parent 3028301fb1
commit 7bd3a3a888
3 changed files with 19 additions and 11 deletions
+2 -2
View File
@@ -668,7 +668,7 @@ class Browser:
if hasattr(o, "_contained_image"): o = o._contained_image
if hasattr(o, "image_url"):
resolved_image = self.resolve_image(o.image_url)
if resolved_image: o.load(resolved_image)
if resolved_image: o.load(resolved_image, remote_source=True)
else:
image = { "widget": o, "id": o.image_id, "url": o.image_url, "refresh": None, "updated": None,
"update_requested": None, "request_id": None, "link": None, "failed": False, "pr_throttle": 0,
@@ -858,7 +858,7 @@ class Browser:
shutil.move(file_handle.name, file_destination)
resolved_path = self.resolve_image(url)
if resolved_path: w.load(resolved_path)
if resolved_path: w.load(resolved_path, remote_source=True)
except Exception as e:
RNS.log("Error while handling image response: "+str(e), RNS.LOG_ERROR)
+12 -7
View File
@@ -69,7 +69,7 @@ def parse_image_header(data):
# (Kitty's f=100 data format). The dimensions are used only for layout.
# WebP sources are converted transparently to PNG on load.
class ImageData(object):
def __init__(self, path, max_bytes=MAX_PAYLOAD_BYTES):
def __init__(self, path, max_bytes=MAX_PAYLOAD_BYTES, remote_source=False):
self.path = path
self.error = None
self.format = None
@@ -81,15 +81,15 @@ class ImageData(object):
try:
with open(path, "rb") as f: data = f.read()
except OSError as e:
self.error = "could not read file: %s" % e
self.error = "Could not read file: %s" % e
return
if len(data) > max_bytes:
self.error = "file too large (%.1f MiB > %d MiB)" % (len(data) / (1024 * 1024), max_bytes // (1024 * 1024))
self.error = "File too large (%.1f MiB > %d MiB)" % (len(data) / (1024 * 1024), max_bytes // (1024 * 1024))
return
if not data:
self.error = "empty file"
self.error = "Empty file"
return
try: self.format, self.width, self.height = parse_image_header(data)
@@ -102,17 +102,22 @@ class ImageData(object):
from . import _webp
png = _webp.convert_webp_to_png(data)
if png is None:
self.error = "webp conversion failed (no working backend available)"
self.error = "WebP conversion failed (no working backend available)"
return
if len(png) > MAX_CONVERTED_PAYLOAD_BYTES:
self.error = "converted image too large (%.1f MiB > %d MiB)" % (len(png) / (1024 * 1024), MAX_CONVERTED_PAYLOAD_BYTES // (1024 * 1024))
self.error = "Converted image too large (%.1f MiB > %d MiB)" % (len(png) / (1024 * 1024), MAX_CONVERTED_PAYLOAD_BYTES // (1024 * 1024))
return
self.data = png
self.format = "PNG"
self.conversion_backend = _webp.last_backend()
else: self.data = data
else:
if remote_source:
self.error = "Invalid image format, remote images must be WebP"
return
else:
self.data = data
# Content key for de-duplication: identical bytes = same key, so
# the same image transmitted once can be placed many times.
+5 -2
View File
@@ -86,12 +86,12 @@ class ImageWidget(urwid.Widget):
super().__init__()
if self.path: self.load()
def load(self, path=None):
def load(self, path=None, remote_source=False):
if path: self.path = path
if self.path:
from ._imagedata import ImageData
self._ti_path = os.path.abspath(os.fspath(self.path))
self._ti_data = ImageData(self._ti_path)
self._ti_data = ImageData(self._ti_path, remote_source=remote_source)
if self._ti_data.ok:
# Register with the image store (de-duplicates identical data
@@ -99,6 +99,9 @@ class ImageWidget(urwid.Widget):
self._ti_key = self._ti_data.key
image_store.register(self._ti_key, self._ti_data.data)
self._invalidate()
else:
error_msg = self._ti_data.error or "Unknown error"
self.notice(f"Error: {error_msg}")
def notice(self, msg=""):
if not msg: self._notice = None