diff --git a/lib/galaxy/tool_shed/util/shed_util_common.py b/lib/galaxy/tool_shed/util/shed_util_common.py index 648b9de4eaf..90b8079f8a0 100644 --- a/lib/galaxy/tool_shed/util/shed_util_common.py +++ b/lib/galaxy/tool_shed/util/shed_util_common.py @@ -1,5 +1,6 @@ import logging import re +from urllib.parse import quote from galaxy import util from galaxy.tool_shed.util import repository_util @@ -149,7 +150,10 @@ def set_image_paths(app, text, encoded_repository_id=None, tool_shed_repository= # We're in the tool shed. route_to_images = f"/repository/static/images/{encoded_repository_id}" elif tool_shed_repository and tool_id and tool_version: - route_to_images = f"shed_tool_static/{tool_shed_repository.tool_shed}/{tool_shed_repository.owner}/{tool_shed_repository.name}/{tool_id}/{tool_version}" + route_to_images = quote( + f"shed_tool_static/{tool_shed_repository.tool_shed}/{tool_shed_repository.owner}/{tool_shed_repository.name}/{tool_id}/{tool_version}", + safe="/", + ) else: raise Exception( "encoded_repository_id or tool_shed_repository and tool_id and tool_version must be provided" diff --git a/lib/galaxy/webapps/galaxy/controllers/shed_tool_static.py b/lib/galaxy/webapps/galaxy/controllers/shed_tool_static.py index 069ff8a8f01..6e88939b2ee 100644 --- a/lib/galaxy/webapps/galaxy/controllers/shed_tool_static.py +++ b/lib/galaxy/webapps/galaxy/controllers/shed_tool_static.py @@ -2,7 +2,10 @@ import logging import os from galaxy import web -from galaxy.exceptions import RequestParameterInvalidException +from galaxy.exceptions import ( + ObjectNotFound, + RequestParameterInvalidException, +) from galaxy.util.path import ( join, safe_contains, @@ -34,6 +37,8 @@ class ShedToolStatic(BaseUIController): """ guid = "/".join((shed, "repos", owner, repo, tool, version)) tool = trans.app.toolbox.get_tool(guid) + if tool is None: + raise ObjectNotFound(f"Could not find tool with guid '{guid}'.") repo_path = os.path.abspath(tool._repository_dir) found_path = None diff --git a/test/unit/tool_shed/test_shed_util_common.py b/test/unit/tool_shed/test_shed_util_common.py new file mode 100644 index 00000000000..3b49dfbec9b --- /dev/null +++ b/test/unit/tool_shed/test_shed_util_common.py @@ -0,0 +1,56 @@ +from types import SimpleNamespace + +from galaxy.tool_shed.util.shed_util_common import set_image_paths + + +def test_set_image_paths_encodes_special_characters_in_tool_id(): + tool_shed_repository = SimpleNamespace( + tool_shed="toolshed.g2.bx.psu.edu", + owner="devteam", + name="emboss_5", + ) + text = ".. image:: static/images/isochore.png" + result = set_image_paths( + app=None, + text=text, + tool_shed_repository=tool_shed_repository, + tool_id="EMBOSS: isochore47", + tool_version="5.0.0.1", + ) + assert "EMBOSS%3A%20isochore47" in result + assert "EMBOSS: isochore47" not in result + + +def test_set_image_paths_preserves_slashes_in_route(): + tool_shed_repository = SimpleNamespace( + tool_shed="toolshed.g2.bx.psu.edu", + owner="devteam", + name="emboss_5", + ) + text = ".. image:: isochore.png" + result = set_image_paths( + app=None, + text=text, + tool_shed_repository=tool_shed_repository, + tool_id="isochore", + tool_version="5.0.0", + ) + assert "shed_tool_static/toolshed.g2.bx.psu.edu/devteam/emboss_5/isochore/5.0.0/" in result + + +def test_set_image_paths_does_not_modify_http_urls(): + tool_shed_repository = SimpleNamespace( + tool_shed="toolshed.g2.bx.psu.edu", + owner="devteam", + name="emboss_5", + ) + text = ".. image:: https://example.com/image.png" + result = set_image_paths( + app=None, + text=text, + tool_shed_repository=tool_shed_repository, + tool_id="mytool", + tool_version="1.0", + ) + assert ".. image:: https://example.com/image.png" in result + assert "shed_tool_static" not in result