X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=Debbugs%2FMIME.pm;h=482a30b4d182e530bbcd3b780a5479dc53f4cae4;hb=9dd18b2a38fae81a660504da29147937596ba206;hp=95dafb8dc5075ed9a515143c00dd8e584e653bb0;hpb=dfffc9e4190838650697c3758a477e92f49939a3;p=debbugs.git diff --git a/Debbugs/MIME.pm b/Debbugs/MIME.pm index 95dafb8..482a30b 100644 --- a/Debbugs/MIME.pm +++ b/Debbugs/MIME.pm @@ -31,12 +31,20 @@ use warnings; use strict; use base qw(Exporter); -use vars qw($VERSION @EXPORT_OK); +use vars qw($DEBUG $VERSION @EXPORT_OK %EXPORT_TAGS @EXPORT); BEGIN { $VERSION = 1.00; + $DEBUG = 0 unless defined $DEBUG; - @EXPORT_OK = qw(parse decode_rfc1522 encode_rfc1522 convert_to_utf8 create_mime_message getmailbody); + @EXPORT = (); + + %EXPORT_TAGS = (mime => [qw(parse create_mime_message getmailbody)], + rfc1522 => [qw(decode_rfc1522 encode_rfc1522)], + ); + @EXPORT_OK=(); + Exporter::export_ok_tags(keys %EXPORT_TAGS); + $EXPORT_TAGS{all} = [@EXPORT_OK]; } use File::Path; @@ -46,6 +54,9 @@ use MIME::Parser; use POSIX qw(strftime); use List::MoreUtils qw(apply); +# for convert_to_utf8 +use Debbugs::UTF8 qw(convert_to_utf8); + # for decode_rfc1522 use MIME::WordDecoder qw(); use Encode qw(decode encode encode_utf8 decode_utf8 is_utf8); @@ -60,7 +71,7 @@ sub getmailbody if ($type eq 'text/plain' or ($type =~ m#text/?# and $type ne 'text/html') or $type eq 'application/pgp') { - return $entity->bodyhandle; + return $entity; } elsif ($type eq 'multipart/alternative') { # RFC 2046 says we should use the last part we recognize. for my $part (reverse $entity->parts) { @@ -92,8 +103,15 @@ sub parse @headerlines = @{$entity->head->header}; chomp @headerlines; - my $entity_body = getmailbody($entity); - @bodylines = $entity_body ? $entity_body->as_lines() : (); + my $entity_body = getmailbody($entity); + my $entity_body_handle; + my $charset; + if (defined $entity_body) { + $entity_body_handle = $entity_body->bodyhandle(); + $charset = $entity_body->head()->mime_attr('content-type.charset'); + } + @bodylines = $entity_body_handle ? $entity_body_handle->as_lines() : (); + @bodylines = map {convert_to_utf8($_,$charset)} @bodylines; chomp @bodylines; } else { # Legacy pre-MIME code, kept around in case MIME::Parser fails. @@ -185,7 +203,7 @@ sub create_mime_message{ my $msg = MIME::Entity->build('Content-Type' => 'text/plain; charset=utf-8', 'Encoding' => 'quoted-printable', (map{encode_rfc1522($_)} @{$headers}), - Data => $body + Data => is_utf8($body)?encode_utf8($body):$body, ); # Attach the attachments @@ -220,25 +238,6 @@ sub create_mime_message{ } -# Bug #61342 et al. - -sub convert_to_utf8 { - my ($data, $charset) = @_; - # raw data just gets returned (that's the charset WordDecorder - # uses when it doesn't know what to do) - return $data if $charset eq 'raw' or is_utf8($data,1); - my $result; - eval { - # this encode/decode madness is to make sure that the data - # really is valid utf8 and that the is_utf8 flag is off. - $result = encode("utf8",decode($charset,$data)) - }; - if ($@) { - warn "Unable to decode charset; '$charset' and '$data': $@"; - return $data; - } - return $result; -} =head2 decode_rfc1522 @@ -286,10 +285,15 @@ sub encode_rfc1522 { # handle being passed undef properly return undef if not defined $rawstr; + if (is_utf8($rawstr)) { + $rawstr= encode_utf8($rawstr); + } # We process words in reverse so we can preserve spacing between # encoded words. This regex splits on word|nonword boundaries and - # nonword|nonword boundaries. - my @words = reverse split /(?:(?<=[\s\n])|(?=[\s\n]))/m, $rawstr; + # nonword|nonword boundaries. We also consider parenthesis and " + # to be nonwords to avoid escaping them in comments in violation + # of RFC1522 + my @words = reverse split /(?:(?<=[\s\n\)\(\"])|(?=[\s\n\)\(\"]))/m, $rawstr; my $previous_word_encoded = 0; my $string = ''; @@ -311,7 +315,7 @@ sub encode_rfc1522 { if (length $encoded > 75) { # Turn utf8 into the internal perl representation # so . is a character, not a byte. - my $tempstr = decode_utf8($word,Encode::FB_DEFAULT); + my $tempstr = is_utf8($word)?$word:decode_utf8($word,Encode::FB_DEFAULT); my @encoded; # Strip it into 10 character long segments, and encode # the segments