=================================================================== RCS file: /cvs/cvsweb/cvsweb.cgi,v retrieving revision 4.35 retrieving revision 4.39 diff -u -p -r4.35 -r4.39 --- cvsweb/cvsweb.cgi 2019/11/29 18:15:48 4.35 +++ cvsweb/cvsweb.cgi 2019/11/29 23:42:40 4.39 @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $Id: cvsweb.cgi,v 4.35 2019/11/29 18:15:48 schwarze Exp $ +# $Id: cvsweb.cgi,v 4.39 2019/11/29 23:42:40 schwarze Exp $ # $knu: cvsweb.cgi,v 1.299 2010/11/13 16:37:18 simon # # cvsweb - a CGI interface to CVS trees. @@ -55,9 +55,8 @@ use filetest qw(access); use vars qw ( $VERSION $CheckoutMagic $MimeTypes $DEBUG - $config $allow_version_select @CVSrepositories @CVSROOT %CVSROOT %CVSROOTdescr %DEFAULTVALUE %MTYPES - %DIFF_COMMANDS @DIFFTYPES %DIFFTYPES @LOGSORTKEYS %LOGSORTKEYS + @DIFFTYPES %DIFFTYPES @LOGSORTKEYS %LOGSORTKEYS %alltags %fileinfo %tags @branchnames %nameprinted %symrev %revsym @allrevisions %date %author @revdisplayorder @revisions %state %difflines %log %branchpoint @revorder $keywordsubstitution @@ -66,10 +65,10 @@ use vars qw ( $is_links $is_lynx $is_w3m $is_msie $is_mozilla3 $is_textbased %input $query $barequery $sortby $bydate $byrev $byauthor $bylog $byfile $defaultDiffType $logsort $cvstree $cvsroot - $charset $output_filter %CMD $allow_compress $backicon $diricon $fileicon + %CMD $allow_compress $backicon $diricon $fileicon $fullname $logo $defaulttitle $address $binfileicon $iconsdir $shortLogLen $show_author $hr_breakable $hr_ignwhite $hr_ignkeysubst - $inputTextSize $mime_types $allow_annotate $allow_markup $allow_mailtos + $mime_types $allow_annotate $allow_markup $allow_mailtos $allow_log_extra $allow_dir_extra $allow_source_extra $edit_option_form $show_subdir_lastmod $show_log_in_markup $preformat_in_markup @@ -86,7 +85,7 @@ use Cwd qw(abs_path); use File::Path qw(rmtree); use File::Spec::Functions qw(canonpath catdir catfile curdir devnull rootdir tmpdir updir); -use File::Temp qw(tempdir tempfile); +use File::Temp qw(tempdir); use IPC::Run qw(); use Time::Local qw(timegm); use URI::Escape qw(uri_escape uri_unescape); @@ -126,8 +125,6 @@ EOM $MimeTypes = undef if $@; $CheckoutMagic = '~checkout~'; - $CMD{$_} = "/usr/bin/$_" for (qw(cvs rcsdiff rlog)); - $CMD{tar} = "/bin/tar"; } # ----------------------------------------------------------------------------- @@ -149,7 +146,6 @@ sub search_path($); sub getMimeType($;$); sub head($;$); sub scan_directives(@); -sub openOutputFilter(); sub doAnnotate($$); sub doCheckout($$$); sub cvswebMarkup($$$$$$;$); @@ -182,7 +178,6 @@ sub link_tags($); sub forbidden($); sub startproc(@); sub runproc(@); -sub checkout_to_temp($$$); # Get rid of unsafe environment vars. Don't do this in the BEGIN block # (think mod_perl)... @@ -192,25 +187,90 @@ delete(@ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}); # with cvs >= 1.12.1 and doesn't hurt other versions. $ENV{CVSREADONLYFS} = 1; -# Location of the configuration file inside the web server chroot: -$config = '/conf/cvsweb/cvsweb.conf'; +######## configuration defaults ######### -######## Configuration parameters ######### +%CMD = ( + cvs => '/usr/bin/cvs', + rcsdiff => '/usr/bin/rcsdiff', + rlog => '/usr/bin/rlog', + tar => '/bin/tar', +); -@CVSrepositories = @CVSROOT = %CVSROOT = %DEFAULTVALUE = - %MTYPES = %tags = %alltags = %fileinfo = %DIFF_COMMANDS = (); +%DEFAULTVALUE = ( + f => 'u', + hideattic => 1, + hidecvsroot => 0, + hidenonreadable => 1, + ignorecase => 0, + ln => 0, + logsort => 'date', + sortby => 'file', +); -$logo = $defaulttitle = - $address = $shortLogLen = $show_author = - $hr_breakable = $hr_ignwhite = - $hr_ignkeysubst = $inputTextSize = $mime_types = $allow_annotate = - $allow_markup = $allow_compress = $edit_option_form = - $show_subdir_lastmod = $show_log_in_markup = $preformat_in_markup = - $tabstop = $use_moddate = $gzip_open = $DEBUG = - $allow_tar = undef; +@ForbiddenFiles = ( + qr|^CVSROOT/+passwd$|o, # CVSROOT/passwd should not be 'cvs add'ed though. + qr|/\.cvspass$|o, # Ditto. Just in case. +); -$allow_version_select = $allow_mailtos = $allow_log_extra = 1; +%MTYPES = ( + gif => 'image/gif', + html => 'text/html', + jpeg => 'image/jpeg', + jpg => 'image/jpeg', + png => 'image/png', +); +$address = 'CVSweb'; +$allow_annotate = 1; +$allow_compress = 0; +$allow_dir_extra = 1; +$allow_log_extra = 1; +$allow_mailtos = 1; +$allow_markup = 1; +$allow_source_extra = 1; +$allow_tar = 0; +@annotate_options = qw(-f -R); +$cssurl = '/css/cvsweb.css'; +@cvs_options = qw(-f -R); +@CVSrepositories = ('local', ['Local Repository', '/cvs']); +$DEBUG = 0; +$defaulttitle = 'CVS Repository'; +$edit_option_form = 1; +$file_list_len = 0; +$hr_breakable = 1; +$hr_ignkeysubst = 1; +$hr_ignwhite = 0; +$iconsdir = '/icons'; +$logo = undef; +$mancgi = 'https://man.openbsd.org/%s.%s'; +$mime_types = '/conf/mime.types'; +$preformat_in_markup = 0; +@rcsdiff_options = qw(-q); +$shortLogLen = 80; +$show_author = 1; +$show_log_in_markup = 1; +$show_subdir_lastmod = 0; +$tabstop = 8; +@tar_options = qw(); +$use_descriptions = 0; +$use_moddate = 1; + +######## load configuration ######### + +{ + my $config = '/conf/cvsweb/cvsweb.conf'; + last unless -e $config; + defined do $config and last; + $@ and fatal '500 Internal Error', + 'Error loading configuration file "%s":
%s
', + $config, $@; + fatal '500 Internal Error', + 'Cannot read configuration file "%s": %s', + $config, $! || 'unknown error'; +} + +######## other global variables ######### + @DIFFTYPES = qw(h H u c); @DIFFTYPES{@DIFFTYPES} = ( { @@ -242,8 +302,16 @@ $allow_version_select = $allow_mailtos = $allow_log_ex { descr => 'Revision', }, ); -##### End of configuration parameters ##### +%alltags = (); +@CVSROOT = (); +%CVSROOT = (); +%CVSROOTdescr = (); +%fileinfo = (); +$gzip_open = 0; +%tags = (); +######## end of global variables ######### + my $pathinfo = ''; if (defined($ENV{PATH_INFO}) && $ENV{PATH_INFO} ne '') { ($pathinfo) = ($ENV{PATH_INFO} =~ VALID_PATH) @@ -316,20 +384,6 @@ $maycompress = ( qw(cvsroot hideattic ignorecase sortby logsort f only_with_tag ln hidecvsroot hidenonreadable); -# Load configuration. -{ - $config =~ m|^/| or fatal '500 Internal Error', - 'Configuration file name "%s" is not an absolute path.', - $config; - defined do $config and last; - $@ and fatal '500 Internal Error', - 'Error loading configuration file "%s":
%s
', - $config, $@; - fatal '500 Internal Error', - 'Cannot read configuration file "%s": %s', - $config, $! || 'unknown error'; -} - # Try to find a readable dir where we can cd into. Some abs_path() # implementations as well as various cvs operations require such a dir to # work properly. @@ -479,10 +533,7 @@ for (my $i = 0; $i < scalar(@CVSrepositories); $i += 2 push(@CVSROOT, $key); } unless ($rootfound) { - fatal('500 Internal Error', - 'No valid CVS roots found! See @CVSrepositories in ' . - 'the configuration file (%s).', - $config); + fatal('500 Internal Error', 'no valid CVS roots found'); } undef $rootfound; @@ -586,17 +637,6 @@ if ($iconsdir) { $binfileicon = 'binfile'; } -my $config_cvstree = "$config-$cvstree"; - -# Do some special configuration for cvstrees -if (-f $config_cvstree) { - do "$config_cvstree" - or fatal("500 Internal Error", - 'Error in loading configuration file: %s

%s
', - $config_cvstree, $@); -} -undef $config_cvstree; - $fullname = catfile($cvsroot, $where); my $rewrite = 0; @@ -1631,18 +1671,6 @@ sub scan_directives(@) } -sub openOutputFilter() -{ - return unless $output_filter; - - open(STDOUT, "|-") and return; - - # child of child - open(STDERR, '>', devnull()) unless $DEBUG; - exec($output_filter) or exit -1; -} - - ############################### # show Annotation ############################### @@ -2062,60 +2090,6 @@ sub doDiff($$$$$$) my $mimetype = getMimeType($fullname); - # - # Check for per-MIME type diff commands. - # - my $diffcmd = undef; - if (my $diffcmds = $DIFF_COMMANDS{lc($mimetype)}) { - if ($f =~ /^ext(\d*)$/) { - my $n = $1 || 0; - $diffcmd = $diffcmds->[$n]; - } - } - if ($diffcmd && $diffcmd->{cmd} && $diffcmd->{name}) { - - if ($diffcmd->{args} && ref($diffcmd->{args}) ne 'ARRAY') { - fatal('500 Internal Error', - 'Configuration error: arguments to external diff tools must ' . - 'be given as array refs. See "%s" in ' . - '%%DIFF_COMMANDS.', - $diffcmd->{name}); - } - - (my $cvsname = $where) =~ s/\.diff$//; - - # Create two temporary files with the two revisions - my $temp_fn1 = checkout_to_temp($cvsroot, $cvsname, $rev1); - my $temp_fn2 = checkout_to_temp($cvsroot, $cvsname, $rev2); - - # Execute chosen diff binary. - local (*DIFF_OUT); - my @cmd = ($diffcmd->{cmd}); - push(@cmd, @{$diffcmd->{args}}) if $diffcmd->{args}; - push(@cmd, $temp_fn1, $temp_fn2); - my ($h, $err) = startproc(\@cmd, \"", '>pipe', \*DIFF_OUT); - if (!$h) { - unlink($temp_fn1); - unlink($temp_fn2); - fatal('500 Internal Error', - 'Diff failure (exit status %s), output:
%s
', - $? >> 8 || -1, $err); - } - - http_header($diffcmd->{type} || 'text/plain'); - local $/ = undef; - print ; - $h->finish(); - unlink($temp_fn1); - unlink($temp_fn2); - - exit; - } - - # - # Normal CVS diff. - # - $f = $DEFAULTVALUE{f} || 'u' if ($f =~ /^ext\d*$/); my $difftype = $DIFFTYPES{$f}; if (!$difftype) { @@ -2136,7 +2110,6 @@ sub doDiff($$$$$$) my $fh = do { local (*FH); }; if (!open($fh, "-|")) { # child open(STDERR, ">&STDOUT"); # Redirect stderr to stdout - openOutputFilter(); exec($CMD{rcsdiff}, @rcsdiff_options, @difftype, "-r$rev1", "-r$rev2", $fullname) or exit -1; } @@ -2243,7 +2216,6 @@ sub getDirLogs($$@) my $fh = do { local (*FH); }; if (!open($fh, '-|')) { # Child open(STDERR, '>', devnull()) unless $DEBUG; # Ignore rlog's complaints. - openOutputFilter(); if ($file_list_len && $file_list_len > 1) { while (scalar(@files) > $file_list_len) { # Process files in chunks. system(@cmd, splice(@files, 0, $file_list_len)) == 0 or exit -1; @@ -2421,7 +2393,6 @@ sub readLog($;$) my $fh = do { local (*FH); }; if (!open($fh, "-|")) { # child - openOutputFilter(); $revision = defined($revision) ? "-r$revision" : ''; if ($revision =~ /\./) { # Normal revision, not a branch/tag name. @@ -2647,13 +2618,6 @@ sub getDiffLinks($$$) &link(htmlquote(lc($DIFFTYPES{$difftype}{descr})), "$url;f=$f")); } } - if (my $extdiffs = $DIFF_COMMANDS{lc($mimetype)}) { - for my $i (0 .. scalar(@$extdiffs)-1) { - my $extdiff = $extdiffs->[$i]; - push(@links, &link(htmlquote($extdiff->{name}), "$url;f=ext$i")) - if ($extdiff->{cmd} && $extdiff->{name}); - } - } return @links; } @@ -2705,7 +2669,7 @@ sub printLog($$$;$$) print ' - view: ', join(', ', @vlinks) if @vlinks; undef @vlinks; - if (!$isbin && $allow_version_select) { + unless ($isbin) { print ' - '; if ($isSelected) { print '[selected for diffs]'; @@ -2929,8 +2893,8 @@ EOF my $diffrev = defined($input{r1}) ? $input{r1} : $revdisplayorder[$#revdisplayorder]; - printf(< + printf(< @@ -2946,8 +2910,8 @@ EOF $diffrev = defined($input{r2}) ? $input{r2} : $revdisplayorder[0]; - printf(< + printf(< @@ -3641,10 +3605,8 @@ sub http_header(;$$) { my ($content_type, $moddate) = @_; $content_type ||= 'text/html'; + $content_type .= '; charset="UTF-8"' if $content_type =~ /^text\//; - $content_type .= "; charset=$charset" - if ($charset && $content_type =~ m,^text/,); - # Note that in the following, we explicitly join() and concatenate the # headers instead of printing them as an array. This is because some # systems, eg. early versions of mod_perl 2 don't quite get it if the @@ -3770,37 +3732,6 @@ sub runproc(@) $errormsg = "'@{$_[0]}' failed: $@"; } return ($exitcode, $errormsg); -} - -# -# Check out a file to a temporary file. -# -sub checkout_to_temp($$$) -{ - my ($cvsroot, $cvsname, $rev) = @_; - - # Pipe given cvs file into a temporary place. - my ($temp_fh, $temp_fn) = tempfile('.cvsweb.XXXXXXXX', DIR => tmpdir()); - - my @cmd = ($CMD{cvs}, @cvs_options, '-Qd', $cvsroot, - 'co', '-p', "-r$rev", $cvsname); - - local (*DIFF_OUT); - my ($h, $err) = startproc(\@cmd, \"", '>pipe', \*DIFF_OUT); - if ($h) { - local $/ = undef; - print $temp_fh ; - $h->finish(); - close($temp_fh); - } else { - close($temp_fh); - unlink($temp_fn); - fatal('500 Internal Error', - 'Checkout failure (exit status %s), output:
%s
', - $? >> 8 || -1, $err); - } - - return $temp_fn; } #