Git 1.6.5.9
authorJunio C Hamano <gitster@pobox.com>
Wed, 15 Dec 2010 19:27:41 +0000 (11:27 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Dec 2010 19:27:41 +0000 (11:27 -0800)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
1  2 
Documentation/RelNotes/1.6.5.9.txt
GIT-VERSION-GEN
RelNotes
gitweb/gitweb.perl
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bb469dd71e55318319acab1f3af23bdf658fc2da
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,18 @@@
++Git v1.6.5.9 Release Notes
++==========================
++
++Fixes since v1.6.5.8
++--------------------
++
++ * An overlong line after ".gitdir: " in a git file caused out of bounds
++   access to an array on the stack.
++
++ * "git blame -L $start,$end" segfaulted when too large $start was given.
++
++ * "git rev-parse --parseopt --stop-at-non-option" did not stop at non option
++   when --keep-dashdash was in effect.
++
++ * "gitweb" can sometimes be tricked into parrotting a filename argument
++   given in a request without properly quoting.
++
++Other minor fixes and documentation updates are included.
diff --combined GIT-VERSION-GEN
index 52b058a5868e904f6384a922e7edd0ced5f70d89,d453662e5af42d6d67345f8da1f69c60b5a3a3ed..1d79f482961d30b91c2ba1ee9ad062e2545a0965
@@@ -1,7 -1,7 +1,7 @@@
  #!/bin/sh
  
  GVF=GIT-VERSION-FILE
- DEF_VER=v1.6.5.8
 -DEF_VER=v1.6.4.5
++DEF_VER=v1.6.5.9
  
  LF='
  '
diff --combined RelNotes
index f60e868f4721b24cfe989303193bf0a9be3473a7,feba6e41245a74acbea47797b5c3f740e53a2cd2..3c23099a3734f8fb9de7c7894308334d5a5b4aec
+++ b/RelNotes
@@@ -1,1 -1,1 +1,1 @@@
- Documentation/RelNotes-1.6.5.8.txt
 -Documentation/RelNotes/1.6.4.5.txt
++Documentation/RelNotes/1.6.5.9.txt
diff --combined gitweb/gitweb.perl
index c77cd0341d98f6a38af55c6ed6f09704abf4e967,c3a04b122352650e22f81f7ae5acdc3cdf100135..620b5bdbbe238a79f3d9d8fcf852c8d0f3609818
@@@ -160,8 -160,7 +160,8 @@@ our %known_snapshot_formats = 
        #       'suffix' => filename suffix,
        #       'format' => --format for git-archive,
        #       'compressor' => [compressor command and arguments]
 -      #                       (array reference, optional)}
 +      #                       (array reference, optional)
 +      #       'disabled' => boolean (optional)}
        #
        'tgz' => {
                'display' => 'tar.gz',
                'format' => 'tar',
                'compressor' => ['bzip2']},
  
 +      'txz' => {
 +              'display' => 'tar.xz',
 +              'type' => 'application/x-xz',
 +              'suffix' => '.tar.xz',
 +              'format' => 'tar',
 +              'compressor' => ['xz'],
 +              'disabled' => 1},
 +
        'zip' => {
                'display' => 'zip',
                'type' => 'application/x-zip',
  our %known_snapshot_format_aliases = (
        'gzip'  => 'tgz',
        'bzip2' => 'tbz2',
 +      'xz'    => 'txz',
  
        # backward compatibility: legacy gitweb config support
        'x-gzip' => undef, 'gz' => undef,
@@@ -504,8 -494,7 +504,8 @@@ sub filter_snapshot_fmts 
                exists $known_snapshot_format_aliases{$_} ?
                       $known_snapshot_format_aliases{$_} : $_} @fmts;
        @fmts = grep {
 -              exists $known_snapshot_formats{$_} } @fmts;
 +              exists $known_snapshot_formats{$_} &&
 +              !$known_snapshot_formats{$_}{'disabled'}} @fmts;
  }
  
  our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
@@@ -951,13 -940,10 +951,13 @@@ sub href 
                        if (defined $params{'hash_parent_base'}) {
                                $href .= esc_url($params{'hash_parent_base'});
                                # skip the file_parent if it's the same as the file_name
 -                              delete $params{'file_parent'} if $params{'file_parent'} eq $params{'file_name'};
 -                              if (defined $params{'file_parent'} && $params{'file_parent'} !~ /\.\./) {
 -                                      $href .= ":/".esc_url($params{'file_parent'});
 -                                      delete $params{'file_parent'};
 +                              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'});
 +                                              delete $params{'file_parent'};
 +                                      }
                                }
                                $href .= "..";
                                delete $params{'hash_parent'};
@@@ -1083,7 -1069,8 +1083,7 @@@ sub to_utf8 
  # 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/\+/%2B/g;
 +      $str =~ s/([^A-Za-z0-9\-_.~()\/:@ ]+)/CGI::escape($1)/eg;
        $str =~ s/ /\+/g;
        return $str;
  }
@@@ -1097,6 -1084,13 +1097,13 @@@ sub esc_url 
        return $str;
  }
  
+ # quote unsafe characters in HTML attributes
+ sub esc_attr {
+       # for XHTML conformance escaping '"' to '&quot;' is not enough
+       return esc_html(@_);
+ }
  # replace invalid utf8 character with SUBSTITUTION sequence
  sub esc_html {
        my $str = shift;
@@@ -1502,7 -1496,7 +1509,7 @@@ sub format_ref_marker 
                                        hash=>$dest
                                )}, $name);
  
-                       $markers .= " <span class=\"$class\" title=\"$ref\">" .
+                       $markers .= " <span class=\"".esc_attr($class)."\" title=\"".esc_attr($ref)."\">" .
                                $link . "</span>";
                }
        }
@@@ -1523,10 -1517,10 +1530,10 @@@ sub format_subject_html 
                $long =~ s/[[:cntrl:]]/?/g;
                return $cgi->a({-href => $href, -class => "list subject",
                                -title => to_utf8($long)},
 -                     esc_html($short) . $extra);
 +                     esc_html($short)) . $extra;
        } else {
                return $cgi->a({-href => $href, -class => "list subject"},
 -                     esc_html($long)  . $extra);
 +                     esc_html($long)) . $extra;
        }
  }
  
@@@ -1586,7 -1580,7 +1593,7 @@@ sub git_get_avatar 
                return $pre_white .
                       "<img width=\"$size\" " .
                            "class=\"avatar\" " .
-                           "src=\"$url\" " .
+                           "src=\"".esc_url($url)."\" " .
                            "alt=\"\" " .
                       "/>" . $post_white;
        } else {
@@@ -2258,7 -2252,7 +2265,7 @@@ sub git_show_project_tagcloud 
        } else {
                my @tags = sort { $cloud->{$a}->{count} <=> $cloud->{$b}->{count} } keys %$cloud;
                return '<p align="center">' . join (', ', map {
-                       "<a href=\"$home_link?by_tag=$_\">$cloud->{$_}->{topname}</a>"
+                       $cgi->a({-href=>"$home_link?by_tag=$_"}, $cloud->{$_}->{topname})
                } splice(@tags, 0, $count)) . '</p>';
        }
  }
        # print out each stylesheet that exist, providing backwards capability
        # for those people who defined $stylesheet in a config file
        if (defined $stylesheet) {
-               print '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n";
+               print '<link rel="stylesheet" type="text/css" href="'.esc_url($stylesheet).'"/>'."\n";
        } else {
                foreach my $stylesheet (@stylesheets) {
                        next unless $stylesheet;
-                       print '<link rel="stylesheet" type="text/css" href="'.$stylesheet.'"/>'."\n";
+                       print '<link rel="stylesheet" type="text/css" href="'.esc_url($stylesheet).'"/>'."\n";
                }
        }
        if (defined $project) {
                        my $type = lc($format);
                        my %link_attr = (
                                '-rel' => 'alternate',
-                               '-title' => "$project - $href_params{'-title'} - $format feed",
+                               '-title' => esc_attr("$project - $href_params{'-title'} - $format feed"),
                                '-type' => "application/$type+xml"
                        );
  
        } else {
                printf('<link rel="alternate" title="%s projects list" '.
                       'href="%s" type="text/plain; charset=utf-8" />'."\n",
-                      $site_name, href(project=>undef, action=>"project_index"));
+                      esc_attr($site_name), href(project=>undef, action=>"project_index"));
                printf('<link rel="alternate" title="%s projects feeds" '.
                       'href="%s" type="text/x-opml" />'."\n",
-                      $site_name, href(project=>undef, action=>"opml"));
+                      esc_attr($site_name), href(project=>undef, action=>"opml"));
        }
        if (defined $favicon) {
-               print qq(<link rel="shortcut icon" href="$favicon" type="image/png" />\n);
+               print qq(<link rel="shortcut icon" href=").esc_url($favicon).qq(" type="image/png" />\n);
        }
  
        print "</head>\n" .
        print "<div class=\"page_header\">\n" .
              $cgi->a({-href => esc_url($logo_url),
                       -title => $logo_label},
-                     qq(<img src="$logo" width="72" height="27" alt="git" class="logo"/>));
+                     qq(<img src=").esc_url($logo).qq(" width="72" height="27" alt="git" class="logo"/>));
        print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / ";
        if (defined $project) {
                print $cgi->a({-href => href(action=>"summary")}, esc_html($project));
@@@ -4813,7 -4807,7 +4820,7 @@@ sub git_blame 
        git_print_page_path($file_name, $ftype, $hash_base);
  
        # page body
 -      my @rev_color = qw(light2 dark2);
 +      my @rev_color = qw(light dark);
        my $num_colors = scalar(@rev_color);
        my $current_color = 0;
        my %metainfo = ();
                my ($full_rev, $orig_lineno, $lineno, $group_size) =
                   ($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);
                if (!exists $metainfo{$full_rev}) {
 -                      $metainfo{$full_rev} = {};
 +                      $metainfo{$full_rev} = { 'nprevious' => 0 };
                }
                my $meta = $metainfo{$full_rev};
                my $data;
                while ($data = <$fd>) {
                        chomp $data;
                        last if ($data =~ s/^\t//); # contents of line
 -                      if ($data =~ /^(\S+) (.*)$/) {
 -                              $meta->{$1} = $2;
 +                      if ($data =~ /^(\S+)(?: (.*))?$/) {
 +                              $meta->{$1} = $2 unless exists $meta->{$1};
 +                      }
 +                      if ($data =~ /^previous /) {
 +                              $meta->{'nprevious'}++;
                        }
                }
                my $short_rev = substr($full_rev, 0, 8);
                if ($group_size) {
                        $current_color = ($current_color + 1) % $num_colors;
                }
 -              print "<tr id=\"l$lineno\" class=\"$rev_color[$current_color]\">\n";
 +              my $tr_class = $rev_color[$current_color];
 +              $tr_class .= ' boundary' if (exists $meta->{'boundary'});
 +              $tr_class .= ' no-previous' if ($meta->{'nprevious'} == 0);
 +              $tr_class .= ' multiple-previous' if ($meta->{'nprevious'} > 1);
 +              print "<tr id=\"l$lineno\" class=\"$tr_class\">\n";
                if ($group_size) {
                        print "<td class=\"sha1\"";
                        print " title=\"". esc_html($author) . ", $date\"";
                                                     hash=>$full_rev,
                                                     file_name=>$file_name)},
                                      esc_html($short_rev));
 +                      if ($group_size >= 2) {
 +                              my @author_initials = ($author =~ /\b([[:upper:]])\B/g);
 +                              if (@author_initials) {
 +                                      print "<br />" .
 +                                            esc_html(join('', @author_initials));
 +                                      #           or join('.', ...)
 +                              }
 +                      }
                        print "</td>\n";
                }
 -              my $parent_commit;
 -              if (!exists $meta->{'parent'}) {
 -                      open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
 -                              or die_error(500, "Open git-rev-parse failed");
 -                      $parent_commit = <$dd>;
 -                      close $dd;
 -                      chomp($parent_commit);
 -                      $meta->{'parent'} = $parent_commit;
 -              } else {
 -                      $parent_commit = $meta->{'parent'};
 -              }
 +              # 'previous' <sha1 of parent commit> <filename at commit>
 +              if (exists $meta->{'previous'} &&
 +                  $meta->{'previous'} =~ /^([a-fA-F0-9]{40}) (.*)$/) {
 +                      $meta->{'parent'} = $1;
 +                      $meta->{'file_parent'} = unquote($2);
 +              }
 +              my $linenr_commit =
 +                      exists($meta->{'parent'}) ?
 +                      $meta->{'parent'} : $full_rev;
 +              my $linenr_filename =
 +                      exists($meta->{'file_parent'}) ?
 +                      $meta->{'file_parent'} : unquote($meta->{'filename'});
                my $blamed = href(action => 'blame',
 -                                file_name => $meta->{'filename'},
 -                                hash_base => $parent_commit);
 +                                file_name => $linenr_filename,
 +                                hash_base => $linenr_commit);
                print "<td class=\"linenr\">";
                print $cgi->a({ -href => "$blamed#l$orig_lineno",
                                -class => "linenr" },
@@@ -5045,14 -5023,14 +5052,14 @@@ sub git_blob 
        } else {
                print "<div class=\"page_nav\">\n" .
                      "<br/><br/></div>\n" .
-                     "<div class=\"title\">$hash</div>\n";
+                     "<div class=\"title\">".esc_html($hash)."</div>\n";
        }
        git_print_page_path($file_name, "blob", $hash_base);
        print "<div class=\"page_body\">\n";
        if ($mimetype =~ m!^image/!) {
-               print qq!<img type="$mimetype"!;
+               print qq!<img type="!.esc_attr($mimetype).qq!"!;
                if ($file_name) {
-                       print qq! alt="$file_name" title="$file_name"!;
+                       print qq! alt="!.esc_attr($file_name).qq!" title="!.esc_attr($file_name).qq!"!;
                }
                print qq! src="! .
                      href(action=>"blob_plain", hash=>$hash,
                        chomp $line;
                        $nr++;
                        $line = untabify($line);
-                       printf "<div class=\"pre\"><a id=\"l%i\" href=\"" . href(-replay => 1)
 -                      printf "<div class=\"pre\"><a id=\"l%i\" href=\"#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
++                      printf "<div class=\"pre\"><a id=\"l%i\" href=\""
++                              . esc_attr(href(-replay => 1))
 +                              . "#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
                               $nr, $nr, $nr, esc_html($line, -nbsp=>1);
                }
        }
@@@ -5124,7 -5101,7 +5132,7 @@@ sub git_tree 
                undef $hash_base;
                print "<div class=\"page_nav\">\n";
                print "<br/><br/></div>\n";
-               print "<div class=\"title\">$hash</div>\n";
+               print "<div class=\"title\">".esc_html($hash)."</div>\n";
        }
        if (defined $file_name) {
                $basedir = $file_name;
@@@ -5190,8 -5167,6 +5198,8 @@@ sub git_snapshot 
                die_error(400, "Invalid snapshot format parameter");
        } elsif (!exists($known_snapshot_formats{$format})) {
                die_error(400, "Unknown snapshot format");
 +      } elsif ($known_snapshot_formats{$format}{'disabled'}) {
 +              die_error(403, "Snapshot format not allowed");
        } elsif (!grep($_ eq $format, @snapshot_fmts)) {
                die_error(403, "Unsupported snapshot format");
        }
@@@ -5328,7 -5303,7 +5336,7 @@@ sub git_commit 
                        } @$parents ) .
                        ')';
        }
 -      if (gitweb_check_feature('patches')) {
 +      if (gitweb_check_feature('patches') && @$parents <= 1) {
                $formats_nav .= " | " .
                        $cgi->a({-href => href(action=>"patch", -replay=>1)},
                                "patch");
@@@ -5543,7 -5518,7 +5551,7 @@@ sub git_blobdiff 
                        git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
                } else {
                        print "<div class=\"page_nav\"><br/>$formats_nav<br/></div>\n";
-                       print "<div class=\"title\">$hash vs $hash_parent</div>\n";
+                       print "<div class=\"title\">".esc_html("$hash vs $hash_parent")."</div>\n";
                }
                if (defined $file_name) {
                        git_print_page_path($file_name, "blob", $hash_base);
@@@ -5616,7 -5591,7 +5624,7 @@@ sub git_commitdiff 
                $formats_nav =
                        $cgi->a({-href => href(action=>"commitdiff_plain", -replay=>1)},
                                "raw");
 -              if ($patch_max) {
 +              if ($patch_max && @{$co{'parents'}} <= 1) {
                        $formats_nav .= " | " .
                                $cgi->a({-href => href(action=>"patch", -replay=>1)},
                                        "patch");
@@@ -5824,7 -5799,7 +5832,7 @@@ sub git_commitdiff_plain 
  
  # format-patch-style patches
  sub git_patch {
 -      git_commitdiff(-format => 'patch', -single=> 1);
 +      git_commitdiff(-format => 'patch', -single => 1);
  }
  
  sub git_patches {