X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Debbugs%2FCGI%2FBugreport.pm;h=d085ed4fb76681c4ca9f20a6ce1dabea01f177c8;hb=305a309e2c038f2ebf4c2f603a00cea175eea3f0;hp=b3f4ec6defafd3cb7287029ba9859abbc8d72743;hpb=507e7fb021c286bcb59d961f9f25c89410d451a2;p=debbugs.git diff --git a/Debbugs/CGI/Bugreport.pm b/Debbugs/CGI/Bugreport.pm index b3f4ec6..d085ed4 100644 --- a/Debbugs/CGI/Bugreport.pm +++ b/Debbugs/CGI/Bugreport.pm @@ -33,7 +33,7 @@ use base qw(Exporter); use IO::Scalar; use Params::Validate qw(validate_with :types); use Digest::MD5 qw(md5_hex); -use Debbugs::Mail qw(get_addresses); +use Debbugs::Mail qw(get_addresses :reply); use Debbugs::MIME qw(decode_rfc1522 create_mime_message); use Debbugs::CGI qw(:url :html :util); use Debbugs::Common qw(globify_scalar english_join); @@ -41,6 +41,8 @@ use Debbugs::UTF8; use Debbugs::Config qw(:config); use POSIX qw(strftime); use Encode qw(decode_utf8 encode_utf8); +use URI::Escape qw(uri_escape_utf8); +use Scalar::Util qw(blessed); BEGIN{ ($VERSION) = q$Revision: 494 $ =~ /^Revision:\s+([^\s+])/; @@ -137,9 +139,8 @@ sub display_entity { if ($param{outer} and not $param{terse} and not exists $param{att}) { - my $header = $entity->head; print {$output} "
\n"; - if ($param{trim_headers}) { + if ($param{trim_headers}) { my @headers; foreach (qw(From To Cc Subject Date)) { my $head_field = $head->get($_); @@ -148,10 +149,10 @@ sub display_entity { if ($_ eq 'From' and $param{avatars}) { my $libravatar_url = __libravatar_url(decode_rfc1522($head_field)); if (defined $libravatar_url and length $libravatar_url) { - push @headers,q(\n); + push @headers,q(\n); } } - push @headers, qq(

$_: ) . html_escape(decode_rfc1522($head_field))."

\n"; + push @headers, qq(
$_: ) . html_escape(decode_rfc1522($head_field))."
\n"; } print {$output} join(qq(), @headers); } else { @@ -172,7 +173,6 @@ sub display_entity { my $body = $entity->stringify_body; # this attachment has its own content type, so we must not # try to convert it to UTF-8 or do anything funky. - my @layers = PerlIO::get_layers($output); binmode($output,':raw'); print {$output} "Content-Type: $type"; my ($charset) = $head->get('Content-Type:') =~ m/charset\s*=\s*\"?([\w-]+)\"?/i; @@ -187,10 +187,10 @@ sub display_entity { print {$output} "\n"; my $decoder = MIME::Decoder->new($head->mime_encoding); $decoder->decode(IO::Scalar->new(\$body), $output); - if (grep {/utf8/} @layers) { - binmode($output,':utf8'); - } - return; + # we don't reset the layers here, because it makes no + # sense to add anything to the output handle after this + # point. + return(1); } elsif (not exists $param{att}) { my @dlargs = (msg=>$xmessage, att=>$#$attachments); @@ -206,26 +206,30 @@ sub display_entity { } } - return if not $param{outer} and $disposition eq 'attachment' and not exists $param{att}; - return unless ($type =~ m[^text/?] and - $type !~ m[^text/(?:html|enriched)(?:;|$)]) or - $type =~ m[^application/pgp(?:;|$)] or - $entity->parts; + return 0 if not $param{outer} and $disposition eq 'attachment' and not exists $param{att}; + return 0 unless (($type =~ m[^text/?] and + $type !~ m[^text/(?:html|enriched)(?:;|$)]) or + $type =~ m[^application/pgp(?:;|$)] or + $entity->parts); if ($entity->is_multipart) { my @parts = $entity->parts; foreach my $part (@parts) { - display_entity(entity => $part, - bug_num => $ref, - outer => 0, - msg_num => $xmessage, - output => $output, - attachments => $attachments, - terse => $param{terse}, - exists $param{msg}?(msg=>$param{msg}):(), - exists $param{att}?(att=>$param{att}):(), - exists $param{avatars}?(avatars=>$param{avatars}):(), - ); + my $raw_output = + display_entity(entity => $part, + bug_num => $ref, + outer => 0, + msg_num => $xmessage, + output => $output, + attachments => $attachments, + terse => $param{terse}, + exists $param{msg}?(msg=>$param{msg}):(), + exists $param{att}?(att=>$param{att}):(), + exists $param{avatars}?(avatars=>$param{avatars}):(), + ); + if ($raw_output) { + return $raw_output; + } # print {$output} "\n"; } } elsif ($entity->parts) { @@ -270,7 +274,11 @@ sub display_entity { ((?:\>\;)?[)]?(?:'|\&\#39\;)?[:.\,]?(?:\s|$)) # terminators }{$1$2}gox; # Add links to bug closures - $body =~ s[(closes:\s*(?:bug)?\#?\s?\d+(?:,?\s*(?:bug)?\#?\s?\d+)*)] + $body =~ s[((?:closes|see):\s* # start of closed/referenced bugs + (?:bug)?\#?\s?\d+\s? # first bug + (?:,?\s*(?:bug)?\#?\s?\d+)* # additional bugs + (?:\s|\n|\)|\]|\}|\.|\,|$)) # ends with a space, newline, end of string, or ); fixes #747267 + ] [my $temp = $1; $temp =~ s{(\d+)} {bug_links(bug=>$1)}ge; @@ -279,13 +287,14 @@ sub display_entity { length $config{cve_tracker} ) { # Add links to CVE vulnerabilities (closes #568464) - $body =~ s{(^|\s)(CVE-\d{4}-\d{4,})(\s|[,.-\[\]]|$)} + $body =~ s{(^|\s|[\(\[])(CVE-\d{4}-\d{4,})(\s|[,.-\[\]\)]|$)} {$1$2$3}gxm; } if (not exists $param{att}) { print {$output} qq(
$body
\n); } } + return 0; } @@ -307,26 +316,32 @@ sub handle_email_message{ my $output; my $output_fh = globify_scalar(\$output); - my $parser = MIME::Parser->new(); - # Because we are using memory, not tempfiles, there's no need to - # clean up here like in Debbugs::MIME - $parser->tmp_to_core(1); - $parser->output_to_core(1); - my $entity = $parser->parse_data( $email); + my $entity; + if (not blessed $email) { + my $parser = MIME::Parser->new(); + # Because we are using memory, not tempfiles, there's no need to + # clean up here like in Debbugs::MIME + $parser->tmp_to_core(1); + $parser->output_to_core(1); + $entity = $parser->parse_data( $email); + } else { + $entity = $email + } my @attachments = (); - display_entity(entity => $entity, - bug_num => $param{ref}, - outer => 1, - msg_num => $param{msg_num}, - output => $output_fh, - attachments => \@attachments, - terse => $param{terse}, - exists $param{msg}?(msg=>$param{msg}):(), - exists $param{att}?(att=>$param{att}):(), - exists $param{trim_headers}?(trim_headers=>$param{trim_headers}):(), - exists $param{avatars}?(avatars=>$param{avatars}):(), - ); - return decode_utf8($output); + my $raw_output = + display_entity(entity => $entity, + bug_num => $param{ref}, + outer => 1, + msg_num => $param{msg_num}, + output => $output_fh, + attachments => \@attachments, + terse => $param{terse}, + exists $param{msg}?(msg=>$param{msg}):(), + exists $param{att}?(att=>$param{att}):(), + exists $param{trim_headers}?(trim_headers=>$param{trim_headers}):(), + exists $param{avatars}?(avatars=>$param{avatars}):(), + ); + return $raw_output?$output:decode_utf8($output); } =head2 handle_record @@ -371,7 +386,7 @@ sub handle_record{ {$1.$2.(bug_links(bug=>$3)).$4. english_join([map {bug_links(bug=>$_)} (split /\,?\s+(?:and\s+)?/, $5)])}eo; # Add links to reassigned packages - $output =~ s{(Bug reassigned from package \`)([^']+?)((?:'|\&\#39;) to \`)([^']+?)((?:'|\&\#39;))} + $output =~ s{(Bug reassigned from package (?:[\`']|\&\#39;))([^']+?)((?:'|\&\#39;) to (?:[\`']|\&\#39;))([^']+?)((?:'|\&\#39;))} {$1.q($2).$3.q($4).$5}eo; if (defined $time) { $output .= ' ('.strftime('%a, %d %b %Y %T GMT',gmtime($time)).') '; @@ -427,8 +442,21 @@ sub handle_record{ options => {msg=>$msg_number, mbox=>'yes'} ) - ) .'">mbox)'.":

\n"; - $output .= handle_email_message($record->{text}, + ) .'">mbox, '; + my $parser = MIME::Parser->new(); + # Because we are using memory, not tempfiles, there's no need to + # clean up here like in Debbugs::MIME + $parser->tmp_to_core(1); + $parser->output_to_core(1); + my $entity = $parser->parse_data($record->{text}); + my $r_l = reply_headers($entity); + $output .= q(reply); + + $output .= ')'.":

\n"; + $output .= handle_email_message($entity, ref => $bug_number, msg_num => $msg_number, %param, @@ -446,8 +474,8 @@ sub __libravatar_url { if (not defined $config{libravatar_uri} or not length $config{libravatar_uri}) { return undef; } - ($email) = get_addresses($email); - return $config{libravatar_uri}.md5_hex(lc($email)).($config{libravatar_uri_options}//''); + ($email) = grep {/\@/} get_addresses($email); + return $config{libravatar_uri}.uri_escape_utf8($email.($config{libravatar_uri_options}//'')); }