From 88ee66d5dd83870dad27267781b3d84386264beb Mon Sep 17 00:00:00 2001 From: Patrick McCarty Date: Sun, 24 Jan 2010 14:46:51 -0800 Subject: [PATCH] Fix #887: Use ly:string-percent-encode for textedit URIs. * Add an overloaded instance of String_convert::bin2hex optimized for converting single bytes to hex. * Add a new callback, ly:string-percent-encode, to be used for percent escaping paths in textedit URIs. This does the following: - Leave unreserved characters in textedit URIs unescaped. This includes 0-9, A-Z, a-z, and three punctuation characters (hyphen, underscore, and full-stop). - Leave the forward slash (/) unescaped, since it is used as a path delimiter. - Escape all other characters. Don't check for a null byte, since those likely won't sneak into a full pathname. * Use the callback function in the PS backend. --- flower/include/string-convert.hh | 1 + flower/string-convert.cc | 9 ++++++ lily/general-scheme.cc | 51 ++++++++++++++++++++++++++++++++ scm/output-ps.scm | 9 +++--- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/flower/include/string-convert.hh b/flower/include/string-convert.hh index 1277890929..21ec7f189e 100644 --- a/flower/include/string-convert.hh +++ b/flower/include/string-convert.hh @@ -22,6 +22,7 @@ public: static string pad_to (string s, int length); static string bool_string (bool b); static string bin2dec (string bin_string); + static string bin2hex (Byte bin_char); static string bin2hex (string bin_string); static string dec2bin (string str); static int bin2int (string bin_string); diff --git a/flower/string-convert.cc b/flower/string-convert.cc index ef64af25b6..03bb05b319 100644 --- a/flower/string-convert.cc +++ b/flower/string-convert.cc @@ -33,6 +33,15 @@ String_convert::bool_string (bool b) return string (b ? "true" : "false"); } +string +String_convert::bin2hex (Byte bin_char) +{ + string str; + str += to_string ((char) nibble2hex_byte (bin_char >> 4)); + str += to_string ((char) nibble2hex_byte (bin_char++)); + return str; +} + string String_convert::bin2hex (string bin_string) { diff --git a/lily/general-scheme.cc b/lily/general-scheme.cc index e1414dc602..76cd33ad78 100644 --- a/lily/general-scheme.cc +++ b/lily/general-scheme.cc @@ -224,6 +224,57 @@ LY_DEFINE (ly_string_substitute, "ly:string-substitute", return ly_string2scm (ss); } +bool +is_not_escape_character (Byte c) +{ + switch (c) + { + case '-': + case '.': + case '/': + case '0'...'9': + case 'A'...'Z': + case '_': + case 'a'...'z': + return true; + } + + return false; +} + +LY_DEFINE (ly_string_percent_encode, "ly:string-percent-encode", + 1, 0, 0, (SCM str), + "Encode all characters in string @var{str} with hexadecimal" + " percent escape sequences, with the following exceptions:" + " characters @code{-}, @code{.}, @code{/}, and @code{_}; and" + " characters in ranges @code{0-9}, @code{A-Z}, and @code{a-z}.") +{ + LY_ASSERT_TYPE (scm_is_string, str, 1); + + string orig_str = ly_scm2string (str); + string new_str = ""; + + vsize i = 0; + vsize n = orig_str.size (); + + while (i < n) + { + Byte cur = orig_str[i]; + + if (is_not_escape_character (cur)) + new_str += cur; + else + { + new_str += '%'; + new_str += String_convert::bin2hex (cur); + } + + i++; + } + + return ly_string2scm (new_str); +} + LY_DEFINE (ly_number_2_string, "ly:number->string", 1, 0, 0, (SCM s), "Convert @var{num} to a string without generating many decimals.") diff --git a/scm/output-ps.scm b/scm/output-ps.scm index bb34b1f3a6..5cedc80a05 100644 --- a/scm/output-ps.scm +++ b/scm/output-ps.scm @@ -162,12 +162,11 @@ (+ (car offset) (cdr x-ext)) (+ (cdr offset) (cdr y-ext)) - ;; TODO - ;;full escaping. + ;; Backslashes are not valid + ;; file URI path separators. + (ly:string-substitute + "\\" "/" (ly:string-percent-encode file)) - ;; backslash is interpreted by GS. - (ly:string-substitute "\\" "/" - (ly:string-substitute " " "%20" file)) (cadr location) (caddr location) (cadddr location)) -- 2.39.2