diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index d42b6e68..796c08aa 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -254,7 +254,7 @@ class Node: try: self._width, self._height, filetype = self._project.controller.symbols.get_size(val) except (ValueError, OSError) as e: - log.error("Could not write symbol: {}".format(e)) + log.error("Could not set symbol: {}".format(e)) # If symbol is invalid we replace it by the default self.symbol = ":/symbols/computer.svg" if self._label is None: diff --git a/gns3server/handlers/api/controller/symbol_handler.py b/gns3server/handlers/api/controller/symbol_handler.py index 3d378766..92e2d12a 100644 --- a/gns3server/handlers/api/controller/symbol_handler.py +++ b/gns3server/handlers/api/controller/symbol_handler.py @@ -60,7 +60,7 @@ class SymbolHandler: r"/symbols/{symbol_id:.+}/raw", description="Write the symbol file", status_codes={ - 200: "Symbol returned" + 200: "Symbol written" }, raw=True) def upload(request, response): @@ -78,6 +78,7 @@ class SymbolHandler: f.write(chunk) except (UnicodeEncodeError, OSError) as e: raise aiohttp.web.HTTPConflict(text="Could not write symbol file '{}': {}".format(path, e)) + # Reset the symbol list controller.symbols.list() response.set_status(204) diff --git a/gns3server/utils/picture.py b/gns3server/utils/picture.py index d7c3103b..3e9fd416 100644 --- a/gns3server/utils/picture.py +++ b/gns3server/utils/picture.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import re import io import struct from xml.etree.ElementTree import ElementTree, ParseError @@ -103,13 +104,21 @@ def get_size(data, default_width=0, default_height=0): root = tree.getroot() try: - width_attr = root.attrib.get("width", "0") - height_attr = root.attrib.get("height", "0") + width_attr = root.attrib.get("width", "100%") + height_attr = root.attrib.get("height", "100%") if width_attr.endswith("%") or height_attr.endswith("%"): # check to viewBox attribute if width or height value is a percentage - _, _, width_attr, height_attr = root.attrib.get("viewBox").split() + viewbox = root.attrib.get("viewBox") + if not viewbox: + raise ValueError("Invalid SVG file: missing viewBox attribute") + _, _, viewbox_width, viewbox_height = re.split(r'[\s,]+', viewbox) + if width_attr.endswith("%"): + width = _svg_convert_size(viewbox_width, width_attr) else: width = _svg_convert_size(width_attr) + if height_attr.endswith("%"): + height = _svg_convert_size(viewbox_height, height_attr) + else: height = _svg_convert_size(height_attr) except (AttributeError, IndexError) as e: raise ValueError("Invalid SVG file: {}".format(e)) @@ -117,11 +126,12 @@ def get_size(data, default_width=0, default_height=0): return width, height, filetype -def _svg_convert_size(size): +def _svg_convert_size(size, percent=None): """ Convert svg size to the px version :param size: String with the size + :param percent: String with the percentage, None = 100% """ # https://www.w3.org/TR/SVG/coords.html#Units @@ -133,8 +143,11 @@ def _svg_convert_size(size): "in": 90, "px": 1 } - if len(size) > 3: + factor = 1.0 + if len(size) >= 3: if size[-2:] in conversion_table: - return round(float(size[:-2]) * conversion_table[size[-2:]]) - - return round(float(size)) + factor = conversion_table[size[-2:]] + size = size[:-2] + if percent: + factor *= float(percent.rstrip("%")) / 100.0 + return round(float(size) * factor)