Skip to content

Commit 2335bf5

Browse files
committed
Fix decoding percent characters in URL issue
According to CommonMark specification, we should not decode percent encoded characters in URL except control characters and spaces.
1 parent d51c469 commit 2335bf5

3 files changed

Lines changed: 35 additions & 1 deletion

File tree

‎CHANGES.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Fix list item bound calculation when tab indentation is used [GH-904][]
1818
- Fix `markdown-heading-at-point` at the end of line [GH-912][]
1919
- Catch an exception when `scan-sexp` fails [GH-917][]
20+
- `markdown-link-at-pos` should decode both control characters and spaces [GH-921][]
2021

2122
* Improvements:
2223
- Support drag and drop features on Windows and multiple files' drag and drop
@@ -34,6 +35,7 @@
3435
[gh-910]: https://github.com/jrblevin/markdown-mode/issues/910
3536
[gh-912]: https://github.com/jrblevin/markdown-mode/issues/912
3637
[gh-917]: https://github.com/jrblevin/markdown-mode/issues/917
38+
[gh-921]: https://github.com/jrblevin/markdown-mode/issues/921
3739

3840
# Markdown Mode 2.7
3941

‎markdown-mode.el‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
(require 'thingatpt)
3939
(require 'cl-lib)
4040
(require 'url-parse)
41+
(require 'url-util)
4142
(require 'button)
4243
(require 'color)
4344
(require 'rx)
@@ -8167,6 +8168,27 @@ See `markdown-wiki-link-p' for more information."
81678168
(thing-at-point-looking-at markdown-regex-uri)
81688169
(thing-at-point-looking-at markdown-regex-angle-uri))))))
81698170

8171+
(defun markdown--unhex-url-string (url)
8172+
"Unhex control characters and spaces in URL.
8173+
This is similar to `url-unhex-string' but this doesn't unhex all percent-encoded
8174+
characters."
8175+
(let ((str (or url ""))
8176+
(tmp "")
8177+
(case-fold-search t))
8178+
(while (string-match "%\\([01][0-9a-f]\\|20\\)" str)
8179+
(let* ((start (match-beginning 0))
8180+
(ch1 (url-unhex (elt str (+ start 1))))
8181+
(code (+ (* 16 ch1)
8182+
(url-unhex (elt str (+ start 2))))))
8183+
(setq tmp (concat
8184+
tmp (substring str 0 start)
8185+
(cond
8186+
((or (= code ?\n) (= code ?\r))
8187+
" ")
8188+
(t (byte-to-string code))))
8189+
str (substring str (match-end 0)))))
8190+
(concat tmp str)))
8191+
81708192
(defun markdown-link-at-pos (pos)
81718193
"Return properties of link or image at position POS.
81728194
Value is a list of elements describing the link:
@@ -8202,7 +8224,7 @@ Value is a list of elements describing the link:
82028224
(setq url (match-string-no-properties 1 destination-part)
82038225
title (substring (match-string-no-properties 2 destination-part) 1 -1)))
82048226
(t (setq url destination-part)))
8205-
(setq url (url-unhex-string url))))
8227+
(setq url (markdown--unhex-url-string url))))
82068228
;; Reference link at point.
82078229
((thing-at-point-looking-at markdown-regex-link-reference)
82088230
(setq bang (match-string-no-properties 1)

‎tests/markdown-test.el‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5703,6 +5703,16 @@ A link can contain spaces if it is wrapped with angle brackets"
57035703
(markdown-test-string "[text](<bar%20baz.md>)"
57045704
(should (equal (nth 3 (markdown-link-at-pos (point))) "bar baz.md"))))
57055705

5706+
(ert-deftest test-markdown-link/inline-link-with-percent-encoded-characters ()
5707+
"Test URL decoding in `markdown-link-at-pos'.
5708+
It should decode only control characters and spaces in URL according
5709+
to CommonMark specification.
5710+
5711+
Details: https://github.com/jrblevin/markdown-mode/issues/921"
5712+
5713+
(markdown-test-string "[text](bar%2F%30baz.md)"
5714+
(should (string= (nth 3 (markdown-link-at-pos (point))) "bar%2F%30baz.md"))))
5715+
57065716
(ert-deftest test-markdown-link/reference-link-at-pos ()
57075717
"Test `markdown-link-at-pos' return values with a reference link."
57085718
(markdown-test-string "[text][ref]"

0 commit comments

Comments
 (0)