X-Git-Url: https://git.ladys.computer/Gitweb/blobdiff_plain/d17c98dcc7eae4189f5790d28b693c0b545c1b25f2e5caab76f446e640019bf5..3b953a73778cf7b94aeaa4ff571eab16402143b14de4ecea1af215089afdec20:/gitweb.perl diff --git a/gitweb.perl b/gitweb.perl index 1db4801..afed850 100755 --- a/gitweb.perl +++ b/gitweb.perl @@ -15,6 +15,7 @@ use CGI::Carp qw(fatalsToBrowser); use Encode; use Fcntl ':mode'; use File::Find qw(); +use File::Basename qw(basename); binmode STDOUT, ':utf8'; our $cgi = new CGI; @@ -34,7 +35,7 @@ our $projectroot = "++GITWEB_PROJECTROOT++"; our $git_temp = "/tmp/gitweb"; # target of the home link on top of all pages -our $home_link = $my_uri; +our $home_link = $my_uri || "/"; # string of the home link on top of all pages our $home_link_str = "++GITWEB_HOME_LINK_STR++"; @@ -66,6 +67,76 @@ our $default_text_plain_charset = undef; # (relative to the current git repository) our $mimetypes_file = undef; +# You define site-wide feature defaults here; override them with +# $GITWEB_CONFIG as necessary. +our %feature = ( + # feature => {'sub' => feature-sub, 'override' => allow-override, 'default' => [ default options...] + # if feature is overridable, feature-sub will be called with default options; + # return value indicates if to enable specified feature + + 'blame' => { + 'sub' => \&feature_blame, + 'override' => 0, + 'default' => [0]}, + + 'snapshot' => { + 'sub' => \&feature_snapshot, + 'override' => 0, + # => [content-encoding, suffix, program] + 'default' => ['x-gzip', 'gz', 'gzip']}, +); + +sub gitweb_check_feature { + my ($name) = @_; + return undef unless exists $feature{$name}; + my ($sub, $override, @defaults) = ( + $feature{$name}{'sub'}, + $feature{$name}{'override'}, + @{$feature{$name}{'default'}}); + if (!$override) { return @defaults; } + return $sub->(@defaults); +} + +# To enable system wide have in $GITWEB_CONFIG +# $feature{'blame'}{'default'} = [1]; +# To have project specific config enable override in $GITWEB_CONFIG +# $feature{'blame'}{'override'} = 1; +# and in project config gitweb.blame = 0|1; + +sub feature_blame { + my ($val) = git_get_project_config('blame', '--bool'); + + if ($val eq 'true') { + return 1; + } elsif ($val eq 'false') { + return 0; + } + + return $_[0]; +} + +# To disable system wide have in $GITWEB_CONFIG +# $feature{'snapshot'}{'default'} = [undef]; +# To have project specific config enable override in $GITWEB_CONFIG +# $feature{'blame'}{'override'} = 1; +# and in project config gitweb.snapshot = none|gzip|bzip2 + +sub feature_snapshot { + my ($ctype, $suffix, $command) = @_; + + my ($val) = git_get_project_config('snapshot'); + + if ($val eq 'gzip') { + return ('x-gzip', 'gz', 'gzip'); + } elsif ($val eq 'bzip2') { + return ('x-bzip2', 'bz2', 'bzip2'); + } elsif ($val eq 'none') { + return (); + } + + return ($ctype, $suffix, $command); +} + our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++"; require $GITWEB_CONFIG if -e $GITWEB_CONFIG; @@ -84,19 +155,15 @@ if (defined $action) { if ($action =~ m/[^0-9a-zA-Z\.\-_]/) { die_error(undef, "Invalid action parameter"); } - # action which does not check rest of parameters - if ($action eq "opml") { - git_opml(); - exit; - } } our $project = ($cgi->param('p') || $ENV{'PATH_INFO'}); if (defined $project) { $project =~ s|^/||; $project =~ s|/$||; + $project = undef unless $project; } -if (defined $project && $project) { +if (defined $project) { if (!validate_input($project)) { die_error(undef, "Invalid project parameter"); } @@ -107,9 +174,6 @@ if (defined $project && $project) { die_error(undef, "No such project"); } $ENV{'GIT_DIR'} = "$projectroot/$project"; -} else { - git_project_list(); - exit; } our $file_name = $cgi->param('f'); @@ -119,6 +183,13 @@ if (defined $file_name) { } } +our $file_parent = $cgi->param('fp'); +if (defined $file_parent) { + if (!validate_input($file_parent)) { + die_error(undef, "Invalid file parent parameter"); + } +} + our $hash = $cgi->param('h'); if (defined $hash) { if (!validate_input($hash)) { @@ -140,6 +211,13 @@ if (defined $hash_base) { } } +our $hash_parent_base = $cgi->param('hpb'); +if (defined $hash_parent_base) { + if (!validate_input($hash_parent_base)) { + die_error(undef, "Invalid hash parent base parameter"); + } +} + our $page = $cgi->param('pg'); if (defined $page) { if ($page =~ m/[^0-9]$/) { @@ -175,9 +253,17 @@ my %actions = ( "tag" => \&git_tag, "tags" => \&git_tags, "tree" => \&git_tree, + "snapshot" => \&git_snapshot, + # those below don't need $project + "opml" => \&git_opml, + "project_list" => \&git_project_list, ); -$action = 'summary' if (!defined($action)); +if (defined $project) { + $action ||= 'summary'; +} else { + $action ||= 'project_list'; +} if (!defined($actions{$action})) { die_error(undef, "Unknown action"); } @@ -188,26 +274,32 @@ exit; ## action links sub href(%) { - my %mapping = ( - action => "a", + my %params = @_; + + my @mapping = ( project => "p", + action => "a", file_name => "f", + file_parent => "fp", hash => "h", hash_parent => "hp", hash_base => "hb", + hash_parent_base => "hpb", page => "pg", searchtext => "s", ); + my %mapping = @mapping; - my %params = @_; $params{"project"} ||= $project; - my $href = "$my_uri?"; - $href .= esc_param( join(";", - map { "$mapping{$_}=$params{$_}" } keys %params - ) ); - - return $href; + my @result = (); + for (my $i = 0; $i < @mapping; $i += 2) { + my ($name, $symbol) = ($mapping[$i], $mapping[$i+1]); + if (defined $params{$name}) { + push @result, $symbol . "=" . esc_param($params{$name}); + } + } + return "$my_uri?" . join(';', @result); } @@ -362,7 +454,13 @@ sub mode_str { # convert file mode in octal to file type string sub file_type { - my $mode = oct shift; + my $mode = shift; + + if ($mode !~ m/^[0-7]+$/) { + return $mode; + } else { + $mode = oct $mode; + } if (S_ISDIR($mode & S_IFMT)) { return "directory"; @@ -388,7 +486,9 @@ sub format_log_line_html { if ($line =~ m/([0-9a-fA-F]{40})/) { my $hash_text = $1; if (git_get_type($hash_text) eq "commit") { - my $link = $cgi->a({-class => "text", -href => href(action=>"commit", hash=>$hash_text)}, $hash_text); + my $link = + $cgi->a({-href => href(action=>"commit", hash=>$hash_text), + -class => "text"}, $hash_text); $line =~ s/$hash_text/$link/; } } @@ -429,15 +529,35 @@ sub format_subject_html { $extra = '' unless defined($extra); if (length($short) < length($long)) { - return $cgi->a({-href => $href, -class => "list", + return $cgi->a({-href => $href, -class => "list subject", -title => $long}, esc_html($short) . $extra); } else { - return $cgi->a({-href => $href, -class => "list"}, + return $cgi->a({-href => $href, -class => "list subject"}, esc_html($long) . $extra); } } +sub format_diff_line { + my $line = shift; + my $char = substr($line, 0, 1); + my $diff_class = ""; + + chomp $line; + + if ($char eq '+') { + $diff_class = " add"; + } elsif ($char eq "-") { + $diff_class = " rem"; + } elsif ($char eq "@") { + $diff_class = " chunk_header"; + } elsif ($char eq "\\") { + $diff_class = " incomplete"; + } + $line = untabify($line); + return "