]> git.donarmstrong.com Git - debbugs.git/blobdiff - Debbugs/CGI/Bugreport.pm
decode_utf8 the html record before calling decode_rfc1522; use Debbugs::UTF8
[debbugs.git] / Debbugs / CGI / Bugreport.pm
index cb1f48cf261fe35c6242e30e90d149cce199387f..707c3a0d68a315d6e7791b265a04312be1b16522 100644 (file)
@@ -32,10 +32,13 @@ use base qw(Exporter);
 
 use IO::Scalar;
 use Params::Validate qw(validate_with :types);
-use Debbugs::MIME qw(convert_to_utf8 decode_rfc1522 create_mime_message);
+use Debbugs::MIME qw(decode_rfc1522 create_mime_message);
 use Debbugs::CGI qw(:url :html :util);
-use Debbugs::Common qw(globify_scalar);
+use Debbugs::Common qw(globify_scalar english_join);
+use Debbugs::UTF8;
+use Debbugs::Config qw(:config);
 use POSIX qw(strftime);
+use Encode qw(decode_utf8);
 
 BEGIN{
      ($VERSION) = q$Revision: 494 $ =~ /^Revision:\s+([^\s+])/;
@@ -43,7 +46,7 @@ BEGIN{
 
      @EXPORT = ();
      %EXPORT_TAGS = ();
-     @EXPORT_OK = (qw(display_entities handle_record handle_email_message));
+     @EXPORT_OK = (qw(display_entity handle_record handle_email_message));
      Exporter::export_ok_tags(keys %EXPORT_TAGS);
      $EXPORT_TAGS{all} = [@EXPORT_OK];
 }
@@ -155,10 +158,14 @@ sub display_entity {
            my $head = $entity->head;
            chomp(my $type = $entity->effective_type);
            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($param{output});
+           binmode($param{output},':raw');
            print {$param{output}} "Content-Type: $type";
            my ($charset) = $head->get('Content-Type:') =~ m/charset\s*=\s*\"?([\w-]+)\"?/i;
            print {$param{output}} qq(; charset="$charset") if defined $charset;
-           print {$param{output}}"\n";
+           print {$param{output}} "\n";
            if ($filename ne '') {
                my $qf = $filename;
                $qf =~ s/"/\\"/g;
@@ -168,15 +175,22 @@ sub display_entity {
            print {$param{output}} "\n";
            my $decoder = MIME::Decoder->new($head->mime_encoding);
            $decoder->decode(IO::Scalar->new(\$body), $param{output});
+           if (grep {/utf8/} @layers) {
+               binmode($param{output},':utf8');
+           }
            return;
        }
        elsif (not exists $param{att}) {
-            my @dlargs = ($ref, msg=>$xmessage, att=>$#$attachments);
+            my @dlargs = (msg=>$xmessage, att=>$#$attachments);
             push @dlargs, (filename=>$filename) if $filename ne '';
             my $printname = $filename;
             $printname = 'Message part ' . ($#$attachments + 1) if $filename eq '';
-            print {$param{output}} '<pre class="mime">[<a href="' . html_escape(bug_url(@dlargs)) . qq{">$printname</a> } .
-                 "($type, $disposition)]</pre>\n";
+            print {$param{output}} '<pre class="mime">[<a href="' .
+                 html_escape(bug_links(bug => $ref,
+                                       links_only => 1,
+                                       options => {@dlargs})
+                            ) . qq{">$printname</a> } .
+                                 "($type, $disposition)]</pre>\n";
        }
     }
 
@@ -212,7 +226,7 @@ sub display_entity {
                           bug_num => $ref,
                           outer => 1,
                           msg_num => $xmessage,
-                          ouput => $param{output},
+                          output => $param{output},
                           attachments => $attachments,
                           terse => $param{terse},
                           exists $param{msg}?(msg=>$param{msg}):(),
@@ -227,7 +241,7 @@ sub display_entity {
         my $content_type = $entity->head->get('Content-Type:') || "text/html";
         my ($charset) = $content_type =~ m/charset\s*=\s*\"?([\w-]+)\"?/i;
         my $body = $entity->bodyhandle->as_string;
-        $body = convert_to_utf8($body,$charset) if defined $charset;
+        $body = convert_to_utf8($body,$charset//'utf8');
         $body = html_escape($body);
         # Attempt to deal with format=flowed
         if ($content_type =~ m/format\s*=\s*\"?flowed\"?/i) {
@@ -245,12 +259,15 @@ sub display_entity {
         $body =~ s[(closes:\s*(?:bug)?\#?\s?\d+(?:,?\s*(?:bug)?\#?\s?\d+)*)]
                   [my $temp = $1;
                    $temp =~ s{(\d+)}
-                             {qq(<a href=").
-                                   html_escape(bug_url($1)).
-                                        qq(">$1</a>)
-                                   }ge;
+                             {bug_links(bug=>$1)}ge;
                    $temp;]gxie;
-
+        if (defined $config{cve_tracker} and
+            length $config{cve_tracker}
+           ) {
+            # Add links to CVE vulnerabilities (closes #568464)
+            $body =~ s{(^|\s)(CVE-\d{4}-\d{4,})(\s|[,.-\[\]]|$)}
+                      {$1<a href="http://$config{cve_tracker}$2">$2</a>$3}gxm;
+        }
         if (not exists $param{att}) {
              print {$param{output}} qq(<pre class="message">$body</pre>\n);
         }
@@ -274,7 +291,9 @@ appropriate.
 sub handle_email_message{
      my ($email,%param) = @_;
 
-     my $output = '';
+     # output needs to have the is_utf8 flag on to avoid double
+     # encoding
+     my $output = decode_utf8('');
      my $parser = MIME::Parser->new();
      # Because we are using memory, not tempfiles, there's no need to
      # clean up here like in Debbugs::MIME
@@ -291,6 +310,7 @@ sub handle_email_message{
                    terse       => $param{terse},
                    exists $param{msg}?(msg=>$param{msg}):(),
                    exists $param{att}?(att=>$param{att}):(),
+                   exists $param{trim_headers}?(trim_headers=>$param{trim_headers}):(),
                   );
      return $output;
 
@@ -309,31 +329,51 @@ should be output to the browser.
 sub handle_record{
      my ($record,$bug_number,$msg_number,$seen_msg_ids) = @_;
 
-     my $output = '';
+     # output needs to have the is_utf8 flag on to avoid double
+     # encoding
+     my $output = decode_utf8('');
      local $_ = $record->{type};
      if (/html/) {
-         my ($time) = $record->{text} =~ /<!--\s+time:(\d+)\s+-->/;
-         my $class = $record->{text} =~ /^<strong>(?:Acknowledgement|Reply|Information|Report|Notification)/ ? 'infmessage':'msgreceived';
-         $output .= decode_rfc1522($record->{text});
+        # $record->{text} is not in perl's internal encoding; convert it
+        my $text = decode_rfc1522(decode_utf8($record->{text}));
+         my ($time) = $text =~ /<!--\s+time:(\d+)\s+-->/;
+         my $class = $text =~ /^<strong>(?:Acknowledgement|Reply|Information|Report|Notification)/m ? 'infmessage':'msgreceived';
+         $output .= $text;
          # Link to forwarded http:// urls in the midst of the report
          # (even though these links already exist at the top)
-         $output =~ s,((?:ftp|http|https)://[\S~-]+?/?)([\)\'\:\.\,]?(?:\s|\.<|$)),<a href=\"$1\">$1</a>$2,go;
+         $output =~ s,((?:ftp|http|https)://[\S~-]+?/?)((?:[\)\'\:\.\,]|\&\#39;)?(?:\s|\.<|$)),<a href=\"$1\">$1</a>$2,go;
          # Add links to the cloned bugs
-         $output =~ s{(Bug )(\d+)( cloned as bugs? )(\d+)(?:\-(\d+)|)}{$1.bug_links(bug=>$2).$3.bug_links(bug=>[$4..$5])}eo;
+         $output =~ s{(Bug )(\d+)( cloned as bugs? )(\d+)(?:\-(\d+)|)}{$1.bug_links(bug=>$2).$3.bug_links(bug=>(defined $5)?[$4..$5]:$4)}eo;
          # Add links to merged bugs
          $output =~ s{(?<=Merged )([\d\s]+)(?=\.)}{join(' ',map {bug_links(bug=>$_)} (split /\s+/, $1))}eo;
          # Add links to blocked bugs
          $output =~ s{(?<=Blocking bugs)(?:( of )(\d+))?( (?:added|set to|removed):\s+)([\d\s\,]+)}
                      {(defined $2?$1.bug_links(bug=>$2):'').$3.
-                           join(' ',map {bug_links(bug=>$_)} (split /\,?\s+/, $4))}eo;
+                          english_join([map {bug_links(bug=>$_)} (split /\,?\s+/, $4)])}eo;
+         $output =~ s{((?:[Aa]dded|[Rr]emoved)\ blocking\ bug(?:\(s\))?)(?:(\ of\ )(\d+))?(:?\s+)
+                      (\d+(?:,\s+\d+)*(?:\,?\s+and\s+\d+)?)}
+                     {$1.(defined $3?$2.bug_links(bug=>$3):'').$4.
+                          english_join([map {bug_links(bug=>$_)} (split /\,?\s+(?:and\s+)?/, $5)])}xeo;
+         $output =~ s{([Aa]dded|[Rr]emoved)( indication that bug )(\d+)( blocks )([\d\s\,]+)}
+                     {$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;))}
-         {$1.q(<a href=").html_escape(pkg_url(pkg=>$2)).qq(">$2</a>).$3.q(<a href=").html_escape(pkg_url(pkg=>$4)).qq(">$4</a>).$5}eo;
+         {$1.q(<a href=").html_escape(package_links(package=>$2)).qq(">$2</a>).$3.q(<a href=").html_escape(package_links(package=>$4)).qq(">$4</a>).$5}eo;
          if (defined $time) {
               $output .= ' ('.strftime('%a, %d %b %Y %T GMT',gmtime($time)).') ';
          }
-         $output .= '<a href="' . html_escape(bug_url($bug_number, msg => ($msg_number+1))) . '">Full text</a> and <a href="' .
-              html_escape(bug_url($bug_number, msg => ($msg_number+1), mbox => 'yes')) . '">rfc822 format</a> available.';
+         $output .= '<a href="' .
+              html_escape(bug_links(bug => $bug_number,
+                                    options => {msg => ($msg_number+1)},
+                                    links_only => 1,
+                                   )
+                         ) . '">Full text</a> and <a href="' .
+                              html_escape(bug_links(bug => $bug_number,
+                                                    options => {msg => ($msg_number+1),
+                                                                mbox => 'yes'},
+                                                    links_only => 1)
+                                         ) . '">rfc822 format</a> available.';
 
          $output = qq(<div class="$class"><hr>\n<a name="$msg_number"></a>\n) . $output . "</div>\n";
      }
@@ -346,7 +386,7 @@ sub handle_record{
               $$seen_msg_ids{$msg_id} = 1;
          }
          $output .= qq(<hr><p class="msgreceived"><a name="$msg_number"></a>\n);
-         $output .= 'View this message in <a href="' . html_escape(bug_url($bug_number, msg=>$msg_number, mbox=>'yes')) . '">rfc822 format</a></p>';
+         $output .= 'View this message in <a href="' . html_escape(bug_links(bug=>$bug_number, links_only => 1, options=>{msg=>$msg_number, mbox=>'yes'})) . '">rfc822 format</a></p>';
          $output .= handle_email_message($record->{text},
                                          ref     => $bug_number,
                                          msg_num => $msg_number,
@@ -367,8 +407,13 @@ sub handle_record{
          my ($received,$hostname) = $record->{text} =~ m/Received: \(at (\S+)\) by (\S+)\;/;
          $output .= qq|<hr><p class="msgreceived"><a name="$msg_number"></a><a name="msg$msg_number"></a><a href="#$msg_number">Message #$msg_number</a> received at |.
               html_escape("$received\@$hostname") .
-                   q| (<a href="| . html_escape(bug_url($bug_number, msg=>$msg_number)) . '">full text</a>'.
-                        q|, <a href="| . html_escape(bug_url($bug_number, msg=>$msg_number,mbox=>'yes')) .'">mbox</a>)'.":</p>\n";
+                   q| (<a href="| . html_escape(bug_links(bug => $bug_number, links_only => 1, options => {msg=>$msg_number})) . '">full text</a>'.
+                        q|, <a href="| . html_escape(bug_links(bug => $bug_number,
+                                                               links_only => 1,
+                                                               options => {msg=>$msg_number,
+                                                                           mbox=>'yes'}
+                                                              )
+                                                    ) .'">mbox</a>)'.":</p>\n";
          $output .= handle_email_message($record->{text},
                                          ref     => $bug_number,
                                          msg_num => $msg_number,