From 302f09d54a6ea30a9b56f8bacc22e236bde997c6 Mon Sep 17 00:00:00 2001 From: Guillaume Ayoub Date: Mon, 3 Jan 2022 14:14:36 +0100 Subject: [PATCH] Always use absolute paths to get hrefs in SVG Also be more fault-tolerant when trying to render use tags. Fix #1531. --- weasyprint/svg/__init__.py | 8 ++++++-- weasyprint/svg/defs.py | 8 ++++---- weasyprint/svg/images.py | 4 +--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/weasyprint/svg/__init__.py b/weasyprint/svg/__init__.py index 5430a90ffb..e62ff52c6d 100644 --- a/weasyprint/svg/__init__.py +++ b/weasyprint/svg/__init__.py @@ -12,6 +12,7 @@ from cssselect2 import ElementWrapper +from ..urls import get_url_attribute from .bounding_box import bounding_box, is_valid_bounding_box from .css import parse_declarations, parse_stylesheets from .defs import ( @@ -175,9 +176,12 @@ def get_viewbox(self): return tuple( float(number) for number in normalize(viewbox).split()) - def get_href(self): + def get_href(self, base_url): """Get the href attribute, with or without a namespace.""" - return self.get('{http://www.w3.org/1999/xlink}href', self.get('href')) + for attr_name in ('{http://www.w3.org/1999/xlink}href', 'href'): + url = get_url_attribute(self, attr_name, base_url) + if url: + return url @staticmethod def process_whitespace(string, preserve): diff --git a/weasyprint/svg/defs.py b/weasyprint/svg/defs.py index 132a00dd47..9ed471d797 100644 --- a/weasyprint/svg/defs.py +++ b/weasyprint/svg/defs.py @@ -25,14 +25,14 @@ def use(svg, node, font_size): if attribute in node.attrib: del node.attrib[attribute] - parsed_url = parse_url(node.get_href()) - if parsed_url.fragment and not parsed_url.path: + parsed_url = parse_url(node.get_href(svg.url)) + if parsed_url.fragment and parsed_url[:3] == parse_url(svg.url)[:3]: if parsed_url.fragment in svg.use_cache: tree = svg.use_cache[parsed_url.fragment].copy() else: try: tree = svg.tree.get_child(parsed_url.fragment).copy() - except AttributeError: + except Exception: return else: svg.use_cache[parsed_url.fragment] = tree @@ -41,7 +41,7 @@ def use(svg, node, font_size): try: bytestring_svg = svg.url_fetcher(url) use_svg = SVG(bytestring_svg, url) - except TypeError: + except Exception: return else: use_svg.get_intrinsic_size(font_size) diff --git a/weasyprint/svg/images.py b/weasyprint/svg/images.py index d0307d4a1e..e40b414486 100644 --- a/weasyprint/svg/images.py +++ b/weasyprint/svg/images.py @@ -6,8 +6,6 @@ """ -from urllib.parse import urljoin - from .utils import preserve_ratio @@ -34,7 +32,7 @@ def image(svg, node, font_size): x, y = svg.point(node.get('x'), node.get('y'), font_size) svg.stream.transform(e=x, f=y) base_url = node.get('{http://www.w3.org/XML/1998/namespace}base') - url = urljoin(base_url or svg.url, node.get_href()) + url = node.get_href(base_url or svg.url) image = svg.context.get_image_from_uri(url=url, forced_mime_type='image/*') if image is None: return