From 149769378a6ffc3bf4407866d2ccb23296ddbc23 Mon Sep 17 00:00:00 2001 From: Dylan Hardison Date: Tue, 12 Jul 2016 20:51:17 -0400 Subject: Bug 1285835 - BMO sending bogus Content-Disposition filenames when the filename is not ASCII --- attachment.cgi | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'attachment.cgi') diff --git a/attachment.cgi b/attachment.cgi index 772674bfc..7f6353bdd 100755 --- a/attachment.cgi +++ b/attachment.cgi @@ -54,9 +54,11 @@ use Bugzilla::Token; use Bugzilla::Keyword; use Bugzilla::Hook; -use Encode qw(encode find_encoding); +use Encode qw(encode find_encoding from_to); use URI; use URI::QueryParam; +use URI::Escape qw(uri_escape_utf8); +use File::Basename qw(basename); # For most scripts we don't make $cgi and $template global variables. But # when preparing Bugzilla for mod_perl, this script used these @@ -381,7 +383,7 @@ sub view { # At this point, Bugzilla->login has been called if it had to. my $contenttype = $attachment->contenttype; - my $filename = $attachment->filename; + my $filename = basename($attachment->filename); my $contenttype_override = 0; # Bug 111522: allow overriding content-type manually in the posted form @@ -397,18 +399,6 @@ sub view { # BMO add a hook for github url redirection Bugzilla::Hook::process('attachment_view', { attachment => $attachment }); - $filename =~ s/^.*[\/\\]//; - # escape quotes and backslashes in the filename, per RFCs 2045/822 - $filename =~ s/\\/\\\\/g; # escape backslashes - $filename =~ s/"/\\"/g; # escape quotes - - # Avoid line wrapping done by Encode, which we don't need for HTTP - # headers. See discussion in bug 328628 for details. - local $Encode::Encoding{'MIME-Q'}->{'bpl'} = 10000; - $filename = encode('MIME-Q', $filename); - - my $disposition = Bugzilla->params->{'allow_attachment_display'} ? 'inline' : 'attachment'; - my $do_redirect = 0; Bugzilla::Hook::process('attachment_should_redirect_login', { do_redirect => \$do_redirect }); @@ -437,11 +427,26 @@ sub view { } Bugzilla->log_user_request($attachment->bug_id, $attachment->id, "attachment-get") if Bugzilla->user->id; + + my $disposition = Bugzilla->params->{'allow_attachment_display'} ? 'inline' : 'attachment'; + + my $ascii_filename = $filename; + utf8::encode($ascii_filename); + from_to($ascii_filename, 'UTF-8', 'ascii'); + $ascii_filename =~ s/(["\\])/\\$1/g; + my $qfilename = qq{"$filename"}; + my $ufilename = qq{UTF-8''} . uri_escape_utf8($filename); + + my $filenames = "filename=$qfilename"; + if ($ascii_filename ne $filename) { + $filenames .= "; filename*=$ufilename"; + } + # IE8 and older do not support RFC 6266. So for these old browsers # we still pass the old 'filename' attribute. Modern browsers will # automatically pick the new 'filename*' attribute. print $cgi->header(-type=> $contenttype, - -content_disposition=> "$disposition; filename=\"$filename\"; filename*=UTF-8''$filename", + -content_disposition=> "$disposition; $filenames", -content_length => $attachment->datasize); disable_utf8(); print $attachment->data; -- cgit v1.2.3-24-g4f1b