From 1a8d01dce9762036ffce7d330e58317cc5de6fb4 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Fri, 9 Oct 2026 16:32:20 +0100 Subject: [PATCH 1/5] :sparkles: Add a utility function to clean up a MIME type --- src/rogallo/mime_checks.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/rogallo/mime_checks.py b/src/rogallo/mime_checks.py index 2281c3c4..b5d131da 100644 --- a/src/rogallo/mime_checks.py +++ b/src/rogallo/mime_checks.py @@ -47,6 +47,23 @@ def is_gopher_mime_type(mime_type: str | None) -> bool: ) +############################################################################## +def clean_mime_type(mime_type: str | None) -> str | None: + """The MIME type cleaned of any parameters. + + Args: + mime_type: The MIME type to clean. + + Returns: + The MIME type cleaned of any parameters, or `None` if the input was + `None`. + """ + if mime_type is None: + return None + mime_type, _, _ = mime_type.partition(";") + return mime_type.strip().lower() + + ############################################################################## @cache def is_displayable_mime_type(mime_type: str | None) -> bool: @@ -58,9 +75,8 @@ def is_displayable_mime_type(mime_type: str | None) -> bool: Returns: `True` if the MIME type is displayable, `False` otherwise. """ - if mime_type is None: + if (mime_type := clean_mime_type(mime_type)) is None: return False - mime_type, _, _ = mime_type.partition(";") return mime_type.startswith("text/") or mime_type in { ItemType.MENU.mime_type, ItemType.INDEX_SEARCH.mime_type, From 2dd91c400312af3dceac6847b3eba89dd60d2652 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Fri, 9 Oct 2026 16:32:41 +0100 Subject: [PATCH 2/5] :hammer: Use the MIME type leaning function in the Document class --- src/rogallo/document.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/rogallo/document.py b/src/rogallo/document.py index 0e84e615..1605ff91 100644 --- a/src/rogallo/document.py +++ b/src/rogallo/document.py @@ -28,7 +28,7 @@ ############################################################################## # Local imports. -from .mime_checks import is_gemini_mime_type, is_gopher_mime_type +from .mime_checks import clean_mime_type, is_gemini_mime_type, is_gopher_mime_type from .types import RogalloLocation @@ -83,13 +83,9 @@ def __bool__(self) -> bool: """Return `True` if there is a location, `False` if not.""" return self.location is not None - @cached_property def mime_type_sans_parameters(self) -> str | None: """The MIME type cleaned of any parameters..""" - if self.mime_type is None: - return None - mime_type, _, _ = self.mime_type.partition(";") - return mime_type.strip().lower() + return clean_mime_type(self.mime_type) @property def is_gemtext(self) -> bool: From 83826fc3f599642c09bd542f269c0d686aa5ac5e Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Fri, 9 Oct 2026 16:33:01 +0100 Subject: [PATCH 3/5] :sparkles: Clean up a MIME type before handling it --- src/rogallo/screens/main/unsupported.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/rogallo/screens/main/unsupported.py b/src/rogallo/screens/main/unsupported.py index 34dddb5e..2ed69146 100644 --- a/src/rogallo/screens/main/unsupported.py +++ b/src/rogallo/screens/main/unsupported.py @@ -23,6 +23,7 @@ save_trusted_schemes, ) from ...messages import DownloadURI +from ...mime_checks import clean_mime_type from ..confirm_unsupported import ConfirmUnsupportedURI from .local_messages import OpenUnsupportedMIMEType, OpenUnsupportedURI @@ -91,17 +92,17 @@ async def maybe_open_unsupported_mime_type( ) return + mime_type = clean_mime_type(message.mime_type) or "application/octet-stream" + # If the MIME type isn't trusted, let's see what the user wants to # do about it. if not ( - open_uri := ( - message.mime_type in (trusted_mime_types := load_trusted_mime_types()) - ) + open_uri := (mime_type in (trusted_mime_types := load_trusted_mime_types())) ): match await owner.app.push_screen_wait( ConfirmUnsupportedURI( str(message.location), - f"The MIME type '{message.mime_type}' is not supported by Rogallo. " + f"The MIME type '{mime_type}' is not supported by Rogallo. " "Do you want to open the location in your external browser?", allow_download=not isinstance(message.location, Path), ) @@ -110,7 +111,7 @@ async def maybe_open_unsupported_mime_type( open_uri = True case "always": open_uri = True - trusted_mime_types.add(message.mime_type) + trusted_mime_types.add(mime_type) save_trusted_mime_types(trusted_mime_types) case "download": open_uri = False From 44e091e01ce72b67485b554788b2327064d09aaa Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Fri, 9 Oct 2026 16:35:56 +0100 Subject: [PATCH 4/5] :books: Update the ChangeLog --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index 1e534bf0..4f5f8bcb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,6 +7,8 @@ - Added the ability to copy a link, as Gemtext, to the clipboard (`gemtext_link.copy_link_as_gemtext`). ([#492](https://github.com/davep/rogallo/pull/492)) +- Fixed MIME type checks to ensure parameters are ignored when performing + the check. ([#495](https://github.com/davep/rogallo/pull/495)) ## v3.1.0 From deaef97a75a9a73d131781eb7a34910b1d2378f7 Mon Sep 17 00:00:00 2001 From: Dave Pearson Date: Fri, 9 Oct 2026 16:41:26 +0100 Subject: [PATCH 5/5] :bug: Add missing @property I'd stepped back from it being a cached_property, but forgot to make it a simple property. --- src/rogallo/document.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rogallo/document.py b/src/rogallo/document.py index 1605ff91..00d66a94 100644 --- a/src/rogallo/document.py +++ b/src/rogallo/document.py @@ -83,6 +83,7 @@ def __bool__(self) -> bool: """Return `True` if there is a location, `False` if not.""" return self.location is not None + @property def mime_type_sans_parameters(self) -> str | None: """The MIME type cleaned of any parameters..""" return clean_mime_type(self.mime_type)