}
}
+# We have to handle those containing any characters:
our $file_name = $cgi->param('f');
-if (defined $file_name) {
- if (!validate_input($file_name)) {
- die_error(undef, "Invalid file parameter");
- }
-}
-
our $file_parent = $cgi->param('fp');
-if (defined $file_parent) {
- if (!validate_input($file_parent)) {
- die_error(undef, "Invalid file parent parameter");
- }
-}
our $hash = $cgi->param('h');
if (defined $hash) {
$action ||= "blob_plain";
}
$hash_base ||= validate_input($refname);
- $file_name ||= validate_input($pathname);
+ $file_name ||= $pathname;
} elsif (defined $refname) {
# we got "project.git/branch"
$action ||= "shortlog";
# correct, but quoted slashes look too horrible in bookmarks
sub esc_param {
my $str = shift;
- $str =~ s/([^A-Za-z0-9\-_.~();\/;?:@&=])/sprintf("%%%02X", ord($1))/eg;
+ $str =~ s/([^A-Za-z0-9\-_.~()\/:@])/sprintf("%%%02X", ord($1))/eg;
$str =~ s/\+/%2B/g;
$str =~ s/ /\+/g;
return $str;
sub git_get_project_url_list {
my $path = shift;
- open my $fd, "$projectroot/$path/cloneurl" or return undef;
+ open my $fd, "$projectroot/$path/cloneurl" or return;
my @git_project_url_list = map { chomp; $_ } <$fd>;
close $fd;
if (defined $action) {
$title .= "/$action";
if (defined $file_name) {
- $title .= " - $file_name";
+ $title .= " - " . esc_html($file_name);
if ($action eq "tree" && $file_name !~ m|/$|) {
$title .= "/";
}
my %base_key = ();
$base_key{hash_base} = $hash_base if defined $hash_base;
+ # The format of a table row is: mode list link. Where mode is
+ # the mode of the entry, list is the name of the entry, an href,
+ # and link is the action links of the entry.
+
print "<td class=\"mode\">" . mode_str($t->{'mode'}) . "</td>\n";
if ($t->{'type'} eq "blob") {
print "<td class=\"list\">" .
- $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key),
- -class => "list"}, esc_html($t->{'name'})) .
- "</td>\n" .
- "<td class=\"link\">" .
- $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "blob");
+ $cgi->a({-href => href(action=>"blob", hash=>$t->{'hash'},
+ file_name=>"$basedir$t->{'name'}", %base_key),
+ -class => "list"}, esc_html($t->{'name'})) . "</td>\n";
+ print "<td class=\"link\">";
if ($have_blame) {
- print " | " .
- $cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "blame");
+ print $cgi->a({-href => href(action=>"blame", hash=>$t->{'hash'},
+ file_name=>"$basedir$t->{'name'}", %base_key)},
+ "blame");
}
if (defined $hash_base) {
- print " | " .
- $cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
+ if ($have_blame) {
+ print " | ";
+ }
+ print $cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")},
"history");
}
print " | " .
$cgi->a({-href => href(action=>"blob_plain",
hash=>$t->{'hash'}, file_name=>"$basedir$t->{'name'}")},
- "raw") .
- "</td>\n";
+ "raw");
+ print "</td>\n";
} elsif ($t->{'type'} eq "tree") {
- print "<td class=\"list\">" .
- $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
+ print "<td class=\"list\">";
+ print $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
file_name=>"$basedir$t->{'name'}", %base_key)},
- esc_html($t->{'name'})) .
- "</td>\n" .
- "<td class=\"link\">" .
- $cgi->a({-href => href(action=>"tree", hash=>$t->{'hash'},
- file_name=>"$basedir$t->{'name'}", %base_key)},
- "tree");
+ esc_html($t->{'name'}));
+ print "</td>\n";
+ print "<td class=\"link\">";
if (defined $hash_base) {
- print " | " .
- $cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
+ print $cgi->a({-href => href(action=>"history", hash_base=>$hash_base,
file_name=>"$basedir$t->{'name'}")},
"history");
}
if ($ftype !~ "blob") {
die_error("400 Bad Request", "Object is not a blob");
}
- open ($fd, "-|", git_cmd(), "blame", '-l', $file_name, $hash_base)
+ open ($fd, "-|", git_cmd(), "blame", '-l', '--', $file_name, $hash_base)
or die_error(undef, "Open git-blame failed");
git_header_html();
my $formats_nav =
print <<HTML;
<div class="page_body">
<table class="blame">
-<tr><th>Commit</th><th>Line</th><th>Data</th></tr>
+<tr><th>Prev</th><th>Diff</th><th>Commit</th><th>Line</th><th>Data</th></tr>
HTML
while (<$fd>) {
/^([0-9a-fA-F]{40}).*?(\d+)\)\s{1}(\s*.*)/;
my $rev = substr($full_rev, 0, 8);
my $lineno = $2;
my $data = $3;
+ my %pco = parse_commit($full_rev);
+ my $parent = $pco{'parent'};
if (!defined $last_rev) {
$last_rev = $full_rev;
$current_color = ++$current_color % $num_colors;
}
print "<tr class=\"$rev_color[$current_color]\">\n";
+ # Print the Prev link
+ print "<td class=\"sha1\">";
+ print $cgi->a({-href => href(action=>"blame", hash_base=>$parent, file_name=>$file_name)},
+ esc_html(substr($parent, 0, 8)));
+ print "</td>\n";
+ # Print the Diff (blobdiff) link
+ print "<td>";
+ print $cgi->a({-href => href(action=>"blobdiff", file_name=>$file_name, hash_parent_base=>$parent,
+ hash_base=>$full_rev)},
+ esc_html("Diff"));
+ print "</td>\n";
+ # Print the Commit link
print "<td class=\"sha1\">" .
$cgi->a({-href => href(action=>"commit", hash=>$full_rev, file_name=>$file_name)},
esc_html($rev)) . "</td>\n";
+ # Print the Line number
print "<td class=\"linenr\"><a id=\"l$lineno\" href=\"#l$lineno\" class=\"linenr\">" .
esc_html($lineno) . "</a></td>\n";
+ # Print the Data
print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
print "</tr>\n";
}
if ($have_snapshot) {
# FIXME: Should be available when we have no hash base as well.
push @views_nav,
- $cgi->a({-href => href(action=>"snapshot")},
+ $cgi->a({-href => href(action=>"snapshot", hash=>$hash)},
"snapshot");
}
git_print_page_nav('tree','', $hash_base, undef, undef, join(' | ', @views_nav));
-type => 'text/plain',
-charset => 'utf-8',
-expires => $expires,
- -content_disposition => qq(inline; filename="${file_name}.patch"));
+ -content_disposition => qq(inline; filename=") . quotemeta($file_name) . qq(.patch"));
print "X-Git-Url: " . $cgi->self_url() . "\n\n";
} else {
while (my $line = <$fd>) {
- $line =~ s!a/($hash|$hash_parent)!a/$diffinfo{'from_file'}!g;
- $line =~ s!b/($hash|$hash_parent)!b/$diffinfo{'to_file'}!g;
+ $line =~ s!a/($hash|$hash_parent)!'a/'.esc_html($diffinfo{'from_file'})!eg;
+ $line =~ s!b/($hash|$hash_parent)!'b/'.esc_html($diffinfo{'to_file'})!eg;
print $line;
if (!($line =~ m/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/)) {
next;
}
- my $file = validate_input(unquote($7));
+ my $file = esc_html(unquote($7));
$file = decode("utf8", $file, Encode::FB_DEFAULT);
print "$file<br/>\n";
}