summaryrefslogtreecommitdiffstats
path: root/gitweb
diff options
context:
space:
mode:
Diffstat (limited to 'gitweb')
-rwxr-xr-xgitweb/gitweb.perl64
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