version 4.14, 2019/11/11 12:46:23 |
version 4.38, 2019/11/29 19:30:16 |
Line 56 use filetest qw(access); |
|
Line 56 use filetest qw(access); |
|
use vars qw ( |
use vars qw ( |
$VERSION $CheckoutMagic $MimeTypes $DEBUG |
$VERSION $CheckoutMagic $MimeTypes $DEBUG |
$config $allow_version_select |
$config $allow_version_select |
@CVSrepositories @CVSROOT %CVSROOT %CVSROOTdescr |
@CVSrepositories @CVSROOT %CVSROOT %CVSROOTdescr %DEFAULTVALUE %MTYPES |
%MIRRORS %DEFAULTVALUE %ICONS %MTYPES |
@DIFFTYPES %DIFFTYPES @LOGSORTKEYS %LOGSORTKEYS |
%DIFF_COMMANDS @DIFFTYPES %DIFFTYPES @LOGSORTKEYS %LOGSORTKEYS |
|
%alltags %fileinfo %tags @branchnames %nameprinted |
%alltags %fileinfo %tags @branchnames %nameprinted |
%symrev %revsym @allrevisions %date %author @revdisplayorder |
%symrev %revsym @allrevisions %date %author @revdisplayorder |
@revisions %state %difflines %log %branchpoint @revorder $keywordsubstitution |
@revisions %state %difflines %log %branchpoint @revorder $keywordsubstitution |
$prcgi @prcategories $re_prcategories $prkeyword $re_prkeyword $mancgi |
$mancgi $doCheckout $scriptname $scriptwhere |
$doCheckout $scriptname $scriptwhere |
|
$where $Browser $nofilelinks $maycompress @stickyvars |
$where $Browser $nofilelinks $maycompress @stickyvars |
$is_links $is_lynx $is_w3m $is_msie $is_mozilla3 $is_textbased |
$is_links $is_lynx $is_w3m $is_msie $is_mozilla3 $is_textbased |
%input $query $barequery $sortby $bydate $byrev $byauthor |
%input $query $barequery $sortby $bydate $byrev $byauthor |
$bylog $byfile $defaultDiffType $logsort $cvstree $cvsroot |
$bylog $byfile $defaultDiffType $logsort $cvstree $cvsroot |
$charset $output_filter |
%CMD $allow_compress $backicon $diricon $fileicon |
@command_path %CMD $allow_compress $backicon $diricon $fileicon $graphicon |
$fullname $logo $defaulttitle $address $binfileicon $iconsdir |
$fullname $cvstreedefault $logo $defaulttitle $address $binfileicon |
$shortLogLen $show_author $hr_breakable $hr_ignwhite $hr_ignkeysubst |
$long_intro $short_instruction $shortLogLen $show_author |
$mime_types $allow_annotate $allow_markup $allow_mailtos |
$tablepadding $hr_breakable $showfunc $hr_ignwhite $hr_ignkeysubst |
|
$inputTextSize $mime_types $allow_annotate $allow_markup $allow_mailtos |
|
$allow_log_extra $allow_dir_extra $allow_source_extra |
$allow_log_extra $allow_dir_extra $allow_source_extra |
$allow_cvsgraph $cvsgraph_config $use_java_script $edit_option_form |
$edit_option_form |
$show_subdir_lastmod $show_log_in_markup $preformat_in_markup |
$show_subdir_lastmod $show_log_in_markup $preformat_in_markup |
$tabstop $state $annTable $sel @ForbiddenFiles |
$tabstop $state $annTable $sel @ForbiddenFiles |
$use_descriptions %descriptions @mytz $dwhere |
$use_descriptions %descriptions $dwhere |
$use_moddate $gzip_open $file_list_len |
$use_moddate $gzip_open $file_list_len |
$allow_tar @tar_options @gzip_options @zip_options @cvs_options |
$allow_tar @tar_options @cvs_options |
@annotate_options @rcsdiff_options |
@annotate_options @rcsdiff_options |
$HTML_DOCTYPE $HTML_META $cssurl $CSS $cvshistory_url |
$HTML_DOCTYPE $HTML_META $cssurl $CSS |
$allow_enscript @enscript_options %enscript_types |
|
); |
); |
|
|
require Compress::Zlib; |
require Compress::Zlib; |
Line 91 use Cwd qw(abs_path); |
|
Line 86 use Cwd qw(abs_path); |
|
use File::Path qw(rmtree); |
use File::Path qw(rmtree); |
use File::Spec::Functions qw(canonpath catdir catfile curdir devnull rootdir |
use File::Spec::Functions qw(canonpath catdir catfile curdir devnull rootdir |
tmpdir updir); |
tmpdir updir); |
use File::Temp qw(tempdir tempfile); |
use File::Temp qw(tempdir); |
use IPC::Run qw(); |
use IPC::Run qw(); |
use Time::Local qw(timegm); |
use Time::Local qw(timegm); |
use URI::Escape qw(uri_escape uri_unescape); |
use URI::Escape qw(uri_escape uri_unescape); |
Line 103 use constant CVSWEBMARKUP => qr{^text/(x-cvsweb|vnd\.v |
|
Line 98 use constant CVSWEBMARKUP => qr{^text/(x-cvsweb|vnd\.v |
|
use constant LOG_FILESEPR => qr/^={77}$/o; |
use constant LOG_FILESEPR => qr/^={77}$/o; |
use constant LOG_REVSEPR => qr/^-{28}$/o; |
use constant LOG_REVSEPR => qr/^-{28}$/o; |
|
|
use constant HAS_EDIFF => eval { require String::Ediff; }; |
|
|
|
# ----------------------------------------------------------------------------- |
# ----------------------------------------------------------------------------- |
|
|
# All global initialization that can be done in compile time should go to |
# All global initialization that can be done in compile time should go to |
|
|
|
|
$HTML_META = <<EOM; |
$HTML_META = <<EOM; |
<meta name="robots" content="nofollow" /> |
<meta name="robots" content="nofollow" /> |
<meta name="generator" content="FreeBSD-CVSweb $VERSION" /> |
<meta name="generator" content="CVSweb $VERSION" /> |
<meta http-equiv="Content-Script-Type" content="text/javascript" /> |
|
<meta http-equiv="Content-Style-Type" content="text/css" /> |
<meta http-equiv="Content-Style-Type" content="text/css" /> |
EOM |
EOM |
|
|
|
|
$MimeTypes = undef if $@; |
$MimeTypes = undef if $@; |
|
|
$CheckoutMagic = '~checkout~'; |
$CheckoutMagic = '~checkout~'; |
|
$CMD{$_} = "/usr/bin/$_" for (qw(cvs rcsdiff rlog)); |
|
$CMD{tar} = "/bin/tar"; |
} |
} |
|
|
# ----------------------------------------------------------------------------- |
# ----------------------------------------------------------------------------- |
|
|
sub printDiffSelect($); |
sub printDiffSelect(); |
sub printDiffSelectStickyVars(); |
sub printDiffSelectStickyVars(); |
sub getDiffLinks($$$); |
sub getDiffLinks($$$); |
sub printLogSortSelect($); |
sub printLogSortSelect(); |
sub findLastModifiedSubdirs(@); |
sub findLastModifiedSubdirs(@); |
sub htmlify_sub(&$); |
sub htmlify_sub(&$); |
sub htmlify($;$); |
sub htmlify($;$); |
Line 149 sub spacedHtmlText($;$); |
|
Line 143 sub spacedHtmlText($;$); |
|
sub link($$); |
sub link($$); |
sub revcmp($$); |
sub revcmp($$); |
sub fatal($$@); |
sub fatal($$@); |
sub config_error($$); |
|
sub redirect($;$); |
sub redirect($;$); |
sub safeglob($); |
sub safeglob($); |
sub search_path($); |
sub search_path($); |
sub getEnscriptHL($); |
|
sub getMimeType($;$); |
sub getMimeType($;$); |
sub head($;$); |
sub head($;$); |
sub scan_directives(@); |
sub scan_directives(@); |
sub openOutputFilter(); |
|
sub doAnnotate($$); |
sub doAnnotate($$); |
sub doCheckout($$$); |
sub doCheckout($$$); |
sub doEnscript($$$;$); |
|
sub doGraph(); |
|
sub doGraphView(); |
|
sub cvswebMarkup($$$$$$;$); |
sub cvswebMarkup($$$$$$;$); |
sub viewable($); |
sub viewable($); |
sub doDiff($$$$$$); |
sub doDiff($$$$$$); |
Line 177 sub plural_write($$); |
|
Line 165 sub plural_write($$); |
|
sub readableTime($$); |
sub readableTime($$); |
sub clickablePath($$); |
sub clickablePath($$); |
sub chooseCVSRoot(); |
sub chooseCVSRoot(); |
sub chooseMirror(); |
|
sub fileSortCmp(); |
sub fileSortCmp(); |
sub download_url($$;$); |
sub download_url($$;$); |
sub download_link($$$;$); |
sub download_link($$$;$); |
sub display_url($$;$); |
sub display_url($$;$); |
sub display_link($$;$$); |
sub display_link($$;$$); |
sub graph_link($;$); |
|
sub history_link($$;$); |
|
sub toggleQuery($;$); |
sub toggleQuery($;$); |
sub htmlquote($); |
sub htmlquote($); |
sub htmlunquote($); |
sub htmlunquote($); |
Line 196 sub link_tags($); |
|
Line 181 sub link_tags($); |
|
sub forbidden($); |
sub forbidden($); |
sub startproc(@); |
sub startproc(@); |
sub runproc(@); |
sub runproc(@); |
sub checkout_to_temp($$$); |
|
|
|
# Get rid of unsafe environment vars. Don't do this in the BEGIN block |
# Get rid of unsafe environment vars. Don't do this in the BEGIN block |
# (think mod_perl)... |
# (think mod_perl)... |
delete(@ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}); |
delete(@ENV{qw(PATH IFS CDPATH ENV BASH_ENV)}); |
|
|
|
# Helps to achieve read only access to the repositories |
|
# with cvs >= 1.12.1 and doesn't hurt other versions. |
|
$ENV{CVSREADONLYFS} = 1; |
|
|
# Location of the configuration file inside the web server chroot: |
# Location of the configuration file inside the web server chroot: |
$config = '/conf/cvsweb/cvsweb.conf'; |
$config = '/conf/cvsweb/cvsweb.conf'; |
|
|
######## Configuration parameters ######### |
######## Configuration parameters ######### |
|
|
@CVSrepositories = @CVSROOT = %CVSROOT = %MIRRORS = %DEFAULTVALUE = %ICONS = |
@CVSrepositories = @CVSROOT = %CVSROOT = %DEFAULTVALUE = |
%MTYPES = %tags = %alltags = %fileinfo = %DIFF_COMMANDS = (); |
%MTYPES = %tags = %alltags = %fileinfo = (); |
|
|
$cvstreedefault = $logo = $defaulttitle = |
$logo = $defaulttitle = |
$address = $long_intro = $short_instruction = $shortLogLen = $show_author = |
$address = $shortLogLen = $show_author = |
$tablepadding = $hr_breakable = $showfunc = $hr_ignwhite = |
$hr_breakable = $hr_ignwhite = |
$hr_ignkeysubst = $inputTextSize = $mime_types = $allow_annotate = |
$hr_ignkeysubst = $mime_types = $allow_annotate = |
$allow_markup = $allow_compress = $use_java_script = $edit_option_form = |
$allow_markup = $allow_compress = $edit_option_form = |
$show_subdir_lastmod = $show_log_in_markup = $preformat_in_markup = |
$show_subdir_lastmod = $show_log_in_markup = $preformat_in_markup = |
$tabstop = $use_moddate = $gzip_open = $DEBUG = $allow_cvsgraph = |
$tabstop = $use_moddate = $gzip_open = $DEBUG = |
$cvsgraph_config = $cvshistory_url = $allow_tar = undef; |
$allow_tar = undef; |
|
|
$allow_version_select = $allow_mailtos = $allow_log_extra = 1; |
$allow_version_select = $allow_mailtos = $allow_log_extra = 1; |
|
|
Line 273 $scriptname = '' unless defined($scriptname); |
|
Line 261 $scriptname = '' unless defined($scriptname); |
|
$where = $pathinfo; |
$where = $pathinfo; |
$doCheckout = $where =~ s|^/$CheckoutMagic/|/|o; |
$doCheckout = $where =~ s|^/$CheckoutMagic/|/|o; |
$where =~ s|^/||; |
$where =~ s|^/||; |
$scriptname =~ s|^/*|/|; |
$scriptname =~ s|^/+||; |
|
|
# Let's workaround thttpd's stupidity.. |
# Let's workaround thttpd's stupidity.. |
if ($scriptname =~ m|/$|) { |
if ($scriptname =~ m|/$|) { |
Line 281 if ($scriptname =~ m|/$|) { |
|
Line 269 if ($scriptname =~ m|/$|) { |
|
my $re = quotemeta $pathinfo; |
my $re = quotemeta $pathinfo; |
$scriptname =~ s/$re$//; |
$scriptname =~ s/$re$//; |
} |
} |
|
$scriptname = "/$scriptname" if $scriptname; |
|
|
# $scriptname : the URI escaped path to this script |
# $scriptname : the URI escaped path to this script |
# $where : the path in the CVS repository (without leading /, or only /) |
# $where : the path in the CVS repository (without leading /, or only /) |
Line 325 $maycompress = ( |
|
Line 314 $maycompress = ( |
|
qw(cvsroot hideattic ignorecase sortby logsort f only_with_tag ln |
qw(cvsroot hideattic ignorecase sortby logsort f only_with_tag ln |
hidecvsroot hidenonreadable); |
hidecvsroot hidenonreadable); |
|
|
# |
|
# Load configuration. |
# Load configuration. |
# |
{ |
if (-f $config) { |
$config =~ m|^/| or fatal '500 Internal Error', |
do "$config" or config_error($config, $@); |
'Configuration file name "<code>%s</code>" is not an absolute path.', |
} else { |
$config; |
fatal("500 Internal Error", |
defined do $config and last; |
'Configuration not found. Set the parameter <code>$config</code> in cvsweb.cgi to your <b>cvsweb.conf</b> configuration file first.'); |
$@ and fatal '500 Internal Error', |
|
'Error loading configuration file "<code>%s</code>": <pre>%s</pre>', |
|
$config, $@; |
|
fatal '500 Internal Error', |
|
'Cannot read configuration file "<code>%s</code>": %s', |
|
$config, $! || 'unknown error'; |
} |
} |
|
|
# Try to find a readable dir where we can cd into. Some abs_path() |
# Try to find a readable dir where we can cd into. Some abs_path() |
Line 376 if (defined($ENV{QUERY_STRING})) { |
|
Line 369 if (defined($ENV{QUERY_STRING})) { |
|
undef %input; |
undef %input; |
|
|
my $t; |
my $t; |
for my $p (qw(graph hideattic hidecvsroot hidenonreadable ignorecase ln copt |
for my $p (qw(hideattic hidecvsroot hidenonreadable ignorecase ln copt |
makeimage options tarball)) { |
options tarball)) { |
$t = $query{$p}; |
$t = $query{$p}; |
if (defined($t)) { |
if (defined($t)) { |
($input{$p}) = ($t =~ /^([01]|on)$/) |
($input{$p}) = ($t =~ /^([01]|on)$/) |
Line 479 for (my $i = 0; $i < scalar(@CVSrepositories); $i += 2 |
|
Line 472 for (my $i = 0; $i < scalar(@CVSrepositories); $i += 2 |
|
next; |
next; |
} |
} |
$rootfound ||= 1; |
$rootfound ||= 1; |
$cvstreedefault = $key unless defined($cvstreedefault); |
|
$CVSROOTdescr{$key} = $descr; |
$CVSROOTdescr{$key} = $descr; |
$CVSROOT{$key} = $root; |
$CVSROOT{$key} = $root; |
push(@CVSROOT, $key); |
push(@CVSROOT, $key); |
Line 492 unless ($rootfound) { |
|
Line 484 unless ($rootfound) { |
|
} |
} |
undef $rootfound; |
undef $rootfound; |
|
|
# |
$DEFAULTVALUE{cvsroot} = $CVSrepositories[0]; |
# Default CVS root |
|
# |
|
if (!defined($CVSROOT{$cvstreedefault})) { |
|
fatal("500 Internal Error", |
|
'<code>$cvstreedefault</code> points to a repository (%s) not ' . |
|
'defined in <code>@CVSrepositories</code> in your configuration ' . |
|
'file (<code>%s</code>).', |
|
$cvstreedefault, |
|
$config); |
|
} |
|
|
|
$DEFAULTVALUE{cvsroot} = $cvstreedefault; |
|
|
|
while (my ($key, $defval) = each %DEFAULTVALUE) { |
while (my ($key, $defval) = each %DEFAULTVALUE) { |
|
|
# Replace not given parameters with defaults. |
# Replace not given parameters with defaults. |
Line 540 foreach (@stickyvars) { |
|
Line 520 foreach (@stickyvars) { |
|
} |
} |
} |
} |
|
|
if ($allow_enscript) { |
|
push(@DIFFTYPES, qw(uc cc)); |
|
@DIFFTYPES{qw(uc cc)} = ( |
|
{ |
|
'descr' => 'unified, colored', |
|
'opts' => ['-u'], |
|
'colored' => 0, |
|
}, |
|
{ |
|
'descr' => 'context, colored', |
|
'opts' => ['-c'], |
|
'colored' => 0, |
|
}, |
|
); |
|
} else { |
|
# No Enscript -> respect difftype, but don't offer colorization. |
|
if ($input{f} && $input{f} =~ /^([ucs])c$/) { |
|
$input{f} = $1; |
|
} |
|
} |
|
|
|
# is there any query ? |
# is there any query ? |
if (@barequery) { |
if (@barequery) { |
$barequery = join (';', @barequery); |
$barequery = join (';', @barequery); |
Line 604 $logsort = $input{logsort}; |
|
Line 563 $logsort = $input{logsort}; |
|
if ($input{cvsroot} && $CVSROOT{$input{cvsroot}}) { |
if ($input{cvsroot} && $CVSROOT{$input{cvsroot}}) { |
$cvstree = $input{cvsroot}; |
$cvstree = $input{cvsroot}; |
} else { |
} else { |
$cvstree = $cvstreedefault; |
$cvstree = $CVSrepositories[0]; |
} |
} |
|
|
$cvsroot = $CVSROOT{$cvstree}; |
$cvsroot = $CVSROOT{$cvstree}; |
|
|
# create icons out of description |
if ($iconsdir) { |
foreach my $k (keys %ICONS) { |
$backicon = '<img src="' . $iconsdir . '/back.gif" alt="[BACK]"' . |
my ($itxt, $ipath, $iwidth, $iheight) = @{$ICONS{$k}}; |
' border="0" width="20" height="22"/>'; |
no strict 'refs'; |
$diricon = '<img src="' . $iconsdir . '/dir.gif" alt="[DIR]"' . |
if ($ipath) { |
' border="0" width="20" height="22"/>'; |
${"${k}icon"} = |
$fileicon = '<img src="' . $iconsdir . '/text.gif" alt="[TXT]"' . |
sprintf('<img src="%s" alt="%s" border="0" width="%d" height="%d" />', |
' border="0" width="20" height="22"/>'; |
htmlquote($ipath), htmlquote($itxt), $iwidth, $iheight); |
$binfileicon = '<img src="' . $iconsdir . '/binary.gif" alt="[BIN]"' . |
} else { |
' border="0" width="20" height="22"/>'; |
${"${k}icon"} = $itxt; |
} else { |
} |
$backicon = 'back'; |
|
$diricon = 'dir'; |
|
$fileicon = 'file'; |
|
$binfileicon = 'binfile'; |
} |
} |
|
|
my $config_cvstree = "$config-$cvstree"; |
my $config_cvstree = "$config-$cvstree"; |
Line 633 if (-f $config_cvstree) { |
|
Line 595 if (-f $config_cvstree) { |
|
} |
} |
undef $config_cvstree; |
undef $config_cvstree; |
|
|
$re_prcategories = '(?:' . join ('|', @prcategories) . ')' if @prcategories; |
|
$re_prkeyword = quotemeta($prkeyword) if defined($prkeyword); |
|
$prcgi .= '%s' if defined($prcgi) && $prcgi !~ /%s/; |
|
|
|
$fullname = catfile($cvsroot, $where); |
$fullname = catfile($cvsroot, $where); |
|
|
my $rewrite = 0; |
my $rewrite = 0; |
Line 682 if ($input{tarball}) { |
|
Line 640 if ($input{tarball}) { |
|
|
|
my ($module) = ($where =~ m,^/?(.*),); # untaint |
my ($module) = ($where =~ m,^/?(.*),); # untaint |
$module =~ s,/([^/]*)$,,; |
$module =~ s,/([^/]*)$,,; |
my ($ext) = ($1 =~ /(\.t(?:ar\.)?gz|\.zip)$/); |
my ($ext) = ($1 =~ /(\.t(?:ar\.)?gz)$/); |
my ($basedir) = ($module =~ m,([^/]+)$,); |
my ($basedir) = ($module =~ m,([^/]+)$,); |
|
|
if ($basedir eq '' || $module eq '') { |
if ($basedir eq '' || $module eq '') { |
Line 690 if ($input{tarball}) { |
|
Line 648 if ($input{tarball}) { |
|
'You cannot download the top level directory.'); |
'You cannot download the top level directory.'); |
} |
} |
|
|
my $istar = ($ext eq '.tar.gz' || $ext eq '.tgz'); |
unless ($ext eq '.tar.gz' || $ext eq '.tgz') { |
if ($istar) { |
fatal('404 Not Found', 'Unsupported archive type.'); |
fatal('500 Internal Error', 'tar command not found.') unless $CMD{tar}; |
|
fatal('500 Internal Error', 'gzip command not found.') unless $CMD{gzip}; |
|
} |
} |
my $iszip = ($ext eq '.zip'); |
|
if ($iszip && !$CMD{zip}) { |
|
fatal('500 Internal Error', 'zip command not found.'); |
|
} |
|
if (!$istar && !$iszip) { |
|
fatal('500 Internal Error', 'Unsupported archive type.'); |
|
} |
|
|
|
my $tmpexportdir; |
my $tmpexportdir; |
eval { |
eval { |
Line 732 if ($input{tarball}) { |
|
Line 681 if ($input{tarball}) { |
|
('500 Internal Error', |
('500 Internal Error', |
'Export failure (exit status %s), output: <pre>%s</pre>', |
'Export failure (exit status %s), output: <pre>%s</pre>', |
$errcode, $err || $export_err); |
$errcode, $err || $export_err); |
|
|
} else { |
} else { |
|
|
$| = 1; # Essential to get the buffering right. |
$| = 1; # Essential to get the buffering right. |
local (*TAR_OUT); |
local (*TAR_OUT); |
|
my ($h, $err) = startproc($CMD{tar}, @tar_options, '-czf', '-', |
my (@cmd, $ctype); |
$basedir, '>pipe', \*TAR_OUT); |
if ($istar) { |
|
my @tar = ($CMD{tar}, @tar_options, '-cf', '-', $basedir); |
|
my @gzip = ($CMD{gzip}, @gzip_options, '-c'); |
|
push(@cmd, \@tar, '|', \@gzip); |
|
$ctype = 'application/x-gzip'; |
|
} elsif ($iszip) { |
|
my @zip = ($CMD{zip}, @zip_options, '-r', '-', $basedir); |
|
push(@cmd, \@zip, \''); |
|
$ctype = 'application/zip'; |
|
} |
|
push(@cmd, '>pipe', \*TAR_OUT); |
|
|
|
my ($h, $err) = startproc(@cmd); |
|
if ($h) { |
if ($h) { |
print "Content-Type: $ctype\r\n\r\n"; |
print "Content-Type: application/x-gzip\r\n\r\n"; |
local $/ = undef; |
local $/ = undef; |
print <TAR_OUT>; |
print <TAR_OUT>; |
$h->finish(); |
$h->finish(); |
} else { |
} else { |
@fatal = ('500 Internal Error', |
@fatal = ('500 Internal Error', |
'%s failure (exit status %s), output: <pre>%s</pre>', |
'tar failure (exit status %s), output: <pre>%s</pre>', |
$istar ? 'Tar' : 'Zip', $? >> 8 || -1, $err); |
$? >> 8 || -1, $err); |
} |
} |
} |
} |
|
|
Line 787 if (-d $fullname) { |
|
Line 721 if (-d $fullname) { |
|
|
|
if ($where eq '/') { |
if ($where eq '/') { |
html_header($defaulttitle); |
html_header($defaulttitle); |
$long_intro =~ s/!!CVSROOTdescr!!/$CVSROOTdescr{$cvstree}/g; |
|
print $long_intro; |
|
} else { |
} else { |
html_header($where); |
html_header($where); |
my $html = (-f catfile($fullname, 'README.cvs.html,v') || |
my $html = (-f catfile($fullname, 'README.cvs.html,v') || |
Line 825 if (-d $fullname) { |
|
Line 757 if (-d $fullname) { |
|
} |
} |
$h->finish(); |
$h->finish(); |
} |
} |
print $short_instruction; |
|
} |
} |
|
|
if ($use_descriptions && |
if ($use_descriptions && |
Line 842 if (-d $fullname) { |
|
Line 773 if (-d $fullname) { |
|
|
|
# give direct access to dirs |
# give direct access to dirs |
if ($where eq '/') { |
if ($where eq '/') { |
chooseMirror(); |
|
chooseCVSRoot(); |
chooseCVSRoot(); |
|
|
} else { |
} else { |
print '<p>Current directory: <b>', clickablePath($where, 0), '</b>'; |
print '<p>Current directory: <b>', clickablePath($where, 0), '</b>'; |
if ($cvshistory_url) { |
|
(my $d = $where) =~ s|^/*(.*?)/*$|$1|; |
|
print ' - ', history_link($d, ''); |
|
} |
|
print "</p>\n"; |
print "</p>\n"; |
print "<p>Current tag: <b>", htmlquote($input{only_with_tag}), "</b></p>\n" |
print "<p>Current tag: <b>", htmlquote($input{only_with_tag}), "</b></p>\n" |
if $input{only_with_tag}; |
if $input{only_with_tag}; |
Line 860 if (-d $fullname) { |
|
Line 785 if (-d $fullname) { |
|
|
|
my $infocols = 1; |
my $infocols = 1; |
|
|
printf(<<EOF, $tablepadding, 'Directory index of ' . htmlquote($where)); |
printf(<<EOF, 'Directory index of ' . htmlquote($where)); |
<table class="dir" width="100%%" cellspacing="0" cellpadding="%s" summary="%s"> |
<table class="dir" width="100%%" cellspacing="0" cellpadding="2" summary="%s"> |
<tr> |
<tr> |
EOF |
EOF |
printf('<th colspan="2"%s>', ($byfile ? ' class="sorted"' : '')); |
printf('<th colspan="2"%s>', ($byfile ? ' class="sorted"' : '')); |
|
|
$filesfound++; |
$filesfound++; |
|
|
printf "<tr class=\"%s\">\n", ($dirrow % 2) ? 'even' : 'odd'; |
printf "<tr class=\"%s\">\n", ($dirrow % 2) ? 'even' : 'odd'; |
printf '<td class="file"%s>', $allow_cvsgraph ? '' : ' colspan="2"'; |
printf '<td class="file" colspan="2">'; |
|
|
my $icon = $isbinary ? $binfileicon : $fileicon; |
my $icon = $isbinary ? $binfileicon : $fileicon; |
print $nofilelinks ? $icon : &link($icon, $url); |
print $nofilelinks ? $icon : &link($icon, $url); |
print ' ', &link(htmlquote($file), $url), $attic; |
print ' ', &link(htmlquote($file), $url), $attic; |
print '</td><td class="graph">', graph_link($fileurl) if $allow_cvsgraph; |
|
print "</td>\n<td width=\"30\">", display_link($fileurl, $rev); |
print "</td>\n<td width=\"30\">", display_link($fileurl, $rev); |
my $ageclass = 'age'; |
my $ageclass = 'age'; |
my $age = ''; |
my $age = ''; |
|
|
|| $input{$var} ne $DEFAULTVALUE{$var}) |
|| $input{$var} ne $DEFAULTVALUE{$var}) |
&& $var ne 'only_with_tag'); |
&& $var ne 'only_with_tag'); |
} |
} |
printf(<<EOF, ($use_java_script ? ' onchange="this.form.submit()"' : '')); |
print <<EOF; |
<span class="nowrap"> |
<span class="nowrap"> |
<label for="only_with_tag" accesskey="T">Show only files with tag: |
<label for="only_with_tag" accesskey="T">Show only files with tag: |
<select id="only_with_tag" name="only_with_tag"%s> |
<select id="only_with_tag" name="only_with_tag"> |
<option value="">All tags / default branch</option> |
<option value="">All tags / default branch</option> |
EOF |
EOF |
foreach my $tag (reverse sort { lc $a cmp lc $b } keys %tags) { |
foreach my $tag (reverse sort { lc $a cmp lc $b } keys %tags) { |
|
|
|
|
if ($allow_tar && $filesfound) { |
if ($allow_tar && $filesfound) { |
my ($basefile) = ($where =~ m,(?:.*/)?([^/]+),); |
my ($basefile) = ($where =~ m,(?:.*/)?([^/]+),); |
my $havetar = $CMD{tar} && $CMD{gzip}; |
if (defined($basefile) && $basefile ne '') { |
my $havezip = $CMD{zip}; |
|
if (defined($basefile) && $basefile ne '' && ($havetar || $havezip)) { |
|
my $q = ($query ? "$query;" : '?') . 'tarball=1'; |
my $q = ($query ? "$query;" : '?') . 'tarball=1'; |
print "<hr />\n", |
print "<hr />\n", |
'<div style="text-align: center">Download this directory in '; |
'<div style="text-align: center">Download this directory in '; |
# Mangle the filename so browsers show a reasonable filename to download. |
# Mangle the filename so browsers show a reasonable filename to download. |
my @types = (); |
|
$basefile = uri_escape($basefile); |
$basefile = uri_escape($basefile); |
push(@types, &link('tarball', "$basefile.tar.gz$q")) if $havetar; |
print &link('tarball', "$basefile.tar.gz$q"); |
push(@types, &link('zip archive', "$basefile.zip$q")) if $havezip; |
print "</div>\n"; |
print join(' or ', @types), "</div>\n"; |
|
} |
} |
} |
} |
|
|
|
|
printf(qq{<input type="hidden" name="%s" value="%s" />\n}, |
printf(qq{<input type="hidden" name="%s" value="%s" />\n}, |
$v, $input{$v} || 0); |
$v, $input{$v} || 0); |
} |
} |
if ($cvstree ne $cvstreedefault) { |
if ($cvstree ne $CVSrepositories[0]) { |
print "<input type=\"hidden\" name=\"cvsroot\" value=\"$cvstree\" />\n"; |
print "<input type=\"hidden\" name=\"cvsroot\" value=\"$cvstree\" />\n"; |
} |
} |
print <<EOF; |
print <<EOF; |
|
|
</td> |
</td> |
<td class="opt-value"> |
<td class="opt-value"> |
EOF |
EOF |
printLogSortSelect(0); |
printLogSortSelect(); |
print <<EOF; |
print <<EOF; |
</td> |
</td> |
<td class="opt-label"> |
<td class="opt-label"> |
|
|
</td> |
</td> |
<td> |
<td> |
EOF |
EOF |
printDiffSelect(0); |
printDiffSelect(); |
print <<EOF; |
print <<EOF; |
</td> |
</td> |
<td colspan="2" class="opt-label"> |
<td colspan="2" class="opt-label"> |
Line 1288 elsif (-f $fullname . ',v') { |
|
Line 1208 elsif (-f $fullname . ',v') { |
|
exit; |
exit; |
} |
} |
|
|
if ($allow_cvsgraph && $input{graph}) { |
|
if ($input{makeimage}) { |
|
doGraph(); |
|
} else { |
|
doGraphView(); |
|
} |
|
gzipclose(); |
|
exit; |
|
} |
|
|
|
&doLog($fullname); |
&doLog($fullname); |
} |
} |
|
|
|
|
## End MAIN |
## End MAIN |
|
|
|
|
sub printDiffSelect($) |
sub printDiffSelect() |
{ |
{ |
my ($use_java_script) = @_; |
|
|
|
print '<select id="f" name="f"'; |
print '<select id="f" name="f"'; |
print ' onchange="this.form.submit()"' if $use_java_script; |
|
print ">\n"; |
print ">\n"; |
|
|
for my $difftype (@DIFFTYPES) { |
for my $difftype (@DIFFTYPES) { |
Line 1402 sub printDiffSelectStickyVars() |
|
Line 1309 sub printDiffSelectStickyVars() |
|
} |
} |
|
|
|
|
sub printLogSortSelect($) |
sub printLogSortSelect() |
{ |
{ |
my ($use_java_script) = @_; |
|
|
|
print '<select id="logsort" name="logsort"'; |
print '<select id="logsort" name="logsort"'; |
print ' onchange="this.form.submit()"' if $use_java_script; |
|
print ">\n"; |
print ">\n"; |
|
|
for my $sortkey (@LOGSORTKEYS) { |
for my $sortkey (@LOGSORTKEYS) { |
Line 1501 sub htmlify($;$) |
|
Line 1405 sub htmlify($;$) |
|
} |
} |
|
|
if ($extra) { |
if ($extra) { |
|
|
# get PR #'s as link: "PR#nnnn" "PR: nnnn, ..." "PR nnnn, ..." "bin/nnnn" |
|
if (defined($prcgi) && defined($re_prkeyword)) { |
|
my $prev; |
|
|
|
do { |
|
$prev = $_; |
|
$_ = htmlify_sub { |
|
s{ |
|
(\b$re_prkeyword[:\#]?\s* |
|
(?: |
|
\#? |
|
\d+[,\s]\s* |
|
)* |
|
\#?) |
|
(\d+)\b |
|
}{ |
|
$1 . &link($2, sprintf($prcgi, $2)) |
|
}egix; |
|
} $_; |
|
} while ($_ ne $prev); |
|
|
|
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)" |
# get manpage specs as link: "foo.1" "foo(1)" |
if (defined($mancgi)) { |
if (defined($mancgi)) { |
$_ = htmlify_sub { |
$_ = htmlify_sub { |
|
|
|
|
|
|
# |
# |
# Signal a (fatal) configuration error. |
|
# |
|
sub config_error($$) |
|
{ |
|
fatal('500 Internal Error', |
|
'Error loading configuration file "<code>%s</code>":<br /><br />' . |
|
'%s<br />', @_); |
|
} |
|
|
|
|
|
# |
|
# Sends a redirect to the given URL. |
# Sends a redirect to the given URL. |
# |
# |
sub redirect($;$) |
sub redirect($;$) |
Line 1697 sub safeglob($) |
|
Line 1557 sub safeglob($) |
|
|
|
|
|
# |
# |
# Searches @command_path for the given executable file. |
|
# |
|
sub search_path($) |
|
{ |
|
my ($command) = @_; |
|
for my $d (@command_path) { |
|
my $cmd = catfile($d, $command); |
|
return $cmd if (-x $cmd && !-d _); |
|
} |
|
return ''; |
|
} |
|
|
|
|
|
# |
|
# Gets the enscript(1) highlight mode corresponding to the given filename, |
|
# or undef if unsupported. |
|
# |
|
sub getEnscriptHL($) |
|
{ |
|
return undef unless $allow_enscript; |
|
my ($filename) = @_; |
|
while (my ($hl, $regex) = each %enscript_types) { |
|
return $hl if ($filename =~ $regex); |
|
} |
|
return undef; |
|
} |
|
|
|
|
|
# |
|
# Gets the MIME type for the given file name. |
# Gets the MIME type for the given file name. |
# |
# |
sub getMimeType($;$) |
sub getMimeType($;$) |
Line 1798 sub scan_directives(@) |
|
Line 1629 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 |
# show Annotation |
############################### |
############################### |
|
|
printf '<embed src="%s" width="100%%" height="100%%" /><br />', |
printf '<embed src="%s" width="100%%" height="100%%" /><br />', |
$url . $barequery; |
$url . $barequery; |
} else { |
} else { |
|
|
print "<pre>\n"; |
print "<pre>\n"; |
my $linenumbers = $input{ln} || 0; |
my $linenumbers = $input{ln} || 0; |
|
|
if (my $enscript_hl = getEnscriptHL($filename)) { |
|
doEnscript($filehandle, $enscript_hl, $linenumbers); |
|
|
|
} else { |
|
my $ln = 0; |
my $ln = 0; |
my @buf = (); |
my @buf = (); |
my $ts = undef; |
my $ts = undef; |
|
|
} |
} |
print $preformat_in_markup ? spacedHtmlText($_, $ts) : htmlquote($_); |
print $preformat_in_markup ? spacedHtmlText($_, $ts) : htmlquote($_); |
} |
} |
} |
|
|
|
print "</pre>\n"; |
print "</pre>\n"; |
} |
} |
html_footer(); |
html_footer(); |
Line 2237 sub doDiff($$$$$$) |
|
Line 2048 sub doDiff($$$$$$) |
|
|
|
my $mimetype = getMimeType($fullname); |
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 "<code>%s</code>" in ' . |
|
'<code>%%DIFF_COMMANDS</code>.', |
|
$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: <pre>%s</pre>', |
|
$? >> 8 || -1, $err); |
|
} |
|
|
|
http_header($diffcmd->{type} || 'text/plain'); |
|
local $/ = undef; |
|
print <DIFF_OUT>; |
|
$h->finish(); |
|
unlink($temp_fn1); |
|
unlink($temp_fn2); |
|
|
|
exit; |
|
} |
|
|
|
# |
|
# Normal CVS diff. |
|
# |
|
|
|
$f = $DEFAULTVALUE{f} || 'u' if ($f =~ /^ext\d*$/); |
$f = $DEFAULTVALUE{f} || 'u' if ($f =~ /^ext\d*$/); |
my $difftype = $DIFFTYPES{$f}; |
my $difftype = $DIFFTYPES{$f}; |
if (!$difftype) { |
if (!$difftype) { |
Line 2301 sub doDiff($$$$$$) |
|
Line 2058 sub doDiff($$$$$$) |
|
my $human_readable = $difftype->{colored}; |
my $human_readable = $difftype->{colored}; |
|
|
# Apply special diff options. |
# Apply special diff options. |
push @difftype, '-p' if $showfunc; |
push @difftype, '-p'; |
|
|
if ($human_readable) { |
if ($human_readable) { |
push(@difftype, '-w') if $hr_ignwhite; |
push(@difftype, '-w') if $hr_ignwhite; |
Line 2311 sub doDiff($$$$$$) |
|
Line 2068 sub doDiff($$$$$$) |
|
my $fh = do { local (*FH); }; |
my $fh = do { local (*FH); }; |
if (!open($fh, "-|")) { # child |
if (!open($fh, "-|")) { # child |
open(STDERR, ">&STDOUT"); # Redirect stderr to stdout |
open(STDERR, ">&STDOUT"); # Redirect stderr to stdout |
openOutputFilter(); |
|
exec($CMD{rcsdiff}, @rcsdiff_options, @difftype, "-r$rev1", "-r$rev2", |
exec($CMD{rcsdiff}, @rcsdiff_options, @difftype, "-r$rev1", "-r$rev2", |
$fullname) or exit -1; |
$fullname) or exit -1; |
} |
} |
Line 2324 sub doDiff($$$$$$) |
|
Line 2080 sub doDiff($$$$$$) |
|
html_footer(); |
html_footer(); |
gzipclose(); |
gzipclose(); |
exit; |
exit; |
|
|
} elsif ($f =~ /^([ucs])c$/) { |
|
# |
|
# Enscript colored diff. |
|
# |
|
my $hl = 'diff'; |
|
$hl .= $1 if ($1 eq 'u' || $1 eq 's'); |
|
(my $where_nd = $where) =~ s/\.diff$//; |
|
(my $pathname = $where_nd) =~ s|((?<=/)Attic/)?[^/]*$||; |
|
(my $filename = $where_nd) =~ s|^.*/||; |
|
(my $swhere = $scriptwhere) =~ s|\.diff$||; |
|
navigateHeader($swhere, $pathname, $filename, $rev2, 'diff'); |
|
printf(<<EOF, $where_nd, $rev1, $rev2); |
|
<h3 style="text-align: center">Diff for /%s between versions %s and %s</h3> |
|
<pre> |
|
EOF |
|
doEnscript(\$fh, $hl, 0, 'cvsweb_diff'); |
|
print <<EOF; |
|
</pre> |
|
<hr style="width: 100%" /> |
|
<form method="get" action="$scriptwhere"> |
|
EOF |
|
printDiffSelectStickyVars(); |
|
print 'Diff format: '; |
|
printDiffSelect($use_java_script); |
|
print "<input type=\"submit\" value=\"Show\" />\n</form>\n"; |
|
html_footer(); |
|
gzipclose(); |
|
exit; |
|
|
|
} else { |
} else { |
# |
# |
# Plain diff. |
# Plain diff. |
Line 2448 sub getDirLogs($$@) |
|
Line 2174 sub getDirLogs($$@) |
|
my $fh = do { local (*FH); }; |
my $fh = do { local (*FH); }; |
if (!open($fh, '-|')) { # Child |
if (!open($fh, '-|')) { # Child |
open(STDERR, '>', devnull()) unless $DEBUG; # Ignore rlog's complaints. |
open(STDERR, '>', devnull()) unless $DEBUG; # Ignore rlog's complaints. |
openOutputFilter(); |
|
if ($file_list_len && $file_list_len > 1) { |
if ($file_list_len && $file_list_len > 1) { |
while (scalar(@files) > $file_list_len) { # Process files in chunks. |
while (scalar(@files) > $file_list_len) { # Process files in chunks. |
system(@cmd, splice(@files, 0, $file_list_len)) == 0 or exit -1; |
system(@cmd, splice(@files, 0, $file_list_len)) == 0 or exit -1; |
Line 2602 sub getDirLogs($$@) |
|
Line 2327 sub getDirLogs($$@) |
|
|
|
if ($linesread == 0) { |
if ($linesread == 0) { |
fatal('500 Internal Error', |
fatal('500 Internal Error', |
'Failed to spawn GNU rlog on <em>"%s"</em>.<br /><br />Did you set the <b><code>@command_path</code></b> in your configuration file correctly? (Currently: "<code>%s</code>")', |
'Failed to spawn rlog on <em>"%s"</em>', |
htmlquote(join(', ', @files)), join(':', @command_path)); |
htmlquote(join(', ', @files))); |
} |
} |
|
|
return @unreadable; |
return @unreadable; |
} |
} |
|
|
Line 2627 sub readLog($;$) |
|
Line 2351 sub readLog($;$) |
|
|
|
my $fh = do { local (*FH); }; |
my $fh = do { local (*FH); }; |
if (!open($fh, "-|")) { # child |
if (!open($fh, "-|")) { # child |
openOutputFilter(); |
|
$revision = defined($revision) ? "-r$revision" : ''; |
$revision = defined($revision) ? "-r$revision" : ''; |
if ($revision =~ /\./) { |
if ($revision =~ /\./) { |
# Normal revision, not a branch/tag name. |
# Normal revision, not a branch/tag name. |
Line 2853 sub getDiffLinks($$$) |
|
Line 2576 sub getDiffLinks($$$) |
|
&link(htmlquote(lc($DIFFTYPES{$difftype}{descr})), "$url;f=$f")); |
&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; |
return @links; |
} |
} |
|
|
Line 2921 sub printLog($$$;$$) |
|
Line 2637 sub printLog($$$;$$) |
|
$fileurl, $_, $barequery, $_)); |
$fileurl, $_, $barequery, $_)); |
} |
} |
} |
} |
print ' - ', graph_link('', 'revision graph') |
|
if (!$inlogview && $allow_cvsgraph); |
|
} |
} |
print "<br />\n"; |
print "<br />\n"; |
|
|
print '<i>'; |
print '<i>'; |
if (@mytz) { |
print scalar gmtime($date{$_}), ' UTC</i> ('; |
my ($est) = $mytz[(localtime($date{$_}))[8]]; |
|
print scalar localtime($date{$_}), " $est</i> ("; |
|
} else { |
|
print scalar gmtime($date{$_}), " UTC</i> ("; |
|
} |
|
print readableTime(time() - $date{$_}, 1), ' ago)'; |
print readableTime(time() - $date{$_}, 1), ' ago)'; |
print ' by <i>', htmlquote($author{$_}), "</i><br />\n"; |
print ' by <i>', htmlquote($author{$_}), "</i><br />\n"; |
|
|
Line 3055 sub printLog($$$;$$) |
|
Line 2764 sub printLog($$$;$$) |
|
} |
} |
|
|
|
|
# |
|
# Generates the HTML view for CvsGraph. |
|
# |
|
sub doGraphView() |
|
{ |
|
(my $pathname = $where) =~ s|[^/]*$||; |
|
(my $filename = $where) =~ s|^.*/||; |
|
|
|
navigateHeader($scriptwhere, $pathname, $filename, undef, 'graph'); |
|
|
|
my $title = 'Revision graph of ' . htmlquote($pathname . $filename); |
|
my $mapname = 'CvsGraphMap'; |
|
|
|
printf(<<EOF, $title, $mapname, $cvstree, $title); |
|
<h3 style="text-align: center">%s</h3> |
|
<div style="text-align: center"><img border="0" usemap="#%s" src="?cvsroot=%s;graph=1;makeimage=1" alt="%s" /> |
|
EOF |
|
|
|
# Remove any pre-existing tag/branch names from branch links. |
|
(my $notag_query = $barequery) =~ s/;+only_with_tag=.*?(?=;|$)//g; |
|
|
|
my @graph_cmd = |
|
($CMD{cvsgraph}, |
|
'-r', $cvsroot, |
|
'-m', $pathname, |
|
'-i', |
|
'-M', $mapname, |
|
'-x', 'x', |
|
"-Omap_branch_href=\"href=\\\"./?only_with_tag=%(%t%)$notag_query\\\"\"", |
|
"-Omap_rev_href=\"href=\\\"?rev=%(%R%)$barequery\\\"\"", |
|
"-Omap_diff_href=\"href=\\\"%(%F%).diff" . |
|
"?r1=%(%P%);r2=%(%R%)$barequery\\\"\"", |
|
); |
|
push(@graph_cmd, '-c', $cvsgraph_config) if $cvsgraph_config; |
|
push(@graph_cmd, $filename . ',v'); |
|
|
|
local *CVSGRAPH_OUT; |
|
my ($h, $err) = |
|
startproc(\@graph_cmd, \"", '>pipe', \*CVSGRAPH_OUT); |
|
fatal('500 Internal Error', $err) unless $h; |
|
|
|
# Browser compatibility kludge: many browsers do not support client side |
|
# image maps where the <map> element contains only the id attribute. Let's |
|
# add the corresponding name attribute to it on the fly. |
|
while (<CVSGRAPH_OUT>) { |
|
s/(<map\s+id="([^"]+)")\s*>/$1 name="$2">/; |
|
print; |
|
} |
|
|
|
$h->finish(); |
|
print "</div>\n"; |
|
|
|
html_footer(); |
|
} |
|
|
|
|
|
# |
|
# Generates a graph using CvsGraph. |
|
# |
|
sub doGraph() |
|
{ |
|
(my $pathname = $where) =~ s|[^/]*$||; |
|
(my $filename = $where) =~ s|^.*/||; |
|
|
|
http_header('image/png'); |
|
|
|
my @graph_cmd = ($CMD{cvsgraph}, '-r', $cvsroot, '-m', $pathname); |
|
push(@graph_cmd, '-c', $cvsgraph_config) if $cvsgraph_config; |
|
push(@graph_cmd, $filename . ',v'); |
|
|
|
local *CVSGRAPH_OUT; |
|
my ($h, $err) = |
|
startproc(\@graph_cmd, \"", '>pipe', \*CVSGRAPH_OUT); |
|
fatal('500 Internal Error', $err) unless $h; |
|
{ |
|
local $/ = undef; |
|
binmode(\*STDOUT); |
|
print <CVSGRAPH_OUT>; |
|
} |
|
$h->finish(); |
|
} |
|
|
|
|
|
sub doLog($) |
sub doLog($) |
{ |
{ |
my ($fullname) = @_; |
my ($fullname) = @_; |
|
|
&clickablePath($upwhere, 1), "</b>\n</p>\n"; |
&clickablePath($upwhere, 1), "</b>\n</p>\n"; |
print "<p>\n "; |
print "<p>\n "; |
print &link('Request diff between arbitrary revisions', '#diff'); |
print &link('Request diff between arbitrary revisions', '#diff'); |
print ' - ', &graph_link('', 'Display revisions graphically') |
|
if $allow_cvsgraph; |
|
if ($cvshistory_url) { |
|
(my $d = $upwhere) =~ s|/+$||; |
|
print ' - ', history_link($d, $filename); |
|
} |
|
print "\n</p>\n<hr />\n"; |
print "\n</p>\n<hr />\n"; |
|
|
print "<p>\n"; |
print "<p>\n"; |
|
|
my $diffrev = defined($input{r1}) ? |
my $diffrev = defined($input{r1}) ? |
$input{r1} : $revdisplayorder[$#revdisplayorder]; |
$input{r1} : $revdisplayorder[$#revdisplayorder]; |
|
|
printf(<<EOF, $inputTextSize, $diffrev); |
printf(<<EOF, $diffrev); |
<input type="text" size="%s" name="tr1" value="%s" onchange="this.form.r1.selectedIndex=0" /> |
<input type="text" size="12" name="tr1" value="%s" onchange="this.form.r1.selectedIndex=0" /> |
</td> |
</td> |
<td></td> |
<td></td> |
</tr> |
</tr> |
|
|
|
|
$diffrev = defined($input{r2}) ? $input{r2} : $revdisplayorder[0]; |
$diffrev = defined($input{r2}) ? $input{r2} : $revdisplayorder[0]; |
|
|
printf(<<EOF, $inputTextSize, $diffrev, $scriptwhere); |
printf(<<EOF, $diffrev, $scriptwhere); |
<input type="text" size="%s" name="tr2" value="%s" onchange="this.form.r2.selectedIndex=0" /> |
<input type="text" size="12" name="tr2" value="%s" onchange="this.form.r2.selectedIndex=0" /> |
</td> |
</td> |
<td><input type="submit" value="Get Diffs" accesskey="G" /></td> |
<td><input type="submit" value="Get Diffs" accesskey="G" /></td> |
</tr> |
</tr> |
|
|
</td> |
</td> |
<td class="opt-value"> |
<td class="opt-value"> |
EOF |
EOF |
printDiffSelect($use_java_script); |
printDiffSelect(); |
print <<EOF; |
print <<EOF; |
</td> |
</td> |
<td></td> |
<td></td> |
|
|
|
|
if (@branchnames) { |
if (@branchnames) { |
|
|
printf(<<EOF, $use_java_script ? ' onchange="this.form.submit()"' : ''); |
print <<EOF; |
<tr> |
<tr> |
<td class="opt-label"> |
<td class="opt-label"> |
<label for="only_with_tag" accesskey="B">View only branch:</label> |
<label for="only_with_tag" accesskey="B">View only branch:</label> |
</td> |
</td> |
<td class="opt-value"> |
<td class="opt-value"> |
<a name="branch"> |
<a name="branch"> |
<select id="only_with_tag" name="only_with_tag"%s> |
<select id="only_with_tag" name="only_with_tag"> |
EOF |
EOF |
|
|
my @tmp = (); |
my @tmp = (); |
|
|
</td> |
</td> |
<td> |
<td> |
EOF |
EOF |
printLogSortSelect($use_java_script); |
printLogSortSelect(); |
print <<EOF; |
print <<EOF; |
</td> |
</td> |
<td><input type="submit" value="Set" accesskey="S" /></td> |
<td><input type="submit" value="Set" accesskey="S" /></td> |
|
|
} |
} |
} elsif ($state eq "PreChange") { # state eq "PreChange" |
} elsif ($state eq "PreChange") { # state eq "PreChange" |
# we got removes with subsequent adds |
# we got removes with subsequent adds |
if (HAS_EDIFF) { |
|
# construct the suffix tree |
|
my $left_diff = join("\n", @$leftColRef[0..$leftRow-1]); |
|
my $right_diff = join("\n", @$rightColRef[0..$rightRow-1]); |
|
my $diff_str = String::Ediff::ediff($left_diff, $right_diff); |
|
|
|
my @diff_str = split(/ /, $diff_str); |
|
my $INFINITY = 10000000; |
|
push(@diff_str, ($INFINITY) x 8); |
|
my ($idx, $b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) = |
|
(0, @diff_str[0..7]); |
|
my ($l_cul, $r_cul) = (0, 0); |
|
my ($ldx, $rdx) = (0, 0); |
|
my (@left_html, @right_html); |
|
for (my $j = 0; $j < $leftRow; $j++) { |
|
my $line_len = length(@$leftColRef[$j]); |
|
my $line = @$leftColRef[$j]; |
|
$l_cul += length($line) + 1; # includes "\n" |
|
my $l_culx = $l_cul - 1; # not includes "\n" |
|
if ($j < $lb1) { |
|
$line = spacedHtmlText($line); |
|
push(@left_html, "<td class=\"diff diff-changed\">$line</td>"); |
|
} elsif ($lb1 == $j) { |
|
my $html_line; |
|
while ($lb1 == $j) { |
|
my $begin_char = $l_culx - $b1; |
|
|
|
$line =~ /^(.*)(.{$begin_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-unchanged">'; |
|
$line = $2; |
|
last if ($j != $le1); |
|
|
|
my $end_char = $l_culx - $e1; |
|
$line =~ /^(.*)(.{$end_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-changed">'; |
|
$line = $2; |
|
|
|
$idx++; |
|
my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) = |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2); |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) = |
|
@diff_str[$idx*8..($idx+1)*8-1]; |
|
$lb1 = $INFINITY if ($lb1 < 0); |
|
$lb2 = $INFINITY if ($lb2 < 0); |
|
$le1 = $INFINITY if ($le1 < 0); |
|
$le2 = $INFINITY if ($le2 < 0); |
|
if ($te1 > $b1) { |
|
($b1, $lb1) = ($te1, $tle1); |
|
} |
|
if ($te2 > $b2) { |
|
($b2, $lb2) = ($te2, $tle2); |
|
} |
|
} |
|
push(@left_html, |
|
sprintf('<td><span class="diff diff-changed">%s%s</span></td>', |
|
$html_line, spacedHtmlText($line))); |
|
} elsif ($le1 == $j) { |
|
my $html_line; |
|
while ($le1 == $j) { |
|
my $end_char = $l_culx - $e1; |
|
$line =~ /^(.*)(.{$end_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-changed">'; |
|
$line = $2; |
|
|
|
$idx++; |
|
my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) = |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2); |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) = |
|
@diff_str[$idx*8..($idx+1)*8-1]; |
|
$lb1 = $INFINITY if ($lb1 < 0); |
|
$lb2 = $INFINITY if ($lb2 < 0); |
|
$le1 = $INFINITY if ($le1 < 0); |
|
$le2 = $INFINITY if ($le2 < 0); |
|
if ($te1 > $b1) { |
|
($b1, $lb1) = ($te1, $tle1); |
|
} |
|
if ($te2 > $b2) { |
|
($b2, $lb2) = ($te2, $tle2); |
|
} |
|
|
|
last if ($lb1 != $j); |
|
|
|
my $begin_char = $l_culx - $b1; |
|
|
|
$line =~ /^(.*)(.{$begin_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-unchanged">'; |
|
$line = $2; |
|
} |
|
push(@left_html, |
|
sprintf('<td><span class="diff diff-unchanged">%s%s</span></td>', |
|
$html_line, spacedHtmlText($line))); |
|
} else { |
|
$line = spacedHtmlText($line); |
|
push(@left_html, "<td class=\"diff diff-unchanged\">$line</td>"); |
|
} |
|
} |
|
($idx, $b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) = |
|
(0, @diff_str[0..7]); |
|
$lb1 = $INFINITY if ($lb1 < 0); |
|
$lb2 = $INFINITY if ($lb2 < 0); |
|
$le1 = $INFINITY if ($le1 < 0); |
|
$le2 = $INFINITY if ($le2 < 0); |
|
for (my $j = 0; $j < $rightRow; $j++) { |
|
my $line_len = length(@$rightColRef[$j]); |
|
my $line = @$rightColRef[$j]; |
|
$r_cul += length($line) + 1; # includes "\n" |
|
my $r_culx = $r_cul - 1; # not includes "\n" |
|
if ($j < $lb2) { |
|
$line = spacedHtmlText($line); |
|
push(@right_html, "<td class=\"diff diff-changed\">$line</td>"); |
|
} elsif ($lb2 == $j) { |
|
my $html_line; |
|
while ($lb2 == $j) { |
|
my $begin_char = $r_culx - $b2; |
|
|
|
$line =~ /^(.*)(.{$begin_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-unchanged">'; |
|
$line = $2; |
|
|
|
last if ($j != $le2); |
|
|
|
my $end_char = $r_culx - $e2; |
|
$line =~ /^(.*)(.{$end_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-changed">'; |
|
$line = $2; |
|
|
|
$idx++; |
|
my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) = |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2); |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) = |
|
@diff_str[$idx*8..($idx+1)*8-1]; |
|
$lb1 = $INFINITY if ($lb1 < 0); |
|
$lb2 = $INFINITY if ($lb2 < 0); |
|
$le1 = $INFINITY if ($le1 < 0); |
|
$le2 = $INFINITY if ($le2 < 0); |
|
if ($te1 > $b1) { |
|
($b1, $lb1) = ($te1, $tle1); |
|
} |
|
if ($te2 > $b2) { |
|
($b2, $lb2) = ($te2, $tle2); |
|
} |
|
} |
|
push(@right_html, |
|
sprintf('<td><span class="diff diff-changed">%s%s</span></td>', |
|
$html_line, spacedHtmlText($line))); |
|
} elsif ($le2 == $j) { |
|
my $html_line; |
|
while ($le2 == $j) { |
|
my $end_char = $r_culx - $e2; |
|
$line =~ /^(.*)(.{$end_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-changed">'; |
|
$line = $2; |
|
|
|
$idx++; |
|
my ($tb1, $te1, $tlb1, $tle1, $tb2, $te2, $tlb2, $tle2) = |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2); |
|
($b1, $e1, $lb1, $le1, $b2, $e2, $lb2, $le2) = |
|
@diff_str[$idx*8..($idx+1)*8-1]; |
|
$lb1 = $INFINITY if ($lb1 < 0); |
|
$lb2 = $INFINITY if ($lb2 < 0); |
|
$le1 = $INFINITY if ($le1 < 0); |
|
$le2 = $INFINITY if ($le2 < 0); |
|
if ($te1 > $b1) { |
|
($b1, $lb1) = ($te1, $tle1); |
|
} |
|
if ($te2 > $b2) { |
|
($b2, $lb2) = ($te2, $tle2); |
|
} |
|
|
|
last if ($lb2 != $j); |
|
|
|
my $begin_char = $r_culx - $b2; |
|
$line =~ /^(.*)(.{$begin_char})$/; |
|
$html_line .= spacedHtmlText($1) . |
|
'</span><span class="diff diff-unchanged">'; |
|
$line = $2; |
|
} |
|
push(@right_html, |
|
sprintf('<td nowrap="nowrap"><span class="diff diff-unchanged"'. |
|
'>%s%s</span></td>', |
|
$html_line, spacedHtmlText($line))); |
|
} else { |
|
$line = spacedHtmlText ($line); |
|
push @right_html, "<td class=\"diff diff-unchanged\">$line</td>"; |
|
} |
|
} |
|
for (my $j = 0; $j < $leftRow || $j < $rightRow ; $j++) { # dump out both cols |
|
print '<tr>'; |
|
if ($j < $leftRow) { |
|
print $left_html[$j]; |
|
} else { |
|
print '<td class="diff diff-changed-missing"> </td>'; |
|
} |
|
if ($j < $rightRow) { |
|
print $right_html[$j]; |
|
} else { |
|
print '<td class="diff diff-changed-missing"> </td>'; |
|
} |
|
print "</tr>\n"; |
|
} |
|
} else { |
|
for (my $j = 0; $j < $leftRow || $j < $rightRow; $j++) { # dump both cols |
for (my $j = 0; $j < $leftRow || $j < $rightRow; $j++) { # dump both cols |
print "<tr>\n"; |
print "<tr>\n"; |
if ($j < $leftRow) { |
if ($j < $leftRow) { |
|
|
} |
} |
print "\n</tr>\n"; |
print "\n</tr>\n"; |
} |
} |
} |
|
} |
} |
} |
} |
|
|
|
|
<label for="f">Diff format:<br /> |
<label for="f">Diff format:<br /> |
EOF |
EOF |
printDiffSelectStickyVars(); |
printDiffSelectStickyVars(); |
printDiffSelect($use_java_script); |
printDiffSelect(); |
printf(<<EOF, $rev1, $rev2); |
printf(<<EOF, $rev1, $rev2); |
</label> |
</label> |
<input type="submit" value="Show" /> |
<input type="submit" value="Show" /> |
|
|
} |
} |
|
|
|
|
sub doEnscript($$$;$) |
|
{ |
|
my ($filehandle, $highlight, $linenumbers, $lang) = @_; |
|
$lang ||= 'cvsweb'; |
|
|
|
my @cmd = ($CMD{enscript}, |
|
@enscript_options, |
|
'-q', "--language=$lang", '-o', '-', "--highlight=$highlight"); |
|
|
|
local *ENSCRIPT_OUT; |
|
my ($h, $err) = |
|
startproc(\@cmd, $filehandle, '>pipe', \*ENSCRIPT_OUT); |
|
fatal('500 Internal Error', $err) unless $h; |
|
|
|
# We could short-circuit and have enscript output directly to STDOUT above, |
|
# but that doesn't work with mod_perl (at least some 1.99 versions). |
|
if ($linenumbers) { |
|
my $ln = 0; |
|
while (<ENSCRIPT_OUT>) { |
|
printf '<a id="l%d" class="src">%5d: </a>', (++$ln) x 2; |
|
print $_; |
|
} |
|
} else { |
|
local $/ = undef; |
|
print <ENSCRIPT_OUT>; |
|
} |
|
$h->finish(); |
|
} |
|
|
|
|
|
# |
# |
# The passed in $path and $filename should not be URI escaped, and $swhere |
# The passed in $path and $filename should not be URI escaped, and $swhere |
# *should* be. |
# *should* be. |
Line 3960 sub chooseCVSRoot() |
|
Line 3341 sub chooseCVSRoot() |
|
if ($input{$k} && $k ne 'cvsroot'); |
if ($input{$k} && $k ne 'cvsroot'); |
} |
} |
|
|
printf(<<EOF, $use_java_script ? ' onchange="this.form.submit()"' : ''); |
print <<EOF; |
<label for="cvsroot" accesskey="C">CVS Root: |
<label for="cvsroot" accesskey="C">CVS Root: |
<select id="cvsroot" name="cvsroot"%s> |
<select id="cvsroot" name="cvsroot"> |
EOF |
EOF |
|
|
foreach my $k (@CVSROOT) { |
foreach my $k (@CVSROOT) { |
|
|
} |
} |
|
|
|
|
sub chooseMirror() |
|
{ |
|
# This code comes from the original BSD-cvsweb |
|
# and may not be useful for your site; If you don't |
|
# set %MIRRORS this won't show up, anyway. |
|
scalar(%MIRRORS) or return; |
|
|
|
# Should perhaps exclude the current site somehow... |
|
print "\n<p>\nThis CVSweb is mirrored in\n"; |
|
|
|
my @tmp = map(&link(htmlquote($_), $MIRRORS{$_}), sort keys %MIRRORS); |
|
my $tmp = pop (@tmp); |
|
|
|
if (scalar(@tmp)) { |
|
print join (', ', @tmp), ' and '; |
|
} |
|
|
|
print "$tmp.\n</p>\n"; |
|
} |
|
|
|
|
|
sub fileSortCmp() |
sub fileSortCmp() |
{ |
{ |
(my $af = $a) =~ s/,v$//; |
(my $af = $a) =~ s/,v$//; |
Line 4139 sub display_link($$;$$) |
|
Line 3499 sub display_link($$;$$) |
|
htmlquote($textlink)); |
htmlquote($textlink)); |
} |
} |
|
|
# |
|
# Expects the passed in URL to be URI escaped, and without a query string. |
|
# The passed in link text should be already HTML escaped as appropriate. |
|
# |
|
sub graph_link($;$) |
|
{ |
|
my ($url, $text) = @_; |
|
$text ||= $graphicon; |
|
return sprintf('<a href="%s?graph=1%s">%s</a>', $url, $barequery, $text); |
|
} |
|
|
|
# |
|
# Returns a link to CVSHistory for the given directory and filename. |
|
# |
|
sub history_link($$;$) |
|
{ |
|
my ($dir, $file, $text) = @_; |
|
$dir ||= ''; |
|
$file ||= ''; |
|
$text ||= 'History'; |
|
return &link($text, |
|
sprintf('%s?cvsroot=%s;dsearch=%s;fsearch=%s;limit=1', |
|
$cvshistory_url, uri_escape($input{cvsroot} || ''), |
|
uri_escape($dir), uri_escape($file))); |
|
} |
|
|
|
# Returns a Query string with the |
# Returns a Query string with the |
# specified parameter toggled |
# specified parameter toggled |
sub toggleQuery($;$) |
sub toggleQuery($;$) |
Line 4229 sub http_header(;$$) |
|
Line 3563 sub http_header(;$$) |
|
{ |
{ |
my ($content_type, $moddate) = @_; |
my ($content_type, $moddate) = @_; |
$content_type ||= 'text/html'; |
$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 |
# Note that in the following, we explicitly join() and concatenate the |
# headers instead of printing them as an array. This is because some |
# 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 |
# systems, eg. early versions of mod_perl 2 don't quite get it if the |
|
|
$errormsg = "'@{$_[0]}' failed: $@"; |
$errormsg = "'@{$_[0]}' failed: $@"; |
} |
} |
return ($exitcode, $errormsg); |
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 <DIFF_OUT>; |
|
$h->finish(); |
|
close($temp_fh); |
|
} else { |
|
close($temp_fh); |
|
unlink($temp_fn); |
|
fatal('500 Internal Error', |
|
'Checkout failure (exit status %s), output: <pre>%s</pre>', |
|
$? >> 8 || -1, $err); |
|
} |
|
|
|
return $temp_fn; |
|
} |
} |
|
|
# |
# |