]> git.donarmstrong.com Git - debbugs.git/commitdiff
Merge branch 'master' into cgiencoding
authorDon Armstrong <don@donarmstrong.com>
Tue, 17 Apr 2012 23:18:20 +0000 (16:18 -0700)
committerDon Armstrong <don@donarmstrong.com>
Tue, 17 Apr 2012 23:18:20 +0000 (16:18 -0700)
Debbugs/Common.pm
Debbugs/Control.pm
Debbugs/MIME.pm
Debbugs/SOAP.pm
Debbugs/Status.pm
cgi/bugreport.cgi
cgi/pkgreport.cgi
t/01_mime.t
t/02_common.t [new file with mode: 0644]
t/05_mail.t

index 880989843d1cf32f7e52cd1bae317cada4cee633..b59e6fa88b5985287e319af836de7aafb31113db 100644 (file)
@@ -50,12 +50,13 @@ BEGIN{
                                qw(cleanup_eval_fail),
                                qw(hash_slice),
                               ],
+                    utf8   => [qw(encode_utf8_structure)],
                     date   => [qw(secs_to_english)],
                     quit   => [qw(quit)],
                     lock   => [qw(filelock unfilelock lockpid)],
                    );
      @EXPORT_OK = ();
-     Exporter::export_ok_tags(qw(lock quit date util misc));
+     Exporter::export_ok_tags(keys %EXPORT_TAGS);
      $EXPORT_TAGS{all} = [@EXPORT_OK];
 }
 
@@ -70,6 +71,8 @@ use IO::Scalar;
 use Debbugs::MIME qw(decode_rfc1522);
 use Mail::Address;
 use Cwd qw(cwd);
+use Encode qw(encode_utf8 is_utf8);
+use Storable qw(dclone);
 
 use Params::Validate qw(validate_with :types);
 
@@ -823,7 +826,8 @@ sub globify_scalar {
          if (defined ref($scalar)) {
               if (ref($scalar) eq 'SCALAR' and
                   not UNIVERSAL::isa($scalar,'GLOB')) {
-                   return IO::Scalar->new($scalar);
+                   open $handle, '>:scalar:utf8', $scalar;
+                   return $handle;
               }
               else {
                    return $scalar;
@@ -836,7 +840,7 @@ sub globify_scalar {
               carp "Given a non-scalar reference, non-glob to globify_scalar; returning /dev/null handle";
          }
      }
-     return IO::File->new('/dev/null','w');
+     return IO::File->new('/dev/null','>:utf8');
 }
 
 =head2 cleanup_eval_fail()
@@ -894,6 +898,56 @@ sub hash_slice(\%@) {
     return map {exists $hashref->{$_}?($_,$hashref->{$_}):()} @keys;
 }
 
+
+=head1 UTF-8
+
+These functions are exported with the :utf8 tag
+
+=head2 encode_utf8_structure
+
+     %newdata = encode_utf8_structure(%newdata);
+
+Takes a complex data structure and encodes any strings with is_utf8
+set into their constituent octets.
+
+=cut
+
+our $depth = 0;
+sub encode_utf8_structure {
+    ++$depth;
+    my @ret;
+    for my $_ (@_) {
+       if (ref($_) eq 'HASH') {
+           push @ret, {encode_utf8_structure(%{$depth == 1 ? dclone($_):$_})};
+       }
+       elsif (ref($_) eq 'ARRAY') {
+           push @ret, [encode_utf8_structure(@{$depth == 1 ? dclone($_):$_})];
+       }
+       elsif (ref($_)) {
+           # we don't know how to handle non hash or non arrays
+           push @ret,$_;
+       }
+       else {
+           push @ret,__encode_utf8($_);
+       }
+    }
+    --$depth;
+    return @ret;
+}
+
+sub __encode_utf8 {
+    my @ret;
+    for my $r (@_) {
+       if (not ref($r) and is_utf8($r)) {
+           $r = encode_utf8($r);
+       }
+       push @ret,$r;
+    }
+    return @ret;
+}
+
+
+
 1;
 
 __END__
index ed69c84bd4147a3824a4709713937d315ccf8a1c..631504a8d5420a24db292d736732201a3ad9113b 100644 (file)
@@ -996,7 +996,7 @@ sub set_done {
                                                             headers =>
                                                             [To => $data->{submitter},
                                                              Subject => "$config{ubug}#$data->{bug_num} ".
-                                                             "closed by $param{requester} ($param{request_subject})",
+                                                             "closed by $param{requester} ".(defined $param{request_subject}?"($param{request_subject})":""),
                                                             ],
                                                            )
                                            ],
index c2faeaa8621b3f5c580beb5c450425c1d39f9b6c..640627651581826bf8bcce5570d8acb46085a3ce 100644 (file)
@@ -286,6 +286,9 @@ 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. We also consider parenthesis and "
index db066bfd870d4c67902b3f51ad5a2b349556b072..5cb08bb0f11eff7de6ab49dea880731a13dcb8b3 100644 (file)
@@ -24,6 +24,7 @@ None known.
 use warnings;
 use strict;
 use vars qw($DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
+use Debbugs::SOAP::Server;
 use base qw(Exporter SOAP::Server::Parameters);
 
 BEGIN{
@@ -38,12 +39,12 @@ BEGIN{
 
 }
 
-
 use IO::File;
 use Debbugs::Status qw(get_bug_status);
-use Debbugs::Common qw(make_list getbuglocation getbugcomponent);
+use Debbugs::Common qw(make_list getbuglocation getbugcomponent :utf8);
 use Debbugs::Packages;
-use Storable qw(nstore retrieve);
+
+use Storable qw(nstore retrieve dclone);
 use Scalar::Util qw(looks_like_number);
 
 
@@ -75,7 +76,7 @@ sub get_usertag {
               delete $ut{$tag} unless exists $tags{$tag};
          }
      }
-     return \%ut;
+     return encode_utf8_structure(\%ut);
 }
 
 
@@ -142,7 +143,7 @@ sub get_status {
          }
      }
 #     __prepare_response($self);
-     return \%status;
+     return encode_utf8_structure(\%status);
 }
 
 =head2 get_bugs
@@ -172,7 +173,7 @@ sub get_bugs{
      my %params = __collapse_params(@params);
      my @bugs;
      @bugs = Debbugs::Bugs::get_bugs(%params);
-     return \@bugs;
+     return encode_utf8_structure(\@bugs);
 }
 
 =head2 newest_bugs
@@ -188,7 +189,7 @@ sub newest_bugs{
      my $VERSION = __populate_version(pop);
      my ($self,$num) = @_;
      my $newest_bug = Debbugs::Bugs::newest_bug();
-     return [($newest_bug - $num + 1) .. $newest_bug];
+     return encode_utf8_structure([($newest_bug - $num + 1) .. $newest_bug]);
 
 }
 
@@ -249,7 +250,7 @@ sub get_bug_log{
                          msg_num => $current_msg,
                         };
      }
-     return \@messages;
+     return encode_utf8_structure(\@messages);
 }
 
 =head2 binary_to_source
@@ -276,13 +277,13 @@ sub binary_to_source{
      my ($self,@params) = @_;
 
      if ($VERSION <= 1) {
-        return [Debbugs::Packages::binary_to_source(binary => $params[0],
+        return encode_utf8_structure([Debbugs::Packages::binary_to_source(binary => $params[0],
                                                     (@params > 1)?(version => $params[1]):(),
                                                     (@params > 2)?(arch    => $params[2]):(),
-                                                   )];
+                                                   )]);
      }
      else {
-        return [Debbugs::Packages::binary_to_source(@params)];
+        return encode_utf8_structure([Debbugs::Packages::binary_to_source(@params)]);
      }
 }
 
@@ -304,7 +305,7 @@ sub source_to_binary {
      my $VERSION = __populate_version(pop);
      my ($self,@params) = @_;
 
-     return [Debbugs::Packages::sourcetobinary(@params)];
+     return encode_utf8_structure([Debbugs::Packages::sourcetobinary(@params)]);
 }
 
 =head2 get_versions
@@ -349,7 +350,7 @@ sub get_versions{
      my $VERSION = __populate_version(pop);
      my ($self,@params) = @_;
 
-     return scalar Debbugs::Packages::get_versions(@params);
+     return encode_utf8_structure(scalar Debbugs::Packages::get_versions(@params));
 }
 
 =head1 VERSION COMPATIBILITY
index d44d0bdea277da4add795748ab9c200cabafc3b1..e880783ca87493680b3c751e32cd06df7cf54526 100644 (file)
@@ -37,7 +37,7 @@ use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
 use base qw(Exporter);
 
 use Params::Validate qw(validate_with :types);
-use Debbugs::Common qw(:util :lock :quit :misc);
+use Debbugs::Common qw(:util :lock :quit :misc :utf8);
 use Debbugs::Config qw(:config);
 use Debbugs::MIME qw(decode_rfc1522 encode_rfc1522);
 use Debbugs::Packages qw(makesourceversions make_source_versions getversions get_versions binary_to_source);
@@ -45,7 +45,7 @@ use Debbugs::Versions;
 use Debbugs::Versions::Dpkg;
 use POSIX qw(ceil);
 use File::Copy qw(copy);
-use Encode qw(decode encode);
+use Encode qw(decode encode is_utf8);
 
 use Storable qw(dclone);
 use List::Util qw(min max);
@@ -239,10 +239,30 @@ sub read_bug{
     }
 
     my %namemap = reverse %fields;
+    for my $field (keys %fields) {
+        $data{$field} = '' unless exists $data{$field};
+    }
+    if ($version < 3) {
+       for my $field (@rfc1522_fields) {
+           $data{$field} = decode_rfc1522($data{$field});
+       }
+    }
     for my $line (@lines) {
-       eval {
-           $line = decode("utf8",$line,Encode::FB_CROAK);
-       };
+       my @encodings_to_try = qw(utf8 iso8859-1);
+       if ($version >= 3) {
+           @encodings_to_try = qw(utf8);
+       }
+       for (@encodings_to_try) {
+           last if is_utf8($line);
+           my $temp;
+           eval {
+               $temp = decode("$_",$line,Encode::FB_CROAK);
+           };
+           if (not $@) { # only update the line if there are no errors.
+               $line = $temp;
+               last;
+           }
+       }
         if ($line =~ /(\S+?): (.*)/) {
             my ($name, $value) = (lc $1, $2);
            # this is a bit of a hack; we should never, ever have \r
@@ -252,10 +272,6 @@ sub read_bug{
            $data{$namemap{$name}} = $value if exists $namemap{$name};
         }
     }
-    for my $field (keys %fields) {
-        $data{$field} = '' unless exists $data{$field};
-    }
-
     $data{severity} = $config{default_severity} if $data{severity} eq '';
     for my $field (qw(found_versions fixed_versions found_date fixed_date)) {
         $data{$field} = [split ' ', $data{$field}];
@@ -268,11 +284,6 @@ sub read_bug{
               @{$data{"${field}_date"}});
     }
 
-    if ($version < 3) {
-       for my $field (@rfc1522_fields) {
-           $data{$field} = decode_rfc1522($data{$field});
-       }
-    }
     my $status_modified = (stat($status))[9];
     # Add log last modified time
     $data{log_modified} = (stat($log))[9];
@@ -596,7 +607,7 @@ version.
 
 sub makestatus {
     my ($data,$version) = @_;
-    $version = 2 unless defined $version;
+    $version = 3 unless defined $version;
 
     my $contents = '';
 
@@ -609,6 +620,8 @@ sub makestatus {
     }
     %newdata = %{join_status_fields(\%newdata)};
 
+    %newdata = encode_utf8_structure(%newdata);
+
     if ($version < 3) {
         for my $field (@rfc1522_fields) {
             $newdata{$field} = encode_rfc1522($newdata{$field});
@@ -645,9 +658,6 @@ sub makestatus {
             }
         }
     }
-    eval {
-       $contents = encode("utf8",$contents,Encode::FB_CROAK);
-    };
     return $contents;
 }
 
@@ -667,15 +677,23 @@ sub writebug {
     my ($ref, $data, $location, $minversion, $disablebughook) = @_;
     my $change;
 
-    my %outputs = (1 => 'status', 2 => 'summary');
+    my %outputs = (1 => 'status', 3 => 'summary');
     for my $version (keys %outputs) {
         next if defined $minversion and $version < $minversion;
         my $status = getbugcomponent($ref, $outputs{$version}, $location);
         die "can't find location for $ref" unless defined $status;
-        open(S,"> $status.new") || die "opening $status.new: $!";
-        print(S makestatus($data, $version)) ||
+       my $sfh;
+       if ($version >= 3) {
+           open $sfh,">","$status.new"  or
+               die "opening $status.new: $!";
+       }
+       else {
+           open $sfh,">","$status.new"  or
+               die "opening $status.new: $!";
+       }
+        print {$sfh} makestatus($data, $version) or
             die "writing $status.new: $!";
-        close(S) || die "closing $status.new: $!";
+        close($sfh) or die "closing $status.new: $!";
         if (-e $status) {
             $change = 'change';
         } else {
index 8ad688f6923b501ea836557574b2a63f881c738a..0a66311f71909229ddeb7f2bf8d5ac03c5cbfe3c 100755 (executable)
@@ -8,6 +8,9 @@ BEGIN{
     delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
 }
 
+# STDOUT should be using the utf8 io layer
+binmode(STDOUT,':utf8');
+
 use POSIX qw(strftime);
 use MIME::Parser;
 use MIME::Decoder;
index 4f4ea800af986fcd38f0c58ba04dd8e121a41a95..d29c3abc7ff56943a7a0a2196be16e5560bda857 100755 (executable)
@@ -18,6 +18,9 @@ BEGIN{
     delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
 }
 
+# STDOUT should be in utf8 mode
+binmode(STDOUT,':utf8');
+
 use POSIX qw(strftime nice);
 
 use Debbugs::Config qw(:globals :text :config);
index 10bf167ae7410888384d26dc078bdca73a3714b5..5a1aa60d4c00e68f5278935e48b8b212633980bc 100644 (file)
@@ -31,11 +31,11 @@ ok(Debbugs::MIME::decode_rfc1522(q(=?iso-8859-1?Q?D=F6n_Armstr=F3ng?= <don@donar
 
 
 # 2: test encode
-ok(Debbugs::MIME::decode_rfc1522(Debbugs::MIME::encode_rfc1522($test_str)) eq $test_str,
+ok(Debbugs::MIME::decode_rfc1522(Debbugs::MIME::encode_rfc1522($test_str)) eq encode_utf8($test_str),
   "encode_rfc1522 encodes strings that decode_rfc1522 can decode");
-ok(Debbugs::MIME::decode_rfc1522(Debbugs::MIME::encode_rfc1522($test_str2)) eq $test_str2,
+ok(Debbugs::MIME::decode_rfc1522(Debbugs::MIME::encode_rfc1522($test_str2)) eq encode_utf8($test_str2),
   "encode_rfc1522 encodes strings that decode_rfc1522 can decode");
-ok(Debbugs::MIME::decode_rfc1522(Debbugs::MIME::encode_rfc1522($test_str3)) eq $test_str3,
+ok(Debbugs::MIME::decode_rfc1522(Debbugs::MIME::encode_rfc1522($test_str3)) eq encode_utf8($test_str3),
   "encode_rfc1522 properly handles parentesis and \"");
 
 
diff --git a/t/02_common.t b/t/02_common.t
new file mode 100644 (file)
index 0000000..d770d3f
--- /dev/null
@@ -0,0 +1,14 @@
+# -*- mode: cperl;-*-
+
+use Test::More tests => 2;
+use Encode qw(decode_utf8);
+
+use_ok('Debbugs::Common');
+is_deeply(Debbugs::Common::encode_utf8_structure(
+          {a => decode_utf8('föö'),
+          b => [map {decode_utf8($_)} qw(blëh bl♥h)],
+         }),
+         {a => 'föö',
+          b => [qw(blëh bl♥h)],
+         },
+        );
index e92bde14ae2cd72f8776cc1c27a9313e36869be3..3d21049c579ef9e3c994ce261fc701e674ac7fac 100644 (file)
@@ -11,6 +11,7 @@ use utf8;
 use UNIVERSAL;
 
 use Debbugs::MIME qw(decode_rfc1522);
+use Encode qw(encode_utf8);
 
 use_ok('Debbugs::Mail');
 
@@ -24,7 +25,7 @@ blah blah blah
 END
 
 # 1: test decode
-ok(decode_rfc1522(Debbugs::Mail::encode_headers($test_str)) eq $test_str);
+ok(decode_rfc1522(Debbugs::Mail::encode_headers($test_str)) eq encode_utf8($test_str));
 
 # XXX Figure out a good way to test the send message bit of
 # Debbugs::Mail