From 71f44e682fe7b0f68d3a6a609aa5321c081c3fcc Mon Sep 17 00:00:00 2001 From: Max Kanat-Alexander Date: Thu, 1 Jul 2010 14:00:29 -0700 Subject: Bug 382398: Make checksetup.pl localized messages be output in the console's charset r=timello, a=mkanat --- Bugzilla.pm | 9 +++++++-- Bugzilla/Install/Requirements.pm | 4 ++++ Bugzilla/Install/Util.pm | 36 +++++++++++++++++++++++++++++++++++- checksetup.pl | 6 ------ 4 files changed, 46 insertions(+), 9 deletions(-) diff --git a/Bugzilla.pm b/Bugzilla.pm index 2f21c6a18..eedcb85ee 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -44,7 +44,7 @@ use Bugzilla::Extension; use Bugzilla::DB; use Bugzilla::Install::Localconfig qw(read_localconfig); use Bugzilla::Install::Requirements qw(OPTIONAL_MODULES); -use Bugzilla::Install::Util; +use Bugzilla::Install::Util qw(init_console); use Bugzilla::Template; use Bugzilla::User; use Bugzilla::Error; @@ -82,7 +82,12 @@ use constant SHUTDOWNHTML_EXIT_SILENTLY => qw( # Note that this is a raw subroutine, not a method, so $class isn't available. sub init_page { - (binmode STDOUT, ':utf8') if Bugzilla->params->{'utf8'}; + if (Bugzilla->usage_mode == USAGE_MODE_CMDLINE) { + init_console(); + } + elsif (Bugzilla->params->{'utf8'}) { + binmode STDOUT, ':utf8'; + } if (${^TAINT}) { # Some environment variables are not taint safe diff --git a/Bugzilla/Install/Requirements.pm b/Bugzilla/Install/Requirements.pm index 00077a5a9..12a9c20c5 100644 --- a/Bugzilla/Install/Requirements.pm +++ b/Bugzilla/Install/Requirements.pm @@ -541,6 +541,10 @@ sub have_vers { my $wanted = $params->{version}; eval "require $module;"; + # Don't let loading a module change the output-encoding of STDOUT + # or STDERR. (CGI.pm tries to set "binmode" on these file handles when + # it's loaded, and other modules may do the same in the future.) + Bugzilla::Install::Util::set_output_encoding(); # VERSION is provided by UNIVERSAL::, and can be called even if # the module isn't loaded. diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm index 7779f6bda..1e5a7b5e1 100644 --- a/Bugzilla/Install/Util.pm +++ b/Bugzilla/Install/Util.pm @@ -28,11 +28,13 @@ use strict; use Bugzilla::Constants; +use Encode; use File::Basename; use POSIX qw(setlocale LC_CTYPE); use Safe; use Scalar::Util qw(tainted); use Term::ANSIColor qw(colored); +use PerlIO; use base qw(Exporter); our @EXPORT_OK = qw( @@ -47,7 +49,6 @@ our @EXPORT_OK = qw( include_languages template_include_path vers_cmp - get_console_locale init_console ); @@ -569,11 +570,44 @@ sub get_console_locale { return $locale; } +sub set_output_encoding { + # If we've already set an encoding layer on STDOUT, don't + # add another one. + my @stdout_layers = PerlIO::get_layers(STDOUT); + return if grep(/^encoding/, @stdout_layers); + + my $encoding; + if (ON_WINDOWS and eval { require Win32::Console }) { + # Although setlocale() works on Windows, it doesn't always return + # the current *console's* encoding. So we use OutputCP here instead, + # when we can. + $encoding = Win32::Console::OutputCP(); + } + else { + my $locale = setlocale(LC_CTYPE); + if ($locale =~ /\.([^\.]+)$/) { + $encoding = $1; + } + } + $encoding = "cp$encoding" if ON_WINDOWS; + + $encoding = Encode::resolve_alias($encoding) if $encoding; + if ($encoding and $encoding !~ /utf-8/i) { + binmode STDOUT, ":encoding($encoding)"; + binmode STDERR, ":encoding($encoding)"; + } + else { + binmode STDOUT, ':utf8'; + binmode STDERR, ':utf8'; + } +} + sub init_console { eval { ON_WINDOWS && require Win32::Console::ANSI; }; $ENV{'ANSI_COLORS_DISABLED'} = 1 if ($@ || !-t *STDOUT); $SIG{__DIE__} = \&_console_die; prevent_windows_dialog_boxes(); + set_output_encoding(); } sub _console_die { diff --git a/checksetup.pl b/checksetup.pl index a27446e0c..8993ff08d 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -62,12 +62,6 @@ use Bugzilla::Install::Util qw(install_string get_version_and_os init_console); # When we're running at the command line, we need to pick the right # language before ever displaying any string. init_console(); -# Required for displaying strings from install_string, which are always -# in UTF-8, in every language. For other scripts, Bugzilla::init_page -# handles this, but here we just need to assume that checksetup.pl output -# is always UTF-8 in order for install_string to work properly in other -# languages. -binmode STDOUT, ':utf8'; my %switch; GetOptions(\%switch, 'help|h|?', 'check-modules', 'no-templates|t', -- cgit v1.2.1