Git 1.7.0.9
authorJunio C Hamano <gitster@pobox.com>
Wed, 15 Dec 2010 19:38:19 +0000 (11:38 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 15 Dec 2010 19:38:19 +0000 (11:38 -0800)
Signed-off-by: Junio C Hamano <gitster@pobox.com>
1  2 
Documentation/RelNotes/1.7.0.9.txt
GIT-VERSION-GEN
RelNotes
gitweb/gitweb.perl
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bfb31663873cae7a0e24097d89d1d65bb246ed4b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++Git v1.7.0.9 Release Notes
++==========================
++
++Fixes since v1.7.0.8
++--------------------
++
++ * "gitweb" can sometimes be tricked into parrotting a filename argument
++   given in a request without properly quoting.
diff --combined GIT-VERSION-GEN
index 4149fa9eb7a77eef45152394504eb7ab8ba2140b,7d16b013824cc6974fe49e9a49c588146b6d7e2d..c07c5959bb25ef72bbf17f6d0ac13685568236d7
@@@ -1,7 -1,7 +1,7 @@@
  #!/bin/sh
  
  GVF=GIT-VERSION-FILE
- DEF_VER=v1.7.0.8
 -DEF_VER=v1.6.6.3
++DEF_VER=v1.7.0.9
  
  LF='
  '
diff --combined RelNotes
index 882532b0486688b101c5a14b758c3ced5ba82c8a,3dad2389f600053e534a75563049a66b5bdb1ebf..2e4322a073d72f242a56bc2e00c9aa84ff73806c
+++ b/RelNotes
@@@ -1,1 -1,1 +1,1 @@@
- Documentation/RelNotes/1.7.0.8.txt
 -Documentation/RelNotes/1.6.6.3.txt
++Documentation/RelNotes/1.7.0.9.txt
diff --combined gitweb/gitweb.perl
index 9d4c58238ea87963221d948020e928d232c0d90d,0fe8539321e6eb527aef127a17e437edb4998308..f1d857961cf7b873828e66b9873c054f46b6a7a5
@@@ -221,12 -221,6 +221,12 @@@ our %avatar_size = 
        'double'  => 32
  );
  
 +# Used to set the maximum load that we will still respond to gitweb queries.
 +# If server load exceed this value then return "503 server busy" error.
 +# If gitweb cannot determined server load, it is taken to be 0.
 +# Leave it undefined (or set to 'undef') to turn off load checking.
 +our $maxload = 300;
 +
  # You define site-wide feature defaults here; override them with
  # $GITWEB_CONFIG as necessary.
  our %feature = (
@@@ -454,11 -448,7 +454,11 @@@ sub gitweb_get_feature 
                $feature{$name}{'sub'},
                $feature{$name}{'override'},
                @{$feature{$name}{'default'}});
 -      if (!$override) { return @defaults; }
 +      # project specific override is possible only if we have project
 +      our $git_dir; # global variable, declared later
 +      if (!$override || !defined $git_dir) {
 +              return @defaults;
 +      }
        if (!defined $sub) {
                warn "feature $name is not overridable";
                return @defaults;
@@@ -554,36 -544,11 +554,36 @@@ sub filter_snapshot_fmts 
  }
  
  our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
 +our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
 +# die if there are errors parsing config file
  if (-e $GITWEB_CONFIG) {
        do $GITWEB_CONFIG;
 -} else {
 -      our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
 -      do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM;
 +      die $@ if $@;
 +} elsif (-e $GITWEB_CONFIG_SYSTEM) {
 +      do $GITWEB_CONFIG_SYSTEM;
 +      die $@ if $@;
 +}
 +
 +# Get loadavg of system, to compare against $maxload.
 +# Currently it requires '/proc/loadavg' present to get loadavg;
 +# if it is not present it returns 0, which means no load checking.
 +sub get_loadavg {
 +      if( -e '/proc/loadavg' ){
 +              open my $fd, '<', '/proc/loadavg'
 +                      or return 0;
 +              my @load = split(/\s+/, scalar <$fd>);
 +              close $fd;
 +
 +              # The first three columns measure CPU and IO utilization of the last one,
 +              # five, and 10 minute periods.  The fourth column shows the number of
 +              # currently running processes and the total number of processes in the m/n
 +              # format.  The last column displays the last process ID used.
 +              return $load[0] || 0;
 +      }
 +      # additional checks for load average should go here for things that don't export
 +      # /proc/loadavg
 +
 +      return 0;
  }
  
  # version of the core git binary
@@@ -592,10 -557,6 +592,10 @@@ $number_of_git_cmds++
  
  $projects_list ||= $projectroot;
  
 +if (defined $maxload && get_loadavg() > $maxload) {
 +      die_error(503, "The load average on the server is too high");
 +}
 +
  # ======================================================================
  # input validation and dispatch
  
@@@ -1176,6 -1137,13 +1176,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;
@@@ -1337,6 -1305,7 +1344,6 @@@ sub chop_str 
                $str =~ m/^(.*?)($begre)$/;
                my ($lead, $body) = ($1, $2);
                if (length($lead) > 4) {
 -                      $body =~ s/^[^;]*;// if ($lead =~ m/&[^;]*$/);
                        $lead = " ...";
                }
                return "$lead$body";
                $str =~ m/^(.*?)($begre)$/;
                my ($mid, $right) = ($1, $2);
                if (length($mid) > 5) {
 -                      $left  =~ s/&[^;]*$//;
 -                      $right =~ s/^[^;]*;// if ($mid =~ m/&[^;]*$/);
                        $mid = " ... ";
                }
                return "$left$mid$right";
                my $body = $1;
                my $tail = $2;
                if (length($tail) > 4) {
 -                      $body =~ s/&[^;]*$//;
                        $tail = "... ";
                }
                return "$body$tail";
@@@ -1577,7 -1549,7 +1584,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>";
                }
        }
@@@ -1661,7 -1633,7 +1668,7 @@@ sub git_get_avatar 
                return $pre_white .
                       "<img width=\"$size\" " .
                            "class=\"avatar\" " .
-                           "src=\"$url\" " .
+                           "src=\"".esc_url($url)."\" " .
                            "alt=\"\" " .
                       "/>" . $post_white;
        } else {
@@@ -2209,8 -2181,6 +2216,8 @@@ sub config_to_multi 
  sub git_get_project_config {
        my ($key, $type) = @_;
  
 +      return unless defined $git_dir;
 +
        # key sanity check
        return unless ($key);
        $key =~ s/^gitweb\.//;
@@@ -2372,7 -2342,7 +2379,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" .
              "<body>\n";
  
 -      if (-f $site_header) {
 +      if (defined $site_header && -f $site_header) {
                insert_file($site_header);
        }
  
        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));
@@@ -3360,13 -3330,12 +3367,13 @@@ sub git_footer_html 
                print "</div>\n"; # class="page_footer"
        }
  
 -      if (-f $site_footer) {
 +      if (defined $site_footer && -f $site_footer) {
                insert_file($site_footer);
        }
  
-       print qq!<script type="text/javascript" src="$javascript"></script>\n!;
+       print qq!<script type="text/javascript" src="!.esc_url($javascript).qq!"></script>\n!;
 -      if ($action eq 'blame_incremental') {
 +      if (defined $action &&
 +          $action eq 'blame_incremental') {
                print qq!<script type="text/javascript">\n!.
                      qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
                      qq!           "!. href() .qq!");\n!.
  # 500: The server isn't configured properly, or
  #      an internal error occurred (e.g. failed assertions caused by bugs), or
  #      an unknown error occurred (e.g. the git binary died unexpectedly).
 +# 503: The server is currently unavailable (because it is overloaded,
 +#      or down for maintenance).  Generally, this is a temporary state.
  sub die_error {
        my $status = shift || 500;
        my $error = shift || "Internal server error";
 -
 -      my %http_responses = (400 => '400 Bad Request',
 -                            403 => '403 Forbidden',
 -                            404 => '404 Not Found',
 -                            500 => '500 Internal Server Error');
 +      my $extra = shift;
 +
 +      my %http_responses = (
 +              400 => '400 Bad Request',
 +              403 => '403 Forbidden',
 +              404 => '404 Not Found',
 +              500 => '500 Internal Server Error',
 +              503 => '503 Service Unavailable',
 +      );
        git_header_html($http_responses{$status});
        print <<EOF;
  <div class="page_body">
  <br /><br />
  $status - $error
  <br />
 -</div>
  EOF
 +      if (defined $extra) {
 +              print "<hr />\n" .
 +                    "$extra\n";
 +      }
 +      print "</div>\n";
 +
        git_footer_html();
        exit;
  }
@@@ -3520,21 -3478,14 +3527,21 @@@ sub git_print_header_div 
  }
  
  sub print_local_time {
 +      print format_local_time(@_);
 +}
 +
 +sub format_local_time {
 +      my $localtime = '';
        my %date = @_;
        if ($date{'hour_local'} < 6) {
 -              printf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
 +              $localtime .= sprintf(" (<span class=\"atnight\">%02d:%02d</span> %s)",
                        $date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
        } else {
 -              printf(" (%02d:%02d %s)",
 +              $localtime .= sprintf(" (%02d:%02d %s)",
                        $date{'hour_local'}, $date{'minute_local'}, $date{'tz_local'});
        }
 +
 +      return $localtime;
  }
  
  # Outputs the author name and date in long form
@@@ -4358,24 -4309,17 +4365,24 @@@ sub fill_project_list_info 
  # print 'sort by' <th> element, generating 'sort by $name' replay link
  # if that order is not selected
  sub print_sort_th {
 +      print format_sort_th(@_);
 +}
 +
 +sub format_sort_th {
        my ($name, $order, $header) = @_;
 +      my $sort_th = "";
        $header ||= ucfirst($name);
  
        if ($order eq $name) {
 -              print "<th>$header</th>\n";
 +              $sort_th .= "<th>$header</th>\n";
        } else {
 -              print "<th>" .
 -                    $cgi->a({-href => href(-replay=>1, order=>$name),
 -                             -class => "header"}, $header) .
 -                    "</th>\n";
 +              $sort_th .= "<th>" .
 +                          $cgi->a({-href => href(-replay=>1, order=>$name),
 +                                   -class => "header"}, $header) .
 +                          "</th>\n";
        }
 +
 +      return $sort_th;
  }
  
  sub git_project_list_body {
@@@ -4806,7 -4750,7 +4813,7 @@@ sub git_project_list 
        }
  
        git_header_html();
 -      if (-f $home_text) {
 +      if (defined $home_text && -f $home_text) {
                print "<div class=\"index_include\">\n";
                insert_file($home_text);
                print "</div>\n";
@@@ -5376,14 -5320,14 +5383,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=\""
+                               . esc_attr(href(-replay => 1))
                                . "#l%i\" class=\"linenr\">%4i</a> %s</div>\n",
                               $nr, $nr, $nr, esc_html($line, -nbsp=>1);
                }
@@@ -5459,7 -5404,7 +5467,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;
@@@ -5927,7 -5872,7 +5935,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);