diff --git a/en/cgi/cvsweb.cgi b/en/cgi/cvsweb.cgi index e27ecfb06a..9742431b02 100755 --- a/en/cgi/cvsweb.cgi +++ b/en/cgi/cvsweb.cgi @@ -43,9 +43,10 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $Id: cvsweb.cgi,v 1.81 2002-05-08 05:42:25 motoyuki Exp $ +# FreeBSD: projects/cvsweb/cvsweb.cgi,v 1.104 2002/05/22 08:10:18 knu Exp +# $Id: cvsweb.cgi,v 1.82 2002-05-22 08:31:02 knu Exp $ # $Idaemons: /home/cvs/cvsweb/cvsweb.cgi,v 1.84 2001/10/07 20:50:10 knu Exp $ -# $FreeBSD: www/en/cgi/cvsweb.cgi,v 1.80 2002/04/11 01:55:34 fenner Exp $ +# $FreeBSD: www/en/cgi/cvsweb.cgi,v 1.81 2002/05/08 05:42:25 motoyuki Exp $ # ### @@ -64,7 +65,8 @@ use vars qw ( @revisions %state %difflines %log %branchpoint @revorder $prcgi @prcategories $re_prcategories $prkeyword $re_prkeyword $mancgi $checkoutMagic $doCheckout $scriptname $scriptwhere - $where $pathinfo $Browser $nofilelinks $maycompress @stickyvars + $where $pathinfo $Browser $nofilelinks $maycompress + @stickyvars @unsafevars %funcline_regexp $is_mod_perl $is_links $is_lynx $is_w3m $is_msie $is_mozilla3 $is_textbased %input $query $barequery $sortby $bydate $byrev $byauthor @@ -79,8 +81,10 @@ use vars qw ( $columnHeaderColorSorted $hr_breakable $showfunc $hr_ignwhite $hr_ignkeysubst $diffcolorHeading $diffcolorEmpty $diffcolorRemove $diffcolorChange $diffcolorAdd $diffcolorDarkChange $difffontface - $difffontsize $inputTextSize $mime_types $allow_annotate - $allow_markup $use_java_script $open_extern_window + $difffontsize $inputTextSize $mime_types + $allow_annotate $allow_markup + $allow_log_extra $allow_dir_extra $allow_source_extra + $use_java_script $open_extern_window $extern_window_width $extern_window_height $edit_option_form $show_subdir_lastmod $show_log_in_markup $preformat_in_markup $v $navigationHeaderColor $tableBorderColor $markupLogColor @@ -89,7 +93,7 @@ use vars qw ( $use_moddate $has_zlib $gzip_open $allow_tar @tar_options @gzip_options @zip_options @cvs_options $LOG_FILESEPARATOR $LOG_REVSEPARATOR - $tmpdir + $tmpdir $HTML_DOCTYPE ); sub printDiffSelect($); @@ -101,7 +105,7 @@ sub htmlify($;$); sub spacedHtmlText($;$); sub link($$); sub revcmp($$); -sub fatal($$); +sub fatal($$@); sub redirect($); sub safeglob($); sub search_path($); @@ -144,11 +148,11 @@ sub forbidden_module($); ##### Start of Configuration Area ######## delete $ENV{PATH}; -$cvsweb_revision = '2.0.1'; +$cvsweb_revision = '2.0.3'; -use File::Basename; +use File::Basename (); -($mydir) = (dirname($0) =~ /(.*)/); # untaint +($mydir) = (File::Basename::dirname($0) =~ /(.*)/); # untaint # == EDIT this == # Locations to search for user configuration, in order: @@ -163,6 +167,7 @@ for ("$mydir/cvsweb.conf", '/usr/local/etc/cvsweb/cvsweb.conf') { # Defaults for configuration variables that shouldn't need # to be configured.. $allow_version_select = 1; +$allow_log_extra = 1; ##### End of Configuration Area ######## @@ -181,7 +186,7 @@ $cvstreedefault = $body_tag = $body_tag_for_src = $logo = $defaulttitle = $extern_window_width = $extern_window_height = $edit_option_form = $show_subdir_lastmod = $show_log_in_markup = $v = $navigationHeaderColor = $tableBorderColor = $markupLogColor = $tabstop = $use_moddate = $moddate = - $gzip_open = undef; + $gzip_open = $HTML_DOCTYPE = undef; $tmpdir = defined($ENV{TMPDIR}) ? $ENV{TMPDIR} : "/var/tmp"; $LOG_FILESEPARATOR = q/^={77}$/; @@ -230,7 +235,7 @@ $LOG_REVSEPARATOR = q/^-{28}$/; ); $cgi_style::hsty_base = 'http://www.FreeBSD.org'; -$_ = q$FreeBSD: www/en/cgi/cvsweb.cgi,v 1.80 2002/04/11 01:55:34 fenner Exp $; +$_ = q$FreeBSD: www/en/cgi/cvsweb.cgi,v 1.81 2002/05/08 05:42:25 motoyuki Exp $; @_ = split; $cgi_style::hsty_date = "@_[3,4]"; @@ -241,10 +246,13 @@ package cgi_style; require "$main::mydir/cgi-style.pl"; package main; +$HTML_DOCTYPE = + ''; + ##### End of configuration variables ##### -use Time::Local; -use IPC::Open2; +use Time::Local (); +use IPC::Open2 qw(open2); # Check if the zlib C library interface is installed, and if yes # we can avoid using the extra gzip process. @@ -307,21 +315,16 @@ $maycompress = # their current value) to any link/query string # you construct @stickyvars = qw(cvsroot hideattic sortby logsort f only_with_tag); +@unsafevars = qw(logsort only_with_tag r1 r2 rev sortby tr1 tr2); if (-f $config) { - require $config || &fatal( - "500 Internal Error", - sprintf( - 'Error in loading configuration file: %s

%s
', - $config, - &htmlify($@) - ) - ); + do "$config" or fatal("500 Internal Error", + 'Error in loading configuration file: %s

%s
', + $config, $@); } else { - &fatal("500 Internal Error", - 'Configuration not found. Set the variable $config ' - . 'in cvsweb.cgi to your cvsweb.conf configuration file first.' - ); + fatal("500 Internal Error", + 'Configuration not found. Set the variable $config in cvsweb.cgi to your cvsweb.conf configuration file first.' + ); } undef %input; @@ -343,6 +346,20 @@ if (defined($query) && $query ne '') { $input{only_with_tag} = $input{only_on_branch} if (defined($input{only_on_branch})); +# Prevent cross-site scripting +foreach (@unsafevars) { + if (defined($input{$_}) && $input{$_} =~ /[^\w\-.]/) { + fatal("500 Internal Error", + 'Malformed query (%s=%s)', + $_, $input{$_}); + } +} + +if (defined($input{"content-type"})) { + fatal("500 Internal Error", "Unsupported content-type") + if ($input{"content-type"} !~ /^[-0-9A-Za-z]+\/[-0-9A-Za-z]+$/); +} + $DEFAULTVALUE{'cvsroot'} = $cvstreedefault; foreach (keys %DEFAULTVALUE) { @@ -421,28 +438,33 @@ $defaultDiffType = $input{'f'}; $logsort = $input{'logsort'}; -my @tmp = @CVSrepositories; -my @pair; +{ + my @tmp = @CVSrepositories; + my @pair; -while (@pair = splice(@tmp, 0, 2)) { - my ($key, $val) = @pair; - my ($descr, $cvsroot) = @$val; + while (@pair = splice(@tmp, 0, 2)) { + my ($key, $val) = @pair; + my ($descr, $cvsroot) = @$val; - next if !-d $cvsroot; + next if !-d $cvsroot; - $CVSROOTdescr{$key} = $descr; - $CVSROOT{$key} = $cvsroot; - push @CVSROOT, $key; + $CVSROOTdescr{$key} = $descr; + $CVSROOT{$key} = $cvsroot; + push @CVSROOT, $key; + } } -undef @tmp; -undef @pair; +{ + print "..........@CVSrepositories.........\n"; + while (my($x, $y) = each %CVSROOT) { + print "$x = $y\n"; + } +} ## Default CVS-Tree if (!defined($CVSROOT{$cvstreedefault})) { - &fatal("500 Internal Error", - "\$cvstreedefault points to a repository ($cvstreedefault) " - . "not defined in %CVSROOT " - . "(edit your configuration file $config)"); + fatal("500 Internal Error", + '$cvstreedefault points to a repository (%s) not defined in %%CVSROOT (edit your configuration file %s)', + $cvstreedefault, $config); } # alternate CVS-Tree, configured in cvsweb.conf @@ -474,14 +496,10 @@ my $config_cvstree = "$config-$cvstree"; # Do some special configuration for cvstrees if (-f $config_cvstree) { - require $config_cvstree || &fatal( - "500 Internal Error", - sprintf( - 'Error in loading configuration file: %s

%s
', - $config_cvstree, - &htmlify($@) - ) - ); + do "$config_cvstree" or + fatal("500 Internal Error", + 'Error in loading configuration file: %s

%s
', + $config_cvstree, $@); } undef $config_cvstree; @@ -518,9 +536,8 @@ if ($rewrite) { undef $rewrite; if (!-d $cvsroot) { - &fatal("500 Internal Error", - '$CVSROOT not found!

The server on which the CVS tree lives is probably down. Please try again in a few minutes.' - ); + fatal("500 Internal Error", + '$CVSROOT not found!

The server on which the CVS tree lives is probably down. Please try again in a few minutes.'); } # @@ -529,14 +546,17 @@ if (!-d $cvsroot) { $where =~ m:([^/]*):; $module = $1; if ($module && &forbidden_module($module)) { - &fatal("403 Forbidden", "Access to $where forbidden."); + fatal("403 Forbidden", + 'Access to %s forbidden.', + $where); } # # Handle tarball downloads before any headers are output. # if ($input{tarball}) { - &fatal("403 Forbidden", "Downloading tarballs is prohibited.") + fatal("403 Forbidden", + 'Downloading tarballs is prohibited.') unless $allow_tar; my ($module) = ($where =~ m,^/?(.*),); # untaint $module =~ s,/([^/]*)$,,; @@ -544,15 +564,16 @@ if ($input{tarball}) { my ($basedir) = ($module =~ m,([^/]+)$,); if ($basedir eq '' || $module eq '') { - &fatal("500 Internal Error", - "You cannot download the top level directory."); + fatal("500 Internal Error", + 'You cannot download the top level directory.'); } my $tmpexportdir = "$tmpdir/.cvsweb.$$." . int(time); mkdir($tmpexportdir, 0700) - or &fatal("500 Internal Error", - "Unable to make temporary directory: $!"); + or fatal("500 Internal Error", + 'Unable to make temporary directory: %s', + $!); my @fatal; @@ -567,7 +588,9 @@ if ($input{tarball}) { if (system $CMD{cvs}, @cvs_options, '-Qd', $cvsroot, 'export', '-r', $tag, '-d', "$tmpexportdir/$basedir", $module) { - @fatal = ("500 Internal Error", "cvs co failure: $!: $module"); + @fatal = ("500 Internal Error", + 'cvs co failure: %s: %s', + $!, $module); } else { $| = 1; # Essential to get the buffering right. @@ -577,18 +600,22 @@ if ($input{tarball}) { system "$CMD{tar} @tar_options -cf - -C $tmpexportdir $basedir | $CMD{gzip} @gzip_options -c" and @fatal = - ("500 Internal Error", - "tar zc failure: $!: $basedir"); + ("500 Internal Error", + 'tar zc failure: %s: %s', + $!, $basedir); } elsif ($ext eq '.zip' && $CMD{zip}) { print "Content-Type: application/zip\r\n\r\n"; system "cd $tmpexportdir && $CMD{zip} @zip_options -r - $basedir" and @fatal = - ("500 Internal Error", "zip failure: $!: $basedir"); + ("500 Internal Error", + 'zip failure: %s: %s', + $!, $basedir); } else { @fatal = - ("500 Internal Error", "unsupported file type"); + ("500 Internal Error", + 'unsupported file type'); } } @@ -604,7 +631,9 @@ if ($input{tarball}) { ############################### if (-d $fullname) { my $dh = do { local (*DH); }; - opendir($dh, $fullname) || &fatal("404 Not Found", "$where: $!"); + opendir($dh, $fullname) or fatal("404 Not Found", + '%s: %s', + $where, $!); my @dir = readdir($dh); closedir($dh); my @subLevelFiles = findLastModifiedSubdirs(@dir) @@ -653,16 +682,12 @@ if (-d $fullname) { my $infocols = 0; if ($dirtable) { - if (defined($tableBorderColor)) { - - # Can't this be done by defining the border for the inner table? - print - "
"; - } - print - "\n"; + print "
\n"; $infocols++; - printf '\n"; + print "\n"; # do not display the other column-headers, if we do not have any files # with revision information: if (scalar(%fileinfo)) { $infocols++; - printf '"; + print "\n"; $infocols++; - printf '"; + print "\n"; if ($show_author) { $infocols++; - printf '"; + print "\n"; } $infocols++; - printf '"; + print "\n"; } elsif ($use_descriptions) { - printf '\n"; $infocols++; } print "\n"; @@ -825,8 +850,8 @@ if (-d $fullname) { ($rev, $date, $log, $author, $filename) = @{$fileinfo{$_}} if (defined($fileinfo{$_})); - printf '\n\n\n\n\n\n\n"; + print "\n\n"; } else { print "
\n"; } @@ -928,8 +953,8 @@ if (-d $fullname) { next if (!defined($fileinfo{$_})); ($rev, $date, $log, $author) = @{$fileinfo{$_}}; $filesfound++; - printf '\n\n\n\n\n" if ($dirtable); + print "\n" if ($dirtable); print(($dirtable) ? "" : "
"); $dirrow++; } @@ -971,10 +996,6 @@ if (-d $fullname) { print($dirtable ? "
', + printf "
", $byfile ? $columnHeaderColorSorted : $columnHeaderColorDefault; @@ -677,13 +702,13 @@ if (-d $fullname) { ) ); } - print "', + printf '', $byrev ? $columnHeaderColorSorted : $columnHeaderColorDefault; @@ -698,9 +723,9 @@ if (-d $fullname) { ) ); } - print "', + printf '', $bydate ? $columnHeaderColorSorted : $columnHeaderColorDefault; @@ -715,11 +740,11 @@ if (-d $fullname) { ) ); } - print "', + printf '', $byauthor ? $columnHeaderColorSorted : $columnHeaderColorDefault; @@ -737,10 +762,10 @@ if (-d $fullname) { ) ); } - print "', + printf '', $bylog ? $columnHeaderColorSorted : $columnHeaderColorDefault; @@ -755,11 +780,11 @@ if (-d $fullname) { ) ); } - print "', + printf '', $columnHeaderColorDefault; - print "Description"; + print "Description
', $tabcolors[$dirrow % 2] - if $dirtable; + printf "
", + $tabcolors[$dirrow % 2] if $dirtable; if ($_ eq '..') { $url = "../$query"; @@ -835,7 +860,7 @@ if (-d $fullname) { } else { print &link($backicon, $url); } - print " ", &link("Parent Directory", $url); + print ' ', &link("Parent Directory", $url); } else { $url = './' . urlencode($_) . "/$query"; print ""; @@ -845,7 +870,7 @@ if (-d $fullname) { } else { print &link($diricon, $url); } - print " ", &link("$_/", $url), $attic; + print ' ', &link("$_/", $url), $attic; if ($_ eq "Attic") { print "  "; @@ -862,7 +887,7 @@ if (-d $fullname) { # Show last change in dir if ($filename) { - print "  " + print "  " if ($dirtable); if ($date) { print " ", @@ -871,22 +896,22 @@ if (-d $fullname) { } if ($show_author) { - print " " if ($dirtable); + print " " if ($dirtable); print $author; } - print " " if ($dirtable); + print " " if ($dirtable); $filename =~ s%^[^/]+/%%; print "$filename/$rev"; print "
" if ($dirtable); if ($log) { - print " ", + print " ", &htmlify( - substr($log, 0, $shortLogLen)); + substr($log, 0, $shortLogLen), $allow_dir_extra); if (length $log > 80) { print "..."; } - print ""; + print ""; } } else { my ($dwhere) = @@ -905,14 +930,14 @@ if (-d $fullname) { # columns, so that the vertical seperators are visible my ($cols) = $infocols; while ($cols > 1) { - print "
 "; + print " "; $cols--; } } } if ($dirtable) { - print "
', $tabcolors[$dirrow % 2] - if $dirtable; + printf "
", + $tabcolors[$dirrow % 2] if $dirtable; print ""; if ($nofilelinks) { @@ -937,32 +962,32 @@ if (-d $fullname) { } else { print &link($fileicon, $url); } - print " ", &link($_, $url), $attic; - print " " if ($dirtable); + print ' ', &link($_, $url), $attic; + print " " if ($dirtable); download_link($fileurl, $rev, $rev, $defaultViewable ? "text/x-cvsweb-markup" : undef); - print " " if ($dirtable); + print " " if ($dirtable); if ($date) { print " ", readableTime(time() - $date, 0), ""; } if ($show_author) { - print " " if ($dirtable); + print " " if ($dirtable); print $author; } - print " " if ($dirtable); + print " " if ($dirtable); if ($log) { - print " ", - &htmlify(substr($log, 0, $shortLogLen)); + print " ", + &htmlify(substr($log, 0, $shortLogLen), $allow_dir_extra); if (length $log > 80) { print "..."; } - print ""; + print ""; } - print "
\n" : "\n"); - if ($dirtable && defined($tableBorderColor)) { - print "
"; - } - if ($filesexists && !$filesfound) { print "

NOTE: There are $filesexists files, but none matches the current tag ($input{only_with_tag}).

\n"; @@ -987,7 +1008,7 @@ if (-d $fullname) { if (scalar %tags || $input{only_with_tag} || $edit_option_form || defined($input{"options"})) { - print "
"; + print "
\n"; } if (scalar %tags || $input{only_with_tag}) { @@ -1036,49 +1057,51 @@ if (-d $fullname) { &link("zip archive", "./$basefile.zip$query" . ($query ? "&" : "?") . "tarball=1"); } - print ""; + print "\n"; } } - my $formwhere = $scriptwhere; - $formwhere =~ s|Attic/?$|| if ($input{'hideattic'}); - if ($edit_option_form || defined($input{"options"})) { + + my $formwhere = $scriptwhere; + $formwhere =~ s|Attic/?$|| if ($input{'hideattic'}); + print "
\n"; print "\n"; if ($cvstree ne $cvstreedefault) { print "\n"; } - print "
"; - print - ""; - print "\n\n"; + print "\n\n\n
Preferences
Sort files by "; + print "\n\n"; + print "\n\n"; + print "\n"; + " value=\"log\">Log message\n"; + print "\n\n"; print ""; - print "\n\n"; + print "\n"; + print "\n"; print "\n"; - print - "
Preferences
Sort files by Sort log by: "; printLogSortSelect(0); - print "
Diff format: "; + print "
Diff format: "; printDiffSelect(0); - print "
"; - print "
\n"; + $input{'hideattic'} ? " checked" : "", + ">
"; + print ""; + print "
\n
\n\n"; } - print &html_footer; + html_footer(); } ############################### @@ -1167,7 +1190,9 @@ elsif (-f $fullname . ',v') { } } } - &fatal("404 Not Found", "$where: no such file or directory"); + fatal("404 Not Found", + '%s: no such file or directory', + $where); } gzipclose(); @@ -1180,11 +1205,11 @@ sub printDiffSelect($) { print ''; + print ">\n"; local $_; for (@LOGSORTKEYS) { - printf('', $_, + printf("\n", $_, $logsort eq $_ ? ' selected' : '', "\u$LOGSORTKEYS{$_}{'descr'}"); } @@ -1222,7 +1247,7 @@ sub findLastModifiedSubdirs(@) { my ($lastmodtime) = undef; my $dh = do { local (*DH); }; - opendir($dh, $dir) || next; + opendir($dh, $dir) or next; my (@filenames) = readdir($dh); closedir($dh); @@ -1283,8 +1308,7 @@ sub htmlify($;$) { if ($extra) { # get PR #'s as link: "PR#nnnn" "PR: nnnn, ..." "PR nnnn, ..." "bin/nnnn" - if (defined($prcgi) && defined($re_prcategories) - && defined($re_prkeyword)) + if (defined($prcgi) && defined($re_prkeyword)) { my $prev; @@ -1307,14 +1331,16 @@ sub htmlify($;$) { $_; } while ($_ ne $prev); - $_ = htmlify_sub { - s{ - (\b$re_prcategories/(\d+)\b) - }{ - &link($1, sprintf($prcgi, $2)) - }egox; - } - $_; + if (defined($re_prcategories)) { + $_ = htmlify_sub { + s{ + (\b$re_prcategories/(\d+)\b) + }{ + &link($1, sprintf($prcgi, $2)) + }egox; + } + $_; + } } # get manpage specs as link: "foo.1" "foo(1)" @@ -1363,7 +1389,7 @@ sub spacedHtmlText($;$) { s/ /\001nbsp;/g; } - $_ = htmlify($_); + $_ = htmlify($_, $allow_source_extra); # unescape y/\001/&/; @@ -1400,16 +1426,18 @@ sub revcmp($$) { return 0; } -sub fatal($$) { - my ($errcode, $errmsg) = @_; +sub fatal($$@) { + my ($errcode, $format, @args) = @_; if ($is_mod_perl) { Apache->request->status((split (/ /, $errcode))[0]); } else { print "Status: $errcode\r\n"; } html_header("Error"); - print "Error: " . htmlquote($errmsg) . "\n"; - print &html_footer; + print "

Error: ", + sprintf($format, map(htmlquote($_), @args)), + "

\n"; + html_footer(); exit(1); } @@ -1423,8 +1451,8 @@ sub redirect($) { print "Location: $url\r\n"; } html_header("Moved"); - print "This document is located ", &link('here', $url), "\n"; - print &html_footer; + print "

This document is located ", &link('here', $url), "

\n"; + html_footer(); exit(1); } @@ -1538,13 +1566,11 @@ sub scan_directives(@) { sub openOutputFilter() { return if !defined($output_filter) || $output_filter eq ''; - open(STDOUT, "|-") && return; + open(STDOUT, "|-") and return; # child of child open(STDERR, '>/dev/null'); - exec($output_filter); - - exit -1; + exec($output_filter) or exit -1; } ############################### @@ -1560,14 +1586,14 @@ sub doAnnotate($$) { # make sure the revisions are wellformed, for security # reasons .. if ($rev =~ /[^\w.]/) { - &fatal("404 Not Found", - "Malformed query \"$ENV{QUERY_STRING}\""); + fatal("404 Not Found", + 'Malformed query "%s"', + $ENV{QUERY_STRING}); } if (&forbidden_file($fullname)) { - &fatal("403 Forbidden", - "Access forbidden. This file is mentioned in \@ForbiddenFiles" - ); + fatal("403 Forbidden", + 'Access forbidden. This file is mentioned in @ForbiddenFiles'); return; } @@ -1585,8 +1611,8 @@ sub doAnnotate($$) { # we could abandon the use of rlog, rcsdiff and co using # the cvsserver in a similiar way one day (..after rewrite) $pid = open2($reader, $writer, $CMD{cvs}, @cvs_options, "server") - || fatal("500 Internal Error", - "Fatal Error - unable to open cvs for annotation"); + or fatal("500 Internal Error", + 'Fatal Error - unable to open cvs for annotation'); # OK, first send the request to the server. A simplified example is: # Root /home/kingdon/zwork/cvsroot @@ -1641,13 +1667,13 @@ sub doAnnotate($$) { # 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" # were nicer about buffering, then we could just leave it open, I think. - close($writer) || die "cannot close: $!"; + close($writer) or die "cannot close: $!"; http_header(); navigateHeader($scriptwhere, $pathname, $filename, $rev, "annotate"); print - "

Annotation of $pathname$filename, Revision $rev

\n"; + "

Annotation of $pathname$filename, Revision $rev

\n"; # Ready to get the responses from the server. # For example: @@ -1660,7 +1686,7 @@ sub doAnnotate($$) { my ($revprint, $usrprint); if ($annTable) { - print "\n"; + print "
\n"; } else { print "
";
 	}
@@ -1721,7 +1747,8 @@ sub doAnnotate($$) {
 			# CVS command line client.  But for simplicity, we don't.
 		} elsif ($words[0] eq "error") {
 			fatal("500 Internal Error",
-				"Error occured during annotate: $_");
+			      'Error occured during annotate: %s',
+			      $_);
 		}
 	}
 
@@ -1730,7 +1757,7 @@ sub doAnnotate($$) {
 	} else {
 		print "
"; } - close($reader) || warn "cannot close: $!"; + close($reader) or warn "cannot close: $!"; wait; } @@ -1749,14 +1776,14 @@ sub doCheckout($$) { # make sure the revisions a wellformed, for security # reasons .. if (defined($rev) && $rev =~ /[^\w.]/) { - &fatal("404 Not Found", - "Malformed query \"$ENV{QUERY_STRING}\""); + fatal("404 Not Found", + 'Malformed query "%s"', + $ENV{QUERY_STRING}); } if (&forbidden_file($fullname)) { - &fatal("403 Forbidden", - "Access forbidden. This file is mentioned in \@ForbiddenFiles" - ); + fatal("403 Forbidden", + 'Access forbidden. This file is mentioned in @ForbiddenFiles'); return; } @@ -1794,12 +1821,19 @@ sub doCheckout($$) { # chdir to $tmpdir before to avoid non-readable cgi-bin directories chdir($tmpdir); open(STDERR, ">&STDOUT"); # Redirect stderr to stdout - exec($CMD{cvs}, @cvs_options, '-d', $cvsroot, 'co', '-p', - $revopt, $where); + + # work around a bug of cvs -p; expand symlinks + use Cwd 'abs_path'; + exec($CMD{cvs}, @cvs_options, + '-d', abs_path($cvsroot), + 'co', '-p', + $revopt, $where) or exit -1; } if (eof($fh)) { - &fatal("404 Not Found", "$where is not (any longer) pertinent"); + fatal("404 Not Found", + '%s is not (any longer) pertinent', + $where); } #=================================================================== @@ -1823,8 +1857,9 @@ sub doCheckout($$) { } if ($filename ne $where) { - &fatal("500 Internal Error", - "Unexpected output from cvs co: $cvsheader"); + fatal("500 Internal Error", + 'Unexpected output from cvs co: %s', + $cvsheader); } $| = 1; @@ -1849,7 +1884,7 @@ sub cvswebMarkup($$$) { navigateHeader($scriptwhere, $pathname, $filename, $revision, "view"); print "
"; - print "
\n\n
"; + print "\n\n
"; print "File: ", &clickablePath($where, 1); print " ("; &download_link($fileurl, $revision, "download"); @@ -1870,7 +1905,7 @@ sub cvswebMarkup($$$) { print "Tag: ", $input{only_with_tag}, "
\n" if $input{only_with_tag}; } - print "
"; + print "
"; my $url = download_url($fileurl, $revision, $mimetype); print "
"; @@ -1918,9 +1953,8 @@ sub doDiff($$$$$$) { my ($rev1, $rev2, $sym1, $sym2, $f1, $f2); if (&forbidden_file($fullname)) { - &fatal("403 Forbidden", - "Access forbidden. This file is mentioned in \@ForbiddenFiles" - ); + fatal("403 Forbidden", + 'Access forbidden. This file is mentioned in @ForbiddenFiles'); return; } @@ -1945,8 +1979,9 @@ sub doDiff($$$$$$) { # make sure the revisions a wellformed, for security # reasons .. if ($rev1 =~ /[^\w.]/ || $rev2 =~ /[^\w.]/) { - &fatal("404 Not Found", - "Malformed query \"$ENV{QUERY_STRING}\""); + fatal("404 Not Found", + 'Malformed query "%s"', + $ENV{QUERY_STRING}); } # @@ -1961,7 +1996,9 @@ sub doDiff($$$$$$) { my $difftype = $DIFFTYPES{$f}; if (!$difftype) { - fatal("400 Bad arguments", "Diff format $f not understood"); + fatal("400 Bad arguments", + 'Diff format %s not understood', + $f); } my @difftype = @{$difftype->{'opts'}}; @@ -1993,11 +2030,12 @@ sub doDiff($$$$$$) { if (!open($fh, "-|")) { # child open(STDERR, ">&STDOUT"); # Redirect stderr to stdout openOutputFilter(); - exec($CMD{rcsdiff}, @difftype, "-r$rev1", "-r$rev2", $fullname); + exec($CMD{rcsdiff}, @difftype, "-r$rev1", "-r$rev2", $fullname) or exit -1; } if ($human_readable) { http_header(); &human_readable_diff($fh, $rev2); + html_footer(); gzipclose(); exit; } else { @@ -2082,14 +2120,14 @@ sub getDirLogs($$@) { if (!open($fh, "-|")) { # child open(STDERR, '>/dev/null'); # rlog may complain; ignore. openOutputFilter(); - exec($CMD{rlog}, @files); + exec($CMD{rlog}, @files) or exit -1; } } else { if (!open($fh, "-|")) { # child open(STDERR, '>/dev/null'); # rlog may complain; ignore. openOutputFilter(); - exec($CMD{rlog}, '-r', @files); + exec($CMD{rlog}, '-r', @files) or exit -1; } } $state = "start"; @@ -2147,7 +2185,7 @@ sub getDirLogs($$@) { } if ($state eq "tags") { - if (/^\s+(.+):\s+([\d\.]+)\s+$/) { + if (/^\s+([^:]+):\s+([\d\.]+)\s*$/) { push (@filetags, $1); $symrev{$1} = $2; $alltags{$1} = 1; @@ -2239,8 +2277,8 @@ sub getDirLogs($$@) { $state = "log"; $log = ''; next; - } elsif ($rev eq '' && /^revision (.*)$/) { - $rev = $1; + } elsif ($rev eq '' && /^revision (\d+(?:\.\d+)+).*$/) { + $rev = $1; # .*$ eats up the locker(lockers?) info, if any next; } else { $log .= $_; @@ -2254,10 +2292,9 @@ sub getDirLogs($$@) { } if ($. == 0) { - fatal("500 Internal Error", "Failed to spawn GNU rlog on '" - . join (", ", @files) - . "'

Did you set the \$command_path in your configuration file correctly ? (Currently '$command_path'" - ); + fatal("500 Internal Error", + 'Failed to spawn GNU rlog on "%s".

Did you set the $command_path in your configuration file correctly ? (Currently "%s"', + join (", ", @files), $command_path); } close($fh); } @@ -2286,10 +2323,10 @@ sub readLog($;$) { if (!open($fh, "-|")) { # child if ($revision ne '') { openOutputFilter(); - exec($CMD{rlog}, $revision, $fullname); + exec($CMD{rlog}, $revision, $fullname) or exit -1; } else { openOutputFilter(); - exec($CMD{rlog}, $fullname); + exec($CMD{rlog}, $fullname) or exit -1; } } @@ -2319,13 +2356,18 @@ sub readLog($;$) { # date: 1995/11/29 22:15:52; author: fenner; state: Exp; lines: +5 -3 # log info # ---------------------------- + + # For a locked revision, the first line after the separator + # becomes smth like + # revision 9.19 locked by: vassilii; + logentry: while (!/$LOG_FILESEPARATOR/o) { $_ = <$fh>; last logentry if (!defined($_)); # EOF print "R:", $_ if ($verbose); - if (/^revision ([\d\.]+)/) { + if (/^revision (\d+(?:\.\d+)+)/) { $rev = $1; unshift (@allrevisions, $rev); } elsif (/$LOG_FILESEPARATOR/o || /$LOG_REVSEPARATOR/o) { @@ -2340,8 +2382,6 @@ sub readLog($;$) { # these lines since we don't know what revision they go with # any more. next logentry; - - # &fatal("500 Internal Error","Error parsing RCS output: $_"); } $_ = <$fh>; print "D:", $_ if ($verbose); @@ -2361,8 +2401,9 @@ sub readLog($;$) { $state{$rev} = $8; $difflines{$rev} = $10; } else { - &fatal("500 Internal Error", - "Error parsing RCS output: $_"); + fatal("500 Internal Error", + 'Error parsing RCS output: %s', + $_); } line: @@ -2469,7 +2510,8 @@ sub readLog($;$) { if (!defined($onlyonbranch) || $onlybranchpoint eq "") { fatal("404 Tag not found", - "Tag $input{'only_with_tag'} not defined"); + 'Tag %s not defined', + $input{'only_with_tag'}); } } @@ -2528,6 +2570,7 @@ sub printLog($;$) { $link = 1 if (!defined($link)); $isDead = ($state{$_} eq "dead"); + print "

\n"; if ($link && !$isDead) { my ($filename); ($filename = $where) =~ s/^.*\///; @@ -2649,7 +2692,8 @@ sub printLog($;$) { my %diffrev = (); $diffrev{$_} = 1; $diffrev{""} = 1; - print "
Diff"; + print '
'; + my $diff = 'Diff'; # # Offer diff to previous revision @@ -2660,7 +2704,8 @@ sub printLog($;$) { sprintf('%s.diff?r1=%s&r2=%s%s', $scriptwhere, $prev, $_, $barequery); - print " to previous "; + print $diff, " to previous "; + $diff = ''; printDiffLinks($prev, $url); } @@ -2674,7 +2719,8 @@ sub printLog($;$) { sprintf('%s.diff?r1=%s&r2=%s%s', $scriptwhere, $brp, $_, $barequery); - print " to branchpoint "; + print $diff, " to branchpoint "; + $diff = ''; printDiffLinks($brp, $url); } @@ -2716,7 +2762,8 @@ sub printLog($;$) { $scriptwhere, $nextmain, $_, $barequery); - print " next main "; + print $diff, " next main "; + $diff = ''; printDiffLinks($nextmain, $url); } } @@ -2730,12 +2777,15 @@ sub printLog($;$) { sprintf('%s.diff?r1=%s&r2=%s%s', $scriptwhere, $input{'r1'}, $_, $barequery); - print " to selected "; + print $diff, " to selected "; + $diff = ''; printDiffLinks($input{'r1'}, $url); } + + print '
' if $diff; } - print "

\n";
-	print &htmlify($log{$_}, 1);
+	print "\n

\n
\n";
+	print &htmlify($log{$_}, $allow_log_extra);
 	print "
\n"; } @@ -2749,11 +2799,14 @@ sub doLog($) { ($upwhere = $where) =~ s|(Attic/)?[^/]+$||; ($filename = $where) =~ s|^.*/||; $backurl = $scriptname . "/" . urlencode($upwhere) . $query; + print "

\n "; print &link($backicon, "$backurl#$filename"), " Up to ", - &clickablePath($upwhere, 1), "

\n"; + &clickablePath($upwhere, 1), "\n

\n"; + print "

\n "; print &link('Request diff between arbitrary revisions', '#diff'); - print '


'; + print "\n

\n
\n"; + print "

\n"; if ($curbranch) { print "Default branch: ", ($revsym{$curbranch} || $curbranch); } else { @@ -2764,21 +2817,22 @@ sub doLog($) { if ($input{only_with_tag}) { print "Current tag: $input{only_with_tag}
\n"; } + print "

\n"; undef %nameprinted; for (my $i = 0 ; $i <= $#revdisplayorder ; $i++) { - print "
"; + print "
\n"; printLog($revdisplayorder[$i]); } - print "
"; + print "
\n

\n"; print "\n"; print "This form allows you to request diff's between any two\n"; print "revisions of a file. You may select a symbolic revision\n"; print "name using the selection box or you may type in a numeric\n"; print "name using the type-in text box.\n"; - print "

\n"; + print "\n

\n"; print "
\n"; @@ -2789,7 +2843,7 @@ sub doLog($) { && ((!defined($DEFAULTVALUE{$_}) || $input{$_} ne $DEFAULTVALUE{$_}) && $input{$_} ne "")); } - print "\n"; + print "
\n\n"; print ""; - print "\n"; - print "\n"; + print "\n\n"; + print "\n"; + "\n"; print "\n"; + print "\n
Diffs between \n"; print "
and \n"; + "
and \n"; print "
\n"; print "
\n"; - print "\n"; print "
\n"; - print ""; print "\n"; - print ""; + print "
Preferred Diff type:
\n"; + print "\n\n"; print "\n"; + print "\n\n\n"; if (@branchnames) { - print ""; + print "\n\n"; print "\n"; + print "\n\n\n"; } foreach (@stickyvars) { @@ -2852,16 +2906,16 @@ sub doLog($) { && (!defined($DEFAULTVALUE{$_}) || $input{$_} ne $DEFAULTVALUE{$_}) && $input{$_} ne ""); } - print "\n"; + print "Sort log by:\n"; print ""; - print ""; + print "\n"; + print "\n"; + print "\n
Preferred Diff type:"; printDiffSelect($use_java_script); - print "
View only Branch:
View only Branch:"; print "\n"; print "
"; + print "
"; print "\n"; - print "Sort log by:"; printLogSortSelect($use_java_script); - print "
\n"; print "\n"; - print ""; - print &html_footer; + html_footer(); } sub flush_diff_rows($$$$) { @@ -2875,32 +2929,33 @@ sub flush_diff_rows($$$$) { if ($state eq "PreChangeRemove") { # we just got remove-lines before for ($j = 0 ; $j < $leftRow ; $j++) { print - "@$leftColRef[$j]"; + "\n @$leftColRef[$j]\n"; print - " \n"; + " \n\n"; } } elsif ($state eq "PreChange") { # state eq "PreChange" # we got removes with subsequent adds for ($j = 0 ; $j < $leftRow || $j < $rightRow ; $j++) { # dump out both cols - print ""; + print "\n"; if ($j < $leftRow) { print - "@$leftColRef[$j]"; + " @$leftColRef[$j]"; } else { print - " "; + " "; } + print "\n"; if ($j < $rightRow) { print - "@$rightColRef[$j]"; + " @$rightColRef[$j]"; } else { print - " "; + " "; } - print "\n"; + print "\n\n"; } } } @@ -2939,9 +2994,10 @@ sub human_readable_diff($) { } print - "

Diff for /$where_nd between version $rev1 and $rev2

\n", + "

Diff for /$where_nd between version $rev1 and $rev2

\n", + # Using style=\"border: none\" here breaks NS 4.x badly... "\n", - "\n", "\n", "\n"; - my $fs = ""; - my $fe = ""; - my $leftRow = 0; my $rightRow = 0; my ($oldline, $newline, $funname, $diffcode, $rest); # Process diff text - # The diffrows are could make excellent use of - # cascading style sheets because we've to set the - # font and color for each row. anyone ...? - #### # prefetch several lines my @buf = head($fh); @@ -2975,17 +3024,18 @@ sub human_readable_diff($) { ($oldline, $newline, $funname) = $difftxt =~ /@@ \-([0-9]+).*\+([0-9]+).*@@(.*)/; $funname = htmlquote($funname); + $funname =~ s/\s/ /go; print - "\n\n\n"; $state = "dump"; $leftRow = 0; @@ -2994,9 +3044,6 @@ sub human_readable_diff($) { ($diffcode, $rest) = $difftxt =~ /^([-+ ])(.*)/; $_ = spacedHtmlText($rest, $d{'tabstop'}); - # Add fontface, size - $_ = "$fs $_$fe"; - ######### # little state machine to parse unified-diff output (Hen, zeller@think.de) # in order to get some nice 'ediff'-mode output @@ -3010,7 +3057,7 @@ sub human_readable_diff($) { if ($state eq "dump") { # 'change' never begins with '+': just dump out value print - "\n"; + "\n\n\n\n"; } else { # we got minus before $state = "PreChange"; $rightCol[$rightRow++] = $_; @@ -3021,7 +3068,7 @@ sub human_readable_diff($) { } else { # empty diffcode flush_diff_rows \@leftCol, \@rightCol, $leftRow, $rightRow; - print "\n"; + print "\n\n\n\n"; $state = "dump"; $leftRow = 0; $rightRow = 0; @@ -3034,34 +3081,29 @@ sub human_readable_diff($) { # state is empty if we didn't have any change if (!$state) { - print ""; - print ""; + print "\n\n\n"; + print "\n"; print - ""; + "\n\n"; } - print "
", + "
", "version $rev1"; print ", $date1" if (defined($date1)); print "
Tag: $sym1\n" if ($sym1); @@ -2950,18 +3006,11 @@ sub human_readable_diff($) { print "
Tag: $sym2\n" if ($sym1); print "
"; + "
"; print - "\n\n
Line $oldline"; + "\n\n
Line $oldline"; print - " $funname
"; - print "
"; + " $funname
"; + print "
"; print - "\n\n
Line $newline"; + "\n\n
Line $newline"; print - " $funname
"; + " $funname
\n"; print "
 $_
  $_
$_$_
 $_ $_
 
 
- No viewable change -
- No viewable change -
"; + print "\n"; - print "

\n"; - - print ""; - - print "\n"; + print "\n"; - print "
"; + print "
\n"; + print "
\n"; + print "\n\n\n\n
\n"; # print legend - print "\n\n\n\n"; + print "
"; - print "Legend:
\n"; + print "
\n\n
"; + print "Legend:
\n"; print - ""; + "\n\n\n\n"; print - ""; + "\n\n\n"; print - ""; - print "
Removed from v.$rev1 
Removed from v.$rev1 
changed lines
changed lines
 Added in v.$rev2
\n"; - - print "
"; + "
 Added in v.$rev2
\n
\n
"; # Print format selector - print "\n"; foreach my $var (keys %input) { next if ($var eq "f"); next @@ -3072,10 +3114,10 @@ sub human_readable_diff($) { } printDiffSelect($use_java_script); print "\n"; - print "\n"; - print "
"; + print "\n\n"; + print "\n"; } sub navigateHeader($$$$$) { @@ -3083,16 +3125,54 @@ sub navigateHeader($$$$$) { $swhere = "" if ($swhere eq $scriptwhere); $swhere = './' . urlencode($filename) if ($swhere eq ""); + # TODO: this should be moved into external CSS file. + my $css = ''; + if ($title eq 'diff') { + $css = " +"; + } + print < +$HTML_DOCTYPE + + -$path$filename - $title - $rev +$path$filename - $title - $rev$css $body_tag_for_src - +
\n\n
EOF @@ -3207,9 +3287,10 @@ sub clickablePath($$) { } sub chooseCVSRoot() { + + print "
\n"; if (2 <= @CVSROOT) { my ($k); - print "\n"; foreach $k (keys %input) { print "\n" if ($input{$k}) && ($k ne "cvsroot"); @@ -3218,8 +3299,8 @@ sub chooseCVSRoot() { # Form-Elements look wierd in Netscape if the background # isn't gray and the form elements are not placed # within a table ... - print ""; - print ""; + print "
CVS Root:
\n\n"; + print "\n"; print ""; - print "\n
CVS Root:\n\n"; + print "\n"; } else { - # no choice -- but we need the form to select module/path, at least for Netscape - print "\n"; + # no choice -- but we need the form to select module/path, + # at least for Netscape + print "

\n"; print "CVS Root: [$cvstree]"; } @@ -3244,9 +3325,11 @@ sub chooseCVSRoot() { print ""; if (2 <= @CVSROOT) { - print "

"; + print "
"; + } else { + print "

"; } - print ""; + print "\n"; } sub chooseMirror() { @@ -3511,7 +3594,7 @@ sub http_header(;$) { print "\r\n"; # Close headers } print - "Unable to find gzip binary in the \$command_path ($command_path) to compress output
"; + "Unable to find gzip binary in the \$command_path ($command_path) to compress output
"; } } else { @@ -3527,12 +3610,19 @@ sub html_header($) { my ($title) = @_; http_header("text/html"); - (my $header = &cgi_style::html_header) =~ s/^.*\n\n//; # remove HTTP response header + (my $header = &cgi_style::html_header) =~ s,\A.*\n,,s; print < -$header +$HTML_DOCTYPE + + + + + +$title + +$header EOH } diff --git a/en/cgi/cvsweb.conf b/en/cgi/cvsweb.conf index a4448fbfa6..128bb0c610 100644 --- a/en/cgi/cvsweb.conf +++ b/en/cgi/cvsweb.conf @@ -7,9 +7,9 @@ # 2000-2002 A. MUSHA # based on work by Bill Fenner # -# $Id: cvsweb.conf,v 1.26 2002-04-10 20:13:19 knu Exp $ +# $Id: cvsweb.conf,v 1.27 2002-05-22 08:31:06 knu Exp $ # $Idaemons: /home/cvs/cvsweb/cvsweb.conf,v 1.27 2001/08/01 09:48:39 knu Exp $ -# $FreeBSD: www/en/cgi/cvsweb.conf,v 1.25 2002/03/09 20:55:39 wosch Exp $ +# $FreeBSD: www/en/cgi/cvsweb.conf,v 1.26 2002/04/10 20:13:19 knu Exp $ # ### @@ -42,7 +42,7 @@ chomp($uname = `$CMD{uname}`); # 'symbolic_name' => ['name_to_display', 'path_to_the_actual_repository'] # Listed in the order specified: @CVSrepositories = ( - 'freebsd' => ['FreeBSD', '/c/ncvs'], + 'freebsd' => ['FreeBSD', '/home/ncvs'], 'openbsd' => ['OpenBSD', '/usr/local/www/cvsroot/OpenBSD'], 'netbsd' => ['NetBSD', '/usr/local/www/cvsroot/NetBSD'], '44bsdlite' => ['4.4BSD-Lite', '/e/4.4BSD-Lite/4.4BSD-Lite-CVS'], @@ -408,6 +408,15 @@ $allow_annotate = 1; # allow pretty-printed version of files $allow_markup = 1; +# allow extra hlink formatting (such as PR xrefs) in logs +$allow_log_extra = 1; # default: enabled + +# allow extra hlink formatting (such as PR xrefs) in directories +$allow_dir_extra = 1; + +# allow extra hlink formatting in source code/formatted diff views +$allow_source_extra = 1; + # allow compression with gzip # of output if the Browser accepts # it (HTTP_ACCEPT_ENCODING=gzip) diff --git a/en/cgi/cvsweb.conf-netbsd b/en/cgi/cvsweb.conf-netbsd index 961c8c9b1d..1c1ef3486d 100644 --- a/en/cgi/cvsweb.conf-netbsd +++ b/en/cgi/cvsweb.conf-netbsd @@ -3,10 +3,10 @@ # Set up for NetBSD repo options. # # $Idaemons: /home/cvs/cvsweb/cvsweb.conf-netbsd,v 1.5 2001/08/01 09:32:22 knu Exp $ -# $FreeBSD: www/en/cgi/cvsweb.conf-netbsd,v 1.10 2001/11/07 21:25:16 knu Exp $ +# $FreeBSD: www/en/cgi/cvsweb.conf-netbsd,v 1.11 2002/04/10 20:13:19 knu Exp $ if ($uname eq 'FreeBSD') { - $ENV{'RCSLOCALID'} = 'NetBSD=CVSHeader'; + $ENV{'RCSLOCALID'} = 'NetBSD=Id'; $ENV{'RCSINCEXC'} = 'iNetBSD'; } else { $ENV{'RCSLOCALID'} = 'NetBSD'; diff --git a/en/cgi/cvsweb.conf-openbsd b/en/cgi/cvsweb.conf-openbsd index 6376e79be5..e2d847f934 100644 --- a/en/cgi/cvsweb.conf-openbsd +++ b/en/cgi/cvsweb.conf-openbsd @@ -3,10 +3,10 @@ # Set up for OpenBSD repo options. # # $Idaemons: /home/cvs/cvsweb/cvsweb.conf-openbsd,v 1.5 2001/08/01 09:32:22 knu Exp $ -# $FreeBSD: www/en/cgi/cvsweb.conf-openbsd,v 1.8 2001/11/07 21:25:16 knu Exp $ +# $FreeBSD: www/en/cgi/cvsweb.conf-openbsd,v 1.9 2002/04/10 20:13:19 knu Exp $ if ($uname eq 'FreeBSD') { - $ENV{'RCSLOCALID'} = 'OpenBSD=CVSHeader'; + $ENV{'RCSLOCALID'} = 'OpenBSD=Id'; $ENV{'RCSINCEXC'} = 'iOpenBSD'; } else { $ENV{'RCSLOCALID'} = 'OpenBSD';