FIX: Allow SVG uploads if dimensions are a fraction of a unit (#13409)

FIX: Allow SVG uploads if dimensions are a fraction of a unit (#13409)

  • FIX: Allow SVG uploads if dimensions are a fraction of a unit

UploadCreator counts the number of pixels in an file to determine if it is valid. pixels is calculated by multiplying the width and height of the image, as determined by FastImage.

SVG files can have their width/height expressed in a variety of different units of measurement. For example, ‘px’, ‘in’, ‘cm’, ‘mm’, ‘pt’, ‘pc’, etc are all valid within SVG files. If an image has a width of 0.5in, FastImage may interpret this as being a width of 0, meaning it will report the size as being 0.

However, we don’t need to concern ourselves with the number of ‘pixels’ in a SVG files, as that is irrelevant for this file format, so we can skip over the check for pixels == 0 when processing this file type.

  • DEV: Speed up getting SVG dimensions

The -ping flag prevents the entire image from being rasterized before a result is returned. See:

ImageMagick - Command-line Options

diff --git a/lib/upload_creator.rb b/lib/upload_creator.rb
index 942b891..bcb7242 100644
--- a/lib/upload_creator.rb
+++ b/lib/upload_creator.rb
@@ -131,7 +131,7 @@ class UploadCreator
 
           begin
             w, h = Discourse::Utils
-              .execute_command("identify", "-format", "%w %h", @file.path, timeout: Upload::MAX_IDENTIFY_SECONDS)
+              .execute_command("identify", "-ping", "-format", "%w %h", @file.path, timeout: Upload::MAX_IDENTIFY_SECONDS)
               .split(' ')
           rescue
             # use default 0, 0
@@ -194,7 +194,7 @@ class UploadCreator
       @upload.errors.add(:base, I18n.t("upload.images.not_supported_or_corrupted"))
     elsif filesize <= 0
       @upload.errors.add(:base, I18n.t("upload.empty"))
-    elsif pixels == 0
+    elsif pixels == 0 && @image_info.type.to_s != 'svg'
       @upload.errors.add(:base, I18n.t("upload.images.size_not_found"))
     elsif max_image_pixels > 0 && pixels >= max_image_pixels * 2
       @upload.errors.add(:base, I18n.t("upload.images.larger_than_x_megapixels", max_image_megapixels: SiteSetting.max_image_megapixels * 2))
diff --git a/spec/fixtures/images/massive.svg b/spec/fixtures/images/massive.svg
new file mode 100644
index 0000000..55e3a03
--- /dev/null
+++ b/spec/fixtures/images/massive.svg
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg
+  xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"
+  width="120.0in" height="120.99in"
+  viewBox="0 0 1200 900"
+>
+  <line x1="20" x2="1000" y1="20" y2="700" stroke="#ff88ff" stroke-width="25"/>
+</svg>
diff --git a/spec/fixtures/images/pencil.svg b/spec/fixtures/images/pencil.svg
deleted file mode 100644
index a16d2a9..0000000
--- a/spec/fixtures/images/pencil.svg
+++ /dev/null
@@ -1,245 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://creativecommons.org/ns#"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="8in"
-   height="12in"
-   viewBox="0 0 210 297"
-   version="1.1"
-   id="svg8"
-   inkscape:version="0.92.3 (2405546, 2018-03-11)"
-   sodipodi:docname="drawingpencil.svg">
-  <defs
-     id="defs2" />
-  <sodipodi:namedview
-     id="base"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.35"
-     inkscape:cx="446.80634"
-     inkscape:cy="475.54119"
-     inkscape:document-units="mm"
-     inkscape:current-layer="g964"
-     showgrid="false"
-     showguides="true"
-     inkscape:guide-bbox="true"
-     inkscape:snap-global="false"
-     inkscape:window-width="1280"
-     inkscape:window-height="705"
-     inkscape:window-x="-8"
-     inkscape:window-y="-8"
-     inkscape:window-maximized="1">
-    <sodipodi:guide
-       position="-148.16667,180.67263"
-       orientation="1,0"
-       id="guide825"
-       inkscape:locked="false" />
-    <sodipodi:guide
-       position="-204.88879,167.72065"
-       orientation="1,0"
-       id="guide829"
-       inkscape:locked="false" />
-    <sodipodi:guide
-       position="-331.86309,-5.2916668"
-       orientation="1,0"
-       id="guide929"
-       inkscape:locked="false" />
-  </sodipodi:namedview>
-  <metadata
-     id="metadata5">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1">
-    <g
-       id="g1389"
-       transform="translate(112.6369,-4.5357143)">
-      <g
-         transform="matrix(0.39765029,-0.37613964,0.40337233,0.37080392,-33.707976,96.609766)"
-         id="g964">
-        <g
-           id="g866">
-          <path
-             inkscape:export-ydpi="362.10001"
-             inkscape:export-xdpi="362.10001"
-             sodipodi:nodetypes="ccccccccccccc"
-             inkscape:connector-curvature="0"
-             id="path827"
-             d="m -171.39994,58.522452 4.56312,-0.517578 -96.41169,41.09967 92.39126,41.964876 0.0103,0.65784 1.02112,-0.18965 0.41703,0.18965 6.80757,-1.02363 213.349901,-40.08755 -218.860531,-42.072367 0.0119,-0.777213 16.14253,2.05244 z"
-             style="opacity:1;fill:#ffe680;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
-          <path
-             inkscape:export-ydpi="362.10001"
-             inkscape:export-xdpi="362.10001"
-             sodipodi:nodetypes="cccccc"
-             inkscape:connector-curvature="0"
-             id="path909"
-             d="m -167.29418,58.090286 -1.96525,-0.130741 -94.74512,40.389265 0.46973,0.213426 203.965548,27.214284 z"
-             style="opacity:1;fill:#d4aa00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
-          <path
-             inkscape:export-ydpi="362.10001"
-             inkscape:export-xdpi="362.10001"
-             transform="scale(0.26458333)"
-             id="path833"
-             d="m -648.57227,534.84766 v 1.95703 H 522.85742 V 219.66211 H -639.06836 l 85.92578,47.42969 -89.9707,54.27734 91.11328,50.29297 -87.39453,52.72461 90.82226,50.13281 z"
-             style="fill:#ffcc00;fill-rule:evenodd;stroke:#000000;stroke-width:0.99999994"
-             inkscape:connector-curvature="0" />
-          <path
-             inkscape:export-ydpi="362.10001"
-             inkscape:export-xdpi="362.10001"
-             inkscape:connector-curvature="0"
-             id="path841"
-             d="m -230.72987,84.444087 -4.91908,2.137336 -28.12903,12.220958 27.87271,12.660209 3.58428,1.62781 a 25.702381,21.544643 0 0 0 7.23057,-12.98629 l 0.0264,-0.243397 a 25.702381,21.544643 0 0 0 -5.6658,-15.416626 z m -4.1367,3.635951 a 20.410631,23.056417 0 0 1 0.60771,1.484665 20.410631,23.056417 0 0 0 -0.60771,-1.484665 z"
-             style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
-          <path
-             inkscape:export-ydpi="362.10001"
-             inkscape:export-xdpi="362.10001"
-             transform="scale(0.26458333)"
-             id="path870"
-             d="M 282.85742,219.66211 H 116.00195 -17.142578 V 536.80469 H 98.123047 282.85742 Z"
-             style="fill:#ffcc00;fill-rule:evenodd;stroke-width:0.99999994"
-             inkscape:connector-curvature="0" />
-          <path
-             inkscape:export-ydpi="362.10001"
-             inkscape:export-xdpi="362.10001"
-             sodipodi:nodetypes="ccaccccccczcccccccaac"
-             inkscape:connector-curvature="0"
-             id="path855"

[... diff too long, it was truncated ...]

GitHub sha: fbfd1fd80b03b83670ec179c5daa102de253b5be

This commit appears in #13409 which was approved by eviltrout. It was merged by jbrw.