diff options
Diffstat (limited to 'gitweb')
-rwxr-xr-x | gitweb/gitweb.perl | 64 |
1 files changed, 47 insertions, 17 deletions
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5c7011a37b..e92596c295 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -94,6 +94,13 @@ our $default_text_plain_charset = undef; # (relative to the current git repository) our $mimetypes_file = undef; +# assume this charset if line contains non-UTF-8 characters; +# it should be valid encoding (see Encoding::Supported(3pm) for list), +# for which encoding all byte sequences are valid, for example +# 'iso-8859-1' aka 'latin1' (it is decoded without checking, so it +# could be even 'utf-8' for the old behavior) +our $fallback_encoding = 'latin1'; + # You define site-wide feature defaults here; override them with # $GITWEB_CONFIG as necessary. our %feature = ( @@ -132,7 +139,7 @@ our %feature = ( # $feature{'snapshot'}{'default'} = [undef]; # To have project specific config enable override in $GITWEB_CONFIG # $feature{'snapshot'}{'override'} = 1; - # and in project config gitweb.snapshot = none|gzip|bzip2; + # and in project config gitweb.snapshot = none|gzip|bzip2|zip; 'snapshot' => { 'sub' => \&feature_snapshot, 'override' => 0, @@ -244,6 +251,8 @@ sub feature_snapshot { return ('x-gzip', 'gz', 'gzip'); } elsif ($val eq 'bzip2') { return ('x-bzip2', 'bz2', 'bzip2'); + } elsif ($val eq 'zip') { + return ('x-zip', 'zip', ''); } elsif ($val eq 'none') { return (); } @@ -600,6 +609,20 @@ sub validate_refname { return $input; } +# decode sequences of octets in utf8 into Perl's internal form, +# which is utf-8 with utf8 flag set if needed. gitweb writes out +# in utf-8 thanks to "binmode STDOUT, ':utf8'" at beginning +sub to_utf8 { + my $str = shift; + my $res; + eval { $res = decode_utf8($str, Encode::FB_CROAK); }; + if (defined $res) { + return $res; + } else { + return decode($fallback_encoding, $str, Encode::FB_DEFAULT); + } +} + # quote unsafe chars, but keep the slash, even when it's not # correct, but quoted slashes look too horrible in bookmarks sub esc_param { @@ -624,7 +647,7 @@ sub esc_html ($;%) { my $str = shift; my %opts = @_; - $str = decode_utf8($str); + $str = to_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -638,7 +661,7 @@ sub esc_path { my $str = shift; my %opts = @_; - $str = decode_utf8($str); + $str = to_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -923,7 +946,7 @@ sub format_subject_html { if (length($short) < length($long)) { return $cgi->a({-href => $href, -class => "list subject", - -title => decode_utf8($long)}, + -title => to_utf8($long)}, esc_html($short) . $extra); } else { return $cgi->a({-href => $href, -class => "list subject"}, @@ -1237,7 +1260,7 @@ sub git_get_projects_list { if (check_export_ok("$projectroot/$path")) { my $pr = { path => $path, - owner => decode_utf8($owner), + owner => to_utf8($owner), }; push @list, $pr; (my $forks_path = $path) =~ s/\.git$//; @@ -1267,7 +1290,7 @@ sub git_get_project_owner { $pr = unescape($pr); $ow = unescape($ow); if ($pr eq $project) { - $owner = decode_utf8($ow); + $owner = to_utf8($ow); last; } } @@ -1757,7 +1780,7 @@ sub get_file_owner { } my $owner = $gcos; $owner =~ s/[,;].*$//; - return decode_utf8($owner); + return to_utf8($owner); } ## ...................................................................... @@ -1840,7 +1863,7 @@ sub git_header_html { my $title = "$site_name"; if (defined $project) { - $title .= " - " . decode_utf8($project); + $title .= " - " . to_utf8($project); if (defined $action) { $title .= "/$action"; if (defined $file_name) { @@ -2114,7 +2137,7 @@ sub git_print_page_path { print "<div class=\"page_path\">"; print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), - -title => 'tree root'}, decode_utf8("[$project]")); + -title => 'tree root'}, to_utf8("[$project]")); print " / "; if (defined $name) { my @dirname = split '/', $name; @@ -2934,7 +2957,7 @@ sub git_project_list_body { ($pr->{'age'}, $pr->{'age_string'}) = @aa; if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; - $pr->{'descr_long'} = decode_utf8($descr); + $pr->{'descr_long'} = to_utf8($descr); $pr->{'descr'} = chop_str($descr, 25, 5); } if (!defined $pr->{'owner'}) { @@ -3976,19 +3999,26 @@ sub git_snapshot { $hash = git_get_head_hash($project); } - my $filename = decode_utf8(basename($project)) . "-$hash.tar.$suffix"; + my $git = git_cmd_str(); + my $name = $project; + $name =~ s/\047/\047\\\047\047/g; + my $filename = to_utf8(basename($project)); + my $cmd; + if ($suffix eq 'zip') { + $filename .= "-$hash.$suffix"; + $cmd = "$git archive --format=zip --prefix=\'$name\'/ $hash"; + } else { + $filename .= "-$hash.tar.$suffix"; + $cmd = "$git archive --format=tar --prefix=\'$name\'/ $hash | $command"; + } print $cgi->header( -type => "application/$ctype", -content_disposition => 'inline; filename="' . "$filename" . '"', -status => '200 OK'); - my $git = git_cmd_str(); - my $name = $project; - $name =~ s/\047/\047\\\047\047/g; - open my $fd, "-|", - "$git archive --format=tar --prefix=\'$name\'/ $hash | $command" - or die_error(undef, "Execute git-tar-tree failed"); + open my $fd, "-|", $cmd + or die_error(undef, "Execute git-archive failed"); binmode STDOUT, ':raw'; print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi |