X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=gitweb%2Fgitweb.perl;h=933e137386fe561d5ded885e62ebc82e27c08179;hb=6e13921b4f7adcc7316a76c0c4955b85b1589a65;hp=06da30c50186eaaaba59dde91b8b8a34f6b89840;hpb=a5b2d4ac24ef18cf8c628e258bef8a20d9bf4b2b;p=git.git diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 06da30c50..933e13738 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -297,10 +297,10 @@ our %feature = ( # The 'default' value consists of a list of triplets in the form # (label, link, position) where position is the label after which - # to inster the link and link is a format string where %n expands + # to insert the link and link is a format string where %n expands # to the project name, %f to the project path within the filesystem, # %h to the current hash (h gitweb parameter) and %b to the current - # hash base (hb gitweb parameter). + # hash base (hb gitweb parameter); %% expands to %. # To enable system wide have in $GITWEB_CONFIG e.g. # $feature{'actions'}{'default'} = [('graphiclog', @@ -622,6 +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 +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 +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 +829,10 @@ sub href (%) { $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 +872,18 @@ sub href (%) { $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 @@ -1652,8 +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. @@ -3027,14 +3085,19 @@ sub git_print_page_nav { $arg{'tree'}{'hash_base'} = $treebase if defined $treebase; my @actions = gitweb_check_feature('actions'); + my %repl = ( + '%' => '%', + 'n' => $project, # project name + 'f' => $git_dir, # project path within filesystem + 'h' => $treehead || '', # current hash ('h' parameter) + 'b' => $treebase || '', # hash base ('hb' parameter) + ); while (@actions) { - my ($label, $link, $pos) = (shift(@actions), shift(@actions), shift(@actions)); + my ($label, $link, $pos) = splice(@actions,0,3); + # insert @navs = map { $_ eq $pos ? ($_, $label) : $_ } @navs; # munch munch - $link =~ s#%n#$project#g; - $link =~ s#%f#$git_dir#g; - $treehead ? $link =~ s#%h#$treehead#g : $link =~ s#%h##g; - $treebase ? $link =~ s#%b#$treebase#g : $link =~ s#%b##g; + $link =~ s/%([%nfhb])/$repl{$1}/g; $arg{$label}{'_href'} = $link; } @@ -4855,20 +4918,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"); }