From: Junio C Hamano Date: Wed, 19 Jan 2011 16:26:04 +0000 (-0800) Subject: Merge branch 'jn/maint-gitweb-pathinfo-fix' into maint X-Git-Tag: v1.7.4-rc3~5^2~6 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/305579f78d3a1bd5fa7a9ce2038b7f7afca8b1e6?ds=inline;hp=-c Merge branch 'jn/maint-gitweb-pathinfo-fix' into maint * jn/maint-gitweb-pathinfo-fix: gitweb: Fix handling of whitespace in generated links --- 305579f78d3a1bd5fa7a9ce2038b7f7afca8b1e6 diff --combined gitweb/gitweb.perl index 59b2e08b98,75cef245a2..fda9d30f37 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@@ -1186,7 -1186,7 +1186,7 @@@ sub href $href =~ s,/$,,; # Then add the project name, if present - $href .= "/".esc_url($params{'project'}); + $href .= "/".esc_path_info($params{'project'}); delete $params{'project'}; # since we destructively absorb parameters, we keep this @@@ -1196,7 -1196,8 +1196,8 @@@ # Summary just uses the project path URL, any other action is # added to the URL if (defined $params{'action'}) { - $href .= "/".esc_url($params{'action'}) unless $params{'action'} eq 'summary'; + $href .= "/".esc_path_info($params{'action'}) + unless $params{'action'} eq 'summary'; delete $params{'action'}; } @@@ -1206,13 -1207,13 +1207,13 @@@ || $params{'hash_parent'} || $params{'hash'}); if (defined $params{'hash_base'}) { if (defined $params{'hash_parent_base'}) { - $href .= esc_url($params{'hash_parent_base'}); + $href .= esc_path_info($params{'hash_parent_base'}); # skip the file_parent if it's the same as the file_name if (defined $params{'file_parent'}) { if (defined $params{'file_name'} && $params{'file_parent'} eq $params{'file_name'}) { delete $params{'file_parent'}; } elsif ($params{'file_parent'} !~ /\.\./) { - $href .= ":/".esc_url($params{'file_parent'}); + $href .= ":/".esc_path_info($params{'file_parent'}); delete $params{'file_parent'}; } } @@@ -1220,19 -1221,19 +1221,19 @@@ delete $params{'hash_parent'}; delete $params{'hash_parent_base'}; } elsif (defined $params{'hash_parent'}) { - $href .= esc_url($params{'hash_parent'}). ".."; + $href .= esc_path_info($params{'hash_parent'}). ".."; delete $params{'hash_parent'}; } - $href .= esc_url($params{'hash_base'}); + $href .= esc_path_info($params{'hash_base'}); if (defined $params{'file_name'} && $params{'file_name'} !~ /\.\./) { - $href .= ":/".esc_url($params{'file_name'}); + $href .= ":/".esc_path_info($params{'file_name'}); delete $params{'file_name'}; } delete $params{'hash'}; delete $params{'hash_base'}; } elsif (defined $params{'hash'}) { - $href .= esc_url($params{'hash'}); + $href .= esc_path_info($params{'hash'}); delete $params{'hash'}; } @@@ -1265,6 -1266,9 +1266,9 @@@ } $href .= "?" . join(';', @result) if scalar @result; + # final transformation: trailing spaces must be escaped (URI-encoded) + $href =~ s/(\s+)$/CGI::escape($1)/e; + return $href; } @@@ -1347,6 -1351,17 +1351,17 @@@ sub esc_param return $str; } + # the quoting rules for path_info fragment are slightly different + sub esc_path_info { + my $str = shift; + return undef unless defined $str; + + # path_info doesn't treat '+' as space (specially), but '?' must be escaped + $str =~ s/([^A-Za-z0-9\-_.~();\/;:@&= +]+)/CGI::escape($1)/eg; + + return $str; + } + # quote unsafe chars in whole URL, so some characters cannot be quoted sub esc_url { my $str = shift; @@@ -1356,13 -1371,6 +1371,13 @@@ return $str; } +# quote unsafe characters in HTML attributes +sub esc_attr { + + # for XHTML conformance escaping '"' to '"' is not enough + return esc_html(@_); +} + # replace invalid utf8 character with SUBSTITUTION sequence sub esc_html { my $str = shift; @@@ -1768,7 -1776,7 +1783,7 @@@ sub format_ref_marker hash=>$dest )}, $name); - $markers .= " " . + $markers .= " " . $link . ""; } } @@@ -1852,7 -1860,7 +1867,7 @@@ sub git_get_avatar return $pre_white . "" . $post_white; } else { @@@ -2563,7 -2571,7 +2578,7 @@@ sub git_show_project_tagcloud } else { my @tags = sort { $cloud->{$a}->{count} <=> $cloud->{$b}->{count} } keys %$cloud; return '

' . join (', ', map { - "$cloud->{$_}->{topname}" + $cgi->a({-href=>"$home_link?by_tag=$_"}, $cloud->{$_}->{topname}) } splice(@tags, 0, $count)) . '

'; } } @@@ -3394,51 -3402,6 +3409,51 @@@ sub get_page_title return $title; } +sub print_feed_meta { + if (defined $project) { + my %href_params = get_feed_info(); + if (!exists $href_params{'-title'}) { + $href_params{'-title'} = 'log'; + } + + foreach my $format qw(RSS Atom) { + my $type = lc($format); + my %link_attr = ( + '-rel' => 'alternate', + '-title' => esc_attr("$project - $href_params{'-title'} - $format feed"), + '-type' => "application/$type+xml" + ); + + $href_params{'action'} = $type; + $link_attr{'-href'} = href(%href_params); + print "\n"; + + $href_params{'extra_options'} = '--no-merges'; + $link_attr{'-href'} = href(%href_params); + $link_attr{'-title'} .= ' (no merges)'; + print "\n"; + } + + } else { + printf(''."\n", + esc_attr($site_name), href(project=>undef, action=>"project_index")); + printf(''."\n", + esc_attr($site_name), href(project=>undef, action=>"opml")); + } +} + sub git_header_html { my $status = shift || "200 OK"; my $expires = shift; @@@ -3481,17 -3444,57 +3496,17 @@@ EO # print out each stylesheet that exist, providing backwards capability # for those people who defined $stylesheet in a config file if (defined $stylesheet) { - print ''."\n"; + print ''."\n"; } else { foreach my $stylesheet (@stylesheets) { next unless $stylesheet; - print ''."\n"; + print ''."\n"; } } - if (defined $project) { - my %href_params = get_feed_info(); - if (!exists $href_params{'-title'}) { - $href_params{'-title'} = 'log'; - } - - foreach my $format qw(RSS Atom) { - my $type = lc($format); - my %link_attr = ( - '-rel' => 'alternate', - '-title' => "$project - $href_params{'-title'} - $format feed", - '-type' => "application/$type+xml" - ); - - $href_params{'action'} = $type; - $link_attr{'-href'} = href(%href_params); - print "\n"; - - $href_params{'extra_options'} = '--no-merges'; - $link_attr{'-href'} = href(%href_params); - $link_attr{'-title'} .= ' (no merges)'; - print "\n"; - } - - } else { - printf(''."\n", - $site_name, href(project=>undef, action=>"project_index")); - printf(''."\n", - $site_name, href(project=>undef, action=>"opml")); - } + print_feed_meta() + if ($status eq '200 OK'); if (defined $favicon) { - print qq(\n); + print qq(\n); } print "\n" . @@@ -3504,7 -3507,7 +3519,7 @@@ print "
\n" . $cgi->a({-href => esc_url($logo_url), -title => $logo_label}, - qq()); + qq()); print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / "; if (defined $project) { print $cgi->a({-href => href(action=>"summary")}, esc_html($project)); @@@ -3602,7 -3605,7 +3617,7 @@@ sub git_footer_html insert_file($site_footer); } - print qq!\n!; + print qq!\n!; if (defined $action && $action eq 'blame_incremental') { print qq!