Percent-decode local image hrefs - #1121
Closed
teddytennant wants to merge 1 commit into
Closed
Conversation
An <image> href is an IRI, so SVG editors like Inkscape store non-ASCII file names percent-encoded. The default string resolver passed the href to the filesystem verbatim, so such images were never found and silently dropped with an 'is not a path to an image' warning. The raw path is still checked first, so file names containing a literal percent sign keep working.
Collaborator
|
Thanks, but that's not how it should be implemented. The fix should land into |
Author
|
Makes sense, closing this. Hand-rolling the decoding in the resolver was the wrong layer, and it only helps callers who use the default resolver anyway. I can put it in svgtypes instead and come back here with the SVG and PNG pair once that lands, if you want it. |
Collaborator
|
Yep. You can add SVG + PNG pair together with svgtypes bump. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1073.
The bug
An
<image>hrefis an IRI, so SVG editors percent-encode characters thatcan't appear in one. Inkscape, for example, writes a local file named
images/细节3-mine.pngas:ImageHrefResolver::default_string_resolverpassed that string straight toOptions::get_abs_pathand then toPath::exists, so it looked for a fileliterally named
%E7%BB%86%E8%8A%823-mine.png. That file doesn't exist, and theimage was silently dropped:
Reproducer (from the issue):
The same SVG with the decoded file name in the
hrefrenders fine.The fix
The default string resolver now percent-decodes the
hrefand retries, using asmall local decoder (no new dependency).
The raw path is still checked first and the decoded path is only used as a
fallback, so a file whose name genuinely contains a percent sign — including
one that happens to look like a valid escape sequence, e.g.
%41.svg— keepsresolving exactly as before. Nothing that works today changes behaviour; this
only adds a second attempt for hrefs that currently fail. Invalid escape
sequences are left as-is, and if the decoded bytes aren't valid UTF-8 the
original path is kept.
This is fixed in the resolver rather than in the parser because that's where the
href is turned into a filesystem path, and it keeps custom
ImageHrefResolvers free to do their own thing.Deliberately out of scope
data:URLs — they're handled byresolve_dataand never touch the filesystem.fontdb/resources_dirpath handling in general.+as space).usvg doesn't resolve URLs, and treating
+as a space would break existingfile names.
Verification
New tests in
crates/usvg/tests/parser.rs. Before the change:After:
cargo test --all --releaseis green: 1730 render tests, 29 usvg parser tests,31 usvg writer tests, 2 resvg unit tests, 1 doctest.
cargo fmt --all --check,.github/copyright.shandtyposare clean (the twotyposhits onmain—oppenin the changelog andplanedinparser/filter.rs— are pre-existingand untouched). Also built with an older toolchain to check nothing here needs a
recent compiler.