[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.4 and 3.2

version 1.1.1.4, 2000/09/03 18:41:30 version 3.2, 2000/07/20 11:52:05
Line 1 
Line 1 
 #!/usr/bin/perl5 -ws  #!/usr/bin/perl -ws
 #  #
 # cvsweb - a CGI interface to CVS trees.  # cvsweb - a CGI interface to CVS trees.
 #  #
 # Written in their spare time by  # Written in their spare time by
 #             Bill Fenner      <fenner@FreeBSD.org>   (original work)  #             Bill Fenner      <fenner@FreeBSD.org>   (original work)
 # extended by Henner Zeller    <zeller@think.de>,  # extended by Henner Zeller    <zeller@think.de>,
 #             Henrik Nordstrom <hno@hem.passagen.se>  #             Henrik Nordstrom <hno@hem.passagen.se>
 #             Ken Coar         <coar@Apache.Org>  #             Ken Coar         <coar@Apache.Org>
 #             Dick Balaska     <dick@buckosoft.com>  #             Dick Balaska     <dick@buckosoft.com>
 #             Akinori MUSHA    <knu@FreeBSD.org>  #             Akinori MUSHA    <knu@FreeBSD.org>
 #  #
 # Based on:  # Based on:
 # * Bill Fenners cvsweb.cgi revision 1.28 available from:  # * Bill Fenners cvsweb.cgi revision 1.28 available from:
 #   http://www.FreeBSD.org/cgi/cvsweb.cgi/www/en/cgi/cvsweb.cgi  #   http://www.freebsd.org/cgi/cvsweb.cgi/www/en/cgi/cvsweb.cgi
 #  #
 # Copyright (c) 1996-1998 Bill Fenner  # Copyright (c) 1996-1998 Bill Fenner
 #           (c) 1998-1999 Henner Zeller  #           (c) 1998-1999 Henner Zeller
Line 41 
Line 41 
 # 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.
 #  #
 # $zId: cvsweb.cgi,v 1.94 2000/08/24 06:41:22 hnordstrom Exp $  # $Id$
 # $kId: cvsweb.cgi,v 1.17 2000/09/03 18:25:47 knu Exp $  
 #  #
 ###  ###
   
Line 53  use vars qw (
Line 52  use vars qw (
     %CVSROOT %CVSROOTdescr %MIRRORS %DEFAULTVALUE %ICONS %MTYPES      %CVSROOT %CVSROOTdescr %MIRRORS %DEFAULTVALUE %ICONS %MTYPES
     %alltags @tabcolors %fileinfo %tags @branchnames %nameprinted      %alltags @tabcolors %fileinfo %tags @branchnames %nameprinted
     %symrev %revsym @allrevisions %date %author @revdisplayorder      %symrev %revsym @allrevisions %date %author @revdisplayorder
     @revisions %state %difflines %log %branchpoint @revorder      @revisions %state %difflines %log %branchpoint @revorder $prcgi
     $prcgi @prcategories $prcategories $mancgi      @prcategories $prcategories
     $checkoutMagic $doCheckout $scriptname $scriptwhere      $checkoutMagic $doCheckout $scriptname $scriptwhere
     $where $pathinfo $Browser $nofilelinks $maycompress @stickyvars      $where $Browser $nofilelinks $maycompress @stickyvars
     %funcline_regexp $is_mod_perl      %functionlineregexp
     $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 $hr_default $logsort $cvstree $cvsroot      $bylog $byfile $hr_default $logsort $cvstree $cvsroot
     $mimetype $defaultTextPlain $defaultViewable $allow_compress      $mimetype $defaultTextPlain $defaultViewable $allow_compress
Line 66  use vars qw (
Line 64  use vars qw (
     $cvstreedefault $body_tag $logo $defaulttitle $address      $cvstreedefault $body_tag $logo $defaulttitle $address
     $backcolor $long_intro $short_instruction $shortLogLen      $backcolor $long_intro $short_instruction $shortLogLen
     $show_author $dirtable $tablepadding $columnHeaderColorDefault      $show_author $dirtable $tablepadding $columnHeaderColorDefault
     $columnHeaderColorSorted $hr_breakable $showfunc $hr_ignwhite      $columnHeaderColorSorted $hr_breakable $hr_funout $hr_ignwhite
     $hr_ignkeysubst $diffcolorHeading $diffcolorEmpty $diffcolorRemove      $hr_ignkeysubst $diffcolorHeading $diffcolorEmpty $diffcolorRemove
     $diffcolorChange $diffcolorAdd $diffcolorDarkChange $difffontface      $diffcolorChange $diffcolorAdd $diffcolorDarkChange $difffontface
     $difffontsize $inputTextSize $mime_types $allow_annotate      $difffontsize $inputTextSize $mime_types $allow_annotate
Line 79  use vars qw (
Line 77  use vars qw (
     $use_moddate      $use_moddate
 );  );
   
 sub printDiffSelect($);  
 sub findLastModifiedSubdirs(@);  
 sub htmlify($;$);  
 sub spacedHtmlText($);  
 sub link($$);  
 sub revcmp($$);  
 sub fatal($$);  
 sub redirect($);  
 sub safeglob($);  
 sub getMimeTypeFromSuffix($);  
 sub doAnnotate($$);  
 sub doCheckout($$);  
 sub cvswebMarkup($$$);  
 sub viewable($);  
 sub doDiff($$$$$$);  
 sub getDirLogs($$@);  
 sub readLog($;$);  
 sub printLog($;$);  
 sub doLog($);  
 sub flush_diff_rows($$$$);  
 sub human_readable_diff($);  
 sub navigateHeader($$$$$);  
 sub plural_write($$);  
 sub readableTime($$);  
 sub clickablePath($$);  
 sub chooseCVSRoot();  
 sub chooseMirror();  
 sub fileSortCmp();  
 sub download_url($$;$);  
 sub download_link($$$;$);  
 sub toggleQuery($$);  
 sub urlencode($);  
 sub http_header(;$);  
 sub html_header($);  
 sub html_footer();  
 sub link_tags($);  
 sub forbidden_module($);  
   
 ##### Start of Configuration Area ########  ##### Start of Configuration Area ########
 use Cwd;  # == EDIT this ==
   
 # == EDIT this ==  
 # User configuration is stored in  # User configuration is stored in
 $config = undef;  $config = $ENV{'CVSWEB_CONFIG'} || '/usr/local/etc/cvsweb.conf';
   
 for ($ENV{CVSWEB_CONFIG},  
 #     '/home/knu/etc/cvsweb.conf',  
      '/usr/local/etc/cvsweb.conf',  
      getcwd . '/cvsweb.conf') {  
   $config = $_ if defined($_) && -r $_;  
 }  
   
 # == Configuration defaults ==  # == Configuration defaults ==
 # Defaults for configuration variables that shouldn't need  # Defaults for configuration variables that shouldn't need
 # to be configured..  # to be configured..
Line 145  $allow_version_select = 1;
Line 96  $allow_version_select = 1;
 $cvstreedefault = $body_tag = $logo = $defaulttitle = $address =  $cvstreedefault = $body_tag = $logo = $defaulttitle = $address =
 $backcolor = $long_intro = $short_instruction = $shortLogLen =  $backcolor = $long_intro = $short_instruction = $shortLogLen =
 $show_author = $dirtable = $tablepadding = $columnHeaderColorDefault =  $show_author = $dirtable = $tablepadding = $columnHeaderColorDefault =
 $columnHeaderColorSorted = $hr_breakable = $showfunc = $hr_ignwhite =  $columnHeaderColorSorted = $hr_breakable = $hr_funout = $hr_ignwhite =
 $hr_ignkeysubst = $diffcolorHeading = $diffcolorEmpty = $diffcolorRemove =  $hr_ignkeysubst = $diffcolorHeading = $diffcolorEmpty = $diffcolorRemove =
 $diffcolorChange = $diffcolorAdd = $diffcolorDarkChange = $difffontface =  $diffcolorChange = $diffcolorAdd = $diffcolorDarkChange = $difffontface =
 $difffontsize = $inputTextSize = $mime_types = $allow_annotate =  $difffontsize = $inputTextSize = $mime_types = $allow_annotate =
 $allow_markup = $use_java_script = $open_extern_window =  $allow_markup = $use_java_script = $open_extern_window =
 $extern_window_width = $extern_window_height = $edit_option_form =  $extern_window_width = $extern_window_height = $edit_option_form =
 $checkout_magic = $show_subdir_lastmod = $show_log_in_markup = $v =  $checkout_magic = $show_subdir_lastmod = $show_log_in_markup = $v =
 $navigationHeaderColor = $tableBorderColor = $markupLogColor =  $navigationHeaderColor = $tableBorderColor = $markupLogColor =
 $tabstop = $use_moddate = $moddate = undef;  $tabstop = $use_moddate = $moddate = undef;
   
 ##### End of configuration variables #####  ##### End of configuration variables #####
Line 162  use IPC::Open2;
Line 113  use IPC::Open2;
   
 $verbose = $v;  $verbose = $v;
 $checkoutMagic = "~checkout~";  $checkoutMagic = "~checkout~";
 $pathinfo = defined($ENV{PATH_INFO}) ? $ENV{PATH_INFO} : '';  $where = defined($ENV{'PATH_INFO'}) ? $ENV{'PATH_INFO'} : "";
 $where = $pathinfo;  
 $doCheckout = ($where =~ /^\/$checkoutMagic/);  $doCheckout = ($where =~ /^\/$checkoutMagic/);
 $where =~ s|^/($checkoutMagic)?||;  $where =~ s|^/($checkoutMagic)?||;
 $where =~ s|/+$||;  $where =~ s|/+$||;
 $scriptname = defined($ENV{SCRIPT_NAME}) ? $ENV{SCRIPT_NAME} : '';  ($scriptname = $ENV{'SCRIPT_NAME'}) =~ s|^/?|/|;
 $scriptname =~ s|^/?|/|;  
 $scriptname =~ s|/+$||;  $scriptname =~ s|/+$||;
 $scriptwhere = $scriptname;  
 if ($where) {  if ($where) {
     $scriptwhere .= '/' . urlencode($where);      $scriptwhere = $scriptname . '/' . urlencode($where);
 }  }
   else {
       $scriptwhere = $scriptname;
   }
   $scriptwhere =~ s|/+$||;
   
 $is_mod_perl = defined($ENV{MOD_PERL});  
   
 # in lynx, it it very annoying to have two links  # in lynx, it it very annoying to have two links
 # per file, so disable the link at the icon  # per file, so disable the link at the icon
 # in this case:  # in this case:
 $Browser = $ENV{HTTP_USER_AGENT};  $Browser = $ENV{'HTTP_USER_AGENT'};
 $is_lynx = ($Browser =~ m`^Lynx/`i);  $nofilelinks = ($Browser =~ m'^Lynx/');
 $is_w3m = ($Browser =~ m`^w3m/`i);  
 $is_msie = ($Browser =~ m`MSIE`);  
 $is_mozilla3 = ($Browser =~ m`^Mozilla/[3-9]`);  
   
 $is_textbased = ($is_lynx || $is_w3m);  
   
 $nofilelinks = $is_textbased;  
   
 # newer browsers accept gzip content encoding  # newer browsers accept gzip content encoding
 # and state this in a header  # and state this in a header
 # (netscape did always but didn't state it)  # (netscape did always but didn't state it)
Line 200  $nofilelinks = $is_textbased;
Line 143  $nofilelinks = $is_textbased;
 # Turn off gzip if running under mod_perl. piping does  # Turn off gzip if running under mod_perl. piping does
 # not work as expected inside the server. One can probably  # not work as expected inside the server. One can probably
 # achieve the same result using Apache::GZIPFilter.  # achieve the same result using Apache::GZIPFilter.
 $maycompress = (($ENV{HTTP_ACCEPT_ENCODING} =~ m`gzip`  $maycompress =(($ENV{'HTTP_ACCEPT_ENCODING'} =~ m|gzip|
                  || $is_mozilla3)                  || $Browser =~ m%^Mozilla/3%)
                 && !$is_msie                 && ($Browser !~ m/MSIE/)
                 && !$is_mod_perl);                 && !defined($ENV{'MOD_PERL'}));
   
 # put here the variables we need in order  # put here the variables we need in order
 # to hold our state - they will be added (with  # to hold our state - they will be added (with
 # their current value) to any link/query string  # their current value) to any link/query string
 # you construct  # you construct
 @stickyvars = qw(cvsroot hideattic sortby logsort f only_with_tag);  @stickyvars = ('cvsroot','hideattic','sortby','logsort','f','only_with_tag');
   
 if (-f $config) {  if (-f $config) {
     do $config;      do "$config";
 }  }
 else {  else {
    &fatal("500 Internal Error",     &fatal("500 Internal Error",
Line 223  else {
Line 166  else {
 }  }
   
 undef %input;  undef %input;
 $query = $ENV{QUERY_STRING};  if ($query = $ENV{'QUERY_STRING'}) {
   
 if (defined($query) && $query ne '') {  
     foreach (split(/&/, $query)) {      foreach (split(/&/, $query)) {
         s/%(..)/sprintf("%c", hex($1))/ge;      # unquote %-quoted          s/%(..)/sprintf("%c", hex($1))/ge;      # unquote %-quoted
         if (/(\S+)=(.*)/) {          if (/(\S+)=(.*)/) {
Line 237  if (defined($query) && $query ne '') {
Line 178  if (defined($query) && $query ne '') {
     }      }
 }  }
   
 # For backwards compability, set only_with_tag to only_on_branch if set.  # For backwards compability, set only_with_tag to only_on_branch if set.
 $input{only_with_tag} = $input{only_on_branch}  $input{only_with_tag} = $input{only_on_branch}
     if (defined($input{only_on_branch}));      if (defined($input{only_on_branch}));
   
Line 264  foreach (keys %DEFAULTVALUE)
Line 205  foreach (keys %DEFAULTVALUE)
         }          }
     }      }
 }  }
   
 $barequery = "";  $barequery = "";
 foreach (@stickyvars) {  foreach (@stickyvars) {
     # construct a query string with the sticky non default parameters set      # construct a query string with the sticky non default parameters set
     if (defined($input{$_}) && $input{$_} ne '' &&      if (defined($input{$_}) && $input{$_} ne "" && $input{$_} ne $DEFAULTVALUE{$_}) {
         !(defined($DEFAULTVALUE{$_}) && $input{$_} eq $DEFAULTVALUE{$_})) {          if ($barequery) {
         if ($barequery) {  
             $barequery = $barequery . "&amp;";              $barequery = $barequery . "&amp;";
         }          }
         my $thisval = urlencode($_) . "=" . urlencode($input{$_});          my $thisval = urlencode($_) . "=" . urlencode($input{$_});
Line 311  else {
Line 251  else {
   
 $hr_default = $input{'f'} eq 'h';  $hr_default = $input{'f'} eq 'h';
   
 $logsort = $input{'logsort'};  $logsort = $input{"logsort"};
   
   
 ## Default CVS-Tree  ## Default CVS-Tree
Line 336  foreach my $k (keys %ICONS) {
Line 276  foreach my $k (keys %ICONS) {
     no strict 'refs';      no strict 'refs';
     my ($itxt,$ipath,$iwidth,$iheight) = @{$ICONS{$k}};      my ($itxt,$ipath,$iwidth,$iheight) = @{$ICONS{$k}};
     if ($ipath) {      if ($ipath) {
         ${"${k}icon"} = "<IMG SRC=\"$ipath\" ALT=\"$itxt\" BORDER=\"0\" WIDTH=\"$iwidth\" HEIGHT=\"$iheight\">";          $ {"${k}icon"} = "<IMG SRC=\"$ipath\" ALT=\"$itxt\" BORDER=\"0\" WIDTH=\"$iwidth\" HEIGHT=\"$iheight\">";
     }      }
     else {      else {
         ${"${k}icon"} = $itxt;          $ {"${k}icon"} = $itxt;
     }      }
 }  }
   
Line 347  foreach my $k (keys %ICONS) {
Line 287  foreach my $k (keys %ICONS) {
 do "$config-$cvstree" if (-f "$config-$cvstree");  do "$config-$cvstree" if (-f "$config-$cvstree");
   
 $prcategories = '(?:' . join('|', @prcategories) . ')';  $prcategories = '(?:' . join('|', @prcategories) . ')';
 $prcgi .= '%s' if defined($prcgi) && $prcgi !~ /%s/;  
   
 $fullname = $cvsroot . '/' . $where;  $fullname = $cvsroot . '/' . $where;
 $mimetype = &getMimeTypeFromSuffix ($fullname);  $mimetype = &getMimeTypeFromSuffix ($fullname);
Line 357  $defaultViewable = $allow_markup && viewable($mimetype
Line 296  $defaultViewable = $allow_markup && viewable($mimetype
 # search for GZIP if compression allowed  # search for GZIP if compression allowed
 # We've to find out if the GZIP-binary exists .. otherwise  # We've to find out if the GZIP-binary exists .. otherwise
 # ge get an Internal Server Error if we try to pipe the  # ge get an Internal Server Error if we try to pipe the
 # output through the nonexistent gzip ..  # output through the nonexistent gzip ..
 # any more elegant ways to prevent this are welcome!  # any more elegant ways to prevent this are welcome!
 if ($allow_compress && $maycompress) {  if ($allow_compress && $maycompress) {
     foreach (split(/:/, $ENV{PATH})) {      foreach (split(/:/, $ENV{PATH})) {
Line 373  if (-d $fullname) {
Line 312  if (-d $fullname) {
     # ensure, that directories always end with (exactly) one '/'      # ensure, that directories always end with (exactly) one '/'
     # to allow relative URL's. If they're not, make a redirect.      # to allow relative URL's. If they're not, make a redirect.
     ##      ##
       my $pathinfo = defined($ENV{'PATH_INFO'}) ? $ENV{'PATH_INFO'} : "";
     if (!($pathinfo =~ m|/$|) || ($pathinfo =~ m |/{2,}$|)) {      if (!($pathinfo =~ m|/$|) || ($pathinfo =~ m |/{2,}$|)) {
         redirect ($scriptwhere . '/' . $query);          redirect ($scriptwhere . '/' . $query);
     }      }
Line 407  elsif (-d $fullname) {
Line 347  elsif (-d $fullname) {
         getDirLogs($cvsroot,$where,@subLevelFiles);          getDirLogs($cvsroot,$where,@subLevelFiles);
   
         if ($where eq '/') {          if ($where eq '/') {
             html_header($defaulttitle);              html_header("$defaulttitle");
             $long_intro =~ s/!!CVSROOTdescr!!/$CVSROOTdescr{$cvstree}/g;              $long_intro =~ s/!!CVSROOTdescr!!/$CVSROOTdescr{$cvstree}/g;
             print $long_intro;              print $long_intro;
         }          }
         else {          else {
             html_header($where);              html_header("$where");
             print $short_instruction;              print $short_instruction;
         }          }
   
Line 438  elsif (-d $fullname) {
Line 378  elsif (-d $fullname) {
                 $input{only_with_tag};                  $input{only_with_tag};
   
         }          }
   
   
   
         print "<HR NOSHADE>\n";          print "<HR NOSHADE>\n";
         # Using <MENU> in this manner violates the HTML2.0 spec but          # Using <MENU> in this manner violates the HTML2.0 spec but
         # provides the results that I want in most browsers.  Another          # provides the results that I want in most browsers.  Another
         # case of layout spooging up HTML.          # case of layout spooging up HTML.
   
         my $infocols = 0;          my $infocols = 0;
         if ($dirtable) {          if ($dirtable) {
             if (defined($tableBorderColor)) {              if (defined($tableBorderColor)) {
Line 453  elsif (-d $fullname) {
Line 393  elsif (-d $fullname) {
             }              }
             print "<table  width=\"100%\" border=0 cellspacing=1 cellpadding=$tablepadding>\n";              print "<table  width=\"100%\" border=0 cellspacing=1 cellpadding=$tablepadding>\n";
             $infocols++;              $infocols++;
             print "<tr><th align=left bgcolor=\"" . (($byfile) ?              print "<tr><th align=left bgcolor=\"" . (($byfile) ?
                                                    $columnHeaderColorSorted :                                                     $columnHeaderColorSorted :
                                                    $columnHeaderColorDefault) . "\">";                                                     $columnHeaderColorDefault) . "\">";
             print "<a href=\"./" . &toggleQuery("sortby","file") .              print "<a href=\"./" . &toggleQuery("sortby","file") .
                 "#dirlist\">" if (!$byfile);                  "#dirlist\">" if (!$byfile);
Line 465  elsif (-d $fullname) {
Line 405  elsif (-d $fullname) {
             # with revision information:              # with revision information:
             if (scalar(%fileinfo)) {              if (scalar(%fileinfo)) {
                 $infocols++;                  $infocols++;
                 print "<th align=left bgcolor=\"" . (($byrev) ?                  print "<th align=left bgcolor=\"" . (($byrev) ?
                                                    $columnHeaderColorSorted :                                                     $columnHeaderColorSorted :
                                                    $columnHeaderColorDefault) . "\">";                                                     $columnHeaderColorDefault) . "\">";
                 print "<a href=\"./" . &toggleQuery ("sortby","rev") .                  print "<a href=\"./" . &toggleQuery ("sortby","rev") .
                     "#dirlist\">" if (!$byrev);                      "#dirlist\">" if (!$byrev);
Line 474  elsif (-d $fullname) {
Line 414  elsif (-d $fullname) {
                 print "</a>" if (!$byrev);                  print "</a>" if (!$byrev);
                 print "</th>";                  print "</th>";
                 $infocols++;                  $infocols++;
                 print "<th align=left bgcolor=\"" . (($bydate) ?                  print "<th align=left bgcolor=\"" . (($bydate) ?
                                                    $columnHeaderColorSorted :                                                     $columnHeaderColorSorted :
                                                    $columnHeaderColorDefault) . "\">";                                                     $columnHeaderColorDefault) . "\">";
                 print "<a href=\"./" . &toggleQuery ("sortby","date") .                  print "<a href=\"./" . &toggleQuery ("sortby","date") .
                     "#dirlist\">" if (!$bydate);                      "#dirlist\">" if (!$bydate);
Line 484  elsif (-d $fullname) {
Line 424  elsif (-d $fullname) {
                 print "</th>";                  print "</th>";
                 if ($show_author) {                  if ($show_author) {
                     $infocols++;                      $infocols++;
                     print "<th align=left bgcolor=\"" . (($byauthor) ?                      print "<th align=left bgcolor=\"" . (($byauthor) ?
                                                    $columnHeaderColorSorted :                                                     $columnHeaderColorSorted :
                                                    $columnHeaderColorDefault) . "\">";                                                     $columnHeaderColorDefault) . "\">";
                     print "<a href=\"./" . &toggleQuery ("sortby","author") .                      print "<a href=\"./" . &toggleQuery ("sortby","author") .
                             "#dirlist\">" if (!$byauthor);                              "#dirlist\">" if (!$byauthor);
Line 494  elsif (-d $fullname) {
Line 434  elsif (-d $fullname) {
                     print "</th>";                      print "</th>";
                 }                  }
                 $infocols++;                  $infocols++;
                 print "<th align=left bgcolor=\"" . (($bylog) ?                  print "<th align=left bgcolor=\"" . (($bylog) ?
                                                $columnHeaderColorSorted :                                                 $columnHeaderColorSorted :
                                                $columnHeaderColorDefault) . "\">";                                                 $columnHeaderColorDefault) . "\">";
                 print "<a href=\"./", toggleQuery("sortby","log"), "#dirlist\">" if (!$bylog);                  print "<a href=\"./", toggleQuery("sortby","log"), "#dirlist\">" if (!$bylog);
                 print "Last log entry";                  print "Last log entry";
Line 513  elsif (-d $fullname) {
Line 453  elsif (-d $fullname) {
             print "<menu>\n";              print "<menu>\n";
         }          }
         my $dirrow = 0;          my $dirrow = 0;
   
         my $i;          my $i;
         lookingforattic:          lookingforattic:
         for ($i = 0; $i <= $#dir; $i++) {          for ($i = 0; $i <= $#dir; $i++) {
Line 528  elsif (-d $fullname) {
Line 468  elsif (-d $fullname) {
             closedir($dh);              closedir($dh);
         }          }
   
         my $hideAtticToggleLink = "<a href=\"./" .          my $hideAtticToggleLink = "<a href=\"./" .
                 &toggleQuery ("hideattic") .                  &toggleQuery ("hideattic") .
                 "#dirlist\">[Hide]</a>" if (!$input{'hideattic'});                  "#dirlist\">[Hide]</a>" if (!$input{'hideattic'});
   
Line 590  elsif (-d $fullname) {
Line 530  elsif (-d $fullname) {
                     }                      }
                     print " ", &link($_ . "/", $url), $attic;                      print " ", &link($_ . "/", $url), $attic;
                     if ($_ eq "Attic") {                      if ($_ eq "Attic") {
                         print "&nbsp; <a href=\"./" .                          print "&nbsp; <a href=\"./" .
                             &toggleQuery ("hideattic") .                              &toggleQuery ("hideattic") .
                                 "#dirlist\">[Don't hide]</a>";                                  "#dirlist\">[Don't hide]</a>";
                     }                      }
                 }                  }
                 # Show last change in dir                  # Show last change in dir
                 if ($filename) {                  if ($filename) {
                     print "</td><td>&nbsp;</td><td>&nbsp;" if ($dirtable);                      print "</td><td>&nbsp;</td><td>&nbsp;" if ($dirtable);
Line 663  elsif (-d $fullname) {
Line 603  elsif (-d $fullname) {
                 print " ", &link($_, $url), $attic;                  print " ", &link($_, $url), $attic;
                 print "</td><td>&nbsp;" if ($dirtable);                  print "</td><td>&nbsp;" if ($dirtable);
                 download_link($fileurl,                  download_link($fileurl,
                         $rev, $rev,                          $rev, $rev,
                         $defaultViewable ? "text/x-cvsweb-markup" : undef);                          $defaultViewable ? "text/x-cvsweb-markup" : undef);
                 print "</td><td>&nbsp;" if ($dirtable);                  print "</td><td>&nbsp;" if ($dirtable);
                 if ($date) {                  if ($date) {
Line 691  elsif (-d $fullname) {
Line 631  elsif (-d $fullname) {
             print "</td></tr></table>";              print "</td></tr></table>";
         }          }
         print "". ($dirtable == 1) ? "</table>" : "</menu>" . "\n";          print "". ($dirtable == 1) ? "</table>" : "</menu>" . "\n";
   
         if ($filesexists && !$filesfound) {          if ($filesexists && !$filesfound) {
             print "<P><B>NOTE:</B> There are $filesexists files, but none matches the current tag ($input{only_with_tag})\n";              print "<P><B>NOTE:</B> There are $filesexists files, but none matches the current tag ($input{only_with_tag})\n";
         }          }
         if ($input{only_with_tag} && (!%tags || !$tags{$input{only_with_tag}})) {          if ($input{only_with_tag} && (!%tags || !$tags{$input{only_with_tag}})) {
             %tags = %alltags              %tags = %alltags
         }          }
         if (scalar %tags          if (scalar %tags
             || $input{only_with_tag}              || $input{only_with_tag}
             || $edit_option_form              || $edit_option_form
             || defined($input{"options"})) {              || defined($input{"options"})) {
             print "<hr size=1 NOSHADE>";              print "<hr size=1 NOSHADE>";
Line 720  elsif (-d $fullname) {
Line 660  elsif (-d $fullname) {
             print ">";              print ">";
             print "<OPTION VALUE=\"\">All tags / default branch\n";              print "<OPTION VALUE=\"\">All tags / default branch\n";
             foreach my $tag (reverse sort { lc $a cmp lc $b } keys %tags) {              foreach my $tag (reverse sort { lc $a cmp lc $b } keys %tags) {
                 print "<OPTION",defined($input{only_with_tag}) &&                  print "<OPTION",defined($input{only_with_tag}) &&
                        $input{only_with_tag} eq $tag ? " SELECTED" : "",                         $input{only_with_tag} eq $tag ? " SELECTED":"",
                        ">$tag\n";                         ">$tag\n";
             }              }
             print "</SELECT>\n";              print "</SELECT>\n";
Line 754  elsif (-d $fullname) {
Line 694  elsif (-d $fullname) {
             print "<OPTION VALUE=rev",$logsort eq "rev" ? " SELECTED" : "", ">Revision";              print "<OPTION VALUE=rev",$logsort eq "rev" ? " SELECTED" : "", ">Revision";
             print "</SELECT></td></tr>";              print "</SELECT></td></tr>";
             print "<tr><td>Diff format: ";              print "<tr><td>Diff format: ";
             printDiffSelect(0);              printDiffSelect();
             print "</td>";              print "</td>";
             print "<td>Show Attic files: ";              print "<td>Show Attic files: ";
             print "<INPUT NAME=hideattic TYPE=CHECKBOX", $input{'hideattic'} ? " CHECKED" : "",              print "<INPUT NAME=hideattic TYPE=CHECKBOX", $input{'hideattic'}?" CHECKED":"",
             "></td></tr>\n";              "></td></tr>\n";
             print "<tr><td align=center colspan=2><input type=submit value=\"Change Options\">";              print "<tr><td align=center colspan=2><input type=submit value=\"Change Options\">";
             print "</td></tr></table></center></FORM>\n";              print "</td></tr></table></center></FORM>\n";
         }          }
         print &html_footer;          print &html_footer;
         print "</BODY></HTML>\n";          print "</BODY></HTML>\n";
     }      }
   
 ###############################  ###############################
 # View Files  # View Files
Line 838  elsif (-d $fullname) {
Line 778  elsif (-d $fullname) {
     }      }
 ## End MAIN  ## End MAIN
   
 sub printDiffSelect($) {  sub printDiffSelect {
     my ($use_java_script) = @_;      my ($use_java_script) = @_;
       $use_java_script = 0 if (!defined($use_java_script));
     my ($f) = $input{'f'};      my ($f) = $input{'f'};
     print "<SELECT NAME=\"f\"";      print "<SELECT NAME=\"f\"";
     print " onchange=\"submit()\"" if ($use_java_script);      print " onchange=\"submit()\"" if ($use_java_script);
Line 852  sub printDiffSelect($) {
Line 793  sub printDiffSelect($) {
     print "</SELECT>";      print "</SELECT>";
 }  }
   
 sub findLastModifiedSubdirs(@) {  sub findLastModifiedSubdirs {
     my (@dirs) = @_;      my (@dirs) = @_;
     my ($dirname, @files);      my ($dirname, @files);
   
Line 886  sub findLastModifiedSubdirs(@) {
Line 827  sub findLastModifiedSubdirs(@) {
     return @files;      return @files;
 }  }
   
 sub htmlify($;$) {  sub htmlify {
         my($string, $extra) = @_;          my($string, $pr) = @_;
   
         # Special Characters; RFC 1866          # Special Characters; RFC 1866
         $string =~ s/&/&amp;/g;          $string =~ s/&/&amp;/g;
         $string =~ s/\"/&quot;/g;          $string =~ s/\"/&quot;/g;
         $string =~ s/</&lt;/g;          $string =~ s/</&lt;/g;
         $string =~ s/>/&gt;/g;          $string =~ s/>/&gt;/g;
   
         # get URL's as link ..          # get URL's as link ..
         $string =~ s`(http|ftp|https)(://[-a-zA-Z0-9%.~:_/]+)([?&]([-a-zA-Z0-9%.~:_]+)=([-a-zA-Z0-9%.~:_])+)*`<A HREF="$1$2$3">$1$2$3</A>`g;          $string =~ s`(http|ftp|https)(://[-a-zA-Z0-9%.~:_/]+)([?&]([-a-zA-Z0-9%.~:_]+)=([-a-zA-Z0-9%.~:_])+)*`<A HREF="$1$2$3">$1$2$3</A>`;
         # get e-mails as link          # get e-mails as link
         $string =~ s`([-a-zA-Z0-9_.]+@([-a-zA-Z0-9]+\.)+[A-Za-z]{2,4})`<A HREF="mailto:$1">$1</A>`g;          $string =~ s`([-a-zA-Z0-9_.]+@([-a-zA-Z0-9]+\.)+[A-Za-z]{2,4})`<A HREF="mailto:$1">$1</A>`;
   
         if ($extra) {          # get #PR as link ..
             # get PR #'s as link ..          if ($pr && defined($prcgi)) {
             if (defined($prcgi)) {              1 while $string =~ s`\b(pr[:#]?\s*(?:#?\d+[,\s]\s*)*#?)(\d+)\b`$1<A HREF="$prcgi?pr=$2">$2</A>`i;
                 1 while $string =~ s`\b(pr[:#]?\s*(?:#?\d+[,\s]\s*)*#?)(\d+)\b`sprintf('%s<A HREF="%s">%s</A>', $1, sprintf($prcgi, $2), $2)`ie;              $string =~ s`\b${prcategories}/(\d+)\b`<A HREF="$prcgi?pr=$1">$&</A>`igo;
                 $string =~ s`\b${prcategories}/(\d+)\b`sprintf('<A HREF="%s">%s</A>', sprintf($prcgi, $1), $&)`igeo;  
             }  
   
             # get manpage specs as link ..  
             if (defined($mancgi)) {  
                 $string =~ s`\b([a-zA-Z]\w+)\(([0-9n])\)\B`sprintf('<A HREF="%s">%s</A>', sprintf($mancgi, $2, $1), $&)`ge;  
             }  
         }          }
   
         return $string;          return $string;
 }  }
   
 sub spacedHtmlText($) {  sub spacedHtmlText {
         local $_ = $_[0];          my($string, $pr) = @_;
   
         # Cut trailing spaces          # Cut trailing spaces
         s/\s+\n$//;          s/\s+$//;
   
         # Expand tabs          # Expand tabs
         s/\t+/' ' x (length($&) * $tabstop - length($`) % $tabstop)/e          $string =~ s/\t+/' ' x (length($&) * $tabstop - length($`) % $tabstop)/e
             if (defined($tabstop));              if (defined($tabstop));
   
         # replace <tab> and <space> (\001 is to protect us from htmlify)          # replace <tab> and <space> (\001 is to protect us from htmlify)
         # gzip can make excellent use of this repeating pattern :-)          # gzip can make excellent use of this repeating pattern :-)
         s/\001/\001%/g; #protect our & substitute          $string =~ s/\001/\001%/g; #protect our & substitute
         if ($hr_breakable) {          if ($hr_breakable) {
             # make every other space 'breakable'              # make every other space 'breakable'
             s/  / \001nbsp; \001nbsp; \001nbsp; \001nbsp;/g;    # <tab>              $string =~ s/       / \001nbsp; \001nbsp; \001nbsp; \001nbsp;/g;    # <tab>
             s/  / \001nbsp;/g;                              # 2 * <space>              $string =~ s/  / \001nbsp;/g;                              # 2 * <space>
             # leave single space as it is              # leave single space as it is
         }          }
         else {          else {
             s/  /\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;/g;              $string =~ s/       /\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;\001nbsp;/g;
             s/ /\001nbsp;/g;              $string =~ s/ /\001nbsp;/g;
         }          }
   
         $_ = htmlify($_);          $string = htmlify($string);
   
         # unescape          # unescape
         s/\001([^%])/&$1/g;          $string =~ s/\001([^%])/&$1/g;
         s/\001%/\001/g;          $string =~ s/\001%/\001/g;
   
         return $_;          return $string;
 }  }
   
 sub link($$) {  sub link {
         my($name, $where) = @_;          my($name, $where) = @_;
   
         return "<A HREF=\"$where\">$name</A>\n";          return "<A HREF=\"$where\">$name</A>\n";
 }  }
   
 sub revcmp($$) {  sub revcmp {
         my($rev1, $rev2) = @_;          my($rev1, $rev2) = @_;
   
         # make no comparison for a tag or a branch  
         return 0 if $rev1 =~ /[^\d.]/ || $rev2 =~ /[^\d.]/;  
   
         my(@r1) = split(/\./, $rev1);          my(@r1) = split(/\./, $rev1);
         my(@r2) = split(/\./, $rev2);          my(@r2) = split(/\./, $rev2);
         my($a,$b);          my($a,$b);
Line 975  sub revcmp($$) {
Line 905  sub revcmp($$) {
         return 0;          return 0;
 }  }
   
 sub fatal($$) {  sub fatal {
         my($errcode, $errmsg) = @_;          my($errcode, $errmsg) = @_;
         if ($is_mod_perl) {          if (defined($ENV{'MOD_PERL'})) {
                 Apache->request->status((split(/ /, $errcode))[0]);                  Apache->request->status((split(/ /, $errcode))[0]);
         }          }
         else {          else {
                 print "Status: $errcode\r\n";                  print "Status: $errcode\n";
         }          }
         html_header("Error");          html_header("Error");
         print "Error: $errmsg\n";          print "Error: $errmsg\n";
Line 989  sub fatal($$) {
Line 919  sub fatal($$) {
         exit(1);          exit(1);
 }  }
   
 sub redirect($) {  sub redirect {
         my($url) = @_;          my($url) = @_;
         if ($is_mod_perl) {          if (defined($ENV{'MOD_PERL'})) {
                 Apache->request->status(301);                  Apache->request->status(301);
                 Apache->request->header_out(Location => $url);                  Apache->request->header_out(Location => $url);
         }          }
         else {          else {
                 print "Status: 301 Moved\r\n";                  print "Status: 301 Moved\n";
                 print "Location: $url\r\n";                  print "Location: $url\n";
         }          }
         html_header("Moved");          html_header("Moved");
         print "This document is located <A HREF=$url>here</A>.\n";          print "This document is located <A HREF=$url>here</A>.\n";
Line 1005  sub redirect($) {
Line 935  sub redirect($) {
         exit(1);          exit(1);
 }  }
   
 sub safeglob($) {  sub safeglob {
         my ($filename) = @_;          my ($filename) = @_;
         my ($dirname);          my ($dirname);
         my (@results);          my (@results);
Line 1034  sub safeglob($) {
Line 964  sub safeglob($) {
         @results;          @results;
 }  }
   
 sub getMimeTypeFromSuffix($) {  sub getMimeTypeFromSuffix {
     my ($fullname) = @_;      my ($fullname) = @_;
     my ($mimetype, $suffix);      my ($mimetype, $suffix);
     my $fh = do {local(*FH);};      my $fh = do {local(*FH);};
Line 1042  sub getMimeTypeFromSuffix($) {
Line 972  sub getMimeTypeFromSuffix($) {
     ($suffix = $fullname) =~ s/^.*\.([^.]*)$/$1/;      ($suffix = $fullname) =~ s/^.*\.([^.]*)$/$1/;
     $mimetype = $MTYPES{$suffix};      $mimetype = $MTYPES{$suffix};
     $mimetype = $MTYPES{'*'} if (!$mimetype);      $mimetype = $MTYPES{'*'} if (!$mimetype);
   
     if (!$mimetype && -f $mime_types) {      if (!$mimetype && -f $mime_types) {
         # okey, this is something special - search the          # okey, this is something special - search the
         # mime.types database          # mime.types database
Line 1055  sub getMimeTypeFromSuffix($) {
Line 985  sub getMimeTypeFromSuffix($) {
         }          }
         close ($fh);          close ($fh);
     }      }
   
 # okey, didn't find anything useful ..  # okey, didn't find anything useful ..
     if (!($mimetype =~ /\S\/\S/)) {      if (!($mimetype =~ /\S\/\S/)) {
         $mimetype = "text/plain";          $mimetype = "text/plain";
Line 1066  sub getMimeTypeFromSuffix($) {
Line 996  sub getMimeTypeFromSuffix($) {
 ###############################  ###############################
 # show Annotation  # show Annotation
 ###############################  ###############################
 sub doAnnotate($$) {  sub doAnnotate ($$) {
     my ($rev) = @_;      my ($rev) = @_;
     my ($pid);      my ($pid);
     my ($pathname, $filename);      my ($pathname, $filename);
Line 1075  sub doAnnotate($$) {
Line 1005  sub doAnnotate($$) {
   
     # make sure the revisions a wellformed, for security      # make sure the revisions a wellformed, for security
     # reasons ..      # reasons ..
     if ($rev =~ /[^\w.]/) {      if (!($rev =~ /^[\d\.]+$/)) {
         &fatal("404 Not Found",          &fatal("404 Not Found",
                 "Malformed query \"$ENV{QUERY_STRING}\"");                  "Malformed query \"$ENV{'QUERY_STRING'}\"");
     }      }
   
     ($pathname = $where) =~ s/(Attic\/)?[^\/]*$//;      ($pathname = $where) =~ s/(Attic\/)?[^\/]*$//;
Line 1085  sub doAnnotate($$) {
Line 1015  sub doAnnotate($$) {
   
     http_header();      http_header();
   
     navigateHeader($scriptwhere,$pathname,$filename,$rev, "annotate");      navigateHeader ($scriptwhere,$pathname,$filename,$rev, "annotate");
     print "<h3 align=center>Annotation of $pathname$filename, Revision $rev</h3>\n";      print "<h3 align=center>Annotation of $pathname$filename, Revision $rev</h3>\n";
   
     # this seems to be necessary      # this seems to be necessary
Line 1097  sub doAnnotate($$) {
Line 1027  sub doAnnotate($$) {
     # the public domain.      # the public domain.
     # we could abandon the use of rlog, rcsdiff and co using      # we could abandon the use of rlog, rcsdiff and co using
     # the cvsserver in a similiar way one day (..after rewrite)      # the cvsserver in a similiar way one day (..after rewrite)
     $pid = open2($reader, $writer, "cvs server") || fatal ("500 Internal Error",      $pid = open2($reader, $writer, "cvs server") || fatal ("500 Internal Error",
                                                                "Fatal Error - unable to open cvs for annotation");                                                                 "Fatal Error - unable to open cvs for annotation");
   
     # OK, first send the request to the server.  A simplified example is:      # OK, first send the request to the server.  A simplified example is:
     #     Root /home/kingdon/zwork/cvsroot      #     Root /home/kingdon/zwork/cvsroot
     #     Argument foo/xx      #     Argument foo/xx
Line 1109  sub doAnnotate($$) {
Line 1039  sub doAnnotate($$) {
     #     /home/kingdon/zwork/cvsroot      #     /home/kingdon/zwork/cvsroot
     #     annotate      #     annotate
     # although as you can see there are a few more details.      # although as you can see there are a few more details.
   
     print $writer "Root $cvsroot\n";      print $writer "Root $cvsroot\n";
     print $writer "Valid-responses ok error Valid-requests Checked-in Updated Merged Removed M E\n";      print $writer "Valid-responses ok error Valid-requests Checked-in Updated Merged Removed M E\n";
     # Don't worry about sending valid-requests, the server just needs to      # Don't worry about sending valid-requests, the server just needs to
Line 1123  sub doAnnotate($$) {
Line 1053  sub doAnnotate($$) {
     # least to the point of including the directories down to the one      # least to the point of including the directories down to the one
     # containing the file in question).      # containing the file in question).
     # So if $where is "dir/sdir/file", then @dirs will be ("dir","sdir","file")      # So if $where is "dir/sdir/file", then @dirs will be ("dir","sdir","file")
     my @dirs = split('/', $where);      my @dirs = split (/\//, $where);
     my $path = "";      my $path = "";
     foreach (@dirs) {      foreach (@dirs) {
         if ($path eq "") {          if ($path eq "") {
             # In our example, $_ is "dir".              # In our example, $_ is "dir".
             $path = $_;              $path = $_;
         }          }
         else {          else {
             print $writer "Directory $path\n";              print $writer "Directory " . $path . "\n";
             print $writer "$cvsroot/$path\n";              print $writer "$cvsroot/" . $path ."\n";
             # In our example, $_ is "sdir" and $path becomes "dir/sdir"              # In our example, $_ is "sdir" and $path becomes "dir/sdir"
             # And the next time, "file" and "dir/sdir/file" (which then gets              # And the next time, "file" and "dir/sdir/file" (which then gets
             # ignored, because we don't need to send Directory for the file).              # ignored, because we don't need to send Directory for the file).
             $path .= "/$_";              $path = $path . "/" . $_;
         }          }
     }      }
     # And the last "Directory" before "annotate" is the top level.      # And the last "Directory" before "annotate" is the top level.
     print $writer "Directory .\n";      print $writer "Directory .\n";
     print $writer "$cvsroot\n";      print $writer "$cvsroot\n";
   
     print $writer "annotate\n";      print $writer "annotate\n";
     # OK, we've sent our command to the server.  Thing to do is to      # OK, we've sent our command to the server.  Thing to do is to
     # close the writer side and get all the responses.  If "cvs server"      # close the writer side and get all the responses.  If "cvs server"
     # were nicer about buffering, then we could just leave it open, I think.      # were nicer about buffering, then we could just leave it open, I think.
     close ($writer) || die "cannot close: $!";      close ($writer) || die "cannot close: $!";
   
     # Ready to get the responses from the server.      # Ready to get the responses from the server.
     # For example:      # For example:
     #     E Annotations for foo/xx      #     E Annotations for foo/xx
     #     E ***************      #     E ***************
     #     M 1.3          (kingdon  06-Sep-97): hello      #     M 1.3          (kingdon  06-Sep-97): hello
     #     ok      #     ok
     my ($lineNr) = 0;      my ($lineNr) = 0;
     my ($oldLrev, $oldLusr) = ("", "");      my ($oldLrev, $oldLusr) = ("", "");
Line 1193  sub doAnnotate($$) {
Line 1123  sub doAnnotate($$) {
             $oldLusr = $lusr;              $oldLusr = $lusr;
             # is there a less timeconsuming way to strip spaces ?              # is there a less timeconsuming way to strip spaces ?
             ($lrev = $lrev) =~ s/\s+//g;              ($lrev = $lrev) =~ s/\s+//g;
             my $isCurrentRev = ($rev eq $lrev);              my $isCurrentRev = ("$rev" eq "$lrev");
   
             print "<b>" if ($isCurrentRev);              print "<b>" if ($isCurrentRev);
             printf ("%8s%s%8s %4d:", $revprint, ($isCurrentRev ? "|" : " "), $usrprint, $lineNr);              printf ("%8s%s%8s %4d:", $revprint, ($isCurrentRev ? "|" : " "), $usrprint, $lineNr);
             print spacedHtmlText($line);              print spacedHtmlText($line);
Line 1221  sub doAnnotate($$) {
Line 1151  sub doAnnotate($$) {
 ###############################  ###############################
 # make Checkout  # make Checkout
 ###############################  ###############################
 sub doCheckout($$) {  sub doCheckout {
     my ($fullname, $rev) = @_;      my ($fullname, $rev) = @_;
     my ($mimetype,$revopt);      my ($mimetype,$revopt);
     my $fh = do {local(*FH);};      my $fh = do {local(*FH);};
   
     if ($rev eq 'HEAD' || $rev eq '.') {  
         $rev = undef;  
     }  
   
     # make sure the revisions a wellformed, for security      # make sure the revisions a wellformed, for security
     # reasons ..      # reasons ..
     if (defined($rev) && $rev =~ /[^\w.]/) {      if (defined($rev) && !($rev =~ /^[\d\.]+$/)) {
         &fatal("404 Not Found",          &fatal("404 Not Found",
                 "Malformed query \"$ENV{QUERY_STRING}\"");                  "Malformed query \"$ENV{'QUERY_STRING'}\"");
     }      }
   
     # get mimetype      # get mimetype
Line 1259  sub doCheckout($$) {
Line 1185  sub doCheckout($$) {
             $moddate=$date{$symrev{HEAD}};              $moddate=$date{$symrev{HEAD}};
         }          }
     }      }
   
     ### just for the record:      ### just for the record:
     ### 'cvs co' seems to have a bug regarding single checkout of      ### 'cvs co' seems to have a bug regarding single checkout of
     ### directories/files having spaces in it;      ### directories/files having spaces in it;
Line 1268  sub doCheckout($$) {
Line 1194  sub doCheckout($$) {
     # Safely for a child process to read from.      # Safely for a child process to read from.
     if (! open($fh, "-|")) { # child      if (! open($fh, "-|")) { # child
       open(STDERR, ">&STDOUT"); # Redirect stderr to stdout        open(STDERR, ">&STDOUT"); # Redirect stderr to stdout
       exec("cvs", "-Rld", $cvsroot, "co", "-p", $revopt, $where);        exec("cvs", "-d", "$cvsroot", "co", "-p", "$revopt", "$where");
     }      }
 #===================================================================  #===================================================================
 #Checking out squid/src/ftp.c  #Checking out squid/src/ftp.c
 #RCS:  /usr/src/CVS/squid/src/ftp.c,v  #RCS:  /usr/src/CVS/squid/src/ftp.c,v
Line 1308  sub doCheckout($$) {
Line 1234  sub doCheckout($$) {
     close($fh);      close($fh);
 }  }
   
 sub cvswebMarkup($$$) {  sub cvswebMarkup {
     my ($filehandle,$fullname,$revision) = @_;      my ($filehandle,$fullname,$revision) = @_;
     my ($pathname, $filename);      my ($pathname, $filename);
   
Line 1318  sub cvswebMarkup($$$) {
Line 1244  sub cvswebMarkup($$$) {
   
     http_header();      http_header();
   
     navigateHeader($scriptwhere, $pathname, $filename, $revision, "view");      navigateHeader ($scriptwhere, $pathname, $filename, $revision, "view");
     print "<HR noshade>";      print "<HR noshade>";
     print "<table width=\"100%\"><tr><td bgcolor=\"$markupLogColor\">";      print "<table width=\"100%\"><tr><td bgcolor=\"$markupLogColor\">";
     print "File: ", &clickablePath($where, 1);      print "File: ", &clickablePath($where, 1);
Line 1326  sub cvswebMarkup($$$) {
Line 1252  sub cvswebMarkup($$$) {
     &download_link(urlencode($fileurl), $revision, "(download)");      &download_link(urlencode($fileurl), $revision, "(download)");
     if (!$defaultTextPlain) {      if (!$defaultTextPlain) {
         print "&nbsp;";          print "&nbsp;";
         &download_link(urlencode($fileurl), $revision, "(as text)",          &download_link(urlencode($fileurl), $revision, "(as text)",
                "text/plain");                 "text/plain");
     }      }
     print "<BR>\n";      print "<BR>\n";
Line 1358  sub cvswebMarkup($$$) {
Line 1284  sub cvswebMarkup($$$) {
 sub viewable($) {  sub viewable($) {
     my ($mimetype) = @_;      my ($mimetype) = @_;
   
     $mimetype =~ m%^(text|image)/%;      $mimetype =~ m%^text/% ||
       $mimetype =~ m%^image/% ||
       0;
 }  }
   
 ###############################  ###############################
 # Show Colored Diff  # Show Colored Diff
 ###############################  ###############################
 sub doDiff($$$$$$) {  sub doDiff {
         my($fullname, $r1, $tr1, $r2, $tr2, $f) = @_;          my($fullname, $r1, $tr1, $r2, $tr2, $f) = @_;
         my $fh = do {local(*FH);};          my $fh = do {local(*FH);};
         my ($rev1, $rev2, $sym1, $sym2, @difftype, $diffname, $f1, $f2);          my ($rev1, $rev2, $sym1, $sym2, @difftype, $diffname, $f1, $f2);
Line 1385  sub doDiff($$$$$$) {
Line 1313  sub doDiff($$$$$$) {
             $rev2 = $tr2;              $rev2 = $tr2;
             $sym2 = "";              $sym2 = "";
         }          }
   
         # make sure the revisions a wellformed, for security          # make sure the revisions a wellformed, for security
         # reasons ..          # reasons ..
         if ($rev1 =~ /[^\w.]/ || $rev2 =~ /[^\w.]/) {          if (!($rev1 =~ /^[\d\.]+$/) || !($rev2 =~ /^[\d\.]+$/)) {
             &fatal("404 Not Found",              &fatal("404 Not Found",
                     "Malformed query \"$ENV{QUERY_STRING}\"");                      "Malformed query \"$ENV{'QUERY_STRING'}\"");
         }          }
 #  #
 # rev1 and rev2 are now both numeric revisions.  # rev1 and rev2 are now both numeric revisions.
Line 1429  sub doDiff($$$$$$) {
Line 1356  sub doDiff($$$$$$) {
         }          }
   
         # apply special options          # apply special options
         if ($showfunc) {          if ($human_readable) {
             push @difftype, '-p' if $f =~ /^[cHhu]$/;              if ($hr_funout) {
                   push @difftype, '-p';
   
             my($re1, $re2);                  my($re1, $re2);
   
             while (($re1, $re2) = each %funcline_regexp) {                  while (($re1, $re2) = each %functionlineregexp) {
                 if ($fullname =~ /$re1/) {                      if ($fullname =~ /$re1/) {
                     push @difftype, '-F', '$re2';                          push @difftype, '-F', '$re2';
                     last;                          last;
                       }
                 }                  }
             }              }
         }  
         if ($human_readable) {  
             if ($hr_ignwhite) {              if ($hr_ignwhite) {
                 push @difftype, '-w';                  push @difftype, '-w';
             }              }
Line 1450  sub doDiff($$$$$$) {
Line 1377  sub doDiff($$$$$$) {
             }              }
         }          }
         if (! open($fh, "-|")) { # child          if (! open($fh, "-|")) { # child
             open(STDERR, ">&STDOUT"); # Redirect stderr to stdout                  open(STDERR, ">&STDOUT"); # Redirect stderr to stdout
             exec("rcsdiff",@difftype,"-r$rev1","-r$rev2",$fullname);                  exec("rcsdiff",@difftype,"-r$rev1","-r$rev2",$fullname);
         }          }
         if ($human_readable) {          if ($human_readable) {
             http_header();              http_header();
Line 1509  sub doDiff($$$$$$) {
Line 1436  sub doDiff($$$$$$) {
 ###############################  ###############################
 # Show Logs ..  # Show Logs ..
 ###############################  ###############################
 sub getDirLogs($$@) {  sub getDirLogs {
     my ($cvsroot,$dirname,@otherFiles) = @_;      my ($cvsroot,$dirname,@otherFiles) = @_;
     my ($state,$otherFiles,$tag, $file, $date, $branchpoint, $branch, $log);      my ($state,$otherFiles,$tag, $file, $date, $branchpoint, $branch, $log);
     my ($rev, $revision, $revwanted, $filename, $head, $author);      my ($rev, $revision, $revwanted, $filename, $head, $author);
Line 1527  sub getDirLogs($$@) {
Line 1454  sub getDirLogs($$@) {
     }      }
   
     # just execute rlog if there are any files      # just execute rlog if there are any files
     if ($#files < 0) {      if ($#files < 0) {
         return;          return;
     }      }
   
     if ($tag) {      if ($tag) {
         #can't use -r<tag> as - is allowed in tagnames, but misinterpreated by rlog..          #can't use -r<tag> as - is allowed in tagnames, but misinterpreated by rlog..
         if (! open($fh, "-|")) {          if (! open($fh, "-|")) {
                 open(STDERR, '>/dev/null'); # rlog may complain; ignore.                  close(STDERR); # rlog may complain; ignore.
                 exec('rlog', @files);                  exec("rlog",@files);
         }          }
     }      }
     else {      else {
         my $kidpid = open($fh, "-|");          my $kidpid = open($fh, "-|");
         if (! $kidpid) {          if (! $kidpid) {
                 open(STDERR, '>/dev/null'); # rlog may complain; ignore.                  close(STDERR); # rlog may complain; ignore.
                 exec('rlog', '-r', @files);                  exec("rlog","-r",@files);
         }          }
     }      }
     $state = "start";      $state = "start";
Line 1572  again:
Line 1499  again:
         }          }
         if ($state eq "head" && /^symbolic names/) {          if ($state eq "head" && /^symbolic names/) {
             $state = "tags";              $state = "tags";
             ($branch = $head) =~ s/\.\d+$// if (!defined($branch));              ($branch = $head) =~ s/\.\d+$// if (!defined($branch));
             $branch =~ s/(\.?)(\d+)$/${1}0.$2/;              $branch =~ s/(\.?)(\d+)$/${1}0.$2/;
             $symrev{MAIN} = $branch;              $symrev{MAIN} = $branch;
             $symrev{HEAD} = $branch;              $symrev{HEAD} = $branch;
Line 1670  again:
Line 1597  again:
         }          }
     }      }
     if ($. == 0) {      if ($. == 0) {
         fatal("500 Internal Error",          fatal("500 Internal Error",
               "Failed to spawn GNU rlog on <em>'".join(", ", @files)."'</em><p>did you set the <b>\$ENV{PATH}</b> in your configuration file correctly ?");                "Failed to spawn GNU rlog on <em>'".join(", ", @files)."'</em><p>did you set the <b>\$ENV{PATH}</b> in your configuration file correctly ?");
     }      }
     close($fh);      close($fh);
 }  }
   
 sub readLog($;$) {  sub readLog {
         my($fullname,$revision) = @_;          my($fullname,$revision) = @_;
         my ($symnames, $head, $rev, $br, $brp, $branch, $branchrev);          my ($symnames, $head, $rev, $br, $brp, $branch, $branchrev);
         my $fh = do {local(*FH);};          my $fh = do {local(*FH);};
Line 1939  sub printLog($;$) {
Line 1866  sub printLog($;$) {
             }              }
             if (not $defaultTextPlain) {              if (not $defaultTextPlain) {
                 print " / ";                  print " / ";
                 &download_link($fileurl, $_, "(as text)",                  &download_link($fileurl, $_, "(as text)",
                            "text/plain");                             "text/plain");
             }              }
             if (!$defaultViewable) {              if (!$defaultViewable) {
Line 2080  sub printLog($;$) {
Line 2007  sub printLog($;$) {
         print "</PRE>\n";          print "</PRE>\n";
 }  }
   
 sub doLog($) {  sub doLog {
         my($fullname) = @_;          my($fullname) = @_;
         my ($diffrev, $upwhere, $filename, $backurl);          my ($diffrev, $upwhere, $filename, $backurl);
   
         readLog($fullname);          readLog($fullname);
   
         html_header("CVS log for $where");          html_header("CVS log for $where");
Line 2092  sub doLog($) {
Line 2019  sub doLog($) {
         $backurl = $scriptname . "/" . urlencode($upwhere) . $query;          $backurl = $scriptname . "/" . urlencode($upwhere) . $query;
         print &link($backicon, "$backurl#$filename"),          print &link($backicon, "$backurl#$filename"),
               " <b>Up to ", &clickablePath($upwhere, 1), "</b><p>\n";                " <b>Up to ", &clickablePath($upwhere, 1), "</b><p>\n";
         print <<EOF;          print "<A HREF=\"#diff\">Request diff between arbitrary revisions</A>\n";
 <A HREF="#diff">Request diff between arbitrary revisions</A>          print "<HR NOSHADE>\n";
 <HR NOSHADE>  
 EOF  
         if ($curbranch) {          if ($curbranch) {
             print "Default branch: ", ($revsym{$curbranch} || $curbranch);              print "Default branch: ";
               print ($revsym{$curbranch} || $curbranch);
         }          }
         else {          else {
             print "No default branch";              print "No default branch";
Line 2142  EOF
Line 2068  EOF
         print "</SELECT>\n";          print "</SELECT>\n";
         $diffrev = $revdisplayorder[0];          $diffrev = $revdisplayorder[0];
         $diffrev = $input{"r2"} if (defined($input{"r2"}));          $diffrev = $input{"r2"} if (defined($input{"r2"}));
         print "<INPUT TYPE=\"TEXT\" SIZE=\"$inputTextSize\" NAME=\"tr2\" VALUE=\"$diffrev\" onChange='document.diff_select.r2.selectedIndex=0'>\n";          print "<INPUT TYPE=\"TEXT\" SIZE=\"$inputTextSize\" NAME=\"tr2\" VALUE=\"$diffrev\" onChange='docuement.diff_select.r2.selectedIndex=0'>\n";
         print "<BR>Type of Diff should be a&nbsp;";          print "<BR>Type of Diff should be a&nbsp;";
         printDiffSelect(0);          printDiffSelect();
         print "<INPUT TYPE=SUBMIT VALUE=\"  Get Diffs  \">\n";          print "<INPUT TYPE=SUBMIT VALUE=\"  Get Diffs  \">\n";
         print "</FORM>\n";          print "</FORM>\n";
         print "<HR noshade>\n";          print "<HR noshade>\n";
Line 2199  EOF
Line 2125  EOF
         print "</BODY></HTML>\n";          print "</BODY></HTML>\n";
 }  }
   
 sub flush_diff_rows($$$$) {  sub flush_diff_rows ($$$$)
   {
     my $j;      my $j;
     my ($leftColRef,$rightColRef,$leftRow,$rightRow) = @_;      my ($leftColRef,$rightColRef,$leftRow,$rightRow) = @_;
     if ($state eq "PreChangeRemove") {          # we just got remove-lines before      if ($state eq "PreChangeRemove") {          # we just got remove-lines before
Line 2244  sub human_readable_diff($){
Line 2171  sub human_readable_diff($){
   ($pathname = $where_nd) =~ s/(Attic\/)?[^\/]*$//;    ($pathname = $where_nd) =~ s/(Attic\/)?[^\/]*$//;
   ($scriptwhere_nd = $scriptwhere) =~ s/.diff$//;    ($scriptwhere_nd = $scriptwhere) =~ s/.diff$//;
   
   navigateHeader($scriptwhere_nd, $pathname, $filename, $rev, "diff");    navigateHeader ($scriptwhere_nd, $pathname, $filename, $rev, "diff");
   
   # Read header to pick up read revision and date, if possible    # Read header to pick up read revision and date, if possible
   while (<$fh>) {    while (<$fh>) {
Line 2260  sub human_readable_diff($){
Line 2187  sub human_readable_diff($){
     $rev2 = $r2r;      $rev2 = $r2r;
     $date2 = $r2d;      $date2 = $r2d;
   }    }
   
   print "<h3 align=center>Diff for /$where_nd between version $rev1 and $rev2</h3>\n";    print "<h3 align=center>Diff for /$where_nd between version $rev1 and $rev2</h3>\n";
   
   print "<table border=0 cellspacing=0 cellpadding=0 width=\"100%\">\n";    print "<table border=0 cellspacing=0 cellpadding=0 width=\"100%\">\n";
Line 2290  sub human_readable_diff($){
Line 2217  sub human_readable_diff($){
   ####    ####
   while (<$fh>) {    while (<$fh>) {
       $difftxt = $_;        $difftxt = $_;
   
       if ($difftxt =~ /^@@/) {        if ($difftxt =~ /^@@/) {
           ($oldline,$newline,$funname) = $difftxt =~ /@@ \-([0-9]+).*\+([0-9]+).*@@(.*)/;            ($oldline,$newline,$funname) = $difftxt =~ /@@ \-([0-9]+).*\+([0-9]+).*@@(.*)/;
           print  "<tr bgcolor=\"$diffcolorHeading\"><td width=\"50%\">";            print  "<tr bgcolor=\"$diffcolorHeading\"><td width=\"50%\">";
Line 2310  sub human_readable_diff($){
Line 2237  sub human_readable_diff($){
   
           # Add fontface, size            # Add fontface, size
           $_ = "$fs&nbsp;$_$fe";            $_ = "$fs&nbsp;$_$fe";
   
           #########            #########
           # little state machine to parse unified-diff output (Hen, zeller@think.de)            # little state machine to parse unified-diff output (Hen, zeller@think.de)
           # in order to get some nice 'ediff'-mode output            # in order to get some nice 'ediff'-mode output
Line 2328  sub human_readable_diff($){
Line 2255  sub human_readable_diff($){
                   $state = "PreChange";                    $state = "PreChange";
                   $rightCol[$rightRow++] = $_;                    $rightCol[$rightRow++] = $_;
               }                }
           }            }
           elsif ($diffcode eq '-') {            elsif ($diffcode eq '-') {
               $state = "PreChangeRemove";                $state = "PreChangeRemove";
               $leftCol[$leftRow++] = $_;                $leftCol[$leftRow++] = $_;
Line 2384  sub human_readable_diff($){
Line 2311  sub human_readable_diff($){
   print "</tr></table>";    print "</tr></table>";
 }  }
   
 sub navigateHeader($$$$$) {  sub navigateHeader ($$$$$) {
     my ($swhere,$path,$filename,$rev,$title) = @_;      my ($swhere,$path,$filename,$rev,$title) = @_;
     $swhere = "" if ($swhere eq $scriptwhere);      $swhere = "" if ($swhere eq $scriptwhere);
     $swhere = urlencode($filename) if ($swhere eq "");      $swhere = urlencode($filename) if ($swhere eq "");
     print "<\!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">";      print "<\!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">";
     print "<HTML>\n<HEAD>\n";      print "<HTML>\n<HEAD>\n";
     print '<!-- CVSweb $zRevision: 1.94 $  $kRevision: 1.17 $ -->';      print '<!-- CVSweb $Revision$ -->';
     print "\n<TITLE>$path$filename - $title - $rev</TITLE></HEAD>\n";      print "\n<TITLE>$path$filename - $title - $rev</TITLE></HEAD>\n";
     print  "<BODY BGCOLOR=\"$backcolor\">\n";      print  "<BODY BGCOLOR=\"$backcolor\">\n";
     print "<table width=\"100%\" border=0 cellspacing=0 cellpadding=1 bgcolor=\"$navigationHeaderColor\">";      print "<table width=\"100%\" border=0 cellspacing=0 cellpadding=1 bgcolor=\"$navigationHeaderColor\">";
Line 2398  sub navigateHeader($$$$$) {
Line 2325  sub navigateHeader($$$$$) {
     print  "<a href=\"$swhere$query#rev$rev\">$backicon";      print  "<a href=\"$swhere$query#rev$rev\">$backicon";
     print "</a> <b>Return to ", &link("$filename","$swhere$query#rev$rev")," CVS log";      print "</a> <b>Return to ", &link("$filename","$swhere$query#rev$rev")," CVS log";
     print "</b> $fileicon</td>";      print "</b> $fileicon</td>";
   
     print "<td align=right>$diricon <b>Up to ", &clickablePath($path, 1), "</b></td>";      print "<td align=right>$diricon <b>Up to ", &clickablePath($path, 1), "</b></td>";
     print "</tr></table>";      print "</tr></table>";
 }  }
   
 sub plural_write($$) {  sub plural_write ($$)
   {
     my ($num,$text) = @_;      my ($num,$text) = @_;
     if ($num != 1) {      if ($num != 1) {
         $text = $text . "s";          $text = $text . "s";
Line 2421  sub plural_write($$) {
Line 2349  sub plural_write($$) {
 # '..time ago'  # '..time ago'
 # H. Zeller <zeller@think.de>  # H. Zeller <zeller@think.de>
 ##  ##
 sub readableTime($$) {  sub readableTime ($$)
   {
     my ($i, $break, $retval);      my ($i, $break, $retval);
     my ($secs,$long) = @_;      my ($secs,$long) = @_;
   
Line 2439  sub readableTime($$) {
Line 2368  sub readableTime($$) {
                    31536000, 'year');                     31536000, 'year');
     my @breaks = sort {$a <=> $b} keys %desc;      my @breaks = sort {$a <=> $b} keys %desc;
     $i = 0;      $i = 0;
     while ($i <= $#breaks && $secs >= 2 * $breaks[$i]) {      while ($i <= $#breaks && $secs >= 2 * $breaks[$i]) {
         $i++;          $i++;
     }      }
     $i--;      $i--;
     $break = $breaks[$i];      $break = $breaks[$i];
     $retval = plural_write(int ($secs / $break), $desc{$break});      $retval = plural_write(int ($secs / $break), $desc{"$break"});
   
     if ($long == 1 && $i > 0) {      if ($long == 1 && $i > 0) {
         my $rest = $secs % $break;          my $rest = $secs % $break;
         $i--;          $i--;
         $break = $breaks[$i];          $break = $breaks[$i];
         my $resttime = plural_write(int ($rest / $break),          my $resttime = plural_write(int ($rest / $break),
                                 $desc{$break});                                  $desc{"$break"});
         if ($resttime) {          if ($resttime) {
             $retval = $retval . ", " . $resttime;              $retval = $retval . ", " . $resttime;
         }          }
Line 2468  sub readableTime($$) {
Line 2397  sub readableTime($$) {
 # basename (last directory/file) is a link as well  # basename (last directory/file) is a link as well
 ##  ##
 sub clickablePath($$) {  sub clickablePath($$) {
     my ($pathname,$clickLast) = @_;      my ($pathname,$clickLast) = @_;
     my $retval = '';      my $retval = '';
   
     if ($pathname eq '/') {      if ($pathname eq '/') {
         # this should never happen - chooseCVSRoot() is          # this should never happen - chooseCVSRoot() is
         # intended to do this          # intended to do this
Line 2484  sub clickablePath($$) {
Line 2413  sub clickablePath($$) {
             $retval = $retval . " / ";              $retval = $retval . " / ";
             $wherepath = $wherepath . '/' . $_;              $wherepath = $wherepath . '/' . $_;
             my ($last) = "$wherepath/" eq "/$pathname"              my ($last) = "$wherepath/" eq "/$pathname"
                 || $wherepath eq "/$pathname";                  || "$wherepath" eq "/$pathname";
             if ($clickLast || !$last) {              if ($clickLast || !$last) {
                 $retval = $retval . "<a href=\"${scriptname}"                  $retval = $retval . "<a href=\"${scriptname}"
                     . urlencode($wherepath)                      . urlencode($wherepath)
Line 2512  sub chooseCVSRoot() {
Line 2441  sub chooseCVSRoot() {
         my ($k);          my ($k);
         print "<form method=\"GET\" action=\"${scriptwhere}\">\n";          print "<form method=\"GET\" action=\"${scriptwhere}\">\n";
         foreach $k (keys %input) {          foreach $k (keys %input) {
             print "<input type=hidden NAME=$k VALUE=$input{$k}>\n"              print "<input type=hidden NAME=$k VALUE=$input{$k}>\n"
                 if ($input{$k}) && ($k ne "cvsroot");                  if ($input{$k}) && ($k ne "cvsroot");
         }          }
         # Form-Elements look wierd in Netscape if the background          # Form-Elements look wierd in Netscape if the background
Line 2525  sub chooseCVSRoot() {
Line 2454  sub chooseCVSRoot() {
         print ">\n";          print ">\n";
         foreach $k (@foo) {          foreach $k (@foo) {
             print "<option value=\"$k\"";              print "<option value=\"$k\"";
             print " selected" if ($k eq $cvstree);              print " selected" if ("$k" eq "$cvstree");
             print ">" . ($CVSROOTdescr{$k} ? $CVSROOTdescr{$k} :              print ">" . ($CVSROOTdescr{"$k"} ? $CVSROOTdescr{"$k"} :
                         $k). "</option>\n";                          $k). "</option>\n";
         }          }
         print "</select>\n</td>";          print "</select>\n</td>";
Line 2546  sub chooseMirror() {
Line 2475  sub chooseMirror() {
     # and may not be useful for your site; If you don't      # and may not be useful for your site; If you don't
     # set %MIRRORS this won't show up, anyway      # set %MIRRORS this won't show up, anyway
     #      #
     # Should perhaps exlude the current site somehow..      # Should perhaps exlude the current site somehow..
     if (keys %MIRRORS) {      if (keys %MIRRORS) {
         print "\nThis cvsweb is mirrored in:\n";          print "\nThis cvsweb is mirrored in:\n";
         foreach $mirror (keys %MIRRORS) {          foreach $mirror (keys %MIRRORS) {
Line 2558  sub chooseMirror() {
Line 2487  sub chooseMirror() {
     }      }
 }  }
   
 sub fileSortCmp() {  sub fileSortCmp {
     my ($comp) = 0;      my ($comp) = 0;
     my ($c,$d,$af,$bf);      my ($c,$d,$af,$bf);
   
Line 2589  sub fileSortCmp() {
Line 2518  sub fileSortCmp() {
 }  }
   
 # make A url for downloading  # make A url for downloading
 sub download_url($$;$) {  sub download_url {
     my ($url,$revision,$mimetype) = @_;      my ($url,$revision,$mimetype) = @_;
   
     $revision =~ s/\b0\.//;      $revision =~ s/\b0\.//;
Line 2606  sub download_url($$;$) {
Line 2535  sub download_url($$;$) {
     return $url;      return $url;
 }  }
   
 # Presents a link to download the  # Presents a link to download the
 # selected revision  # selected revision
 sub download_link($$$;$) {  sub download_link {
     my ($url,$revision,$textlink,$mimetype) = @_;      my ($url,$revision,$textlink,$mimetype) = @_;
     my ($fullurl) = download_url($url,$revision,$mimetype);      my ($fullurl) = download_url($url,$revision,$mimetype);
     my ($paren) = $textlink =~ /^\(/;      my ($paren) = $textlink =~ /^\(/;
Line 2680  sub toggleQuery($$) {
Line 2609  sub toggleQuery($$) {
     return "";      return "";
 }  }
   
 sub urlencode($) {  sub urlencode {
     my ($in) = @_;      my ($in) = @_;
     my ($out);      my ($out);
     ($out = $in) =~ s/([\000-+{-\377])/sprintf("%%%02x", ord($1))/ge;      ($out = $in) =~ s/([\000-+{-\377])/sprintf("%%%02x", ord($1))/ge;
     return $out;      return $out;
 }  }
   
 sub http_header(;$) {  sub http_header {
     my $content_type = shift || "text/html";      my $content_type = shift || "text/html";
       my $is_mod_perl = defined($ENV{'MOD_PERL'});
     if (defined($moddate)) {      if (defined($moddate)) {
         if ($is_mod_perl) {          if ($is_mod_perl) {
             Apache->request->header_out(Last_modified => scalar gmtime($moddate) . " GMT");              Apache->request->header_out(Last_modified => scalar gmtime($moddate) . " GMT");
         }          }
         else {          else {
             print "Last-Modified: " . scalar gmtime($moddate) . " GMT\r\n";              print "Last-Modified: " . scalar gmtime($moddate) . " GMT\n";
         }          }
     }      }
     if ($is_mod_perl) {      if ($is_mod_perl) {
         Apache->request->content_type($content_type);          Apache->request->content_type($content_type);
     }      }
     else {      else {
             print "Content-type: $content_type\r\n";              print "Content-type: $content_type\n";
     }      }
     if ($allow_compress && $maycompress) {      if ($allow_compress && $maycompress) {
         my $fh = do {local(*FH);};          my $fh = do {local(*FH);};
Line 2712  sub http_header(;$) {
Line 2642  sub http_header(;$) {
                     Apache->request->send_http_header;                      Apache->request->send_http_header;
             }              }
             else {              else {
                     print "Content-encoding: x-gzip\r\n";                      print "Content-encoding: x-gzip\n";
                     print "Vary: Accept-Encoding\r\n";  #RFC 2068, 14.43                      print "Vary: Accept-Encoding\n";  #RFC 2068, 14.43
                     print "\r\n"; # Close headers                      print "\n"; # Close headers
             }              }
             $| = 1; $| = 0; # Flush header output              $| = 1; $| = 0; # Flush header output
             select ($fh);              select ($fh);
Line 2725  sub http_header(;$) {
Line 2655  sub http_header(;$) {
                     Apache->request->send_http_header;                      Apache->request->send_http_header;
             }              }
             else {              else {
                     print "\r\n"; # Close headers                      print "\n"; # Close headers
             }              }
             print "<font size=-1>Unable to find gzip binary in the \$PATH to compress output</font><br>";              print "<font size=-1>Unable to find gzip binary in the \$PATH to compress output</font><br>";
         }          }
Line 2735  sub http_header(;$) {
Line 2665  sub http_header(;$) {
                     Apache->request->send_http_header;                      Apache->request->send_http_header;
             }              }
             else {              else {
                     print "\r\n"; # Close headers                      print "\n"; # Close headers
             }              }
     }      }
 }  }
   
 sub html_header($) {  sub html_header($) {
     my ($title) = @_;      my ($title) = @_;
     my $version = '$zRevision: 1.94 $  $kRevision: 1.17 $'; #'      my $version = '$Revision$';
     http_header();      http_header();
     print <<EOH;      print <<EOH;
 <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"  <!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN"
  "http://www.w3.org/TR/REC-html40/loose.dtd">   "http://www.w3.org/TR/REC-html40/loose.dtd">
 <html>  <html>
 <title>$title</title>  <title>$title</title>
 <!-- CVSweb $version -->  <!-- hennerik CVSweb $version -->
 </head>  </head>
 $body_tag  $body_tag
 $logo <h1 align="center">$title</h1>  $logo <h1 align="center">$title</h1>
 EOH  EOH
 }  }
   
 sub html_footer() {  sub html_footer {
     return "<hr noshade><address>$address</address>\n";      return "<hr noshade><address>$address</address>\n";
 }  }
   
 sub link_tags($) {  sub link_tags
   {
     my ($tags) = @_;      my ($tags) = @_;
     my ($ret) = "";      my ($ret) = "";
     my ($fileurl,$filename);      my ($fileurl,$filename);
Line 2779  sub link_tags($) {
Line 2710  sub link_tags($) {
 #  #
 # See if a module is listed in the config file's @HideModule list.  # See if a module is listed in the config file's @HideModule list.
 #  #
 sub forbidden_module($) {  sub forbidden_module {
     my($module) = @_;      my($module) = @_;
   
     for (my $i=0; $i < @HideModules; $i++) {      for (my $i=0; $i < @HideModules; $i++) {
         return 1 if $module eq $HideModules[$i];          return 1 if $module eq $HideModules[$i];
     }      }

Legend:
Removed from v.1.1.1.4  
changed lines
  Added in v.3.2

CVSweb