[BACK]Return to cvsweb.cgi CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / cvsweb

Diff for /cvsweb/cvsweb.cgi between version 1.1.1.37 and 4.18

version 1.1.1.37, 2007/03/17 21:52:33 version 4.18, 2019/11/11 14:37:54
Line 1 
Line 1 
 #!/usr/bin/perl -T  #!/usr/bin/perl
   # $Id$
   # $knu: cvsweb.cgi,v 1.299 2010/11/13 16:37:18 simon
 #  #
 # cvsweb - a CGI interface to CVS trees.  # cvsweb - a CGI interface to CVS trees.
 #  #
Line 44 
Line 46 
 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.  # SUCH DAMAGE.
 #  
 # $FreeBSD: projects/cvsweb/cvsweb.cgi,v 1.295 2005/09/25 20:28:51 scop Exp $  
 # $zId: cvsweb.cgi,v 1.112 2001/07/24 13:03:16 hzeller Exp $  
 # $Idaemons: /home/cvs/cvsweb/cvsweb.cgi,v 1.84 2001/10/07 20:50:10 knu Exp $  
 #  
 ###  
   
 require 5.006;  require 5.006;
   
 use strict;  use strict;
   
 use warnings;  use warnings;
 use filetest qw(access);  use filetest qw(access);
   
Line 69  use vars qw (
Line 64  use vars qw (
   @revisions %state %difflines %log %branchpoint @revorder $keywordsubstitution    @revisions %state %difflines %log %branchpoint @revorder $keywordsubstitution
   $prcgi @prcategories $re_prcategories $prkeyword $re_prkeyword $mancgi    $prcgi @prcategories $re_prcategories $prkeyword $re_prkeyword $mancgi
   $doCheckout $scriptname $scriptwhere    $doCheckout $scriptname $scriptwhere
   $where $Browser $nofilelinks $maycompress @stickyvars %funcline_regexp    $where $Browser $nofilelinks $maycompress @stickyvars
   $is_links $is_lynx $is_w3m $is_msie $is_mozilla3 $is_textbased    $is_links $is_lynx $is_w3m $is_msie $is_mozilla3 $is_textbased
   %input $query $barequery $sortby $bydate $byrev $byauthor    %input $query $barequery $sortby $bydate $byrev $byauthor
   $bylog $byfile $defaultDiffType $logsort $cvstree $cvsroot    $bylog $byfile $defaultDiffType $logsort $cvstree $cvsroot
   $charset $output_filter    $charset $output_filter
   @command_path %CMD $allow_compress $backicon $diricon $fileicon $graphicon    @command_path %CMD $allow_compress $backicon $diricon $fileicon
   $fullname $cvstreedefault $logo $defaulttitle $address $binfileicon    $fullname $cvstreedefault $logo $defaulttitle $address $binfileicon
   $long_intro $short_instruction $shortLogLen $show_author    $long_intro $short_instruction $shortLogLen $show_author
   $tablepadding $hr_breakable $showfunc $hr_ignwhite $hr_ignkeysubst    $tablepadding $hr_breakable $showfunc $hr_ignwhite $hr_ignkeysubst
   $inputTextSize $mime_types $allow_annotate $allow_markup $allow_mailtos    $inputTextSize $mime_types $allow_annotate $allow_markup $allow_mailtos
   $allow_log_extra $allow_dir_extra $allow_source_extra    $allow_log_extra $allow_dir_extra $allow_source_extra
   $allow_cvsgraph $cvsgraph_config $use_java_script $edit_option_form    $edit_option_form
   $show_subdir_lastmod $show_log_in_markup $preformat_in_markup    $show_subdir_lastmod $show_log_in_markup $preformat_in_markup
   $tabstop $state $annTable $sel @ForbiddenFiles    $tabstop $state $annTable $sel @ForbiddenFiles
   $use_descriptions %descriptions @mytz $dwhere    $use_descriptions %descriptions @mytz $dwhere
Line 91  use vars qw (
Line 86  use vars qw (
   $allow_enscript @enscript_options %enscript_types    $allow_enscript @enscript_options %enscript_types
 );  );
   
   require Compress::Zlib;
 use Cwd                   qw(abs_path);  use Cwd                   qw(abs_path);
 use File::Basename        qw(dirname);  
 use File::Path            qw(rmtree);  use File::Path            qw(rmtree);
 use File::Spec::Functions qw(canonpath catdir catfile curdir devnull rootdir  use File::Spec::Functions qw(canonpath catdir catfile curdir devnull rootdir
                              tmpdir updir);                               tmpdir updir);
Line 108  use constant CVSWEBMARKUP => qr{^text/(x-cvsweb|vnd\.v
Line 103  use constant CVSWEBMARKUP => qr{^text/(x-cvsweb|vnd\.v
 use constant LOG_FILESEPR => qr/^={77}$/o;  use constant LOG_FILESEPR => qr/^={77}$/o;
 use constant LOG_REVSEPR  => qr/^-{28}$/o;  use constant LOG_REVSEPR  => qr/^-{28}$/o;
   
 use constant HAS_ZLIB     => eval { require Compress::Zlib; };  
 use constant HAS_EDIFF    => eval { require String::Ediff;  };  
   
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
   
 # All global initialization that can be done in compile time should go to  # All global initialization that can be done in compile time should go to
Line 119  use constant HAS_EDIFF    => eval { require String::Ed
Line 111  use constant HAS_EDIFF    => eval { require String::Ed
   
 BEGIN  BEGIN
 {  {
   $VERSION = '3.0.6';    $VERSION = '3.1';
   
   $HTML_DOCTYPE =    $HTML_DOCTYPE =
     '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' .      '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' .
Line 127  BEGIN
Line 119  BEGIN
   
   $HTML_META = <<EOM;    $HTML_META = <<EOM;
 <meta name="robots" content="nofollow" />  <meta name="robots" content="nofollow" />
 <meta name="generator" content="FreeBSD-CVSweb $VERSION" />  <meta name="generator" content="CVSweb $VERSION" />
 <meta http-equiv="Content-Script-Type" content="text/javascript" />  
 <meta http-equiv="Content-Style-Type" content="text/css" />  <meta http-equiv="Content-Style-Type" content="text/css" />
 EOM  EOM
   
Line 144  EOM
Line 135  EOM
   
 # -----------------------------------------------------------------------------  # -----------------------------------------------------------------------------
   
 sub printDiffSelect($);  sub printDiffSelect();
 sub printDiffSelectStickyVars();  sub printDiffSelectStickyVars();
 sub getDiffLinks($$$);  sub getDiffLinks($$$);
 sub printLogSortSelect($);  sub printLogSortSelect();
 sub findLastModifiedSubdirs(@);  sub findLastModifiedSubdirs(@);
 sub htmlify_sub(&$);  sub htmlify_sub(&$);
 sub htmlify($;$);  sub htmlify($;$);
Line 167  sub openOutputFilter();
Line 158  sub openOutputFilter();
 sub doAnnotate($$);  sub doAnnotate($$);
 sub doCheckout($$$);  sub doCheckout($$$);
 sub doEnscript($$$;$);  sub doEnscript($$$;$);
 sub doGraph();  
 sub doGraphView();  
 sub cvswebMarkup($$$$$$;$);  sub cvswebMarkup($$$$$$;$);
 sub viewable($);  sub viewable($);
 sub doDiff($$$$$$);  sub doDiff($$$$$$);
Line 189  sub download_url($$;$);
Line 178  sub download_url($$;$);
 sub download_link($$$;$);  sub download_link($$$;$);
 sub display_url($$;$);  sub display_url($$;$);
 sub display_link($$;$$);  sub display_link($$;$$);
 sub graph_link($;$);  
 sub history_link($$;$);  sub history_link($$;$);
 sub toggleQuery($;$);  sub toggleQuery($;$);
 sub htmlquote($);  sub htmlquote($);
Line 208  sub checkout_to_temp($$$);
Line 196  sub checkout_to_temp($$$);
 # (think mod_perl)...  # (think mod_perl)...
 delete(@ENV{qw(PATH IFS CDPATH ENV BASH_ENV)});  delete(@ENV{qw(PATH IFS CDPATH ENV BASH_ENV)});
   
 my ($mydir) = (dirname($0) =~ /(.*)/);    # untaint  # Location of the configuration file inside the web server chroot:
   $config = '/conf/cvsweb/cvsweb.conf';
   
 ##### Start of Configuration Area ########  
   
 # == EDIT this ==  
 # Locations to search for user configuration, in order:  
 for (catfile($mydir, 'cvsweb.conf'), '/usr/local/etc/cvsweb/cvsweb.conf') {  
   if (-r $_) {  
     $config = $_;  
     last;  
   }  
 }  
   
 ##### End of Configuration Area   ########  
   
 undef $mydir;  
   
 ######## Configuration parameters #########  ######## Configuration parameters #########
   
 @CVSrepositories = @CVSROOT = %CVSROOT = %MIRRORS = %DEFAULTVALUE = %ICONS =  @CVSrepositories = @CVSROOT = %CVSROOT = %MIRRORS = %DEFAULTVALUE = %ICONS =
Line 234  $cvstreedefault = $logo = $defaulttitle =
Line 208  $cvstreedefault = $logo = $defaulttitle =
   $address = $long_intro = $short_instruction = $shortLogLen = $show_author =    $address = $long_intro = $short_instruction = $shortLogLen = $show_author =
   $tablepadding = $hr_breakable = $showfunc = $hr_ignwhite =    $tablepadding = $hr_breakable = $showfunc = $hr_ignwhite =
   $hr_ignkeysubst = $inputTextSize = $mime_types = $allow_annotate =    $hr_ignkeysubst = $inputTextSize = $mime_types = $allow_annotate =
   $allow_markup = $allow_compress = $use_java_script = $edit_option_form =    $allow_markup = $allow_compress = $edit_option_form =
   $show_subdir_lastmod = $show_log_in_markup = $preformat_in_markup =    $show_subdir_lastmod = $show_log_in_markup = $preformat_in_markup =
   $tabstop = $use_moddate = $gzip_open = $DEBUG = $allow_cvsgraph =    $tabstop = $use_moddate = $gzip_open = $DEBUG =
   $cvsgraph_config = $cvshistory_url = $allow_tar = undef;    $cvshistory_url = $allow_tar = undef;
   
 $allow_version_select = $allow_mailtos = $allow_log_extra = 1;  $allow_version_select = $allow_mailtos = $allow_log_extra = 1;
   
 @DIFFTYPES = qw(h H u c s);  @DIFFTYPES = qw(h H u c);
 @DIFFTYPES{@DIFFTYPES} = (  @DIFFTYPES{@DIFFTYPES} = (
   {    {
     'descr'   => 'colored',      'descr'   => 'colored',
Line 263  $allow_version_select = $allow_mailtos = $allow_log_ex
Line 237  $allow_version_select = $allow_mailtos = $allow_log_ex
     'opts'    => ['-c'],      'opts'    => ['-c'],
     'colored' => 0,      'colored' => 0,
   },    },
   {  
     'descr'   => 'side by side',  
     # width=168 should be enough to support 80 character line lengths  
     'opts'    => ['--side-by-side', '--width=168'],  
     'colored' => 0,  
   },  
 );  );
   
 @LOGSORTKEYS = qw(cvs date rev);  @LOGSORTKEYS = qw(cvs date rev);
Line 343  $maycompress = (
Line 311  $maycompress = (
     && $ENV{HTTP_ACCEPT_ENCODING} =~ /gzip/)      && $ENV{HTTP_ACCEPT_ENCODING} =~ /gzip/)
    || $is_mozilla3)     || $is_mozilla3)
   && !$is_msie    && !$is_msie
   && !(defined($ENV{MOD_PERL}) && !HAS_ZLIB)    && !(defined($ENV{MOD_PERL}))
 );  );
   
 # Parameters that will be sticky in all constructed links/query strings.  # Parameters that will be sticky in all constructed links/query strings.
Line 384  if (defined($ENV{QUERY_STRING})) {
Line 352  if (defined($ENV{QUERY_STRING})) {
     $p =~ y/+/ /;      $p =~ y/+/ /;
     my ($key, $val) = split(/=/, $p, 2);      my ($key, $val) = split(/=/, $p, 2);
     next unless defined($key);      next unless defined($key);
     $val = 1 unless defined($val);      $key = uri_unescape($key);
     ($key = uri_unescape($key)) =~ /[[:graph:]]/ or next;      $key =~ /([^a-z_12-])/ and fatal('404 Not Found',
     ($val = uri_unescape($val)) =~ /[[:graph:]]/ or next;        'Invalid character "%s" in query parameter "%s"', $1, $key);
       if (defined $val) {
         $val = uri_unescape($val);
         $val =~ /([^a-zA-Z_01-9.\/-])/ and fatal('404 Not Found',
           'Invalid character "%s" in the value "%s" of the query parameter "%s"',
           $1, $val, $key);
       } else {
         $val = 1;
       }
     $query{$key} = $val;      $query{$key} = $val;
   }    }
 }  }
Line 394  if (defined($ENV{QUERY_STRING})) {
Line 370  if (defined($ENV{QUERY_STRING})) {
 undef %input;  undef %input;
   
 my $t;  my $t;
 for my $p (qw(graph hideattic hidecvsroot hidenonreadable ignorecase ln copt  for my $p (qw(hideattic hidecvsroot hidenonreadable ignorecase ln copt
               makeimage options tarball)) {                options tarball)) {
   $t = $query{$p};    $t = $query{$p};
   if (defined($t)) {    if (defined($t)) {
     ($input{$p}) = ($t =~ /^([01]|on)$/)      ($input{$p}) = ($t =~ /^([01]|on)$/)
Line 559  foreach (@stickyvars) {
Line 535  foreach (@stickyvars) {
 }  }
   
 if ($allow_enscript) {  if ($allow_enscript) {
   push(@DIFFTYPES, qw(uc cc sc));    push(@DIFFTYPES, qw(uc cc));
   @DIFFTYPES{qw(uc cc sc)} = (    @DIFFTYPES{qw(uc cc)} = (
     {      {
      'descr'   => 'unified, colored',       'descr'   => 'unified, colored',
      'opts'    => ['-u'],       'opts'    => ['-u'],
Line 571  if ($allow_enscript) {
Line 547  if ($allow_enscript) {
      'opts'    => ['-c'],       'opts'    => ['-c'],
      'colored' => 0,       'colored' => 0,
     },      },
     {  
      'descr'   => 'side by side, colored',  
      # width=168 should be enough to support 80 character line lengths  
      'opts'    => ['--side-by-side', '--width=168'],  
      'colored' => 0,  
     },  
   );    );
 } else {  } else {
   # No Enscript -> respect difftype, but don't offer colorization.    # No Enscript -> respect difftype, but don't offer colorization.
Line 789  if ($input{tarball}) {
Line 759  if ($input{tarball}) {
   }    }
   
   # Clean up.    # Clean up.
     chdir("..");
   rmtree($tmpexportdir);    rmtree($tmpexportdir);
   
   &fatal(@fatal) if @fatal;    &fatal(@fatal) if @fatal;
Line 883  if (-d $fullname) {
Line 854  if (-d $fullname) {
   
   my $infocols = 1;    my $infocols = 1;
   
   printf(<<EOF, 'Directory index of ' . htmlquote($where));    printf(<<EOF, $tablepadding, 'Directory index of ' . htmlquote($where));
 <table class="dir" width="100%%" cellspacing="0" cellpadding="$tablepadding" summary="%s">  <table class="dir" width="100%%" cellspacing="0" cellpadding="%s" summary="%s">
 <tr>  <tr>
 EOF  EOF
   printf('<th colspan="2"%s>', ($byfile ? ' class="sorted"' : ''));    printf('<th colspan="2"%s>', ($byfile ? ' class="sorted"' : ''));
Line 1028  EOF
Line 999  EOF
   
       # Show last change in dir        # Show last change in dir
       if ($filename) {        if ($filename) {
         print "</td>\n<td>&nbsp;</td>\n<td class=\"age\">";          my $ageclass = 'age';
         print readableTime(time() - $date, 0) if $date;          my $age      = '';
           if ($date) {
             $age       = readableTime(time() - $date, 0);
             $ageclass .= " $1" if ($age =~ /^\d+ ([a-z]+)/);
           }
           print "</td>\n<td>&nbsp;</td>\n<td class=\"$ageclass\">$age";
         print "</td>\n<td class=\"author\">", htmlquote($author)          print "</td>\n<td class=\"author\">", htmlquote($author)
           if $show_author;            if $show_author;
         print "</td>\n<td class=\"log\">";          print "</td>\n<td class=\"log\">";
Line 1077  EOF
Line 1053  EOF
       $filesfound++;        $filesfound++;
   
       printf "<tr class=\"%s\">\n", ($dirrow % 2) ? 'even' : 'odd';        printf "<tr class=\"%s\">\n", ($dirrow % 2) ? 'even' : 'odd';
       printf '<td class="file"%s>', $allow_cvsgraph ? '' : ' colspan="2"';        printf '<td class="file" colspan="2">';
   
       my $icon = $isbinary ? $binfileicon : $fileicon;        my $icon = $isbinary ? $binfileicon : $fileicon;
       print $nofilelinks ? $icon : &link($icon, $url);        print $nofilelinks ? $icon : &link($icon, $url);
       print '&nbsp;', &link(htmlquote($file), $url), $attic;        print '&nbsp;', &link(htmlquote($file), $url), $attic;
       print '</td><td class="graph">', graph_link($fileurl) if $allow_cvsgraph;  
       print "</td>\n<td width=\"30\">", display_link($fileurl, $rev);        print "</td>\n<td width=\"30\">", display_link($fileurl, $rev);
       print "</td>\n<td class=\"age\">";        my $ageclass = 'age';
       print readableTime(time() - $date, 0) if $date;        my $age      = '';
         if ($date) {
           $age       = readableTime(time() - $date, 0);
           $ageclass .= " $1" if ($age =~ /^\d+ ([a-z]+)/);
         }
         print "</td>\n<td class=\"$ageclass\">$age";
       print "</td>\n<td class=\"author\">", htmlquote($author) if $show_author;        print "</td>\n<td class=\"author\">", htmlquote($author) if $show_author;
       print "</td>\n<td class=\"log\">";        print "</td>\n<td class=\"log\">";
   
Line 1135  EOF
Line 1115  EOF
   if (scalar %tags || $input{only_with_tag}) {    if (scalar %tags || $input{only_with_tag}) {
     print "<form method=\"get\" action=\"./\">\n<p>\n";      print "<form method=\"get\" action=\"./\">\n<p>\n";
     foreach my $var (@stickyvars) {      foreach my $var (@stickyvars) {
       printf("<input type=\"hidden\" name=\"$var\" value=\"%s\" />\n",        printf("<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
              htmlquote($input{$var}))               $var, htmlquote($input{$var}))
         if (defined($input{$var})          if (defined($input{$var})
             && (!defined($DEFAULTVALUE{$var})              && (!defined($DEFAULTVALUE{$var})
                 || $input{$var} ne $DEFAULTVALUE{$var})                  || $input{$var} ne $DEFAULTVALUE{$var})
             && $var ne 'only_with_tag');              && $var ne 'only_with_tag');
     }      }
     printf(<<EOF, ($use_java_script ? ' onchange="this.form.submit()"' : ''));      print <<EOF;
 <span class="nowrap">  <span class="nowrap">
 <label for="only_with_tag" accesskey="T">Show only files with tag:  <label for="only_with_tag" accesskey="T">Show only files with tag:
 <select id="only_with_tag" name="only_with_tag"%s>  <select id="only_with_tag" name="only_with_tag">
 <option value="">All tags / default branch</option>  <option value="">All tags / default branch</option>
 EOF  EOF
     foreach my $tag (reverse sort { lc $a cmp lc $b } keys %tags) {      foreach my $tag (reverse sort { lc $a cmp lc $b } keys %tags) {
Line 1192  EOF
Line 1172  EOF
 <legend>General options</legend>  <legend>General options</legend>
 <input type="hidden" name="copt" value="1" />  <input type="hidden" name="copt" value="1" />
 EOF  EOF
     for my $v qw(hidecvsroot hidenonreadable) {      for my $v (qw(hidecvsroot hidenonreadable)) {
       printf(qq{<input type="hidden" name="%s" value="%s" />\n},        printf(qq{<input type="hidden" name="%s" value="%s" />\n},
              $v, $input{$v} || 0);               $v, $input{$v} || 0);
     }      }
Line 1243  EOF
Line 1223  EOF
 </td>  </td>
 <td class="opt-value">  <td class="opt-value">
 EOF  EOF
     printLogSortSelect(0);      printLogSortSelect();
     print <<EOF;      print <<EOF;
 </td>  </td>
 <td class="opt-label">  <td class="opt-label">
Line 1262  EOF
Line 1242  EOF
 </td>  </td>
 <td>  <td>
 EOF  EOF
     printDiffSelect(0);      printDiffSelect();
     print <<EOF;      print <<EOF;
 </td>  </td>
 <td colspan="2" class="opt-label">  <td colspan="2" class="opt-label">
Line 1301  elsif (-f $fullname . ',v') {
Line 1281  elsif (-f $fullname . ',v') {
     exit;      exit;
   }    }
   
   if ($allow_cvsgraph && $input{graph}) {  
     if ($input{makeimage}) {  
       doGraph();  
     } else {  
       doGraphView();  
     }  
     gzipclose();  
     exit;  
   }  
   
   &doLog($fullname);    &doLog($fullname);
 }  }
   
Line 1386  gzipclose();
Line 1356  gzipclose();
 ## End MAIN  ## End MAIN
   
   
 sub printDiffSelect($)  sub printDiffSelect()
 {  {
   my ($use_java_script) = @_;  
   
   print '<select id="f" name="f"';    print '<select id="f" name="f"';
   print ' onchange="this.form.submit()"' if $use_java_script;  
   print ">\n";    print ">\n";
   
   for my $difftype (@DIFFTYPES) {    for my $difftype (@DIFFTYPES) {
Line 1415  sub printDiffSelectStickyVars()
Line 1382  sub printDiffSelectStickyVars()
 }  }
   
   
 sub printLogSortSelect($)  sub printLogSortSelect()
 {  {
   my ($use_java_script) = @_;  
   
   print '<select id="logsort" name="logsort"';    print '<select id="logsort" name="logsort"';
   print ' onchange="this.form.submit()"' if $use_java_script;  
   print ">\n";    print ">\n";
   
   for my $sortkey (@LOGSORTKEYS) {    for my $sortkey (@LOGSORTKEYS) {
Line 1521  sub htmlify($;$)
Line 1485  sub htmlify($;$)
   
       do {        do {
         $prev = $_;          $prev = $_;
   
         $_ = htmlify_sub {          $_ = htmlify_sub {
           s{            s{
             (\b$re_prkeyword[:\#]?\s*              (\b$re_prkeyword[:\#]?\s*
Line 1563  sub htmlify($;$)
Line 1526  sub htmlify($;$)
          }{           }{
             my($text, $name, $section) = ($1, $2, defined($3) ? $3 : $4);              my($text, $name, $section) = ($1, $2, defined($3) ? $3 : $4);
             ($name =~ /[A-Za-z]/ && $name !~ /\.(:|$)/)              ($name =~ /[A-Za-z]/ && $name !~ /\.(:|$)/)
              ? &link($text, sprintf($mancgi, $section, uri_escape($name)))               ? &link($text, sprintf($mancgi, uri_escape($name), $section))
               : $text;                : $text;
          }egx;           }egx;
       } $_;        } $_;
Line 2314  sub doDiff($$$$$$)
Line 2277  sub doDiff($$$$$$)
   my @difftype       = @{$difftype->{opts}};    my @difftype       = @{$difftype->{opts}};
   my $human_readable = $difftype->{colored};    my $human_readable = $difftype->{colored};
   
   # Apply special diff options.  -p and -F are not available with side by side    # Apply special diff options.
   # diffs and may cause problems with older (< 2.8) versions of diffutils if    push @difftype, '-p' if $showfunc;
   # used with --side-by-side.  
   if ($showfunc && $f !~ /^s/) {  
     push(@difftype, '-p');  
     while (my ($re1, $re2) = each %funcline_regexp) {  
       if ($fullname =~ $re1) {  
         push(@difftype, '-F', $re2);  
         last;  
       }  
     }  
   }  
   
   if ($human_readable) {    if ($human_readable) {
     push(@difftype, '-w')  if $hr_ignwhite;      push(@difftype, '-w')  if $hr_ignwhite;
Line 2372  EOF
Line 2325  EOF
 EOF  EOF
     printDiffSelectStickyVars();      printDiffSelectStickyVars();
     print 'Diff format: ';      print 'Diff format: ';
     printDiffSelect($use_java_script);      printDiffSelect();
     print "<input type=\"submit\" value=\"Show\" />\n</form>\n";      print "<input type=\"submit\" value=\"Show\" />\n</form>\n";
     html_footer();      html_footer();
     gzipclose();      gzipclose();
Line 2945  sub printLog($$$;$$)
Line 2898  sub printLog($$$;$$)
                             $fileurl, $_, $barequery, $_));                              $fileurl, $_, $barequery, $_));
       }        }
     }      }
     print ' - ', graph_link('', 'revision graph')  
       if (!$inlogview && $allow_cvsgraph);  
   }    }
   print "<br />\n";    print "<br />\n";
   
   print '<i>';    print '<i>';
   if (defined @mytz) {    if (@mytz) {
     my ($est) = $mytz[(localtime($date{$_}))[8]];      my ($est) = $mytz[(localtime($date{$_}))[8]];
     print scalar localtime($date{$_}), " $est</i> (";      print scalar localtime($date{$_}), " $est</i> (";
   } else {    } else {
Line 3079  sub printLog($$$;$$)
Line 3030  sub printLog($$$;$$)
 }  }
   
   
 #  
 # Generates the HTML view for CvsGraph.  
 #  
 sub doGraphView()  
 {  
   (my $pathname = $where) =~ s|[^/]*$||;  
   (my $filename = $where) =~ s|^.*/||;  
   
   navigateHeader($scriptwhere, $pathname, $filename, undef, 'graph');  
   
   my $title = 'Revision graph of ' . htmlquote($pathname . $filename);  
   my $mapname = 'CvsGraphMap';  
   
   printf(<<EOF, $title, $mapname, $cvstree, $title);  
 <h3 style="text-align: center">%s</h3>  
 <div style="text-align: center"><img border="0" usemap="#%s" src="?cvsroot=%s;graph=1;makeimage=1" alt="%s" />  
 EOF  
   
   # Remove any pre-existing tag/branch names from branch links.  
   (my $notag_query = $barequery) =~ s/;+only_with_tag=.*?(?=;|$)//g;  
   
   my @graph_cmd =  
     ($CMD{cvsgraph},  
      '-r', $cvsroot,  
      '-m', $pathname,  
      '-i',  
      '-M', $mapname,  
      '-x', 'x',  
      "-Omap_branch_href=\"href=\\\"./?only_with_tag=%(%t%)$notag_query\\\"\"",  
      "-Omap_rev_href=\"href=\\\"?rev=%(%R%)$barequery\\\"\"",  
      "-Omap_diff_href=\"href=\\\"%(%F%).diff" .  
      "?r1=%(%P%);r2=%(%R%)$barequery\\\"\"",  
      );  
   push(@graph_cmd, '-c', $cvsgraph_config) if $cvsgraph_config;  
   push(@graph_cmd, $filename . ',v');  
   
   local *CVSGRAPH_OUT;  
   my ($h, $err) =  
     startproc(\@graph_cmd, \"", '>pipe', \*CVSGRAPH_OUT);  
   fatal('500 Internal Error', $err) unless $h;  
   
   # Browser compatibility kludge: many browsers do not support client side  
   # image maps where the <map> element contains only the id attribute.  Let's  
   # add the corresponding name attribute to it on the fly.  
   while (<CVSGRAPH_OUT>) {  
     s/(<map\s+id="([^"]+)")\s*>/$1 name="$2">/;  
     print;  
   }  
   
   $h->finish();  
   print "</div>\n";  
   
   html_footer();  
 }  
   
   
 #  
 # Generates a graph using CvsGraph.  
 #  
 sub doGraph()  
 {  
   (my $pathname = $where) =~ s|[^/]*$||;  
   (my $filename = $where) =~ s|^.*/||;  
   
   http_header('image/png');  
   
   my @graph_cmd = ($CMD{cvsgraph}, '-r', $cvsroot, '-m', $pathname);  
   push(@graph_cmd, '-c', $cvsgraph_config) if $cvsgraph_config;  
   push(@graph_cmd, $filename . ',v');  
   
   local *CVSGRAPH_OUT;  
   my ($h, $err) =  
     startproc(\@graph_cmd, \"", '>pipe', \*CVSGRAPH_OUT);  
   fatal('500 Internal Error', $err) unless $h;  
   {  
     local $/ = undef;  
     binmode(\*STDOUT);  
     print <CVSGRAPH_OUT>;  
   }  
   $h->finish();  
 }  
   
   
 sub doLog($)  sub doLog($)
 {  {
   my ($fullname) = @_;    my ($fullname) = @_;
Line 3186  sub doLog($)
Line 3054  sub doLog($)
     &clickablePath($upwhere, 1), "</b>\n</p>\n";      &clickablePath($upwhere, 1), "</b>\n</p>\n";
   print "<p>\n ";    print "<p>\n ";
   print &link('Request diff between arbitrary revisions', '#diff');    print &link('Request diff between arbitrary revisions', '#diff');
   print ' - ', &graph_link('', 'Display revisions graphically')  
     if $allow_cvsgraph;  
   if ($cvshistory_url) {    if ($cvshistory_url) {
     (my $d = $upwhere) =~ s|/+$||;      (my $d = $upwhere) =~ s|/+$||;
     print ' - ', history_link($d, $filename);      print ' - ', history_link($d, $filename);
Line 3290  EOF
Line 3156  EOF
 </td>  </td>
 <td class="opt-value">  <td class="opt-value">
 EOF  EOF
   printDiffSelect($use_java_script);    printDiffSelect();
   print <<EOF;    print <<EOF;
 </td>  </td>
 <td></td>  <td></td>
Line 3299  EOF
Line 3165  EOF
   
   if (@branchnames) {    if (@branchnames) {
   
     printf(<<EOF, $use_java_script ? ' onchange="this.form.submit()"' : '');      print <<EOF;
 <tr>  <tr>
 <td class="opt-label">  <td class="opt-label">
 <label for="only_with_tag" accesskey="B">View only branch:</label>  <label for="only_with_tag" accesskey="B">View only branch:</label>
 </td>  </td>
 <td class="opt-value">  <td class="opt-value">
 <a name="branch">  <a name="branch">
 <select id="only_with_tag" name="only_with_tag"%s>  <select id="only_with_tag" name="only_with_tag">
 EOF  EOF
   
     my @tmp = ();      my @tmp = ();
Line 3339  EOF
Line 3205  EOF
 </td>  </td>
 <td>  <td>
 EOF  EOF
   printLogSortSelect($use_java_script);    printLogSortSelect();
   print <<EOF;    print <<EOF;
 </td>  </td>
 <td><input type="submit" value="Set" accesskey="S" /></td>  <td><input type="submit" value="Set" accesskey="S" /></td>
Line 3350  EOF
Line 3216  EOF
     next if ($_ eq "f");      next if ($_ eq "f");
     next if ($_ eq "only_with_tag");      next if ($_ eq "only_with_tag");
     next if ($_ eq "logsort");      next if ($_ eq "logsort");
     printf("<input type=\"hidden\" name=\"$_\" value=\"%s\" />\n",      printf("<input type=\"hidden\" name=\"%s\" value=\"%s\" />\n",
            htmlquote($input{$_}))             $_, htmlquote($input{$_}))
       if (defined($input{$_})        if (defined($input{$_})
           && (!defined($DEFAULTVALUE{$_}) || $input{$_} ne $DEFAULTVALUE{$_}));            && (!defined($DEFAULTVALUE{$_}) || $input{$_} ne $DEFAULTVALUE{$_}));
   }    }
Line 3377  EOF
Line 3243  EOF
     }      }
   } elsif ($state eq "PreChange") {     # state eq "PreChange"    } elsif ($state eq "PreChange") {     # state eq "PreChange"
                                         # we got removes with subsequent adds                                          # we got removes with subsequent adds
     if (HAS_EDIFF) {  
       # construct the suffix tree  
       my $left_diff = join("\n", @$leftColRef[0..$leftRow-1]);  
       my $right_diff = join("\n", @$rightColRef[0..$rightRow-1]);  
       my $diff_str = String::Ediff::ediff($left_diff, $right_diff);  
   
       my @diff_str = split(/ /, $diff_str);  
       my $INFINITY = 10000000;  
       push(@diff_str, ($INFINITY) x 8);  
       my ($idx, $b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) =  
         (0, @diff_str[0..7]);  
       my ($l_cul, $r_cul) = (0, 0);  
       my ($ldx, $rdx) = (0, 0);  
       my (@left_html, @right_html);  
       for (my $j = 0; $j < $leftRow; $j++) {  
         my $line_len = length(@$leftColRef[$j]);  
         my $line = @$leftColRef[$j];  
         $l_cul += length($line) + 1; # includes "\n"  
         my $l_culx = $l_cul - 1; # not includes "\n"  
         if ($j < $lb1) {  
           $line = spacedHtmlText($line);  
           push(@left_html, "<td class=\"diff diff-changed\">$line</td>");  
         } elsif ($lb1 == $j) {  
           my $html_line;  
           while ($lb1 == $j) {  
             my $begin_char = $l_culx - $b1;  
   
             $line =~ /^(.*)(.{$begin_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-unchanged">';  
             $line = $2;  
             last if ($j != $le1);  
   
             my $end_char = $l_culx - $e1;  
             $line =~ /^(.*)(.{$end_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-changed">';  
             $line = $2;  
   
             $idx++;  
             my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) =  
               ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2);  
             ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) =  
               @diff_str[$idx*8..($idx+1)*8-1];  
             $lb1 = $INFINITY if ($lb1 < 0);  
             $lb2 = $INFINITY if ($lb2 < 0);  
             $le1 = $INFINITY if ($le1 < 0);  
             $le2 = $INFINITY if ($le2 < 0);  
             if ($te1 > $b1) {  
               ($b1, $lb1) = ($te1, $tle1);  
             }  
             if ($te2 > $b2) {  
               ($b2, $lb2) = ($te2, $tle2);  
             }  
           }  
           push(@left_html,  
                sprintf('<td><span class="diff diff-changed">%s%s</span></td>',  
                        $html_line, spacedHtmlText($line)));  
         } elsif ($le1 == $j) {  
           my $html_line;  
           while ($le1 == $j) {  
             my $end_char = $l_culx - $e1;  
             $line =~ /^(.*)(.{$end_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-changed">';  
             $line = $2;  
   
             $idx++;  
             my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) =  
               ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2);  
             ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) =  
               @diff_str[$idx*8..($idx+1)*8-1];  
             $lb1 = $INFINITY if ($lb1 < 0);  
             $lb2 = $INFINITY if ($lb2 < 0);  
             $le1 = $INFINITY if ($le1 < 0);  
             $le2 = $INFINITY if ($le2 < 0);  
             if ($te1 > $b1) {  
               ($b1, $lb1) = ($te1, $tle1);  
             }  
             if ($te2 > $b2) {  
               ($b2, $lb2) = ($te2, $tle2);  
             }  
   
             last if ($lb1 != $j);  
   
             my $begin_char = $l_culx - $b1;  
   
             $line =~ /^(.*)(.{$begin_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-unchanged">';  
             $line = $2;  
           }  
           push(@left_html,  
               sprintf('<td><span class="diff diff-unchanged">%s%s</span></td>',  
                       $html_line, spacedHtmlText($line)));  
         } else {  
           $line = spacedHtmlText($line);  
           push(@left_html, "<td class=\"diff diff-unchanged\">$line</td>");  
         }  
       }  
       ($idx, $b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) =  
         (0, @diff_str[0..7]);  
       $lb1 = $INFINITY if ($lb1 < 0);  
       $lb2 = $INFINITY if ($lb2 < 0);  
       $le1 = $INFINITY if ($le1 < 0);  
       $le2 = $INFINITY if ($le2 < 0);  
       for (my $j = 0; $j < $rightRow; $j++) {  
         my $line_len = length(@$rightColRef[$j]);  
         my $line = @$rightColRef[$j];  
         $r_cul += length($line) + 1; # includes "\n"  
         my $r_culx = $r_cul - 1; # not includes "\n"  
         if ($j < $lb2) {  
           $line = spacedHtmlText($line);  
           push(@right_html, "<td class=\"diff diff-changed\">$line</td>");  
         } elsif ($lb2 == $j) {  
           my $html_line;  
           while ($lb2 == $j) {  
             my $begin_char = $r_culx - $b2;  
   
             $line =~ /^(.*)(.{$begin_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-unchanged">';  
             $line = $2;  
   
             last if ($j != $le2);  
   
             my $end_char = $r_culx - $e2;  
             $line =~ /^(.*)(.{$end_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-changed">';  
             $line = $2;  
   
             $idx++;  
             my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) =  
               ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2);  
             ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) =  
               @diff_str[$idx*8..($idx+1)*8-1];  
             $lb1 = $INFINITY if ($lb1 < 0);  
             $lb2 = $INFINITY if ($lb2 < 0);  
             $le1 = $INFINITY if ($le1 < 0);  
             $le2 = $INFINITY if ($le2 < 0);  
             if ($te1 > $b1) {  
               ($b1, $lb1) = ($te1, $tle1);  
             }  
             if ($te2 > $b2) {  
               ($b2, $lb2) = ($te2, $tle2);  
             }  
           }  
           push(@right_html,  
                sprintf('<td><span class="diff diff-changed">%s%s</span></td>',  
                        $html_line, spacedHtmlText($line)));  
         } elsif ($le2 == $j) {  
           my $html_line;  
           while ($le2 == $j) {  
             my $end_char = $r_culx - $e2;  
             $line =~ /^(.*)(.{$end_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-changed">';  
             $line = $2;  
   
             $idx++;  
             my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) =  
               ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2);  
             ($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) =  
               @diff_str[$idx*8..($idx+1)*8-1];  
             $lb1 = $INFINITY if ($lb1 < 0);  
             $lb2 = $INFINITY if ($lb2 < 0);  
             $le1 = $INFINITY if ($le1 < 0);  
             $le2 = $INFINITY if ($le2 < 0);  
             if ($te1 > $b1) {  
               ($b1, $lb1) = ($te1, $tle1);  
             }  
             if ($te2 > $b2) {  
               ($b2, $lb2) = ($te2, $tle2);  
             }  
   
             last if ($lb2 != $j);  
   
             my $begin_char = $r_culx - $b2;  
             $line =~ /^(.*)(.{$begin_char})$/;  
             $html_line .= spacedHtmlText($1) .  
               '</span><span class="diff diff-unchanged">';  
             $line = $2;  
           }  
           push(@right_html,  
                sprintf('<td nowrap="nowrap"><span class="diff diff-unchanged"'.  
                        '>%s%s</span></td>',  
                        $html_line, spacedHtmlText($line)));  
         } else {  
           $line = spacedHtmlText ($line);  
           push @right_html, "<td class=\"diff diff-unchanged\">$line</td>";  
         }  
       }  
       for (my $j = 0; $j < $leftRow || $j < $rightRow ; $j++) { # dump out both cols  
         print  '<tr>';  
         if ($j < $leftRow) {  
           print $left_html[$j];  
         } else {  
           print '<td class="diff diff-changed-missing">&nbsp;</td>';  
         }  
         if ($j < $rightRow) {  
           print $right_html[$j];  
         } else {  
           print '<td class="diff diff-changed-missing">&nbsp;</td>';  
         }  
         print "</tr>\n";  
       }  
     } else {  
       for (my $j = 0; $j < $leftRow || $j < $rightRow; $j++) { # dump both cols        for (my $j = 0; $j < $leftRow || $j < $rightRow; $j++) { # dump both cols
         print "<tr>\n";          print "<tr>\n";
         if ($j < $leftRow) {          if ($j < $leftRow) {
Line 3603  EOF
Line 3261  EOF
         }          }
         print "\n</tr>\n";          print "\n</tr>\n";
       }        }
     }  
   }    }
 }  }
   
Line 3774  EOF
Line 3431  EOF
 <label for="f">Diff format:<br />  <label for="f">Diff format:<br />
 EOF  EOF
   printDiffSelectStickyVars();    printDiffSelectStickyVars();
   printDiffSelect($use_java_script);    printDiffSelect();
   printf(<<EOF, $rev1, $rev2);    printf(<<EOF, $rev1, $rev2);
 </label>  </label>
 <input type="submit" value="Show" />  <input type="submit" value="Show" />
Line 3840  sub navigateHeader($$$$$;$)
Line 3497  sub navigateHeader($$$$$;$)
   my $qpath = htmlquote($path);    my $qpath = htmlquote($path);
   my $trev  = $rev ? " - " . htmlquote($rev) : '';    my $trev  = $rev ? " - " . htmlquote($rev) : '';
   
   http_header('', $moddate);    http_header('text/html', $moddate);
   
   print <<EOF;    print <<EOF;
 $HTML_DOCTYPE  $HTML_DOCTYPE
Line 3984  sub chooseCVSRoot()
Line 3641  sub chooseCVSRoot()
         if ($input{$k} && $k ne 'cvsroot');          if ($input{$k} && $k ne 'cvsroot');
     }      }
   
     printf(<<EOF, $use_java_script ? ' onchange="this.form.submit()"' : '');      print <<EOF;
 <label for="cvsroot" accesskey="C">CVS Root:  <label for="cvsroot" accesskey="C">CVS Root:
 <select id="cvsroot" name="cvsroot"%s>  <select id="cvsroot" name="cvsroot">
 EOF  EOF
   
     foreach my $k (@CVSROOT) {      foreach my $k (@CVSROOT) {
Line 4164  sub display_link($$;$$)
Line 3821  sub display_link($$;$$)
 }  }
   
 #  #
 # Expects the passed in URL to be URI escaped, and without a query string.  
 # The passed in link text should be already HTML escaped as appropriate.  
 #  
 sub graph_link($;$)  
 {  
   my ($url, $text) = @_;  
   $text ||= $graphicon;  
   return sprintf('<a href="%s?graph=1%s">%s</a>', $url, $barequery, $text);  
 }  
   
 #  
 # Returns a link to CVSHistory for the given directory and filename.  # Returns a link to CVSHistory for the given directory and filename.
 #  #
 sub history_link($$;$)  sub history_link($$;$)
Line 4227  sub htmlquote($)
Line 3873  sub htmlquote($)
   # Special Characters; RFC 1866    # Special Characters; RFC 1866
   s/&/&amp;/g;    s/&/&amp;/g;
   s/\"/&quot;/g;    s/\"/&quot;/g;
     s/"/&quot;/g;
   s/</&lt;/g;    s/</&lt;/g;
   s/>/&gt;/g;    s/>/&gt;/g;
   return $_;    return $_;
Line 4266  sub http_header(;$$)
Line 3913  sub http_header(;$$)
   push(@headers, 'Last-Modified: ' . scalar gmtime($moddate) . ' GMT')    push(@headers, 'Last-Modified: ' . scalar gmtime($moddate) . ' GMT')
     if $moddate;      if $moddate;
   push(@headers, 'Content-Type: ' . $content_type);    push(@headers, 'Content-Type: ' . $content_type);
     push(@headers, "Content-Security-Policy: default-src 'none'; " .
       "img-src 'self'; style-src 'unsafe-inline'");
   
   if ($allow_compress && $maycompress) {    if ($allow_compress && $maycompress) {
     if (HAS_ZLIB        push(@headers, 'Content-Encoding: gzip');
         || (defined($CMD{gzip}) && open(GZIP, "| $CMD{gzip} -1 -c")))  
     {  
   
       push(@headers, 'Content-Encoding: x-gzip');  
       push(@headers, 'Vary: Accept-Encoding');     # RFC 2616, 14.44        push(@headers, 'Vary: Accept-Encoding');     # RFC 2616, 14.44
       print join("\r\n", @headers) . "\r\n\r\n";        print join("\r\n", @headers) . "\r\n\r\n";
   
       $| = 1;        $| = 1;
       $| = 0;                                      # Flush header output.        $| = 0;                                      # Flush header output.
   
       tie(*GZIP, __PACKAGE__, \*STDOUT) if HAS_ZLIB;        tie(*GZIP, __PACKAGE__, \*STDOUT);
       select(GZIP);        select(GZIP);
       $gzip_open = 1;        $gzip_open = 1;
   
     } else {  
   
       print join("\r\n", @headers) . "\r\n\r\n";  
       printf  
         '<span style="font-size: smaller">Unable to find gzip binary in the <b>$command_path</b> (<code>%s</code>) to compress output</span><br />',  
           htmlquote(join(':', @command_path));  
     }  
   
   } else {    } else {
     print join("\r\n", @headers) . "\r\n\r\n";      print join("\r\n", @headers) . "\r\n\r\n";
   }    }
Line 4458  sub TIEHANDLE
Line 4094  sub TIEHANDLE
               crc    => 0,                crc    => 0,
               len    => 0,                len    => 0,
             };              };
   my ($header) = pack("c10",    my ($header) = pack("C10",
                       MAGIC1, MAGIC2, Compress::Zlib::Z_DEFLATED(),                        MAGIC1, MAGIC2, Compress::Zlib::Z_DEFLATED(),
                       0, 0, 0, 0, 0, 0, OSCODE);                        0, 0, 0, 0, 0, 0, OSCODE);
   print {$o->{handle}} $header;    print {$o->{handle}} $header;

Legend:
Removed from v.1.1.1.37  
changed lines
  Added in v.4.18

CVSweb