@matheusbsbs / matheus-bagliano / commits / 67976c65e0
Fork 0

gitweb: Fix handling of whitespace in generated links

When creating path_info part of link, don't encode space as '+', because while $cgi->param('foo') translates '+' in query param to ' ', neither $ENV{'PATH_INFO'} nor $cgi->path_info() do. This fixes the issue with pathnames with embedded whitespace and $feature{'pathinfo'} / path_info links. It is done by using newly introduced esc_path_info() instead of esc_url() in href() subroutine. Also while links are more clear not escaping space (' ') characters in generated links, the trailing space must be URI-encoded, otherwise would get discarded. Issue noticed thanks to John 'Warthog9' Hawley. Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jakub Narebski committed Dec 14, 2010 at 16:54 UTC 67976c65e0e931ad73ec21e5effe3dc204003df4
1 file changed +23 -8
gitweb/gitweb.perl
+23 -8
@@ -1186,7 +1186,7 @@ sub href {
1186 $href =~ s,/$,,;
1187
1188 # Then add the project name, if present
1189 - $href .= "/".esc_url($params{'project'});
1189 + $href .= "/".esc_path_info($params{'project'});
1190 delete $params{'project'};
1191
1192 # since we destructively absorb parameters, we keep this
@@ -1196,7 +1196,8 @@ sub href {
1196 # Summary just uses the project path URL, any other action is
1197 # added to the URL
1198 if (defined $params{'action'}) {
1199 - $href .= "/".esc_url($params{'action'}) unless $params{'action'} eq 'summary';
1199 + $href .= "/".esc_path_info($params{'action'})
1200 + unless $params{'action'} eq 'summary';
1201 delete $params{'action'};
1202 }
1203
@@ -1206,13 +1207,13 @@ sub href {
1207 || $params{'hash_parent'} || $params{'hash'});
1208 if (defined $params{'hash_base'}) {
1209 if (defined $params{'hash_parent_base'}) {
1209 - $href .= esc_url($params{'hash_parent_base'});
1210 + $href .= esc_path_info($params{'hash_parent_base'});
1211 # skip the file_parent if it's the same as the file_name
1212 if (defined $params{'file_parent'}) {
1213 if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) {
1214 delete $params{'file_parent'};
1215 } elsif ($params{'file_parent'} !~ /\.\./) {
1215 - $href .= ":/".esc_url($params{'file_parent'});
1216 + $href .= ":/".esc_path_info($params{'file_parent'});
1217 delete $params{'file_parent'};
1218 }
1219 }
@@ -1220,19 +1221,19 @@ sub href {
1221 delete $params{'hash_parent'};
1222 delete $params{'hash_parent_base'};
1223 } elsif (defined $params{'hash_parent'}) {
1223 - $href .= esc_url($params{'hash_parent'}). "..";
1224 + $href .= esc_path_info($params{'hash_parent'}). "..";
1225 delete $params{'hash_parent'};
1226 }
1227
1227 - $href .= esc_url($params{'hash_base'});
1228 + $href .= esc_path_info($params{'hash_base'});
1229 if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) {
1229 - $href .= ":/".esc_url($params{'file_name'});
1230 + $href .= ":/".esc_path_info($params{'file_name'});
1231 delete $params{'file_name'};
1232 }
1233 delete $params{'hash'};
1234 delete $params{'hash_base'};
1235 } elsif (defined $params{'hash'}) {
1235 - $href .= esc_url($params{'hash'});
1236 + $href .= esc_path_info($params{'hash'});
1237 delete $params{'hash'};
1238 }
1239
@@ -1265,6 +1266,9 @@ sub href {
1266 }
1267 $href .= "?" . join(';', @result) if scalar @result;
1268
1269 + # final transformation: trailing spaces must be escaped (URI-encoded)
1270 + $href =~ s/(\s+)$/CGI::escape($1)/e;
1271 +
1272 return $href;
1273 }
1274
@@ -1347,6 +1351,17 @@ sub esc_param {
1351 return $str;
1352 }
1353
1354 +# the quoting rules for path_info fragment are slightly different
1355 +sub esc_path_info {
1356 + my $str = shift;
1357 + return undef unless defined $str;
1358 +
1359 + # path_info doesn't treat '+' as space (specially), but '?' must be escaped
1360 + $str =~ s/([^A-Za-z0-9\-_.~();\/;:@&= +]+)/CGI::escape($1)/eg;
1361 +
1362 + return $str;
1363 +}
1364 +
1365 # quote unsafe chars in whole URL, so some characters cannot be quoted
1366 sub esc_url {
1367 my $str = shift;