{"thread":{"id":"26050","subject":"[PATCH] gitweb: Fix handling of whitespace in generated links","startedAt":"2010-12-14T15:54:31Z","lastAt":"2010-12-14T15:54:31Z","messageCount":1,"participants":["Jakub Narebski"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"158058","messageId":"20101214155331.23853.71834.stgit@localhost.localdomain","threadId":"26050","inReplyTo":null,"subject":"[PATCH] gitweb: Fix handling of whitespace in generated links","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-12-14T15:54:31Z","receivedAt":"2010-12-14T15:54:31Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"When creating path_info part of link, don't encode space as '+', because\nwhile $cgi->param('foo') translates '+' in query param to ' ', neither\n$ENV{'PATH_INFO'} nor $cgi->path_info() do.\n\nThis fixes the issue with pathnames with embedded whitespace and\n$feature{'pathinfo'} / path_info links.  It is done bu using newly\nintroduced esc_path_info() instead of esc_url() in href() subroutine.\n\nAlso while links are more clear not escaping space (' ') characters in\ngenerated links, the trailing space must be URI-encoded, otherwise would\nget discarded.\n\nIssue noticed thanks to John 'Warthog9' Hawley.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nJ.H., this fixes the noticed issue.\n\n gitweb/gitweb.perl |   31 +++++++++++++++++++++++--------\n 1 files changed, 23 insertions(+), 8 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 3d0dd4d..f5bfb87 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1230,7 +1230,7 @@ sub href {\n \t\t$href =~ s,/$,,;\n \n \t\t# Then add the project name, if present\n-\t\t$href .= \"/\".esc_url($params{'project'});\n+\t\t$href .= \"/\".esc_path_info($params{'project'});\n \t\tdelete $params{'project'};\n \n \t\t# since we destructively absorb parameters, we keep this\n@@ -1240,7 +1240,8 @@ sub href {\n \t\t# Summary just uses the project path URL, any other action is\n \t\t# added to the URL\n \t\tif (defined $params{'action'}) {\n-\t\t\t$href .= \"/\".esc_url($params{'action'}) unless $params{'action'} eq 'summary';\n+\t\t\t$href .= \"/\".esc_path_info($params{'action'})\n+\t\t\t\tunless $params{'action'} eq 'summary';\n \t\t\tdelete $params{'action'};\n \t\t}\n \n@@ -1250,13 +1251,13 @@ sub href {\n \t\t\t|| $params{'hash_parent'} || $params{'hash'});\n \t\tif (defined $params{'hash_base'}) {\n \t\t\tif (defined $params{'hash_parent_base'}) {\n-\t\t\t\t$href .= esc_url($params{'hash_parent_base'});\n+\t\t\t\t$href .= esc_path_info($params{'hash_parent_base'});\n \t\t\t\t# skip the file_parent if it's the same as the file_name\n \t\t\t\tif (defined $params{'file_parent'}) {\n \t\t\t\t\tif (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) {\n \t\t\t\t\t\tdelete $params{'file_parent'};\n \t\t\t\t\t} elsif ($params{'file_parent'} !~ /\\.\\./) {\n-\t\t\t\t\t\t$href .= \":/\".esc_url($params{'file_parent'});\n+\t\t\t\t\t\t$href .= \":/\".esc_path_info($params{'file_parent'});\n \t\t\t\t\t\tdelete $params{'file_parent'};\n \t\t\t\t\t}\n \t\t\t\t}\n@@ -1264,19 +1265,19 @@ sub href {\n \t\t\t\tdelete $params{'hash_parent'};\n \t\t\t\tdelete $params{'hash_parent_base'};\n \t\t\t} elsif (defined $params{'hash_parent'}) {\n-\t\t\t\t$href .= esc_url($params{'hash_parent'}). \"..\";\n+\t\t\t\t$href .= esc_path_info($params{'hash_parent'}). \"..\";\n \t\t\t\tdelete $params{'hash_parent'};\n \t\t\t}\n \n-\t\t\t$href .= esc_url($params{'hash_base'});\n+\t\t\t$href .= esc_path_info($params{'hash_base'});\n \t\t\tif (defined $params{'file_name'} && $params{'file_name'} !~ /\\.\\./) {\n-\t\t\t\t$href .= \":/\".esc_url($params{'file_name'});\n+\t\t\t\t$href .= \":/\".esc_path_info($params{'file_name'});\n \t\t\t\tdelete $params{'file_name'};\n \t\t\t}\n \t\t\tdelete $params{'hash'};\n \t\t\tdelete $params{'hash_base'};\n \t\t} elsif (defined $params{'hash'}) {\n-\t\t\t$href .= esc_url($params{'hash'});\n+\t\t\t$href .= esc_path_info($params{'hash'});\n \t\t\tdelete $params{'hash'};\n \t\t}\n \n@@ -1309,6 +1310,9 @@ sub href {\n \t}\n \t$href .= \"?\" . join(';', @result) if scalar @result;\n \n+\t# final transformation: trailing spaces must be escaped (URI-encoded)\n+\t$href =~ s/(\\s+)$/CGI::escape($1)/e;\n+\n \treturn $href;\n }\n \n@@ -1391,6 +1395,17 @@ sub esc_param {\n \treturn $str;\n }\n \n+# the quoting rules for path_info fragment are slightly different\n+sub esc_path_info {\n+\tmy $str = shift;\n+\treturn undef unless defined $str;\n+\n+\t# path_info doesn't treat '+' as space (specially), but '?' must be escaped\n+\t$str =~ s/([^A-Za-z0-9\\-_.~();\\/;:@&= +]+)/CGI::escape($1)/eg;\n+\n+\treturn $str;\n+}\n+\n # quote unsafe chars in whole URL, so some characters cannot be quoted\n sub esc_url {\n \tmy $str = shift;\n"}]}