From 8ec8da0491ad89604700b3e29a227966f6d84ba1 Mon Sep 17 00:00:00 2001 From: Perl Tidy Date: Wed, 5 Dec 2018 15:38:52 -0500 Subject: no bug - reformat all the code using the new perltidy rules --- Bugzilla/Install/Util.pm | 907 ++++++++++++++++++++++++----------------------- 1 file changed, 470 insertions(+), 437 deletions(-) (limited to 'Bugzilla/Install/Util.pm') diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm index b6d28d9c7..a5522e134 100644 --- a/Bugzilla/Install/Util.pm +++ b/Bugzilla/Install/Util.pm @@ -27,367 +27,391 @@ use PerlIO; use base qw(Exporter); our @EXPORT_OK = qw( - bin_loc - get_version_and_os - extension_code_files - i_am_persistent - indicate_progress - install_string - include_languages - success - template_include_path - init_console + bin_loc + get_version_and_os + extension_code_files + i_am_persistent + indicate_progress + install_string + include_languages + success + template_include_path + init_console ); sub bin_loc { - my ($bin, $path) = @_; - # This module is not needed most of the time and is a bit slow, - # so we only load it when calling bin_loc(). - require ExtUtils::MM; - - # If the binary is a full path... - if ($bin =~ m{[/\\]}) { - return MM->maybe_command($bin) || ''; - } - - # Otherwise we look for it in the path in a cross-platform way. - my @path = $path ? @$path : File::Spec->path; - foreach my $dir (@path) { - next if !-d $dir; - my $full_path = File::Spec->catfile($dir, $bin); - # MM is an alias for ExtUtils::MM. maybe_command is nice - # because it checks .com, .bat, .exe (etc.) on Windows. - my $command = MM->maybe_command($full_path); - return $command if $command; - } - - return ''; + my ($bin, $path) = @_; + + # This module is not needed most of the time and is a bit slow, + # so we only load it when calling bin_loc(). + require ExtUtils::MM; + + # If the binary is a full path... + if ($bin =~ m{[/\\]}) { + return MM->maybe_command($bin) || ''; + } + + # Otherwise we look for it in the path in a cross-platform way. + my @path = $path ? @$path : File::Spec->path; + foreach my $dir (@path) { + next if !-d $dir; + my $full_path = File::Spec->catfile($dir, $bin); + + # MM is an alias for ExtUtils::MM. maybe_command is nice + # because it checks .com, .bat, .exe (etc.) on Windows. + my $command = MM->maybe_command($full_path); + return $command if $command; + } + + return ''; } sub get_version_and_os { - # Display version information - my @os_details = POSIX::uname; - # 0 is the name of the OS, 2 is the major version, - my $os_name = $os_details[0] . ' ' . $os_details[2]; - if (ON_WINDOWS) { - require Win32; - $os_name = Win32::GetOSName(); - } - # $os_details[3] is the minor version. - return { bz_ver => BUGZILLA_VERSION, - perl_ver => sprintf('%vd', $^V), - os_name => $os_name, - os_ver => $os_details[3] }; + + # Display version information + my @os_details = POSIX::uname; + + # 0 is the name of the OS, 2 is the major version, + my $os_name = $os_details[0] . ' ' . $os_details[2]; + if (ON_WINDOWS) { + require Win32; + $os_name = Win32::GetOSName(); + } + + # $os_details[3] is the minor version. + return { + bz_ver => BUGZILLA_VERSION, + perl_ver => sprintf('%vd', $^V), + os_name => $os_name, + os_ver => $os_details[3] + }; } sub _extension_paths { - my $dir = bz_locations()->{'extensionsdir'}; - my @extension_items = glob("$dir/*"); - my @paths; - foreach my $item (@extension_items) { - my $basename = basename($item); - # Skip CVS directories and any hidden files/dirs. - next if ($basename eq 'CVS' or $basename =~ /^\./); - if (-d $item) { - if (!-e "$item/disabled") { - push(@paths, $item); - } - } - elsif ($item =~ /\.pm$/i) { - push(@paths, $item); - } - } - return @paths; + my $dir = bz_locations()->{'extensionsdir'}; + my @extension_items = glob("$dir/*"); + my @paths; + foreach my $item (@extension_items) { + my $basename = basename($item); + + # Skip CVS directories and any hidden files/dirs. + next if ($basename eq 'CVS' or $basename =~ /^\./); + if (-d $item) { + if (!-e "$item/disabled") { + push(@paths, $item); + } + } + elsif ($item =~ /\.pm$/i) { + push(@paths, $item); + } + } + return @paths; } sub extension_code_files { - my ($requirements_only) = @_; - my @files; - foreach my $path (_extension_paths()) { - my @load_files; - if (-d $path) { - my $extension_file = "$path/Extension.pm"; - my $config_file = "$path/Config.pm"; - if (-e $extension_file) { - push(@load_files, $extension_file); - } - if (-e $config_file) { - push(@load_files, $config_file); - } - - # Don't load Extension.pm if we just want Config.pm and - # we found both. - if ($requirements_only and scalar(@load_files) == 2) { - shift(@load_files); - } - } - else { - push(@load_files, $path); - } - next if !scalar(@load_files); - # We know that these paths are safe, because they came from - # extensionsdir and we checked them specifically for their format. - # Also, the only thing we ever do with them is pass them to "require". - trick_taint($_) foreach @load_files; - push(@files, \@load_files); + my ($requirements_only) = @_; + my @files; + foreach my $path (_extension_paths()) { + my @load_files; + if (-d $path) { + my $extension_file = "$path/Extension.pm"; + my $config_file = "$path/Config.pm"; + if (-e $extension_file) { + push(@load_files, $extension_file); + } + if (-e $config_file) { + push(@load_files, $config_file); + } + + # Don't load Extension.pm if we just want Config.pm and + # we found both. + if ($requirements_only and scalar(@load_files) == 2) { + shift(@load_files); + } } + else { + push(@load_files, $path); + } + next if !scalar(@load_files); + + # We know that these paths are safe, because they came from + # extensionsdir and we checked them specifically for their format. + # Also, the only thing we ever do with them is pass them to "require". + trick_taint($_) foreach @load_files; + push(@files, \@load_files); + } - return (\@files); + return (\@files); } sub indicate_progress { - my ($params) = @_; - my $current = $params->{current}; - my $total = $params->{total}; - my $every = $params->{every} || 1; - - print "." if !($current % $every); - if ($current == $total || $current % ($every * 60) == 0) { - print "$current/$total (" . int($current * 100 / $total) . "%)\n"; - } + my ($params) = @_; + my $current = $params->{current}; + my $total = $params->{total}; + my $every = $params->{every} || 1; + + print "." if !($current % $every); + if ($current == $total || $current % ($every * 60) == 0) { + print "$current/$total (" . int($current * 100 / $total) . "%)\n"; + } } sub feature_description { - my ($feature_name) = @_; - eval { - my $meta = Bugzilla::CPAN->cpan_meta; + my ($feature_name) = @_; + eval { + my $meta = Bugzilla::CPAN->cpan_meta; - return $meta->feature($feature_name)->description - } or warn $@; + return $meta->feature($feature_name)->description; + } or warn $@; } sub install_string { - my ($string_id, $vars) = @_; - _cache()->{install_string_path} ||= template_include_path(); - my $path = _cache()->{install_string_path}; - - my $string_template; - # Find the first template that defines this string. - foreach my $dir (@$path) { - my $base = "$dir/setup/strings"; - $string_template = _get_string_from_file($string_id, "$base.txt.pl") - if !defined $string_template; - last if defined $string_template; - } - - die "No language defines the string '$string_id'" - if !defined $string_template; - - utf8::decode($string_template) if !utf8::is_utf8($string_template); - - $vars ||= {}; - my @replace_keys = keys %$vars; - foreach my $key (@replace_keys) { - my $replacement = $vars->{$key}; - die "'$key' in '$string_id' is tainted: '$replacement'" - if tainted($replacement); - # We don't want people to start getting clever and inserting - # ##variable## into their values. So we check if any other - # key is listed in the *replacement* string, before doing - # the replacement. This is mostly to protect programmers from - # making mistakes. - if (grep($replacement =~ /##$key##/, @replace_keys)) { - die "Unsafe replacement for '$key' in '$string_id': '$replacement'"; - } - $string_template =~ s/\Q##$key##\E/$replacement/g; - } - - return $string_template; + my ($string_id, $vars) = @_; + _cache()->{install_string_path} ||= template_include_path(); + my $path = _cache()->{install_string_path}; + + my $string_template; + + # Find the first template that defines this string. + foreach my $dir (@$path) { + my $base = "$dir/setup/strings"; + $string_template = _get_string_from_file($string_id, "$base.txt.pl") + if !defined $string_template; + last if defined $string_template; + } + + die "No language defines the string '$string_id'" if !defined $string_template; + + utf8::decode($string_template) if !utf8::is_utf8($string_template); + + $vars ||= {}; + my @replace_keys = keys %$vars; + foreach my $key (@replace_keys) { + my $replacement = $vars->{$key}; + die "'$key' in '$string_id' is tainted: '$replacement'" + if tainted($replacement); + + # We don't want people to start getting clever and inserting + # ##variable## into their values. So we check if any other + # key is listed in the *replacement* string, before doing + # the replacement. This is mostly to protect programmers from + # making mistakes. + if (grep($replacement =~ /##$key##/, @replace_keys)) { + die "Unsafe replacement for '$key' in '$string_id': '$replacement'"; + } + $string_template =~ s/\Q##$key##\E/$replacement/g; + } + + return $string_template; } sub _wanted_languages { - my ($requested, @wanted); - - # Checking SERVER_SOFTWARE is the same as i_am_cgi() in Bugzilla::Util. - if (exists $ENV{'SERVER_SOFTWARE'}) { - my $cgi = eval { Bugzilla->cgi } || eval { require CGI; return CGI->new() }; - $requested = $cgi->http('Accept-Language') || ''; - my $lang = $cgi->cookie('LANG'); - push(@wanted, $lang) if $lang; - } - else { - $requested = get_console_locale(); - } - - push(@wanted, _sort_accept_language($requested)); - return \@wanted; + my ($requested, @wanted); + + # Checking SERVER_SOFTWARE is the same as i_am_cgi() in Bugzilla::Util. + if (exists $ENV{'SERVER_SOFTWARE'}) { + my $cgi = eval { Bugzilla->cgi } || eval { require CGI; return CGI->new() }; + $requested = $cgi->http('Accept-Language') || ''; + my $lang = $cgi->cookie('LANG'); + push(@wanted, $lang) if $lang; + } + else { + $requested = get_console_locale(); + } + + push(@wanted, _sort_accept_language($requested)); + return \@wanted; } sub _wanted_to_actual_languages { - my ($wanted, $supported) = @_; - - my @actual; - foreach my $lang (@$wanted) { - # If we support the language we want, or *any version* of - # the language we want, it gets pushed into @actual. - # - # Per RFC 1766 and RFC 2616, things like 'en' match 'en-us' and - # 'en-uk', but not the other way around. (This is unfortunately - # not very clearly stated in those RFC; see comment just over 14.5 - # in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) - my @found = grep(/^\Q$lang\E(-.+)?$/i, @$supported); - push(@actual, @found) if @found; - } + my ($wanted, $supported) = @_; - # We always include English at the bottom if it's not there, even if - # it wasn't selected by the user. - if (!grep($_ eq 'en', @actual)) { - push(@actual, 'en'); - } + my @actual; + foreach my $lang (@$wanted) { - return \@actual; + # If we support the language we want, or *any version* of + # the language we want, it gets pushed into @actual. + # + # Per RFC 1766 and RFC 2616, things like 'en' match 'en-us' and + # 'en-uk', but not the other way around. (This is unfortunately + # not very clearly stated in those RFC; see comment just over 14.5 + # in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4) + my @found = grep(/^\Q$lang\E(-.+)?$/i, @$supported); + push(@actual, @found) if @found; + } + + # We always include English at the bottom if it's not there, even if + # it wasn't selected by the user. + if (!grep($_ eq 'en', @actual)) { + push(@actual, 'en'); + } + + return \@actual; } sub supported_languages { - my $cache = _cache(); - return $cache->{supported_languages} if $cache->{supported_languages}; - - my @dirs = glob(bz_locations()->{'templatedir'} . "/*"); - my @languages; - foreach my $dir (@dirs) { - # It's a language directory only if it contains "default" or - # "custom". This auto-excludes CVS directories as well. - next if (!-d "$dir/default" and !-d "$dir/custom"); - my $lang = basename($dir); - # Check for language tag format conforming to RFC 1766. - next unless $lang =~ /^[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?$/; - push(@languages, $lang); - } + my $cache = _cache(); + return $cache->{supported_languages} if $cache->{supported_languages}; + + my @dirs = glob(bz_locations()->{'templatedir'} . "/*"); + my @languages; + foreach my $dir (@dirs) { - $cache->{supported_languages} = \@languages; - return \@languages; + # It's a language directory only if it contains "default" or + # "custom". This auto-excludes CVS directories as well. + next if (!-d "$dir/default" and !-d "$dir/custom"); + my $lang = basename($dir); + + # Check for language tag format conforming to RFC 1766. + next unless $lang =~ /^[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?$/; + push(@languages, $lang); + } + + $cache->{supported_languages} = \@languages; + return \@languages; } sub include_languages { - my ($params) = @_; - - # Basically, the way this works is that we have a list of languages - # that we *want*, and a list of languages that Bugzilla actually - # supports. If there is only one language installed, we take it. - my $supported = supported_languages(); - return @$supported if @$supported == 1; - - my $wanted; - if ($params->{language}) { - # We can pass several languages at once as an arrayref - # or a single language. - $wanted = $params->{language}; - $wanted = [$wanted] unless ref $wanted; - } - else { - $wanted = _wanted_languages(); - } - my $actual = _wanted_to_actual_languages($wanted, $supported); - return @$actual; + my ($params) = @_; + + # Basically, the way this works is that we have a list of languages + # that we *want*, and a list of languages that Bugzilla actually + # supports. If there is only one language installed, we take it. + my $supported = supported_languages(); + return @$supported if @$supported == 1; + + my $wanted; + if ($params->{language}) { + + # We can pass several languages at once as an arrayref + # or a single language. + $wanted = $params->{language}; + $wanted = [$wanted] unless ref $wanted; + } + else { + $wanted = _wanted_languages(); + } + my $actual = _wanted_to_actual_languages($wanted, $supported); + return @$actual; } # Used by template_include_path sub _template_lang_directories { - my ($languages, $templatedir) = @_; - - my @add = qw(custom default); - my $project = bz_locations->{'project'}; - unshift(@add, $project) if $project; - - my @result; - foreach my $lang (@$languages) { - foreach my $dir (@add) { - my $full_dir = "$templatedir/$lang/$dir"; - if (-d $full_dir) { - trick_taint($full_dir); - push(@result, $full_dir); - } - } - } - return @result; + my ($languages, $templatedir) = @_; + + my @add = qw(custom default); + my $project = bz_locations->{'project'}; + unshift(@add, $project) if $project; + + my @result; + foreach my $lang (@$languages) { + foreach my $dir (@add) { + my $full_dir = "$templatedir/$lang/$dir"; + if (-d $full_dir) { + trick_taint($full_dir); + push(@result, $full_dir); + } + } + } + return @result; } # Used by template_include_path. sub _template_base_directories { - my @template_dirs; + my @template_dirs; - foreach my $path (_extension_paths()) { - next if !-d $path; - if ( -d "$path/template") { - push(@template_dirs, "$path/template"); - } + foreach my $path (_extension_paths()) { + next if !-d $path; + if (-d "$path/template") { + push(@template_dirs, "$path/template"); } + } - state $bz_locations = bz_locations(); - push(@template_dirs, $bz_locations->{'templatedir'}); - return \@template_dirs; + state $bz_locations = bz_locations(); + push(@template_dirs, $bz_locations->{'templatedir'}); + return \@template_dirs; } sub template_include_path { - my ($params) = @_; - my @used_languages = include_languages($params); - # Now, we add template directories in the order they will be searched: - my $template_dirs = _template_base_directories(); - - my @include_path; - foreach my $template_dir (@$template_dirs) { - my @lang_dirs = _template_lang_directories(\@used_languages, - $template_dir); - # Hooks get each set of extension directories separately. - if ($params->{hook}) { - push(@include_path, \@lang_dirs); - } - # Whereas everything else just gets a whole INCLUDE_PATH. - else { - push(@include_path, @lang_dirs); - } + my ($params) = @_; + my @used_languages = include_languages($params); + + # Now, we add template directories in the order they will be searched: + my $template_dirs = _template_base_directories(); + + my @include_path; + foreach my $template_dir (@$template_dirs) { + my @lang_dirs = _template_lang_directories(\@used_languages, $template_dir); + + # Hooks get each set of extension directories separately. + if ($params->{hook}) { + push(@include_path, \@lang_dirs); } - return \@include_path; + + # Whereas everything else just gets a whole INCLUDE_PATH. + else { + push(@include_path, @lang_dirs); + } + } + return \@include_path; } # This is taken straight from Sort::Versions 1.5, which is not included # with perl by default. sub vers_cmp { - my ($a, $b) = @_; - - # Remove leading zeroes - Bug 344661 - $a =~ s/^0*(\d.+)/$1/; - $b =~ s/^0*(\d.+)/$1/; - - my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g); - my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g); - - my ($A, $B); - while (@A and @B) { - $A = shift @A; - $B = shift @B; - if ($A eq '-' and $B eq '-') { - next; - } elsif ( $A eq '-' ) { - return -1; - } elsif ( $B eq '-') { - return 1; - } elsif ($A eq '.' and $B eq '.') { - next; - } elsif ( $A eq '.' ) { - return -1; - } elsif ( $B eq '.' ) { - return 1; - } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { - if ($A =~ /^0/ || $B =~ /^0/) { - return $A cmp $B if $A cmp $B; - } else { - return $A <=> $B if $A <=> $B; - } - } else { - $A = uc $A; - $B = uc $B; - return $A cmp $B if $A cmp $B; - } + my ($a, $b) = @_; + + # Remove leading zeroes - Bug 344661 + $a =~ s/^0*(\d.+)/$1/; + $b =~ s/^0*(\d.+)/$1/; + + my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g); + my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g); + + my ($A, $B); + while (@A and @B) { + $A = shift @A; + $B = shift @B; + if ($A eq '-' and $B eq '-') { + next; + } + elsif ($A eq '-') { + return -1; + } + elsif ($B eq '-') { + return 1; + } + elsif ($A eq '.' and $B eq '.') { + next; + } + elsif ($A eq '.') { + return -1; + } + elsif ($B eq '.') { + return 1; + } + elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) { + if ($A =~ /^0/ || $B =~ /^0/) { + return $A cmp $B if $A cmp $B; + } + else { + return $A <=> $B if $A <=> $B; + } + } + else { + $A = uc $A; + $B = uc $B; + return $A cmp $B if $A cmp $B; } - @A <=> @B; + } + @A <=> @B; } sub no_checksetup_from_cgi { - print "Content-Type: text/html; charset=UTF-8\r\n\r\n"; - print install_string('no_checksetup_from_cgi'); - exit; + print "Content-Type: text/html; charset=UTF-8\r\n\r\n"; + print install_string('no_checksetup_from_cgi'); + exit; } ###################### @@ -396,160 +420,169 @@ sub no_checksetup_from_cgi { # Used by install_string sub _get_string_from_file { - my ($string_id, $file) = @_; - # If we already loaded the file, then use its copy from the cache. - if (my $strings = _cache()->{strings_from_file}->{$file}) { - return $strings->{$string_id}; - } - - # This module is only needed by checksetup.pl, - # so only load it when needed. - require Safe; - - return undef if !-e $file; - my $safe = new Safe; - $safe->rdo($file); - my %strings = %{$safe->varglob('strings')}; - _cache()->{strings_from_file}->{$file} = \%strings; - return $strings{$string_id}; + my ($string_id, $file) = @_; + + # If we already loaded the file, then use its copy from the cache. + if (my $strings = _cache()->{strings_from_file}->{$file}) { + return $strings->{$string_id}; + } + + # This module is only needed by checksetup.pl, + # so only load it when needed. + require Safe; + + return undef if !-e $file; + my $safe = new Safe; + $safe->rdo($file); + my %strings = %{$safe->varglob('strings')}; + _cache()->{strings_from_file}->{$file} = \%strings; + return $strings{$string_id}; } # Make an ordered list out of a HTTP Accept-Language header (see RFC 2616, 14.4) # We ignore '*' and ;q=0 # For languages with the same priority q the order remains unchanged. sub _sort_accept_language { - sub sortQvalue { $b->{'qvalue'} <=> $a->{'qvalue'} } - my $accept_language = $_[0]; - - # clean up string. - $accept_language =~ s/[^A-Za-z;q=0-9\.\-,]//g; - my @qlanguages; - my @languages; - foreach(split /,/, $accept_language) { - if (m/([A-Za-z\-]+)(?:;q=(\d(?:\.\d+)))?/) { - my $lang = $1; - my $qvalue = $2; - $qvalue = 1 if not defined $qvalue; - next if $qvalue == 0; - $qvalue = 1 if $qvalue > 1; - push(@qlanguages, {'qvalue' => $qvalue, 'language' => $lang}); - } - } - - return map($_->{'language'}, (sort sortQvalue @qlanguages)); + sub sortQvalue { $b->{'qvalue'} <=> $a->{'qvalue'} } + my $accept_language = $_[0]; + + # clean up string. + $accept_language =~ s/[^A-Za-z;q=0-9\.\-,]//g; + my @qlanguages; + my @languages; + foreach (split /,/, $accept_language) { + if (m/([A-Za-z\-]+)(?:;q=(\d(?:\.\d+)))?/) { + my $lang = $1; + my $qvalue = $2; + $qvalue = 1 if not defined $qvalue; + next if $qvalue == 0; + $qvalue = 1 if $qvalue > 1; + push(@qlanguages, {'qvalue' => $qvalue, 'language' => $lang}); + } + } + + return map($_->{'language'}, (sort sortQvalue @qlanguages)); } sub get_console_locale { - require Locale::Language; - my $locale = setlocale(LC_CTYPE); - my $language; - # Some distros set e.g. LC_CTYPE = fr_CH.UTF-8. We clean it up. - if ($locale =~ /^([^\.]+)/) { - $locale = $1; - } - $locale =~ s/_/-/; - # It's pretty sure that there is no language pack of the form fr-CH - # installed, so we also include fr as a wanted language. - if ($locale =~ /^(\S+)\-/) { - $language = $1; - $locale .= ",$language"; - } - else { - $language = $locale; - } - - # Some OSs or distributions may have setlocale return a string of the form - # German_Germany.1252 (this example taken from a Windows XP system), which - # is unsuitable for our needs because Bugzilla works on language codes. - # We try and convert them here. - if ($language = Locale::Language::language2code($language)) { - $locale .= ",$language"; - } - - return $locale; + require Locale::Language; + my $locale = setlocale(LC_CTYPE); + my $language; + + # Some distros set e.g. LC_CTYPE = fr_CH.UTF-8. We clean it up. + if ($locale =~ /^([^\.]+)/) { + $locale = $1; + } + $locale =~ s/_/-/; + + # It's pretty sure that there is no language pack of the form fr-CH + # installed, so we also include fr as a wanted language. + if ($locale =~ /^(\S+)\-/) { + $language = $1; + $locale .= ",$language"; + } + else { + $language = $locale; + } + + # Some OSs or distributions may have setlocale return a string of the form + # German_Germany.1252 (this example taken from a Windows XP system), which + # is unsuitable for our needs because Bugzilla works on language codes. + # We try and convert them here. + if ($language = Locale::Language::language2code($language)) { + $locale .= ",$language"; + } + + 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'; - } + # 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(); + 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 { - my ($message) = @_; - # $^S means "we are in an eval" - if ($^S) { - die $message; - } - # Remove newlines from the message before we color it, and then - # add them back in on display. Otherwise the ANSI escape code - # for resetting the color comes after the newline, and Perl thinks - # that it should put "at Bugzilla/Install.pm line 1234" after the - # message. - $message =~ s/\n+$//; - # We put quotes around the message to stringify any object exceptions, - # like Template::Exception. - die colored("$message", COLOR_ERROR) . "\n"; + my ($message) = @_; + + # $^S means "we are in an eval" + if ($^S) { + die $message; + } + + # Remove newlines from the message before we color it, and then + # add them back in on display. Otherwise the ANSI escape code + # for resetting the color comes after the newline, and Perl thinks + # that it should put "at Bugzilla/Install.pm line 1234" after the + # message. + $message =~ s/\n+$//; + + # We put quotes around the message to stringify any object exceptions, + # like Template::Exception. + die colored("$message", COLOR_ERROR) . "\n"; } sub success { - my ($message) = @_; - print colored($message, COLOR_SUCCESS), "\n"; + my ($message) = @_; + print colored($message, COLOR_SUCCESS), "\n"; } sub prevent_windows_dialog_boxes { - # This code comes from http://bugs.activestate.com/show_bug.cgi?id=82183 - # and prevents Perl modules from popping up dialog boxes, particularly - # during checksetup (since loading DBD::Oracle during checksetup when - # Oracle isn't installed causes a scary popup and pauses checksetup). - # - # Win32::API ships with ActiveState by default, though there could - # theoretically be a Windows installation without it, I suppose. - if (ON_WINDOWS and eval { require Win32::API }) { - # Call kernel32.SetErrorMode with arguments that mean: - # "The system does not display the critical-error-handler message box. - # Instead, the system sends the error to the calling process." and - # "A child process inherits the error mode of its parent process." - my $SetErrorMode = Win32::API->new('kernel32', 'SetErrorMode', - 'I', 'I'); - my $SEM_FAILCRITICALERRORS = 0x0001; - my $SEM_NOGPFAULTERRORBOX = 0x0002; - $SetErrorMode->Call($SEM_FAILCRITICALERRORS | $SEM_NOGPFAULTERRORBOX); - } + + # This code comes from http://bugs.activestate.com/show_bug.cgi?id=82183 + # and prevents Perl modules from popping up dialog boxes, particularly + # during checksetup (since loading DBD::Oracle during checksetup when + # Oracle isn't installed causes a scary popup and pauses checksetup). + # + # Win32::API ships with ActiveState by default, though there could + # theoretically be a Windows installation without it, I suppose. + if (ON_WINDOWS and eval { require Win32::API }) { + + # Call kernel32.SetErrorMode with arguments that mean: + # "The system does not display the critical-error-handler message box. + # Instead, the system sends the error to the calling process." and + # "A child process inherits the error mode of its parent process." + my $SetErrorMode = Win32::API->new('kernel32', 'SetErrorMode', 'I', 'I'); + my $SEM_FAILCRITICALERRORS = 0x0001; + my $SEM_NOGPFAULTERRORBOX = 0x0002; + $SetErrorMode->Call($SEM_FAILCRITICALERRORS | $SEM_NOGPFAULTERRORBOX); + } } # This is like request_cache, but it's used only by installation code @@ -561,20 +594,20 @@ use constant _cache => {}; ############################## sub trick_taint { - require Carp; - Carp::confess("Undef to trick_taint") unless defined $_[0]; - my $match = $_[0] =~ /^(.*)$/s; - $_[0] = $match ? $1 : undef; - return (defined($_[0])); + require Carp; + Carp::confess("Undef to trick_taint") unless defined $_[0]; + my $match = $_[0] =~ /^(.*)$/s; + $_[0] = $match ? $1 : undef; + return (defined($_[0])); } sub trim { - my ($str) = @_; - if ($str) { - $str =~ s/^\s+//g; - $str =~ s/\s+$//g; - } - return $str; + my ($str) = @_; + if ($str) { + $str =~ s/^\s+//g; + $str =~ s/\s+$//g; + } + return $str; } __END__ -- cgit v1.2.3-24-g4f1b