From: Junio C Hamano Date: Thu, 13 Nov 2008 06:27:49 +0000 (-0800) Subject: Merge branch 'gb/gitweb-snapshot-pathinfo' X-Git-Tag: v1.6.1-rc1~52 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/ac538e5dbaf13180b7e7a9c4471f1007b8b11d68?ds=inline;hp=-c Merge branch 'gb/gitweb-snapshot-pathinfo' * gb/gitweb-snapshot-pathinfo: gitweb: embed snapshot format parameter in PATH_INFO gitweb: retrieve snapshot format from PATH_INFO gitweb: make the supported snapshot formats array global --- ac538e5dbaf13180b7e7a9c4471f1007b8b11d68 diff --combined gitweb/gitweb.perl index 06da30c501,e2ed1ccab3..d4c500b3b3 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@@ -30,7 -30,7 +30,7 @@@ our $my_uri = $cgi->url(-absolute => 1) # if we're called with PATH_INFO, we have to strip that # from the URL to find our real URL # we make $path_info global because it's also used later on -my $path_info = $ENV{"PATH_INFO"}; +our $path_info = $ENV{"PATH_INFO"}; if ($path_info) { $my_url =~ s,\Q$path_info\E$,,; $my_uri =~ s,\Q$path_info\E$,,; @@@ -95,11 -95,6 +95,11 @@@ our $default_projects_order = "project" # (only effective if this variable evaluates to true) our $export_ok = "++GITWEB_EXPORT_OK++"; +# show repository only if this subroutine returns true +# when given the path to the project, for example: +# sub { return -e "$_[0]/git-daemon-export-ok"; } +our $export_auth_hook = undef; + # only allow viewing of repositories also shown on the overview page our $strict_export = "++GITWEB_STRICT_EXPORT++"; @@@ -405,8 -400,7 +405,8 @@@ sub check_head_link sub check_export_ok { my ($dir) = @_; return (check_head_link($dir) && - (!$export_ok || -e "$dir/$export_ok")); + (!$export_ok || -e "$dir/$export_ok") && + (!$export_auth_hook || $export_auth_hook->($dir))); } # process alternate names for backward compatibility @@@ -442,7 -436,7 +442,7 @@@ $projects_list ||= $projectroot # together during validation: this allows subsequent uses (e.g. href()) to be # agnostic of the parameter origin -my %input_params = (); +our %input_params = (); # input parameters are stored with the long parameter name as key. This will # also be used in the href subroutine to convert parameters to their CGI @@@ -452,7 -446,7 +452,7 @@@ # XXX: Warning: If you touch this, check the search form for updating, # too. -my @cgi_param_mapping = ( +our @cgi_param_mapping = ( project => "p", action => "a", file_name => "f", @@@ -469,10 -463,10 +469,10 @@@ extra_options => "opt", search_use_regexp => "sr", ); -my %cgi_param_mapping = @cgi_param_mapping; +our %cgi_param_mapping = @cgi_param_mapping; # we will also need to know the possible actions, for validation -my %actions = ( +our %actions = ( "blame" => \&git_blame, "blobdiff" => \&git_blobdiff, "blobdiff_plain" => \&git_blobdiff_plain, @@@ -504,7 -498,7 +504,7 @@@ # finally, we have the hash of allowed extra_options for the commands that # allow them -my %allowed_options = ( +our %allowed_options = ( "--no-merges" => [ qw(rss atom log shortlog history) ], ); @@@ -622,6 -616,45 +622,45 @@@ sub evaluate_path_info $input_params{'hash_parent'} ||= $parentrefname; } } + + # for the snapshot action, we allow URLs in the form + # $project/snapshot/$hash.ext + # where .ext determines the snapshot and gets removed from the + # passed $refname to provide the $hash. + # + # To be able to tell that $refname includes the format extension, we + # require the following two conditions to be satisfied: + # - the hash input parameter MUST have been set from the $refname part + # of the URL (i.e. they must be equal) + # - the snapshot format MUST NOT have been defined already (e.g. from + # CGI parameter sf) + # It's also useless to try any matching unless $refname has a dot, + # so we check for that too + if (defined $input_params{'action'} && + $input_params{'action'} eq 'snapshot' && + defined $refname && index($refname, '.') != -1 && + $refname eq $input_params{'hash'} && + !defined $input_params{'snapshot_format'}) { + # We loop over the known snapshot formats, checking for + # extensions. Allowed extensions are both the defined suffix + # (which includes the initial dot already) and the snapshot + # format key itself, with a prepended dot + while (my ($fmt, %opt) = each %known_snapshot_formats) { + my $hash = $refname; + my $sfx; + $hash =~ s/(\Q$opt{'suffix'}\E|\Q.$fmt\E)$//; + next unless $sfx = $1; + # a valid suffix was found, so set the snapshot format + # and reset the hash parameter + $input_params{'snapshot_format'} = $fmt; + $input_params{'hash'} = $hash; + # we also set the format suffix to the one requested + # in the URL: this way a request for e.g. .tgz returns + # a .tgz instead of a .tar.gz + $known_snapshot_formats{$fmt}{'suffix'} = $sfx; + last; + } + } } evaluate_path_info(); @@@ -727,6 -760,10 +766,10 @@@ if (defined $searchtext) our $git_dir; $git_dir = "$projectroot/$project" if $project; + # list of supported snapshot formats + our @snapshot_fmts = gitweb_check_feature('snapshot'); + @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); + # dispatch if (!defined $action) { if (defined $hash) { @@@ -774,6 -811,7 +817,7 @@@ sub href (%) # - action # - hash_parent or hash_parent_base:/file_parent # - hash or hash_base:/filename + # - the snapshot_format as an appropriate suffix # When the script is the root DirectoryIndex for the domain, # $href here would be something like http://gitweb.example.com/ @@@ -785,6 -823,10 +829,10 @@@ $href .= "/".esc_url($params{'project'}) if defined $params{'project'}; delete $params{'project'}; + # since we destructively absorb parameters, we keep this + # boolean that remembers if we're handling a snapshot + my $is_snapshot = $params{'action'} eq 'snapshot'; + # Summary just uses the project path URL, any other action is # added to the URL if (defined $params{'action'}) { @@@ -824,6 -866,18 +872,18 @@@ $href .= esc_url($params{'hash'}); delete $params{'hash'}; } + + # If the action was a snapshot, we can absorb the + # snapshot_format parameter too + if ($is_snapshot) { + my $fmt = $params{'snapshot_format'}; + # snapshot_format should always be defined when href() + # is called, but just in case some code forgets, we + # fall back to the default + $fmt ||= $snapshot_fmts[0]; + $href .= $known_snapshot_formats{$fmt}{'suffix'}; + delete $params{'snapshot_format'}; + } } # now encode the parameters explicitly @@@ -859,7 -913,8 +919,7 @@@ sub validate_project my $input = shift || return undef; if (!validate_pathname($input) || !(-d "$projectroot/$input") || - !check_head_link("$projectroot/$input") || - ($export_ok && !(-e "$projectroot/$input/$export_ok")) || + !check_export_ok("$projectroot/$input") || ($strict_export && !project_in_list($input))) { return undef; } else { @@@ -1652,8 -1707,6 +1712,6 @@@ sub format_diff_line # linked. Pass the hash of the tree/commit to snapshot. sub format_snapshot_links { my ($hash) = @_; - my @snapshot_fmts = gitweb_check_feature('snapshot'); - @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts); my $num_fmts = @snapshot_fmts; if ($num_fmts > 1) { # A parenthesized list of links bearing format names. @@@ -1962,10 -2015,7 +2020,10 @@@ sub git_get_project_ctags my $ctags = {}; $git_dir = "$projectroot/$path"; - foreach (<$git_dir/ctags/*>) { + unless (opendir D, "$git_dir/ctags") { + return $ctags; + } + foreach (grep { -f $_ } map { "$git_dir/ctags/$_" } readdir(D)) { open CT, $_ or next; my $val = ; chomp $val; @@@ -1973,7 -2023,6 +2031,7 @@@ my $ctag = $_; $ctag =~ s#.*/##; $ctags->{$ctag} = $val; } + closedir D; $ctags; } @@@ -4855,20 -4904,17 +4913,17 @@@ sub git_tree } sub git_snapshot { - my @supported_fmts = gitweb_check_feature('snapshot'); - @supported_fmts = filter_snapshot_fmts(@supported_fmts); - my $format = $input_params{'snapshot_format'}; - if (!@supported_fmts) { + if (!@snapshot_fmts) { die_error(403, "Snapshots not allowed"); } # default to first supported snapshot format - $format ||= $supported_fmts[0]; + $format ||= $snapshot_fmts[0]; if ($format !~ m/^[a-z0-9]+$/) { die_error(400, "Invalid snapshot format parameter"); } elsif (!exists($known_snapshot_formats{$format})) { die_error(400, "Unknown snapshot format"); - } elsif (!grep($_ eq $format, @supported_fmts)) { + } elsif (!grep($_ eq $format, @snapshot_fmts)) { die_error(403, "Unsupported snapshot format"); }